SPI总线有4条线
SS:片选使能信号,低电平有效,选中谁和谁进行通信。
SCLK:时钟信号
MOSI:Master Out Slave In
MISO:Master In Slave Out

下图是一对多的链接方式,主机需要用N个片选来选择N个从机

下图是菊花链的方式,所有的从机使用一条片选型号。从机的输入输出依次相连

SPI协议中的一个难点,时钟的极性和相位


SCLK时钟信号极性
SCLK空闲时为0那么极性CPOL=0. 那么打破空闲的是高1,出现跳变沿顺序leading edge 前沿 为上升沿,后沿trailing edge为下降沿。
SCLK空闲时为1,那么CPOL=1.那么打破静默是低 0。出现跳变沿顺序leading edge 前沿 为下降沿,后沿trailing edge为上升沿。

方便记忆,可以理解为时钟默认状态下的电平决定第一个电平的调转方向。

时钟相位。CPHA 表示数据由第一个跳变沿驱动还是第二个跳变沿驱动。也可以理解为数据有效时时钟的相位。
CPHA=0.代表由时钟的第一个跳变沿采集数据,也就是相位0时,数据有效。
CPHA=1.代表时钟的第二个跳变沿采集数据,也就是相位1时,数据有效。

片选使能代表选中通信设备,时钟的第一个跳变决定通信的开始。

SPI 模块

SPI模块的核心是位移寄存器,在时钟的驱动下,发送端依次把移位寄存器的内容传输到中线上。同时也移入输入信号线上的数据。
接收发送是同时进行的,构成一个环。如下图所示


片选信号低有效,在SCLK第一个跳变沿来临前称为leading delay 这个时SCLK的电平是默认电平由SCLK极性决定。当数据帧传输完成后时钟恢复静默状态到下次开始的时间为trailing delay。


1.地址和数据总线 可以由CPU和DMA访问
2.发送缓冲区,在位移寄存器数据被读出或者发送完成前缓冲数据
3.位移寄存器,数据接收发送的 主体。
4.接收缓冲
5.MOSI,MISO可以互通,用于菊花链
6.NSS片选使能,决定 主逻辑,通信控制器是否开启
7.主逻辑控制器,对MOSI,MISO进行控制
8.波特率发送器在SPI_CR1寄存器下按照设定产生SCLK。CPOL,CPHA在这可以看到
9.通信控制器 对应SPI_CR2寄存器主要是接收状态和事件。这些标志在I2C,USART模块中经常见到,大同小异。

SPI从模式

从机模式的工作方式是等待片选有效,有效后根据时钟的极性和相位把数据移入数据位移寄存器,然后接收一帧数据后产生接收完成事件。

  1. 设置 DFF 位,以定义 8 或 16 位数据帧格式。
  2. 选择 CPOL 和 CPHA 位
  3. 帧格式(MSB 在前或 LSB 在前取决于 SPI_CR1 寄存器中 LSBFIRST 位的值)必须与Master器件的帧格式相同。
  4. NSS 引脚在整个字节发送序列期间都必须连接到低电平
  5. 将 MSTR 位清零,并将 SPE 位置 1

    发送序列
    当从器件在其 MOSI 引脚上收到时钟信号和数据的最高有效位时,发送序列开始。其余位(8 位数据帧格式中的 7 个位, 16 位数据帧格式中的 15 个位)将加载到移位寄存器中。SPI_SR 寄存器中的 TXE 标志在数据从发送缓冲区传输到移位寄存器时置 1,并且在SPI_CR2 寄存器中的 TXEIE 位置 1 时将生成中断。


    接收序列

对于接收器,在数据传输完成时:
● 移位寄存器中的数据将传输到接收缓冲区,并且 RXNE 标志(SPI_SR 寄存器)置 1
● 如果 SPI_CR2 寄存器中的 RXNEIE 位置 1,则生成中断
在出现最后一个采样时钟边沿后, RXNE 位置 1, 移位寄存器中接收的数据字节被拷贝到接
收缓冲区中。当读取 SPI_DR 寄存器时, SPI 外设将返回此缓冲值。

数据移位寄存器以“发送缓冲区”为数据源,把数据一位一位地通过数据线发送出去;当从外部接收数据的时候,数据移位寄存器把
数据线采样到的数据一位一位地存储到“接收缓冲区”中。通过写 SPI 的“数据寄存器 DR”把数据填充到发送缓冲区中,通过“数据寄存器 DR”,可以获取接收缓冲区中的内容。其中数据帧长度可以通过“控制寄存器 CR1”的“DFF 位”配置成 8 位及 16 位模式


上图是SPI的传输时序图,不难理解。
TXE,RXNE的理解是关键
数据的写入读取都是对缓冲寄存器操作,分别有写入缓冲,读取缓冲。移位寄存器是无法直接访问的。
TXE代表写入缓冲(发送缓冲)寄存器数据状态,由软件清零。写入一个数据的时候TXE 为低,表示非空状态。当发送缓冲寄存器的
数据被转移到移位寄存器的时候,发送缓冲寄存器为空置位。
同理RXNE,当移位寄存器接收一个完成的数据(8/16 bit)后,就会把数据移动到接收缓冲中。这个时候RXNE为1.表示非空。

如果使用DMA,其实不用看图也能知道。TXE标志出现的时候就会发起DMA写入请求。
同理RXNE出现的时候,就是DMA搬移数据的时候。

最后就是传输过程中的中断和控制位

需要注意的是 NSS引脚是该MCU SPI模块的片选引脚,如果作为主设备应该保证其为高。
练习1 初始化和数据的发送
初始化代码如下
完全按照库函数的简单初始化即可。

STM32F103C8T6
NSS接高电平master模式/*
PA4  SPI1_NSS
PA5  SPI1_SCK
PA6  SPI1_MISO
PA7  SPI1_MOSI
*/void app_spi_train_init(void)
{GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitStruct.GPIO_Mode =  GPIO_Mode_AF_PP ;GPIO_InitStruct.GPIO_Pin  =  GPIO_Pin_4  ;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode =  GPIO_Mode_AF_PP ;GPIO_InitStruct.GPIO_Pin  =  GPIO_Pin_5  ;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode =  GPIO_Mode_AF_PP ;GPIO_InitStruct.GPIO_Pin  =  GPIO_Pin_6  ;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode =  GPIO_Mode_AF_PP ;GPIO_InitStruct.GPIO_Pin  =  GPIO_Pin_7  ;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);app_train_spi_cfg();}void app_spi_module_config(void)
{SPI_InitTypeDef   SPI_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;SPI_InitStruct.SPI_CPHA =SPI_CPHA_2Edge;SPI_InitStruct.SPI_CPOL =SPI_CPOL_High;SPI_InitStruct.SPI_CRCPolynomial = 7;SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStruct.SPI_FirstBit =SPI_FirstBit_MSB;SPI_InitStruct.SPI_Mode = SPI_Mode_Master;SPI_InitStruct.SPI_NSS   =SPI_NSS_Hard ;SPI_Init(SPI1, &SPI_InitStruct);SPI_Cmd(SPI1, ENABLE);
}
void task2_task(void *pvParameters)
{app_spi_train_init();while(1){app_spi_send();vTaskDelay(1000);}}void app_spi_send(void)
{static char data=0;if(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE))SPI_I2S_SendData(SPI1, 0xff & data++);
}


练习2
SPI 双机通信实验
STM32F407从机
配置如下

#define SPI_RX_BUF_LEN 20unsigned char spi_rx_buf[SPI_RX_BUF_LEN];/*
PA4  SPI1_NSS   CH1
PA5  SPI1_SCK   CH3
PA6  SPI1_MISO  CH2
PA7  SPI1_MOSI  CH0
*/void app_spi_train_gpio_init(void)
{GPIO_InitTypeDef  GPIO_InitStruct;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStruct.GPIO_OType= GPIO_OType_PP ;GPIO_InitStruct.GPIO_Pin= GPIO_Pin_7;GPIO_InitStruct.GPIO_PuPd= GPIO_PuPd_UP ;GPIO_InitStruct.GPIO_Speed= GPIO_High_Speed ;GPIO_Init(GPIOA,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin= GPIO_Pin_5;GPIO_Init(GPIOA,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin= GPIO_Pin_6;GPIO_Init(GPIOA,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin= GPIO_Pin_4;GPIO_Init(GPIOA,&GPIO_InitStruct);GPIO_PinAFConfig(GPIOA,GPIO_PinSource4,GPIO_AF_SPI1);GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_SPI1);GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_SPI1);GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_SPI1);}void app_spi_train_it(void)
{NVIC_InitTypeDef  NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel=  SPI1_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =13;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;NVIC_Init(& NVIC_InitStruct);SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE);}void app_spi_train_init(void)
{SPI_InitTypeDef SPI_InitStruct;app_spi_train_gpio_init();RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStruct.SPI_CPOL =SPI_CPOL_High ;SPI_InitStruct.SPI_CRCPolynomial= 7;SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStruct.SPI_FirstBit =SPI_FirstBit_MSB;SPI_InitStruct.SPI_Mode = SPI_Mode_Slave;SPI_InitStruct.SPI_NSS =SPI_NSS_Hard;app_spi_train_it();SPI_Init(SPI1, & SPI_InitStruct);SPI_Cmd(SPI1, ENABLE);}void SPI1_IRQHandler(void)
{static unsigned char index =0;spi_rx_buf[index++] = SPI_I2S_ReceiveData(SPI1);if (index>SPI_RX_BUF_LEN-1){index=0;}}

stm32c8t6主机代码如下
PA8为从机的片选引脚

void app_spi_train_init(void)
{GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitStruct.GPIO_Mode =  GPIO_Mode_AF_PP ;GPIO_InitStruct.GPIO_Pin  =  GPIO_Pin_4  ;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode =  GPIO_Mode_AF_PP ;GPIO_InitStruct.GPIO_Pin  =  GPIO_Pin_5  ;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode =  GPIO_Mode_AF_PP ;GPIO_InitStruct.GPIO_Pin  =  GPIO_Pin_6  ;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode =  GPIO_Mode_AF_PP ;GPIO_InitStruct.GPIO_Pin  =  GPIO_Pin_7  ;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode =  GPIO_Mode_Out_PP ;GPIO_InitStruct.GPIO_Pin  =  GPIO_Pin_8  ;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);app_train_spi_cfg();}void app_train_spi_cfg(void)
{SPI_InitTypeDef SPI_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStruct.SPI_CPOL =SPI_CPOL_High ;SPI_InitStruct.SPI_CRCPolynomial= 7;SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStruct.SPI_FirstBit =SPI_FirstBit_MSB;SPI_InitStruct.SPI_Mode = SPI_Mode_Master;SPI_InitStruct.SPI_NSS =SPI_NSS_Hard;SPI_Init(SPI1, & SPI_InitStruct);SPI_Cmd(SPI1, ENABLE);
}void app_spi_send(void)
{static char data=0;GPIO_WriteBit(GPIOA,GPIO_Pin_8,0);if(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE))SPI_I2S_SendData(SPI1, 0xff & data++);while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_BSY)){}GPIO_WriteBit(GPIOA,GPIO_Pin_8,1);
}

STM32 SPI总线深入理解相关推荐

  1. 单片机软件模拟SPI接口—加深理解SPI总线协议

    单片机软件模拟SPI接口-加深理解SPI总线协议   SPI(Serial Peripheral Interfacer 串行外设接口)是摩托罗拉公司推出的一种同步串行通讯接口,用于微处理器臌控制器和外 ...

  2. 通俗理解STM32 SPI通信(主从双机SPI通信)

    STM32 SPI通信 高速全双工的通信总线 SPI 通讯使用 3 条总线及片选线,3 条总线分别为 SCK.MOSI.MISO,片选线为NSS(CS) NSS 信号线由高变低 ,是 SPI 通讯的起 ...

  3. 学习STM32 Flash存储 W25Q64 SPI总线存储模块进行读写数据

    今天学习 Flash 存储芯片进行数据写入和读取方法.了解W25Q64 存储芯片的使用.能够用 STM32 单片机对 W25Q64 进行写入数据,擦除数据,读取数据. w25q64 是什么? W25Q ...

  4. STM32 HAL 驱动SPI总线2.13寸电子纸墨水屏

    STM32 HAL 驱动SPI总线2.13寸电子纸墨水屏 电子纸墨水屏具有断电界面不失和低反光度的护眼效果.QYEG0213RWS800是2.13寸黑白红三色墨水屏,分辨率为250*122. STM3 ...

  5. STM32:DMA方式接收SPI总线数据,并按照协议进行处理

    一.前言 为满足高速数据传输的要求,采用SPI总线.MCU端(STM32F072  Cortex-M0)接收CPU发送的SPI数据(数据18个字节为一包,起始包为0xAA,最后一包为CheckSum校 ...

  6. STM32 SPI详解

    目录 1.SPI简介 2.SPI特点 2.1.SPI控制方式 2.2.SPI传输方式 2.3.SPI数据交换 2.4.SPI传输模式 3.工作机制 3.1.相关缩写 3.2.CPOL极性 3.3.CP ...

  7. 基于I2C/SPI总线的温湿度采集与OLED显示

    实验一 实验目的 学习I2C总线通信协议,使用STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集,并将采集的温度-湿度值通过串口输出.具体任务: 1)解释什么是"软件I2 ...

  8. I2C和SPI总线优缺点对比

    IIC vs SPI现今,在低端数字通信应用领域,我们随处可见IIC (Inter-Integrated Circuit) 和 SPI (Serial Peripheral Interface)的身影 ...

  9. linux spi双机通信,【转】STM32 SPI双机通信(主从全双工)

    欢迎大家测试 u8 SPI1_ReadByte(u8 TxData) { u8 retry=0; // while((SPI1->SR&1<<1)==0)//等待发送区空 / ...

最新文章

  1. 逻辑回归实例--乳腺癌肿瘤预测
  2. pythonasyncio在哪个版本好_理解Python asyncio的简洁方式
  3. Shift Dot_JAVA
  4. 科研地图来了,看看你的研究领域在哪里!中国科学院科技战略咨询研究院发布《科学结构图谱2021》
  5. 音视频技术开发周刊 | 198
  6. 行列式运算算法c语言,新手作品:行列式计算C语言版
  7. vue对象拼接_vue 俩个数组对象合并成一个
  8. Word文档处理控件TX Text Control .NET for WPF
  9. Python 语言参考手册
  10. TransE算法(Translating Embedding)
  11. GPyTorch中的超参数
  12. 【Microsoft Office】免密破解Microsoft Word文档(.docx)的文档保护
  13. Flutter 报错:Could not resolve io.flutter:flutter_embedding_debug:1.0.0-ee76268252c22f5c11e82a7b87423c
  14. 我换Minecraft启动器啦!
  15. 各大搜索引擎登陆入口
  16. Java之lambda表达式
  17. LeetCode-完成旅途的最少时间
  18. Endnote中有的文献没有Pages信息怎么办?
  19. [IOS APP]大唐雷音寺
  20. facebook-share(分享)

热门文章

  1. VS2008安装失败原因!
  2. HDU——1863 畅通工程(最小生成树问题)
  3. 数据结构C++语言版 -- 霍夫曼树
  4. 合肥学院C语言大作业,C语言实践课程综合大作业..doc
  5. HDFS删除文件之后空间不释放,LINUX删除文件之后空间不释放
  6. Android进度条ProgressBar颜色的渐变设置
  7. networkx随机图生成
  8. networkx 给图的所有边添加相同的属性
  9. linux下命令行制作ISO文件
  10. ENVI中TIF格式文件打不开