资源预览内容
第1页 / 共15页
第2页 / 共15页
第3页 / 共15页
第4页 / 共15页
第5页 / 共15页
第6页 / 共15页
第7页 / 共15页
第8页 / 共15页
第9页 / 共15页
第10页 / 共15页
亲,该文档总共15页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
1.串行外围设备接口入门(Introduction to the Serial Peripheral Interface)Serial Peripheral Interface (SPI)是一种同步串行数据传输协议,用于近距离时,微控制器(Microcontrollers) ,如 Arduino,与其他外围设备的快速通信。他也可以用于 2 个微控制器的通讯。SPI 通讯通常有一个主设备(通常是 Microcontrollers),用于控制外围设备。通常会有 3 种线路通用于各类设备的方法。-Master In Slave Out(MISO)- Slave line,用于 Slave 向 Master 发送数据-Master Out Slave In(MOSI)- Master line,用于 Master 向 Slave 发送数据-Serial Clock(SCK)- 时钟脉冲,主设备用于同步数据传输-Slave Select pin- 分配给所有的设备,用于 enable/disable 指定的设备,同时用于避免由于线路忙导致的错误传输。SPI 最大的问题在于它的标准太不严格了,这导致各个设备在实现它的时候都有一些不同,这就意味着当我们在编写接口代码的时候必须仔细阅读设备数据参数。通常来说有编号为 0-3 的 3 种传输模式(不是 4 种么?)这些模式控制数据是在时钟信号的高电平还是低电平传入或传出,以及在高或低电平时时钟无效。所有的 SPI 设置都由 Arduino SPI 控制寄存器(SPCR)来决定。这个寄存器就是微控制器内存的一个字节,它是可读写的。寄存器提供的服务通常有 3 类:控制、数据和状态。控制寄存器(SPCR)编码设置控制多种微控制器的功能。通常控制寄存器中的一个位影响某个特定的设置,比如速度和极性(这个是啥?)数据寄存器(SPDR)仅仅 hold 住了一个字节。比如,SPI 数据寄存器 hold 住了要发往 MOSI 线的一个字节,或者这个数据是要从 MISO 线传入的。状态寄存器(SPSR)根据多种微控制器的条件改变其状态。比如,SPI 状态寄存器(SPSR)的第七位被设置为 1 表示有数据从 SPI 传入或传出。SPI 控制寄存器(SPCR)共有 8 位,每一个都控制了一种特定的 SPI 设置。SPIE:置为 1 时,表示 enable SPI 的中断SPE:置为 1 时,表示 enable SPIDORD:发送数据时,设置为 1 表示最低有效位,0 表示最高有效位。请各自脑补最低有效位和最高有效位。MSTR:设置为 1 表示 Arduino 为 master 模式,0 为 slave 模式CPOL:设置为 1 时,数据时钟在高时无效,设置为 0 时,在低时无效CPHA:设置为 1 时,时钟低电平时是 Samples data(样本数据?),0 时时钟高电平是 SampledataSPR1 和 SPR0:设置 SPI 的速度,00 是最快的(4MHz),11 是最慢的(250KHz)这些意味着当对一个新的 SPI 设备编码的时候,我们需要注意一些事情并根据如下设置 SPCR:- 数据传入是最高有效位(MSB)还是最低有效位(LSB)?- 数据时钟无效是在高还是低?- samples 是在时钟脉冲上升沿还是下降沿?- SPI 运行的速度是多少?你还要感受一下 feel 一下你的芯片,在你设置好之后需要暂停多久才能继续?Lets go !2.串行 EEPROM 简介AT25HP512 是一个 65536 字节串行 EEPROM。它支持 SPI 的模式 0-3,在10MHz,5V 的环境下运行,同时也可以在 1.8v 的低速下运行。他的内存被组织成 512 个页,每个页有 128 字节。他每次只能写入 128 字节,但是可以同时读出1-128 字节的数据,这个设备同时提供了多种程度的写保护,但这里不涉及这个部分。enable 这个设备只需要让片选信号 CS 为低即可。指令使用 8 位的 opcodes 来发送,同时在时钟上升沿传入数据,大概使用 10 微秒写入 1 个页的数据,所以在每个 EEPROM 的的写程序后面都应该等待 10ms。3.面包板的准备将 AT25HP512 芯片插入面包板,EEPROM 的 3,7,8 引脚接到 5V,引脚 4 接地。红色的线接+5V,GND 线是黑色EERPOM 的引脚 1 连接 Arduino 的引脚 10(Slave 片选),EEPROM 的引脚 2连接 Arduino 的引脚 12(Master In Slave Out - MISO),EEPROM 的引脚 5连接 Arduino 的引脚 11(Master Out Slave In - MOSI),同时 EEPROM 的引脚 6 连接 Arduino 的引脚 13(串口时钟 SCK)。4.Arduino SPI 编程现在我们要编写能让 Arduino 和 EEPROM 进行 SPI 通信的代码了。在启动代码中,这个程序填充 128 字节,或者一个 EEPROM 页。在 main loop 中他将数据读出来,每次读一个字节并通过串口打印出来。我们下面用一小节来过一下代码。第一步是启动我们的预处理指令(其实就是#define 啦),预处理指令是在真正的编译开始前处理的。他们以#开头并且不以分号(; )结尾。反正前面一段就是说,我们接下来要开始使用#define 了。下面定义在我们的 SPI 通讯中要用到的 pins 引脚, DATAOUT, DATAIN, SPICLOCK 和 SLAVESELECT。然后定义 EEPROM 的控制指令(opcodes):接下来分配程序会用到的全局变量。我们将用 char buffer128来保存要传输到EEPROM 的数据:首先我们初始化我们的串口连接,设置我们的 input 和 output 模式并设置SLAVESELECT 线为高时开始。这个设置可以使设备暂时失效,这样可以防止由于线路噪声引起的传输错误。现在我们设置 SPI 控制寄存器( SPCR)为二进制数据 01010000.在控制寄存器中,每一位的设置都表示不同的功能。第 8 位关闭 SPI 中断,第七位 enable SPI,第六位选择数据传输是最高有效位有线,第五位设置 Arduino 为 master 模式,第四位设置数据时钟低时无效,第三位代表 SPI 在数据时钟的上升沿阶段抽样数据,第二位和第一位设置 SPI 和系统的通讯速度, /4 有 4 个级别。当设置了控制寄存后,我们接下来从垃圾回收变量中读取 SPI 的状态寄存器( SPSR)和数据寄存器(SPDR ),以清除以前运行的脏数据:这里我们用数字来填充要发送的数组,并向 EEPROM 写入一个 enable 指令。这个 enable 指令必须在任何一个写指令之前完成。为了发送这个指令,我们将SLAVESELECT 线置为低,enable 这个设备后,使用 spi_transfer 函数发送指令。注意到我们使用了程序开始定义的 WREN opcode。最后我们设置 SLAVESELECT线为高来释放它。在短暂的 delay(10)之后,我们将 SLAVESELECT 线置为低再次选中 EEPROM 设备。我们发送一个写指令来告诉 EEPROM 我们将发送数据到内存中。首先发送 16位,也就是 2 个字节地址来开始,最高有效位。接下来发送 buffer 中的 128 字节数据,一个字节接着一个字节,不需要 pause 暂停。最后我们设置 SLAVESELECT引脚为高来释放设备,同时等待一段时间以保证 EEPROM 写入数据:我们在 setup 函数结束时,通过串口发送 hi 来表示 setup 结束。在我们的主函数 loop 中我们每次从 EEPROM 中读取一个字节并通过串口将它打印出来。为了可读性我们增加一个打印以及等待。每一次 loop 我们都增加EEPROM 的一个地址去读,当地址增加到 128 后,我们重新回到 0 开始读,原因很简单,因为开始我们只写入了 128 字节数据:fill_buffer 函数仅仅将我们的数组用 0-127 这 128 个数字来填充。这个函数很容易就可以改写为你应用程序需要的数据:spi_transfer 函数将要传出的数据放入数据传输寄存器,然后就开始 SPI 传输了哈。可以通过 SPI 状态寄存器( SPSR)的某个位(SPIF)来查看数据传输是否结束了。关于位掩码(bit mask)可以参考这里:http:/www.arduino.cc/en/Tutorial/。最后返回写入 EEPROM 的数据。read_eeprom 函数允许我们从 EEPROM 中读入数据,首先设置 SLAVESELECT为低来 enable 设备。接下来送入一个读指定,接下来送入要读的 16 位地址,最高有效位有限。接下来我们发送一个假数据到 EEPROM 中以将数据传出。最后我们在读入一个字节后,再次设置 SLAVESELECT 线为高来释放设备,并返回数据,如果我们想要一次读入多个数据,那么当我们重复 data=spi_transfer(0XFF)时,需要将 SLAVESELECT 一直设置为低,这样来回 128 次后读出整个页的数据:为了方便大家 CTRL+c、 CTRL+v,下面是整个手册的源码:cpp view plaincopy1. #define DATAOUT 11/MOSI 2. #define DATAIN 12/MISO 3. #define SPICLOCK 13/sck 4. #define SLAVESELECT 10/ss 5. 6. /opcodes 7. #define WREN 6 8. #define WRDI 4 9. #define RDSR 5 10. #define WRSR 1 11. #define READ 3 12. #define WRITE 2 13. 14. byte eeprom_output_data; 15. byte eeprom_input_data=0; 16. byte clr; 17. int address=0; 18. /data buffer 19. char buffer 128; 20. 21. void fill_buffer() 22. 23. for (int I=0;I8); /send MSByte address first 65. spi_transfer(char)(address); /send LSByte address 66. /write 128 bytes 67. for (int I=0;I8); /send MSByte address first 87. spi_transfer(char)(EEPROM_address); /send LSByte address 88. data = spi_transfer(0xFF); /get data byte 89. digitalWrite(SLAVESELECT,HIGH); /release chip, signal end transfer 90. return data; 91. 92. 93. void loop() 94. 95. eeprom_output_data = read_eeprom(address); 96. Serial.print(eeprom_output_data,DEC);
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号