
前言本系列基于复旦微FM33LC0系列MCU的DataSheet编写提供基于寄存器开发指南、应用技巧、注意事项等本文章及本系列其他文章将持续更新本系列其它文章请跳转↓↓↓复旦微FM33 MCU 底层开发指南——总集篇本文章最后更新日期2026/09/03文章目录前言GPIO配置SPI配置1. SPI的寄存器2. SPI的时钟3. SPI的工作模式3.1 主机和从机3.2 单发送模式和单接收模式3.3 工作模式3.4 片选控制4. SPI的时序控制4.1 时钟极性和时钟相位4.2 MISO的时序4.3 SPI两帧之间的时间间隔4.4 SPI帧格式5. SPI的复位SPI发送接收1. SPI的状态标志位2. 等待标志位发送或接收3. 使用中断发送或接收4. 通过DMA发送或接收注意事项1. SPI单接收模式通过DMA接收数据多产生两个时钟周期2. SPI从机模式的注意事项GPIO配置要使用SPI功能需要将使用的引脚配置为数字功能写GPIO寄存器时要注意打开GPIO时钟。有的引脚需要配置额外数字功能寄存器DFS详见GPIO章节【复旦微FM33 MCU 外设开发指南】外设篇1——GPIO通常我们会将MISO、MOSI和CLK引脚配置为数字功能而将CS引脚配置为GPIO输出功能以实现软件片选。可以在SPIx-CR1寄存器中交换MOSI和MISO引脚。SPI配置1. SPI的寄存器SPIx-CR1控制寄存器1用于选择SPI主机/从机、SPI时钟、信号时序SPIx-CR2控制寄存器2用于控制SPI使能、数据字长配置、片选配置SPIx-CR3控制寄存器3用于清空发送缓冲区、清空接收缓冲区、清除错误标志SPIx-IER中断使能寄存器用于发送中断、接收中断、错误中断的使能和关闭SPIx-ISR中断标志寄存器用于SPI BUSY标志、接收缓冲区满标志、发送缓冲区满标志、错误标志等的读取SPIx-TXBUF发送缓冲区用于单次发送数据时写入通过DMA传输的话会自动写入SPIx-RXBUF接收缓冲区用于单次读取数据时写入通过DMA传输的话会自动读取2. SPI的时钟要使用SPI要在RCC-PCLKCR3寄存器中开启SPI外设的时钟使能。SPI外设挂载在APB总线上因此要调整SPI外设的工作时钟可以通过对APBCLK预分频也可以调整SPI的预分频。有关时钟的配置详见【复旦微FM33 MCU 外设开发指南】系统篇——时钟FM33LC0 SPI外设的预分频在SPIx-CR1寄存器中配置最高为APBCLK的二分频3. SPI的工作模式3.1 主机和从机SPI的时序由主机产生。FM33LC0 SPI外设的主机/从机模式选择在SPIx-CR1寄存器中配置注有关Slaver模式有一些注意事项详见文末章节。3.2 单发送模式和单接收模式SPI是全双工通讯因此在读取数据的时候也必须发送数据以产生时钟信号。但我们使用的过程中一般是异步的。比如从一块SRAM中读取数据只需发送一个命令帧告诉SRAM要从哪里读读多长就可以了之后SRAM返回其中保存的数据这种时候主机每一帧发送的数据是无效的。单发送和单接收就可以应用在类似的场景中。可以在SPIx-CR2寄存器中使能或关闭单发送模式/单接收模式。3.3 工作模式可以在SPIx-CR2寄存器中控制SPI的工作模式。SPI有很多种工作模式常用四线全双工模式除此之外有四线半双工一个MISO/MOSI引脚用于区分命令帧和数据帧和三线半双工删除一个MISO/MOSI引脚等四线半双工常见的应用就是SPI显示屏3.4 片选控制可以在SPIx-CR2寄存器中控制片选。当然我日常喜欢使用软件片选而且不通过寄存器去改变片选状态而是将引脚配置为GPIO输出模式写GPIOx-DO寄存器来改变其引脚状态。4. SPI的时序控制4.1 时钟极性和时钟相位SPI时序控制最基本的即为时钟极性和时钟相位SPI的主机和从机应配置为相同的时钟极性和时钟相位。一般MCU作为SPI的主机使用从机的时钟极性和时钟相位一般是固定死的根据从机的DataSheet要求配置即可。FM33LC0 SPI外设的时钟极性和时钟相位在SPIx-CR1寄存器中配置4.2 MISO的时序除了时钟极性和时钟相位还可以在SPIx-CR1寄存器中调整MISO的时序4.3 SPI两帧之间的时间间隔SPI传输时接上示波器可以观察两个时钟周期之间有时间间隔。1.如果是多次的单次传输直接向TXBUF中写入数据然后启动SPI传输那么这个时间间隔主要是软件等待标志位产生的2.如果是通过DMA的连续传输那么这个时间间隔会变得很短。我们用SPI来和显示屏通讯会发现使用DMA的刷屏速率会比不用DMA快很多主要是省下了大量的两帧之间的时间间隔。可以在SPIx-CR1寄存器中调整SPI的两帧数据之间的等待时间。但我认为这个只对DMA传输影响显著因为多次的单次传输SPI两帧的时间间隔实在是太久了4.4 SPI帧格式可以在SPIx-CR2寄存器中调整SPI单帧的传输字长。可以在SPIx-CR1寄存器中调整SPI的帧格式为大端或者小端。5. SPI的复位SPI2的复位在RCC-AHBRSTCR1寄存器中。SPI1的复位在RCC-AHBRSTCR2寄存器中。注意这里的复位不是说写1就复位了复位好了之后要写0取消复位。SPI发送接收1. SPI的状态标志位SPI的状态标志位在SPIx-ISR寄存器中查询。虽说这个寄存器叫中断状态标志位但没开启中断的时候这个标志位也会置位只是不响应中断罢了。SPIx-ISR寄存器中常用的三个标志位RXBF和TXBE标志位对应SPIx-IER寄存器中可以开启的接收完成中断和发送完成中断即开启中断后如果TXBE和RXBF置位就会进入中断服务函数在中断服务函数中可以判断中断来源。那RXBF和TXBE什么时候置位根据描述来看是接收缓存满或者发送缓冲区空的时候。但必须注意接收缓存满不代表接收完成发送缓冲区空也不代表发送完成。通过文首结构框图可以看到不仅有发送/接收缓冲区也有发送/接收移位寄存器。在写入SPIx-TXBUF后数据会从SPIx-TXBUF传入发送移位寄存器中这时SPIx-TXBUF空并置位TXBE标志进入中断服务函数。但这时发送移位寄存器的值还没有发送出去。BUSY标志位才能代表当前是否有数据传输只有在移位寄存器空才会清零BUSY标志位代表SPI当前没有数据传输如果没有意识到这点在写软件的时候会经常遇到一些错误比如接收数组里没有最后一帧。2. 等待标志位发送或接收在发送时向SPIx-TXBUF寄存器写入然后等待BUSY标志在接收时向SPIx-TXBUF寄存器写入任意数据因为SPI是全双工然后等待BUSY标志读取SPIx-RXBUF多字节的发送/接收就是重复这个过程。这种方式最简单缺点是效率很低而且软件死等的方式在软件开发中很危险如果等不到标志程序就死在那里了除非看门狗复位。3. 使用中断发送或接收在发送时使能发送中断向SPIx-TXBUF寄存器写入在中断服务函数中等待BUSY标志为0即为发送完成如果还要继续写入数据在中断服务函数中可以不等待BUSY标志为0直接向SPIx-TXBUF写入以实现连续的发送。当然进入中断之后要判断产生中断的原因是发送完成中断、接受完成中断还是错误中断。4. 通过DMA发送或接收这里DataSheet上写的很好不做过多阐述。注意事项1. SPI单接收模式通过DMA接收数据多产生两个时钟周期应用场景主机使用单发送模式向从机发送命令字节随后开启单接收模式通过DMA接收从机回发数据问题描述用示波器看波形会发现多了两个时钟周期配置spi字长为8bit就会多出两个8bit时钟配置spi字长为16bit就会多出两个16bit时钟调试记录1.收到的数据无误2.使能SPI后时钟线立刻产生了两个时钟周期因此和DMA无关可能是SPI单接收模式的问题3.如SPI不使用单接收模式而使用全双工接收数据相同情况下时钟线不会产生两个时钟周期。确认是单接收模式的问题推测原因在分析原因之前重复一下SPI外设的特性SPI是全双工通信主机即使只接收数据也要向TX缓冲区写数据时钟产生并开启传输。即使将SPI配置为单接收模式也是SPI外设自动向TX缓冲区填写数据时钟产生并开启传输SPI外设有缓冲区和移位寄存器从机返回的数据将先进入移位寄存器再进入接收缓冲区。在接收缓冲区非空的时候移位寄存器的数据是无法进入接收缓冲区的。因此如果主机接收缓冲区读的不及时接收缓冲区非空移位寄存器无法写入接收缓冲区则SPI传输中止时序由主机提供根据以上特性可以分析出原因当读取完一组数据后SPI还在单接收模式中继续往TX缓冲区填写数据因此继续产生时钟有时钟就有接收到的数据如果从机不响应则接收到的就是全0但是SPI主机没有继续读取RX缓冲区的数据因为已经收到了设定长度的数据导致RX缓冲区满进而导致移位寄存器无法写入接收缓冲区。因此多出的第一个时钟周期的数据在接收缓冲区中第二个时钟周期的数据在移位寄存器中最终因为移位寄存器满而停止传输解决办法在DMA传输下不使用单接收模式使用全双工模式。这是因为DMA接收时会自动写TXBUF不需要再配置单接收模式。2. SPI从机模式的注意事项手册对从机模式基本没有相关描述故以下内容都是靠调试得出的结论必须连接对应的硬件片选引脚时钟频率实测最高16MHz而非手册写的最大波特率在通过DMA发送的时候或许也应该打开DMA接收通道