SPI协议

tech2023-11-14  87

Serial Peripheral Interface,串行外围设备接口,一种高速全双工的通信总线。

1 物理层

MOSI

Master Output Slave Input,主设备输出/从设备输入引脚

MISO

Master Input Slave Output,主设备输入/从设备输出引脚

SCK 时钟信号信号线,用于通讯数据同步,由通讯主机产生

NSS

从设备选择信号线,NSS线置低电平为开始信号,NSS线被拉高

作为结束信号

2 协议层

2.1 基本通讯过程

主机控制产生NSS、SCK、MOSI信号,从机产生MISO信号,主机在MISO信号线读取从机的数据。 NSS为低电平时,MOSI和MISO信号有效,在SCK的每个时钟周期MOSI和MISO传输一位数据。

2.2 通讯起始和停止信号

​ SPI通讯的起始信号-NSS信号由高变低 ​ SPI通讯的停止信号-NSS信号由低变高

2.3 数据有效性

​ 参考CPOL和CPHA

2.4 CPOL/CPHA

时钟极性CPOL SPI通讯设备处于空闲时,SCK信号线的电平信号

CPOL=0,SCK在空闲状态时为低电平

CPOL=1,SCK在空闲状态时为高电平

时钟相位CPHA 数据的采样时刻 CPHA=0,数据线在SCK时钟线的"奇数边沿"被采样 CPHA=1,数据线在SCK时钟线的"偶数边沿"被采样

​ CPHA=0,CPOL=0,时钟的奇数边沿是上升沿

​ CPHA=0,CPOL=1,时钟的奇数边沿是下降沿 ​ MOSI和MISO数据线的有效信号在SCK的奇数边沿保持不变;在SCK奇数边沿采样数据信号;在非采样时刻,MOSI和MISO的有效信号发送切换。

​ CPHA=1,CPOL=0,时钟的奇数边沿是下降沿

​ CPHA=1,CPOL=1,时钟的奇数边沿是上升沿

​ 主机和从机需要在相同的模式下才可以正常通讯

模拟SPI

IO配置
/************************************************ 函数名称 : SPI_GPIO_Configuration 功 能 : SPI引脚配置 参 数 : 无 返 回 值 : 无 作 者 : strongerHuang *************************************************/ void SPI_GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; /* CS */ GPIO_InitStructure.GPIO_Pin = PIN_SPI_CS; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_SPI_CS, &GPIO_InitStructure); /* SCK */ GPIO_InitStructure.GPIO_Pin = PIN_SPI_SCK; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_SPI_SCK, &GPIO_InitStructure); /* MISO */ GPIO_InitStructure.GPIO_Pin = PIN_SPI_MISO; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(PORT_SPI_MISO, &GPIO_InitStructure); /* MOSI */ GPIO_InitStructure.GPIO_Pin = PIN_SPI_MOSI; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_SPI_MOSI, &GPIO_InitStructure); } /************************************************ 函数名称 : SPI_Initializes 功 能 : SPI初始化 参 数 : 无 返 回 值 : 无 作 者 : strongerHuang *************************************************/ void SPI_Initializes(void) { SPI_GPIO_Configuration(); SPI_CS_DISABLE; SPI_SCK_HIGH; SPI_MOSI_HIGH; }
写一字节数据
/************************************************ 函数名称 : SPI_WriteByte 功 能 : SPI写一字节数据 参 数 : TxData --- 发送的字节数据 返 回 值 : 无 作 者 : strongerHuang *************************************************/ void SPI_WriteByte(uint8_t TxData) { uint8_t cnt; for(cnt=0; cnt<8; cnt++) { SPI_SCK_LOW; //时钟 - 低 SPI_Delay(); if(TxData & 0x80)//发送数据 SPI_MOSI_HIGH; else SPI_MOSI_LOW; TxData <<= 1; SPI_Delay(); SPI_SCK_HIGH;//时钟 - 高 SPI_Delay(); } }
读一字节数据
/************************************************ 函数名称 : SPI_ReadByte 功 能 : SPI读一字节数据 参 数 : 无 返 回 值 : 读回来的字节数据 作 者 : strongerHuang *************************************************/ uint8_t SPI_ReadByte(void) { uint8_t cnt; uint8_t RxData = 0; for(cnt=0; cnt<8; cnt++) { SPI_SCK_LOW;//时钟 - 低 SPI_Delay(); RxData <<= 1; if(SPI_MISO_READ) //读取数据 { RxData |= 0x01; } SPI_SCK_HIGH;//时钟 - 高 SPI_Delay(); } return RxData; }
最新回复(0)