学习目标:
熟练掌握spi协议,知道时序,原理,作用,特点等
SPI工作模式
接下来以工作模式0为例
SPI 的引脚信息:
MISO(Master In / Slave Out)主设备数据输入,从设备数据输出。
MOSI(Master Out / Slave In)主设备数据输出,从设备数据输入。
SCLK(Serial Clock)时钟信号,由主设备产生。
CS(Chip Select)从设备片选信号,由主设备产生。
SPI 的工作原理:
在主机和从机都有一个串行移位寄存器,主机通过向它的 SPI 串行寄存器写入一个字节来发起一次传输。串行移位寄存器通过 MOSI 信号线将字节传送给从机,从机也将自己的串行移位寄存器中的内容通过 MISO 信号线返回给主机。这样,两个移位寄存器中的内容就被交换。外设的写操作和读操作是同步完成的。如果只是进行写操作,主机只需忽略接收到的字节。反之,若主机要读取从机的一个字节,就必须发送一个空字节引发从机传输。
SPI 的传输方式:
SPI 总线具有三种传输方式:全双工、单工以及半双工传输方式。
全双工通信,就是在任何时刻,主机与从机之间都可以同时进行数据的发送和接收。
单工通信,就是在同一时刻,只有一个传输的方向,发送或者是接收。
半双工通信,就是在同一时刻,只能为一个方向传输数据。
模式0下的时序图
串行时钟的奇数边沿上升沿采样时序图
SPI.c文件下的代码:
初始化配置
/**
* @brief SPI初始化代码
*模式0 SCL空闲状态:低电平
* 采样边沿:上升
* 样时刻:奇数边沿
*模式1 SCL空闲状态:低电平
* 采样边沿:下升
* 样时刻:偶数边沿
*模式2 SCL空闲状态:高电平
* 采样边沿:下升
* 样时刻:奇数边沿
*模式3 SCL空闲状态:高电平
* 采样边沿:上升
* 样时刻:偶数边沿
* @note 主机模式,8位数据,禁止硬件片选
* @param 无
* @retval 无
*/
void spi_init(void)
{
GPIO_InitTypeDef spi_gpio;
__HAL_RCC_GPIOA_CLK_ENABLE();
spi_gpio.Pin = GPIO_PIN_5 | GPIO_PIN_7 | GPIO_PIN_2;//MOSI,CS,CLK
spi_gpio.Mode = GPIO_MODE_OUTPUT_PP; //推挽
spi_gpio.Pull = GPIO_PULLUP;
spi_gpio.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(GPIOA,&spi_gpio);
spi_gpio.Pin = GPIO_PIN_6; //MISO
spi_gpio.Mode = GPIO_MODE_INPUT; //浮空输入
spi_gpio.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(GPIOA,&spi_gpio);
SPI_CS(1);//关片选
SPI_SCK(0);//模式0,平时为低电平
}
开始和停止
void spi_start(void)
{
SPI_CS(0);
}
void spi_stop(void)
{
SPI_CS(1);
}
读写一体函数(全双工)
uint8_t spi_read_write_byte(uint8_t txdata)
{
uint8_t i;
uint8_t rxData = 0x00;
for(i = 0; i < 8; i++)
{
//数据发送
SPI_MOSI(txdata & (0x80 >> i));
SPI_SCK(1);
//数据接收
if(SPI_MISO_GET == 1)
{
rxData |= (0x80 >> i);
}
SPI_SCK(0);
}
return rxData;
}