欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SPI通信协议

程序员文章站 2022-07-09 12:46:58
...

学习资料:正点原子STM32

SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线。两根是双工
通信线,一根时钟线(同步),一根外设片选线。开发板有三个SPI接口。

SPI通信协议

要发送的数据写到发送数据缓存区,缓存区经过移位寄存器,一位一位的通过MOSI接口移出去,
同时MISO接口接收到的数据经过移位寄存器一位一位的移到接收缓存区。

SPI通信协议

SPI接口一般使用4条线通信: 
MISO 主设备数据输入,从设备数据输出。 
MOSI 主设备数据输出,从设备数据输入。 
SCLK时钟信号,由主设备产生。 
CS从设备片选信号,由主设备控制

例:

SPI通信协议

从机最后边一个1移向主机最右边,同时主机最左边的1移向从机最左边,如果是8位寄存器,则在8
个时钟信号下,完成8位的移位。
工作原理 
硬件上为4根线。 
主机和从机都有一个串行移位寄存器,主机通过向它的SPI串行寄存器写入一个字节来发起一次传
输。 
串行移位寄存器通过MOSI信号线将字节传送给从机,从机也将自己的串行移位寄存器中的内容通
过MISO信号线返回给主机。这样,两个移位寄存器中的内容就被交换。 
外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,若
主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。
片选引脚: 
SPI片选线,若有多个外设,则有多个片选线,需要用到的外设片选线接通,不需要的关闭。

时钟的相位和极性

SPI通信协议

SPI通信协议

当CPHA=1时,在第二个边沿采集信号,如图,当CPOL为1时,表示空闲电平是高电平,那么低电
平就是工作时的电平,在时钟的第二个边沿采集信号,如果CPOL是0,则空闲电平是低电平,高电
平有效,在高电平的第二个边沿采集。 
同理CPHA=0时,

SPI通信协议

 

SPI配置代码:

typedef struct
{
uint16_t SPI_Direction; /*!< 传输方向,两向全双工,单向接收等*/
uint16_t SPI_Mode; /*!< 模式选择,确定主机还是从机 */
uint16_t SPI_DataSize; /*!< 数据大小,8位还是16位 */
uint16_t SPI_CPOL; /*!< 时钟极性选择 */
uint16_t SPI_CPHA; /*!< 时钟相位选择 */
uint16_t SPI_NSS; /*!< 片选是硬件还是软件*/
uint16_t SPI_BaudRatePrescaler; /*!< 分频系数 */
uint16_t SPI_FirstBit; /*!< 指定数据传输是从MSB还是LSB位开始的。M
SB就是二进制第一位,LSB就是最后一位 */
uint16_t SPI_CRCPolynomial; /*!< CRC校验 ,设置 CRC 校验多项式,提高通
信可靠性,大于 1 即可*/
}SPI_InitTypeDef;

范例:

SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线
双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主 SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // SPI 发送接收 8 位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;//串行同步时钟的空闲状态为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//第二个跳变沿数据被采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS 信号由软件控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //预
分频 256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从 MSB 位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC 值计算的多项式
SPI_Init(SPI2, &SPI_InitStructure); //根据指定的参数初始化外设 SPIx 寄存器

发送字节函数:

标准库:
u8 SPIx_ReadWriteByte(u8 TxData)
{
    u8 retry=0;
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
    {
    }//等待发送区空
    SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个byte 数据
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
    {
    } //等待接收完一个byte
    return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据
}

HLA库:
uint8_t SPI_SendByte(uint8_t byte)
{
    uint8_t d_read,d_send=byte;
    if(HAL_SPI_TransmitReceive(&hspi1,&d_send,&d_read,1,0xFFFFFF)!=HAL_OK)
    d_read=0XFF;
    return d_read;
}