【复旦微FM33 MCU 外设开发指南】外设篇3——SPI

news2024/12/24 9:05:30

在这里插入图片描述

前言

本系列基于复旦微FM33系列单片机的DataSheet编写,旨在提供一些开发指南。
本文章及本系列其他文章将持续更新,本系列其它文章请跳转【复旦微FM33 MCU 外设开发指南】总集篇

本文章最后更新日期:2024/08/31

文章目录

  • 前言
  • 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接收数据,多产生两个时钟周期

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寄存器中配置
在这里插入图片描述

3.2 单发送模式和单接收模式

SPI是全双工通讯,因此在读取数据的时候,也必须发送数据,以产生时钟信号。

在这里插入图片描述

但我们使用的过程中一般是异步的。比如从一块SRAM中读取数据,只需发送一个命令帧告诉SRAM要从哪里读,读多长就可以了,之后SRAM返回其中保存的数据,这种时候主机每一帧发送的数据是无效的。单发送和单接收就可以应用在类似的场景中。

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

可以在SPIx->CR2寄存器中使能或关闭单发送模式/单接收模式。
在这里插入图片描述
在这里插入图片描述

3.3 工作模式

可以在SPIx->CR2寄存器中控制SPI的工作模式。
在这里插入图片描述
SPI有很多种工作模式,常用四线全双工模式

除此之外有四线半双工(一个MISO/MOSI引脚用于区分命令帧和数据帧)和三线半双工(删除一个MISO/MOSI引脚)等
四线半双工常见的应用就是SPI显示屏

3.4 片选控制

可以在SPIx->CR2寄存器中控制片选。
在这里插入图片描述
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/9839168f4b294fc4a1670b548a75f4d5.png
在这里插入图片描述

当然我日常喜欢使用软件片选,而且不通过寄存器去改变片选状态,而是将引脚配置为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寄存器中常用的三个标志位:
在这里插入图片描述
在这里插入图片描述

RXBFTXBE标志位对应SPIx->IER寄存器中可以开启的接收完成中断发送完成中断,即开启中断后,如果TXBE和RXBF置位,就会进入中断服务函数,在中断服务函数中可以判断中断来源。
在这里插入图片描述

RXBFTXBE什么时候置位?根据描述来开,是接收缓存满或者发送缓冲区空的时候。
但必须注意接收缓存满不代表接收完成,发送缓冲区空也不代表发送完成。

通过文首结构框图,可以看到不仅有发送/接收缓冲区,也有发送/接收移位寄存器。
在写入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,不需要再配置单接收模式。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2092000.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

钓鱼特辑(四)安全较量,摆脱“麻瓜”标签

时至今日,尽管员工们对网络安全有所了解,却往往因缺乏足够的安全意识而对攻防没有直观感知。在红队看来,普通员工可能犹如“麻瓜”,防御薄弱,易于突破。 现在红队以求职者或合作方等“人畜无害”的身份在日常沟通中发动…

2024年【广东省安全员C证第四批(专职安全生产管理人员)】新版试题及广东省安全员C证第四批(专职安全生产管理人员)考试试卷

题库来源:安全生产模拟考试一点通公众号小程序 广东省安全员C证第四批(专职安全生产管理人员)新版试题是安全生产模拟考试一点通生成的,广东省安全员C证第四批(专职安全生产管理人员)证模拟考试题库是根据…

adb大全指令(持续更新)

连接adb adb connect 192.168.1.133(局域网ip)连接调试命令 adb shell打开日志工具 logcat

Shopify接口开发工具shopify-sdk踩坑

背景:   先介绍一下shopify-sdk,它使用java语言开发,是用来做shopify接口二次开发的。做过Shopify独立站的都知道,shopify店铺有管理后台去给管理员增删改查商品和订单等数据,这些数据其实都是可以通过shopify提供的…

uniapp__微信小程序如何对比时间组件框选中框之后的时间大小

1、时间组件框选择时间 2、做判断 if (new Date(selectedDate) < new Date(this.startDate)) {uni.showToast({title: 结束时间不能早于起始时间,icon: none,duration: 2000});return;}console.log(new Date(selectedDate),new Date(this.endDate)); 3、打印出来的时间对比…

C#设计模式

前言 大家熟知的GOF23种设计模式&#xff0c;源自《Design Patterns: Elements of Reusable Object-Oriented Software》一书&#xff0c;由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著&#xff0c;四人组Gang of Four简称GOF&#xff01;总结了在面 向…

【例002】利用MATLAB绘制有趣的空间曲线

题目&#xff1a;利用MATLAB绘制以下函数的空间曲线 空间曲线1&#xff1a; { x cos ⁡ ( 3 t ) y sin ⁡ ( 3 t ) for − m 1000 ≤ t ≤ m 1000 z t \begin{cases} x \cos(3t) \\ y \sin(3t) & \text{for } -\frac{m}{1000} \leq t \leq \frac{m}{1000} \\ z t …

心理健康问答系统-AIGC大模型-小程序制作

制作一个心理健康问答系统的小程序&#xff0c;涉及到多个环节和技术领域。这里将从需求分析、技术选型、开发流程、API调用等方面进行详细说明。 一、需求分析与规划 在开始任何项目之前&#xff0c;首先需要明确的是你的小程序想要解决什么样的问题&#xff0c;提供哪些功…

Spring——控制反转(IOC)与依赖注入(DI)

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

【C++题解】1722 - 输出两位的巧数

问题&#xff1a;1722 - 输出两位的巧数 类型&#xff1a;简单循环 题目描述&#xff1a; 巧数指的是这样一种特殊的数&#xff0c;该数的各个位数字之和加上各个位数字之积等于本身的自然数。 比如整数 19 &#xff0c;就是一个巧数&#xff0c;因为(19)(19)10919。 请编程输…

DataWhale AI夏令营 2024大运河杯-数据开发应用创新赛-task3

DataWhale AI夏令营 2024大运河杯-数据开发应用创新赛 数据增强数据收集打标签 多的不说少的不唠&#xff0c;之前说过初赛基本就是比谁的数据好了&#xff0c;因为原始数据的质量太低了想跑到0.25都很难所以需要使用一些数据增强策略以及收集一些新的数据集。 数据增强 计算…

LVGL 控件之按钮(lv_button)

目录 一、按钮1、概述2、样式2.1 设置背景2.1.1 颜色2.1.2 透明度2.1.3 渐变色2.1.4 渐变色起始位置设置 2.2 修改边界2.2.1 宽度2.2.2 颜色2.2.3 透明度2.2.4 指定边 2.3 修改边框2.4 修改阴影2.4.1 宽度2.4.2 透明度2.4.3 偏移坐标2.4.4 颜色2.4.5 延伸 2.5 设置圆角弧度2.6 …

C++STL~~list

文章目录 一、list的概念二、list的使用三、list的练习四、与vector的对比五、总结 一、list的概念 list 是一种容器&#xff0c;实现了双向链表结构 它具有以下特点&#xff1a; 动态大小&#xff0c;可按需增减元素数量。高效的插入和删除操作&#xff0c;在任意位置插入和…

(四)进入MySQL 【事务】

一、MySQL事务的概念 MySQL 事务主要用于处理操作量大&#xff0c;复杂度高的数据。比如说&#xff0c;在人员管理系统中&#xff0c; 要删除一个人员&#xff0c;即需要删除人员的基本资料&#xff0c;又需要删除和该人员相关的信息&#xff0c;如信箱&#xff0c; 文章等等。…

unity中的InstanceID详解 即Object.GetInstanceID

GetInstanceID 是 Unity 中 Object 类的一个方法,它用于获取一个对象的唯一实例标识符。每个 Unity 对象(如游戏对象、组件、资源等)都有一个唯一的实例 ID,这个 ID 在对象的生命周期内是唯一的。 对于它的生命周期是不确定的。网上说在切换场景或者编辑器关闭重启后会变。…

红黑树刨析(删除部分)

文章目录 红黑树删除节点情景分析情景1&#xff1a;删除节点左右子树都为空情景1.1&#xff1a;删除节点为红色情景1.2&#xff1a;删除节点为黑色情况1.2.1&#xff1a;删除节点的兄弟节点是红色情景1.2.2&#xff1a;删除节点的兄弟节点是黑色情景1.2.2.1&#xff1a;删除节点…

计算机毕业设计选题推荐-大学生竞赛管理系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

初识Arduino

什么是Arduino Arduino是一款便捷灵活、方便上手的开源电子原型平台。它包含硬件部分&#xff08;即各种型号的Arduino板&#xff09;、软件部分&#xff08;即Arduino IDE&#xff09;&#xff0c;以及其Arduino社区平台。 Arduino由一个欧洲开发团队于2005年冬季开发&#…

56基于SpringBoot+Vue+uniapp的教学资源库的详细设计和实现(源码+lw+部署文档+讲解等)

文章目录 前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus 系统测试系统测试目的系统功能测试系统测试结论 为什么选择我代码参考数据库参考源码获取源码获取 前言 &#x1f31e;博主介绍 &#xff1a;✌全网粉丝15W,CSDN特邀作者、21…

信息学奥赛初赛天天练-80-NOIP2015普及组-基础题5-错位排列、二叉树、完全二叉树、叶子节点、完全二叉树叶子节点

NOIP 2015 普及组 基础题5 21 重新排列 1234使得每一个数字都不在原来的位置上&#xff0c;一共有( )种排法 22 一棵结点数为 2015的二叉树最多有( )个叶子结点 2 相关知识点 1) 错位排列 考虑一个有n个元素的排列&#xff0c;若一个排列中所有的元素都不在自己原来的位置…