资源预览内容
第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,下面是整个手册的源码:cppview plaincopy1. #defineDATAOUT11/MOSI2. #defineDATAIN12/MISO3. #defineSPICLOCK13/sck4. #defineSLAVESELECT10/ss5. 6. /opcodes7. #defineWREN68. #defineWRDI49. #defineRDSR510. #defineWRSR111. #defineREAD312. #defineWRITE213. 14. byteeeprom_output_data;15. byteeeprom_input_data=0;16. byteclr;17. intaddress=0;18. /databuffer19. charbuffer128;20. 21. voidfill_buffer()22. 23. for(intI=0;I128;I+)24. 25. bufferI=I;26. 27. 28. 29. charspi_transfer(volatilechardata)30. 31. SPDR=data;/Startthetransmission32. while(!(SPSR&(1SPIF)/Waittheendofthetransmission33. 34. ;35. returnSPDR;/returnthereceivedbyte36. 37. 38. voidsetup()39. 40. Serial.begin(9600);41. 42. pinMode(DATAOUT,OUTPUT);43. pinMode(DATAIN,INPUT);44. pinMode(SPICLOCK,OUTPUT);45. pinMode(SLAVESELECT,OUTPUT);46. digitalWrite(SLAVESELECT,HIGH);/disabledevice
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号