赞
踩
最近因为需要,做了一下基于单片机的SPI主从机通信,实现了两块MCU芯片的数据通信,特此记录。
首先了解下SPI通信,SPI是串行外设接口(Serial Peripheral Interface)的缩写。是 Motorola 公司推出的一种同步串行接口技术,是一种高速的,全双工,同步的通信总线。
SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时),这四根线分别是MISO、MOSI、SCLK、CS。
对于SPI通信来说,以下几个参数,需要重点关注,它们决定了SPI的数据传输方式。
芯片既可以配置为主机模式,也可以配置为从机模式,具体模式还有多种分类:
Full-Duplex Master:全双工主模式
Full-Duplex SlaveHalf-Duplex Master:全双工从模式
Half-Duplex Master:半双工主模式
Half-Duplex Slave:半双工从模式
Receive Only Master:仅接收主模式
Receive Only Slave:仅接收从模式
Transmit Only Master:仅发送主模式
SPI通信有4种不同的模式,作为主从机通信,我们的通信双方必须是工作在同一模式下,所以我们可以对我们的主设备的SPI模式进行配置,通过CPOL(时钟极性)和CPHA(时钟相位)来控制我们主设备的通信模式,具体如下:
其中,极性(CPOL)决定开始的高低电平,相位(CPHA)决定数据采集的上升沿还是下降沿。
这里有几个点一定要掌握,发送缓冲器、接收缓冲器和移位寄存器。其中主机通信时,将数据放到发送缓冲器,如果移位寄存器为空,那就复制给移位寄存器,接着随着时钟SCK信号,依次向外发送数据,发送完成后,移位寄存器将当前数据复制给接收缓冲器,实现数据接收。
有了以上概念,我们就可以开始主从机软件编程了
主机作为数据传输的发起方,周期性发送固定字节数据给从机。我这里采用了循环发送方式。发送完后,为了读取从机数据,又继续发送固定字节空数据给从机,同时读取从机上的数据。
//写数据
for(i=0;i<sizeof(sendBuf);i++)
{
recvBuf[i] = spi_flash_send_read_byte(sendBuf[i]);
DelayUs(100);
}
//读数据
for(i=0;i<sizeof(sendBuf);i++)
{
recvBuf[i] = spi_flash_send_read_byte(0);
DelayUs(100);
}
以下为主机数据发送波形
由于从机接收是被动接收,考虑到时间不确定性, 我们采用的SPI接收中断方式
LL_SPI_EnableIT_RXNE(SPI1)
以下为从机在中断中所做的处理:从机在接收完主机发送前一半数据后,后一半接收数据的同时,会应答发送从机侧的数据。
void SPI1_IRQHandler(void) { if(LL_SPI_IsActiveFlag_RXNE(SPI1)==SET) { //接收数据 if(recvCnt<SPI_BUF_LEN) { recvData[recvCnt] = spi_flash_readByte(); spi_flash_sendByte(0X00); } //发送数据 else { spi_flash_readByte(); spi_flash_sendByte(sendData[recvCnt%20]); } recvCnt++; if(recvCnt>=SPI_BUF_LEN*2) { recvCnt = 0; } } if(LL_SPI_IsActiveFlag_TXE(SPI1)==SET) { recvCnt = 0; } }
以下为从机应答波形:
通过仿真数据分析查看,主从机都能正常收发数据
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。