历史上的今天
今天是:2024年10月28日(星期一)
2019年10月28日 | SPI协议工作过程详解文档,内含实例代码
2019-10-28 来源:51hei
SPI:一种3线(有的没有SS线(选择主或从机模式))或4线的通信方式:
MOSI:主机出从机进数据线
MISO:主机进从机从数据线
SCK: 时钟线
SS: 主从模式选择线
工作过程的理解:设置好相应的配置后就可以发送或接收数据,当放送或接收完成后就会是SPIF置位,此时如果开了中断就会就入中断服务程序。如果没开中断就可以通过查询该标志位来做相应的事。进入中段服务程序后,或者读(写)SPDR寄存器都可以清零SPIF标志位。从而可以开始下一次的传输
相应的寄存器
1:SCPR:控制寄存器:SPI的大部分设置
2:SPSR:标志寄存器:(查看一些标志(主要是SPIF位)和设置SPI速度)
3:SPDR:数据寄存器:
SS引脚的说明:(实质就是当配置为输入时:是主机还是从机由输入的电平来决定)
从机模式: 当 SPI 配置为从机时,从机选择引脚 SS 总是为输入。SS 为低将激活 SPI 接口,MISO
成为输出 ( 用户必须进行相应的端口配置 ) 引脚,其他引脚成为输入引脚。当 SS 为高时
所有的引脚成为输入, SPI 逻辑复位,不再接收数据。
SS引脚对于数据包/字节的同步非常有用,可以使从机的位计数器与主机的时钟发生器同
步。当SS 拉高时SPI从机立即复位接收和发送逻辑,并丢弃移位寄存器里不完整的数据。
主机模式:当 SPI 配置为主机时 (SPCR 的 MSTR置位 ),用户可以决定 SS 引脚的方向。
若 SS 配置为输出,则此引脚可以用作普通的 I/O 口而不影响 SPI 系统。典型应用是用来
驱动从机的 SS 引脚。
如果 SS 配置为输入,必须保持为高以保证 SPI 的正常工作。若系统配置为主机,SS 为
输入,但被外设拉低,则 SPI 系统会将此低电平解释为有一个外部主机将自己选择为从
机。为了防止总线冲突, SPI 系统将实现如下动作:
1. 清零 SPCR 的 MSTR 位,使 SPI 成为从机,从而 MOSI 和 SCK变为输入。
2. SPSR 的 SPIF 置位。若 SPI 中断和全局中断开放,则中断服务程序将得到执行。
因此,使用中断方式处理 SPI 主机的数据传输,并且存在 SS 被拉低的可能性时,中断服
务程序应该检查 MSTR 是否为 "1”。若被清零,用户必须将其置位,以重新使能 SPI 主机
模式。
管脚配置

一:SCPR:控制寄存器:(SPI的大部分设置都在该寄存器)



二SPSR:标志寄存器:(查看一些标志和设置SPI速度,主要是用到SPIF这个标志位,接收完成和发送完成都会置位这个标志,进入中断服务程序或访问SPDR寄存 器都可以清零这个标志)

三SPDR:数据寄存器:


应用步骤:
1先根据是主还是从设置端口的模式(输入还是输出)
主机:SS MOSI SCK 为出 MISO为入
从机:SS MOSI SCK 为入 MISO 为出
2配置相应的寄存器(就三个寄存器,注意用到中断时要先开总中断)
3用中断或查询法发送或接收数据
注意:主机或者从机都可以发送或接收。发送完之后就可以马上发下一个数据了。接收也是只要接收完了也可以马上接收下一个数据了
一:发送:(一般用查询方式发送比较好:此时只要查询发送完毕的标志位SPIF是否置位)
常用:while(!(SPSR & (1< 例子: 主机发送(查询方式)(只要发送完毕了就可以继续发送了) //主机模式下发送1-255 #include #define uint unsigned int #define uchar unsigned char void spi_init(void) { PORTB |= (1< SPSR = 0x00; //SPI2x=0 } void SPI_send_data(char cData) { PORTB &=~ (1< while(!(SPSR & (1< } void Delay(uint z) // { unsigned int i,j; for(i=z;i>0;i--) for(j=2000;j>0;j--); } int main(void) { unsigned int i=0; spi_init(); while(1) { for(i=255;i>0;i--) { SPI_send_data(i); Delay(100); } } } 2从机接收(查询方式) #include #include #define uchar unsigned char #define uint unsigned int void port_init(void) { PORTA = 0x00; DDRA = 0xFF; PORTB = 0xFF; } void spi_init(void) { DDRB = (1<<5) |(1<<7); DDRB&=~(1<<4)|(1<<6); SPCR = 0x63; // SPI允许。从机方式 SPSR = 0x00; // SPI倍速.频率为系统时钟 } void init_devices(void) { port_init(); spi_init(); } //主函数 int main(void) { init_devices(); while(1) { while(!(SPSR & (1< _delay_loop_2(900); } } 3从机中断方式接收数据(注意:当进入中断服务程序后SPIF会自动清零) /*中断方式接收数据*/ #include #include #define uchar unsigned char #define uint unsigned int //端口初始化 void port_init(void) { PORTA = 0xFF; DDRA = 0xFF; } void spi_init(void) { PORTB |= (1<<4) | (1<<5) | (1<<6) | (1<<7); // DDRB |= (1<<5) | (1<<7) | (1<<4); //Set MOSI, SCK AND SS as outputs SPCR = 0xE3; //SPI中断使能,SPI使能,低位首发,从机模式,时钟模式00,上升沿采样;时钟速率Fosc/128 SPSR = 0x00; //SPI2x=0 } void init_devices(void) { port_init(); spi_init(); sei();//开全局中断 } //主函; int main(void) { init_devices(); while(1); } //SPI中断函数 SIGNAL(SIG_SPI) { PORTA=SPDR; }
史海拾趣
|
本帖最后由 paulhyde 于 2014-9-15 03:45 编辑 文件夹中一共11个程序,有很详细的说明,希望对初学NEC单片机和想学习NEC单片机的人有帮助,由于本人学习NEC单片机时间比较短,程序中有错误的还希望大家指点,单片机是0537DA … 查看全部问答> |
|
相信大家都用过磁盘碎片整理方面的软件,VoptXP、Defraggler、O&O Defrag Pro、Diskeeper这些世界级的知名软件,但都是国外的产品,而且就世界范围上讲也就这屈指可数的几种而已,难道咱们中国没有人能够做出这一个小小东西吗?在这里我还是想跟大 ...… 查看全部问答> |
|
P2口8个端口作为DATA BUS数据线,同LCD的8根数据线相连接,单片机89E58芯片未动作时测量P2口电压为1.5V,LCD的接口芯片为S6B0108,P2口输出为低电平时,用示波器测量电压为1.5V,P2口输出高电平时,用示波器测量电压为5V。 请教:为何P2口电压拉不 ...… 查看全部问答> |
|
谁会用 moselsim10.1c 仿真 quartus13.1 例化的 10gbase-kr 有没有具体的细节 步骤 教程 或者 altare ip core 的教程啊 还有就是 10gbase-kr的 手册… 查看全部问答> |
|
这是一款Intel的实感技术的3D摄像头,在官网是还没有正式发布的。不要问我从哪里来 这款摄像头主要针对的是后置摄像头应用,应用在内容创建,增强现实感,物体扫描等应用。 需要开发它的电脑配置要挺高,必须使用USB3.0的接口,酷睿4代以上的CPU ...… 查看全部问答> |




