TMS320F28335的SPI
文章目录1. SPI简介2. F28335的SPI2.1 F28335的SPI的内部框图2.2 SCI与SPI的比较2.3 F28335的SPI主要功能讲解(对照SPI结构框图)2.3.1 有2种工作方式:主、从工作方式2.3.2 125 种可编程波特率2.3.3 可编程的1~16的数据长度2.3.44种时钟模式(由时钟极性和时钟相位控制)2.3.5具有增强的16级发送/接收FIFO2.3.6 2
文章目录
1. SPI简介
SPI(Serial Peripheral Interface),即串行外设接口,是一种全双工同步通信总线,SPI主要应用在EEPROM、FLASH、实时时钟、AD 转换器以及数字信号处理器和数字信号解码器中。
使用SPI通信协议的芯片,管脚上只需要MISO、MOSI、SCLK以及CS共四根线,描述如下:
MISO(master input slave output):主机输入/从机输出线,主机从该信号线上读从机输 出的数据。
MOSI(master output slave input):主机输出/从机输入线,从机从该信号线上读主机输 出的数据。
SCLK(serial clock):时钟信号线,该信号线用于同步两个通信设备的通信速率,该通信速率由主机产生,不同的设备支持的最高通信速率不一样,通信速率受限于低速设备。
CS(chip select):从机选择信号线,当有多个 SPI 从机与 SPI 主机相连时,通过CS端来分辨到底是哪个从机与主机相连,一般来说,主机的CS端置高,通信的从机的CS端置低。
无论是主机还是从机,它们共用SPI的SCLK、MOSI以及MISO三根线,即无论有多少个从设备,都共同使用这3条SPI总线。每个从机都有独立CS信号线,该信号线独占主机的一个引脚,即有多少个从设备,就有多少条片选信号线。当主机要选择从机时,把该从机的CS信号线设置为低电平,则该从机即被选中,接着主机开始与被选中的从机通过MOSI及MISO信号线来传输数据。MOSI及MISO数据线在SCLK的每个时钟周期传输一位数据,且数据输入、输出是同步的,也就是说在输出数据的同时也在读入数据。
主机与从机的简易连接图如下:
2. F28335的SPI
2.1 F28335的SPI的内部框图
F28335内部含有一个SPI模块,结构框图如下:
2.2 SCI与SPI的比较
从SPI的结构框图可以看到,F28335的SPI与SCI有许多相同的结构,如发送接收BUF寄存器、16级的发送接收FIFO缓冲区、移位寄存器、FIFO中断、发送接受中断等。
SCI为串行通信接口,为全双工异步通信工作方式,常与RS232连接,用于与外部机进行串行通信;而SPI为串行外设接口,为全双工同步通信工作方式,可与多个遵循SPI协议的外设进行连接,进行从机与主机的信息交流。
既然两者的内部结构大体类似,那么SPI的配置步骤就类似于SCI的配置。
2.3 F28335的SPI主要功能讲解(对照SPI结构框图)
2.3.1 有2种工作方式:主、从工作方式
F28335的SPI到底作为主机还是从机是由SPICTL.2控制的。
当工作在主机模式时,F28335的SPI将提供串行通信时钟SCLK,数据从SIMO引脚输出,从SOMI引脚输入。此时需要将要发送的数据写到SPITXBUF中,该数据最终会传到SPIDAT中并逐步输出,读到的数据将会存放在SPIRXBUF中,等待CPU读取。
当然数据发送接收完成之后会置相应的标志位,如果相应的中断使能,则会进入相应的中断服务函数,关与SPI中断这一块的内容,我将在后续“TMS320F28335的SPI的中断”中讲到。
当工作在从机模式时,F28335的SPI所需的通信时钟由外部主机提供,输入时钟频率不应超过CLKOUT的1/4,此时F28335的SPI的SIMO引脚为数据输入引脚,SOMI引脚为数据输出引脚。数据的传输移位过程以及中断响应与其作为主机时相同。
2.3.2 125 种可编程波特率
F28335的SPI作为主机时,可以通过对SPIBRR寄存器编程控制SCLK的大小,该寄存器只有8位,但只有低7位可编程,SPIBRR寄存器描述如下:
注意:① 从波特率的计算公式可以看到,一共有125种波特率;
②LSPCLK的大小为37.5MHz,与SCI中的LSPCLK相同;
③当F28335的SPI工作在从机模式时,这个寄存器无效;
④当F28335的SPI工作在从机模式时,主机的输入频率不应超过LSPCLK/4。
2.3.3 可编程的1~16的数据长度
从F28335的SPI结构框图可以看到,无论是SPIDAT(移位寄存器)还是BUF(BUF寄存器)以及FIFO缓冲区,其大小都是16位的。在SPI通信的过程中,我们可以不传输16位数据,即通过SPICCR.0-3控制传输数据的长度,但此时要注意数据的对齐方式。
一般情况下,我们传输的数据都是16位的,因此一般设置SPICCR.0-3的四位都为1。
2.3.4 4种时钟模式(由时钟极性和时钟相位控制)
F28335的SPI在与外部设备进行通信时,虽然通信的双方都使用SPI协议,但是不同设备发送和接收数据所需的电平边沿可能不同。比如F28335作为主机时SPI在SCLK的上升沿发送数据,而从机的SPI在下降沿才能接收数据,此时就可能导致从机接收不到数据;再比如F28335作为主机时SPI在SCLK的上升沿发送数据,而从机的SPI也在上升沿接收数据,但是要滞后一定的时间,此时也可能导致从机接收不到数据。
为防止上述情况出现,保证主、从通信的正确性,有必要通过时钟极性(SPICCR.6)控制有效边沿,通过时钟相位(SPICTL.3)控制有无延时。
2.3.5 具有增强的16级发送/接收FIFO
SPI的FIFO情况类似于SCI的FIFO,无论是接收还是发送都是16级的,还可以通过设置TXFFIL和RXFFIL在某些特殊情况下进入FIFO中断。
2.3.6 2种工作模式
标准工作模式:此模式不启用FIFO,仅通过SPIDAT、SPITXBUF以及SPIRXBUF进行数据的传输。
FIFO工作模式:此模式启用FIFO,在此模式下,SPI接收到的数据直接存放到接收FIFO中,可以通过SPIRXBUF读出,发送的数据通过写SPITXBUF直接存放到发送FIFO中,发送FIFO中的数据可以通过设置延时直接放到SPIDAT中。
2.3.7 2个中断
F28335的SPI可以通过5种方式触发2种中断,即发送/接收数据完成、接收溢出、接收FIFO错误/溢出、接收FIFO比较以及发送FIFO比较,其中,前4种方式一旦触发中断将进入SPIRXINT对应的中断服务函数,最后一种方式触发后将进入SPITXINT对应的中断服务函数。
这里的SPIRXINTA、SPITXINTA就是SPIRXINT和SPITXINT,之所以加上一个A,是因为这是F28335内部的第一个SPI,虽然F28335内部仅有一个SPI。
3. SPI的配置
F28335SPI的配置过程与SCI的配置过程一模一样,均是对照结构框图,然后根据自己想使用的工作模式,设置相应的寄存器的位即可,下面给出SPI自测模式(F28335的SPI作为主机,将F28335SPI的MISO和MOSI连接在一起)并启用FIFO的初始化函数以及发送接收函数的代码,仅供参考。
void SPI_Init(int Baud)
{
EALLOW;
SysCtrlRegs.PCLKCR0.bit.SPIAENCLK = 1; //使能SPI的时钟
EDIS;
InitSpiaGpio(); //将GPIO54~GPIO57复用映射为SPI功能
SpiaRegs.SPICCR.bit.SPICHAR=0xf; //输入输出字符的长度,配置为16位
SpiaRegs.SPICCR.bit.SPILBK = 1; //配置SPI为自测模式
SpiaRegs.SPICTL.bit.SPIINTENA = 0; //失能SPI接收发送中断
SpiaRegs.SPICTL.bit.TALK = 1; //使能SPI发送
SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1; //配置SPI为主机模式
SpiaRegs.SPICTL.bit.OVERRUNINTENA = 0; //失能接收溢出中断
SpiaRegs.SPIBRR = Baud; //设置SPI的通信速率(注意:SPI的CLK有两种计算公式)
SpiaRegs.SPIFFTX.bit.SPIRST = 0; //恢复SPI FIFO的发送和接收
SpiaRegs.SPIFFTX.bit.SPIFFENA = 1; //启用SPI FIFO功能
SpiaRegs.SPIFFTX.bit.TXFIFO = 1; //使能发送FIFO
SpiaRegs.SPIFFTX.bit.TXFFIENA = 0; //失能发送中断FIFO
SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1; //是能接收FIFO
SpiaRegs.SPIFFRX.bit.RXFFIENA = 0; //失能接收中断FIFO
SpiaRegs.SPIFFCT.bit.TXDLY = 0; //无延时发送
SpiaRegs.SPICCR.bit.SPISWRESET = 1; //启动SPI
}
int SPI_LoopBack_ReceiveSend_Data(int SendData)
{
int ReceiveData;
SpiaRegs.SPITXBUF = SendData;
while(SpiaRegs.SPIFFRX.bit.RXFFST != 1);
ReceiveData = SpiaRegs.SPIRXBUF;
return ReceiveData;
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)