STM32 SPI学习笔记!

本文深入探讨了SPI(Serial Peripheral Interface)通信协议的核心概念、关键特性及其在实际开发中的应用。包括SPI的基本组成、通信速率、主从模式、关键设置、发送与中断机制、CRC错误校验以及软件配置步骤。重点介绍了如何通过查询或中断方式实现数据的发送与接收,并讨论了SPI与其他通信协议的相似之处。此外,本文强调了SPI在与外部设备如Flash、EEPROM、ADC等通信时的高效性和便捷性。
A.SPI特性
1.SPI一共有四根线,一根片选线CS,一根时钟线SCK,两根信号线MOSI或者是MISO
2.SPI的通信速率很快,不同舍设备可以达到10M+
3.通信方式
最大的特点使用主从模式,在总线上移动存在主设备和从设备,主设备发送数据,从设备接收数据。主从设备的通信信号,NSS,当主设备要发送数据时,将设一个引脚的电平拉低,从设备的对应NSS引脚接收低电平信号将会进入从设备接收模式。如果不通过硬件相连接NSS,也可以在使用软件方式来内部驱动NSS进入对应主从模式。
注意SPI的两个信号引脚MISO和MOSI,M代表Main,S代表Slave,在主从模式同一引脚并不都为输入获都为输出而是对应交换的。
主设备的SCK输出同步时钟到从设备上面,作为外部时钟驱动。
4.一些关键的设置:
第一、CPOL位设置,在SPI_CR1寄存器中,它决定了在空闲状态下SCK的电平状态。CPOL=1 表示空闲状态下是高电平。
第二、CPHA设置,时钟相位设置,设置在在SCK时钟的第几个时钟边沿进行采样,当CPHA=1时在第二个边沿进行数据采样。
第三、数据帧的格式,SPI_CR1的LSBFIRST设置MSB还是LSB在前;DFF位设置数据时16位还是8位的,SPI的数据寄存器是16位的根据设置自动无额定使用8位或16位。
第四、波特率设置,SPI_CR1中BR[2:0]设置对挂载的时候输入的分频
第五、主从模式设置,设置设置SPI_CR1寄存器的SSM位和SSI位设置SPI的NSS是工作的软件模式或是硬件模式
第六、设置工作模式,有全双工模式、单向只接收获只发送模式。设置SPI_CR1寄存器中的BIDIMODE等。
5.发送方式与中断
a.发送前应该先等待TXE 标志( 发送缓冲器空),表名上一帧数据 已经发送完毕;SPI_CR2寄存器中设置了TXEIE 位是对应的外设中断使能位,如果在打开了NVIC中的CPU中断通道,将会将进入中断,可以采用这种终端的发送方式
b.与上面类似,读数据前应该先等待RXNE 标志置位,表示接收缓冲器非空,可以读取数据,硬件自动清除标志位,如果使能对应RXNEIE,及打SPI开接收中断,如果在使能CPU级别的中断将会进入中断服务程序。
当然也可采用查询的方式来发送或接收。
另外如果需要尖山哦CPU开销,同时提高SPI的发送速率,还可以采用DMA来接管SPI的数据发送和接收,保证总线上通信的连续性。
6.CRC错误校验,CRCEN位启用校验,它会在数据发送完成之后,自动发送一个CRC校验值,从机检查与自己的SPI_TXCRCR数值是否匹配来判断是否有发送错误。
主模式失效事件  MODF ,溢出错误  OVR ,CRC错误标志  CRCERR,对应了一个错误中断ERRIE 通道。
7.软件配置:
第一步开启GPIO的复用:
SPI3的复用引脚:
SPI2的引脚复用:
先挂载GPIO时钟,使能SPI时钟,配置GPIO复用,将输出引荐NSS,SCK,MOSI,MISO,这厮个引脚在SPI通信中都可能出现双向的信号,应该配置成推挽输出。
 
初始化和读写函数如下:
void Init_SPI()
{
  GPIO_InitTypeDef GPIO_InitStructure; 
  SPI_InitTypeDef    SPI_InitStructure; 
 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );         
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,    ENABLE );         
 
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                  
  GPIO_Init(GPIOB, &GPIO_InitStructure);                             
 
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                      
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;         
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                         
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                     
  SPI_InitStructure.SPI_CPOL =  SPI_CPOL_High;                        
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                     
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;    
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                     
  SPI_InitStructure.SPI_CRCPolynomial = 7;                           
  SPI_Init(SPI2, &SPI_InitStructure);                                 
  
  SPI_Cmd(SPI2, ENABLE);                                        
}
 u8 read_data()
{
	u8 ch;
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)	//查询发送器是否为空						{
		ch = SPI_I2S_ReceiveData(SPI2); 
	}
	return ch;
}

void send_data(u8 ch)
{
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)	//查询接收器是否非空			
	{
		SPI_I2S_SendData(SPI2,ch);
	}
}

 
上面的发送方式是采用查询的方式,在想要发送数据的时候调用。
如果想要周期性的发送,或者采用中断发送,可以在想要发送的时候设置使能TXE的中断,变回当TXE位置位以后进入发送中断。
也可以打开接收中断使能,这样当外部有数据到达时,便会自动进入到中断,这是可以对接收到的数据进行处理。
总的来看,SPI通信的使用方法跟SCI是非常像的,所以通信协议的制定可以参考一起拿使用SCI时的方式,一般来讲多用SPI于外部器件如Flash,EEPROM,AD等通信,SPI的速度快,简单易操作,非常常用。
 
 
<think> 嗯,用户需要查找基于江科大教程的STM32 SPI学习笔记。从引用资料来看,用户提供的两份笔记目录都明确提到了SPI相关内容,特别是引用[2]的11章完整覆盖了从协议基础到硬件软件操作的全流程。 用户可能是嵌入式开发者或电子专业学生,正在学习STM32外设通信。ta特意强调"基于江科大教程",说明需要与视频课程配套的实践资料。考虑到SPI是嵌入式开发的核心总线之一,用户应该急于上手实操W25Q64这类经典存储器。 注意到引用[2]的11-111-5小节结构非常清晰:先讲协议理论,再介绍FLASH存储器,接着通过软件模拟SPI深化理解,最后过渡到硬件SPI提升效率。这种从理论到实践的递进结构正是学习者需要的。 需要重点提取的关键内容有:SPI四线制工作原理(特别注意MOSI/MISO的时序关系)、W25Q64的页编程指令序列、CubeMX配置时钟极性的要点。用户大概率会马上动手实验,所以代码示例要确保完整可验证——比如那个等待FLASH就绪的while循环就很重要。 突然想到用户可能遇到电平转换问题,补充了硬件连接注意事项。另外江科大教程的特色是用逻辑分析仪抓波形,这个调试技巧也应该保留。最后主动提供扩展方向(DMA和中断)作为学习延伸点。 相关问题的设计要层层递进:从基础(协议本质)到应用(多设备管理),最后落到具体器件(OLED屏驱动),这样覆盖不同学习阶段的需求。 </think> 以下是基于江科大STM32教程的**SPI通信协议**核心学习笔记整理,结合引用内容梳理关键知识点: --- ### 一、SPI通信基础 1. **协议特点** - **全双工同步串行通信**(1主多从) - **四线制**: $SCK$(时钟)、$MOSI$(主机输出从机输入)、$MISO$(主机输入从机输出)、$NSS$(片选) - **时钟极性(CPOL)与相位(CPHA)** 决定数据采样边沿[^2] 2. **工作流程** ```mermaid graph LR A[主机拉低NSS] --> B[SCK输出时钟] B --> C[MOSI发送数据] C --> D[从机通过MISO回应] D --> E[主机释放NSS] ``` --- ### 二、W25Q64 Flash存储器操作 1. **芯片特性** - 64M-bit存储容量(8MB),支持 **SPI Mode 0/3** - **页编程**(256字节/页),支持扇区擦除(4KB)和整片擦除 2. **关键指令码**(HEX): ```c #define W25X_WriteEnable 0x06 // 写使能 #define W25X_PageProgram 0x02 // 页编程 #define W25X_ReadData 0x03 // 读数据 #define W25X_SectorErase 0x20 // 扇区擦除 ``` --- ### 三、软件SPI vs 硬件SPI | **实现方式** | **优点** | **缺点** | **适用场景** | |--------------------|--------------------------|-----------------------|---------------------| | **软件SPI** | 引脚灵活,协议可控 | 占用CPU资源,速度慢 | 时序调试/引脚冲突时 | | **硬件SPI** | 自动时钟生成,DMA支持 | 引脚固定 | 高速稳定传输 | > 注:硬件SPI需配置`SPI_InitTypeDef`结构体,启用`SPI_Cmd(SPIx, ENABLE)` --- ### 四、代码示例(硬件SPI写W25Q64) ```c // STM32硬件SPI发送单字节 void SPI_SendByte(uint8_t data) { while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); // 等待发送缓冲区空 SPI_I2S_SendData(SPI1, data); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); // 等待接收完成 SPI_I2S_ReceiveData(SPI1); // 清除接收标志 } // 页编程函数 void W25Q64_PageProgram(uint32_t addr, uint8_t *data) { W25Q64_WriteEnable(); // 写使能 SPI_CS_LOW(); // 片选使能 SPI_SendByte(W25X_PageProgram); // 发送页编程指令 SPI_SendByte((addr >> 16) & 0xFF); // 发送地址高字节 SPI_SendByte((addr >> 8) & 0xFF); SPI_SendByte(addr & 0xFF); for (int i = 0; i < 256; i++) SPI_SendByte(data[i]); // 写入数据 SPI_CS_HIGH(); // 片选关闭 W25Q64_WaitBusy(); // 等待编程完成 } ``` --- ### 五、调试要点 1. **逻辑分析仪使用**:捕获SCK/MOSI/MISO波形验证时序 2. **易错点**: - **NSS片选信号**未及时释放导致通信锁死 - **CPOL/CPHA配置错误**使数据采样错位 - 未执行**写使能指令**直接编程 ---
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值