×
嵌入式 > 技术百科 > 详情

MPC5744P-SPI模块(串行外设接口模块)

发布时间:2021-11-17 发布时间:
|

1.结构

5744的SPI模块支持全双工三线同步传输,可运行在主机或从机模式,分别含有深度为5的FIFO发送和接收缓存区。其结构如下图。SPI配置允许模块发送和接收串行数据,同时也支持带FIFO缓存区的的进行扩展队列操作的数据传输。模块接收和发送的数据存放在独立的FIFO内,CPU或DMA控制器从接收FIFO读取数据,写入数据到Tx FIFO内进行发送。

2、传输过程

1)发送过程


发送数据时CPU先查询寄存器SR内TFFF的状态,若TFFF为为0则表明TX FIFO已满,继续写入无效;当TFFF为1则表明TX FIFO未满,可以继续写入。CPU通过写数据到寄存器PUSHR将要发送的数据添加到TX FIFO内,TX FIFO根据先入先出的顺序将数据移入移位寄存器进行发送,只要TX FIFO内有有效的数据,则一直进行发送。在每一次成功传输后,寄存器SR内的TCF被置位表明一次成功的传输。寄存器SR的TXCTR值阈计数TX FIFO内的有效数据数,当有数据被压入或被传送到移位寄存器时,TXCTR随之更新。当PUSHR寄存器中EOQ==1的数据被传输完成后,寄存器SR中的EOQF置位表明数据队列被全部发送完毕,可用于指示多个数据的发送完毕。


2)接收过程


当移位寄存器内的数据接收完成后,接收到的数据被添加到RX FIFO内,CPU通过读POPR寄存器将数据从RX FIFO内取出。当RX FIFO 不为空,寄存器SR中的RFDF被置位,当读取数据时,CPU先查询寄存器SR内RFDF的状态,若RFDF为0则表明RX FIFO为空,继续读取数据无效;当RFDF为1则表明RX FIFO不为空,可通过读POPR寄存器来读取RX FIFO内的数据。相应地,寄存器SR的RXCTR值阈计数RX FIFO内的有效数据数,当有数据被移入到RX FIFO 或被CPU通过POPR取出时,RXCTR随之更新。


3、传输模式

SPI传输可分为主机模式和从机模式,也有经典模式和改进模式。本文以经典主机模式为例。主机模式下SCK、PCS、SOUT为输出,SIN为输入。


1)CPHA=0


如下图CPHA=0时,数据捕捉在SCK的奇数跳边沿,数据变化在SCK的偶数跳边沿。与之相对应地若CPOL=0,SCK高电平有效,则数据捕捉在SCK的上升沿,数据变化在SCK的下降沿;若CPOL=1,SCK低电平有效,则数据捕捉在SCK的下降沿,数据变化在SCK的上升沿。

2)CPHA=1


如下图所示,当CPHA=1,数据捕捉在SCK的偶数跳边沿,数据变化在SCK的奇数跳边沿。相应地若CPOL=0,SCK高电平有效,则数据捕捉在SCK的下降沿,数据变化在SCK的上升沿;若CPOL=1,SCK低电平有效,则数据捕捉在SCK的上升沿,数据变化在SCK的下键沿。

3)持续片选模式和非持续片选模式


持续片选模式是指在两个数据帧之间片选信号PCS一直保持有效为低电平;非持续片选模式是指在两个数据帧之间片选信号PCS变为无效,二者区别如下图所示。持续片选和非持续片选模式有寄存器PUSHR[CONT位决定,PUSHR[CONT]=0选择非持续片选,PUSHR[CONT]=1选择持续片选。具体选择哪种方式要根据所要驱动的外设来确定,由于该模式有PUSHR寄存器选择,故在发送数据时要求连续数据持续片选和非持续片选要保持一致,不可混合使用,否则会造成传输错误。

4.波特率和时序延时

SPI中协议时钟即是外设桥时钟,也就是在时钟模块所配置的时钟频率,文中缩写为fp。


1)波特率


波特率即是SCK的频率。SPI的波特率由寄存器CTARn中DBR、PBR和BR决定,计算公式如下。其中Prescaler由PBR决定,Scaler由BR决定,对应关系如下表。

2)tcsc


tcsc是指从PCS有效到SCK第一个跳变沿的时间,由CTARn寄存器中PCSSCK和CSSCK决定。


3)tasc


tasc时钟从SCK最后一个跳边沿到PCS无效的时间,由CTARn寄存器中PASC和ASC决定。


4)tdt


tdt是指本次传输PCS无效到下次传输PCS有效的时间。


各个延时值如下图所示:

5.初始化

5744初始化步骤如下所示:


1)运行模式选择;


2)管脚复用功能配置;


1)使能SPI模块,停止传输以进行寄存器的配置;


2)配置CTARn以进行数据长度、传输模式、波特率和延时的设置,每个CTAR可有不同的配置,PUSHR写入数据到TX FIFO时可根据需要选择不同的CATR寄存器。


3)启动传输过程。


示例代码如下:


/******************************************************

* 函数名 SPI_SPI0_Init

* 功能 对SPI0模块进行初始化

* 输入参数 无

* 返回值 无

* 示例 SPI_SPI0_Init();//初始化SPI0

******************************************************

*/

void SPI_SPI0_Init()

{

//运行模式选择

MC_ME.PCTL99.B.RUN_CFG=0; //选择运行模式0

//管脚多路复用配置

SIUL2.MSCR[36].B.SSS=1; //PC4,选择作为SPI0_PCS0

SIUL2.MSCR[36].B.OBE=1;

SIUL2.MSCR[36].B.SRC=3;

SIUL2.MSCR[37].B.SSS=1; //PC5,选择作为SPI0_SCK

SIUL2.MSCR[37].B.OBE=1;

SIUL2.MSCR[37].B.SRC=3;

SIUL2.MSCR[38].B.SSS=1; //PC6,选择作为SPI0_SOUT

SIUL2.MSCR[38].B.OBE=1;

SIUL2.MSCR[38].B.SRC=3;

SIUL2.IMCR[41].B.SSS=1; //PC7,选择作为SPI0_SIN

SIUL2.MSCR[39].B.IBE=1;

//SPI配置

SPI_0.MCR.B.MDIS=0; //使能SPI模块

SPI_0.MCR.B.HALT=1; //停止传输

SPI_0.MCR.B.MSTR=1; //选择主机模式

SPI_0.MCR.B.PCSIS=1; //PCS0无效状态为高

//CTAR[0]寄存器

SPI_0.MODE.CTAR[0].B.FMSZ=7; //配置数值长度为8=FMSZ+1

//以下两位要根据对应外设选择,否则SPI通信会失败!!!

SPI_0.MODE.CTAR[0].B.CPHA=1; //数据捕捉在偶数跳变沿

SPI_0.MODE.CTAR[0].B.CPOL=1; //SCK低电平有效

SPI_0.MODE.CTAR[0].B.PCSSCK=2; //tcsc=5*8/45mhz=0.875us

SPI_0.MODE.CTAR[0].B.CSSCK=2;

SPI_0.MODE.CTAR[0].B.PASC=2; //tacs=5*8/45mhz=0.875us

SPI_0.MODE.CTAR[0].B.ASC=2;

//波特率=(fP/PBR)x[(1+DBR)/BR]=45mhz/5*(1+0)/4=2.25MHz

SPI_0.MODE.CTAR[0].B.PBR=2;

SPI_0.MODE.CTAR[0].B.BR=1;

SPI_0.MODE.CTAR[0].B.PDT=2;

SPI_0.MODE.CTAR[0].B.DT=13; //tdt=5*32768/45mhz=3.64ms

SPI_0.MCR.B.HALT=0; //开始传输

}

6.数据发送

发送数据通过将数据写入PUSHR寄存器发送。其实PUSHR寄存器除数据部分外,还有命令部分,可根据需要进行选择。

CONT选择是否为持续片选模式

CTAS用于选择初始化中设置的CTAR寄存器用以选择用于传输的数据长度、传输模式、波特率和延时等。

EOQ用于标识是否为数据队列的最后一帧数据

PCS用于选择片选引脚。

发送步骤为:


1)将数据写入PUSHR寄存器;


2)清空SR寄存器EOQF位开始发送;


3)等待发送完成;


4)清除发送完成标志位;


代码如下:


/******************************************************

* 函数名 SPI_SPI0_Write

* 功能 通过SPI0发送指定数据

* 输入参数

* data

* 要发送的数据

* 返回值 无

* 示例 SPI_SPI0_Write(tempData);//通过SPI发送数据tempData

******************************************************

*/

void SPI_SPI0_Write(uint32_t data)

{

uint32_t temp_data;

temp_data=0x08010000|data; //置位EOF标志为最后一帧数据,选择PCS0为片选引脚

SPI_0.PUSHR.PUSHR.R=temp_data;

SPI_0.SR.B.EOQF=1; //开始传送

while(!SPI_0.SR.B.TCF); //等待传送完成

SPI_0.SR.B.TCF=1; //清除发送标志位

}

7.数据接收

数据接收时需要等待RX FIFO不为空,也即是SR寄存器RFDF为1。若RFDF为1,则通过读取POPR寄存取来读取数据,然后清空对应标志位。示例代码如下:


/******************************************************

* 函数名 SPI_SPI0_Read

* 功能 通过SPI0读取数据

* 输入参数 无

* 返回值 通过SPI0所读取到的数据

* 示例 uint32_t tempData=SPI_SPI0_Read();//通过SPI0读取数据到tempData

******************************************************

*/

uint32_t SPI_SPI0_Read()

{

uint32_t recv_data=0;

while (SPI_0.SR.B.RFDF != 1); //等待Rx FIFO不为空

recv_data= SPI_0.POPR.R; //读取接收到的数据

SPI_0.SR.R = 0xFCFE0000; //清空相应标志位

return recv_data;

}


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
实时控制.安全.如何加速实现未来工厂落地?