STM32 HAL库函数HAL_SPI_Receive_IT和HAL_SPI_Receive的区别

背景

前段时间开发一个按键板驱动,该板用的STM32F103系列单片机,前任工程师用STM32CubeMX生成的工程,里面全是HAL库调用,我接手后,学习了下HAL库的用法,踩坑不少,特别是带IT后缀的函数,初学者对其的理解很容易出错,特此记录一下。
按键板

项目中的按键板通过SPI总线与主板连接,按键板是Slave设备,因此无法确定什么时候收到主板的读写请求,要么轮询,要么依赖控制器提供的中断机制。
带IT的receive

两种Receive流程

说明一下,SPI的BPW(bits per word)=8,不是16,因此一个word就是一个字节。

轮询:HAL_SPI_Receive流程

先看函数签名

HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);

hspi是SPI控制器句柄,pData是接收buf地址,Size是接收buf长度,Timeout是接收超时时间,如果期间一直没收到数据,则返回。

根据HAL源码,梳理流程概要:

获取控制器的锁
记录起始时间
填充控制器的各个字段:
控制器状态=BUSY_RX
接收buf地址=pData
接收buf长度=Size
RxISR = NULL
待接收字节数> 0?
rx fifo为空?
超时?
读取一个字节
待接收字节数-1
释放控制器的锁
返回错误码

注意,RxISR表示接收中断的回调函数,因为我们是轮询模式,所以该字段填0。

中断:HAL_SPI_Receive_IT流程

先看函数签名

HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi);

参数含义跟HAL_SPI_Receive一样,少了个超时参数,因为中断方式并不关心rx fifo深度

根据HAL源码,梳理流程概要:

HAL_SPI_Receive_IT
填充控制器的各个字段:
控制器状态=BUSY_RX
接收buf地址=pData
接收buf长度=Size
RxISR = SPI_RxISR_8BIT
获取控制器的锁
开启rx_fifo非空和rx_error中断
释放控制器的锁
HAL_SPI_IRQHandler
溢出中断置位?
获取中断使能和中断状态
禁用所有中断
HAL_SPI_ErrorCallback
rx fifo非空中断置位?
SPI_RxISR_8BIT
退出中断
SPI_RxISR_8BIT
待接收字节数-1
将FIFO的第一个字节拷贝到pData
待接收字节数== 0?
SPI_CloseRx_ISR
退出函数
SPI_CloseRx_ISR
控制器的错误码为NONE?
禁用rx_fifo非空和rx_error中断
用户定义的HAL_SPI_RxCpltCallback
用户定义的HAL_SPI_ErrorCallback
退出函

注意:

  1. 每个字节的接收都会触发一次中断,因为所谓的rx fifo并不存在,其实就是直接读取控制器的DR寄存器(暂存当前收到的word),如果想提高效率,可以使用DMA版本。
  2. HAL_SPI_Receive_IT运行在后台(主循环),HAL_SPI_IRQHandler以及它调用的其他函数都运行在前台(中断),因此后者代码里一定不能有printf之类的打印语句,否则会影响SPI接收时序!

对比

可以看出,带IT后缀的receive函数,只填充控制器的上下文结构体并开启中断,剩下的都交给中断回调。这种策略将接收分成前后台两部分,后台开启中断,前台响应中断并读取数据,检测数据收够了就关闭中断,因此带IT后缀并不是传言的只能在中断态下运行。

后记

  1. HAL库其他总线,像UART、I2C等,它们的带IT后缀的receive函数,应该也是这种设计模式,大家可以验证一下。
  2. rx_fifo非空中断到底是片选信号触发的,还是SCK信号触发的,不太确定,看过芯片TRM手册,好像是SCK触发的,知道的帮忙确认下。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Typecho用宝塔面板建站(保姆级教程)

提前准备: 1 已备案域名 注意:在腾讯云备案的域名部署阿里云服务器的话还需要在阿里云备案,反之亦然 2 服务器 服务器操作系统设置为windows 服务器实例设置:依次开放8888/888/443/3000-4000/21/22端口 个人用的阿里云,到安全组配…

带您识别RJ45网口连接器/网口插座口的LED灯的平脚/斜脚,带弹/不带弹细节区分

Hqst华强盛(盈盛电子)导读:网口连接器,网口插座,也叫网口母座,因为产品规格众多,常常因为细小差别,耽误工程设计级或者生产排期延误,今天就带大家一起来认识下平脚RJ45网口连接器/网口插座与斜脚…

51.Sentinel微服务保护

目录 (1)初识Sentinel。 (1.1)雪崩问题及解决方案。 (1.1.1)雪崩问题。 (1.1.2)解决雪崩问题的四种方式。 (1.1.3)总结。 (1.2)…

Git 简介及使用

前言 假设有这样一个场景,老板让员工做一个档案,员工这个档案做好了之后交给老板看,此时老板不满意,又让回去改,改完给老板看,但是老板又不是很满意,就这样改了又改,给老板看过之后&…

智慧工地APP全套源码,智慧工地云平台

智慧工地平台 ,智慧工地源码,智慧工地APP全套源码 智慧工地以施工现场风险预知和联动预控为目标,将智能AI、传感技术、人像识别、监控、虚拟现实、物联网、5G、大数据、互联网等新一代科技信息技术植入到建筑、机械、人员穿戴设施、场地进出关…

Leetcode—141.环形链表【简单】

2023每日刷题(三十三) Leetcode—141.环形链表 快慢指针算法思想 关于快慢指针为什么能检测出环,可以这么思考。 假设存在一个环: 慢指针进入环后,快指针和慢指针之间相距为d,每一次移动,d都会缩小1&…

C++模版初阶

泛型编程 如下的交换函数中,它们只有类型的不同,应该怎么实现一个通用的交换函数呢? void Swap(int& left, int& right) {int temp left;left right;right temp; }void Swap(double& left, double& right) {double temp…

资产设备管理系统

dtAsset 是一个固定资产设备管理系统,它专为中小企业的需求而设计。该软件提供了对常用资产设备进行信息化管理的功能,并支持自定义设备类型、导入导出数据、维护工作统计、采购管理、文档管理、运维监控 (使用 Zabbix)、知识库等功能。 主要模块 1.系统…

【一周安全资讯1118】北京高院发布《侵犯公民个人信息犯罪审判白皮书》;工银金融勒索案的事件响应服务商MoxFive是谁?

要闻速览 1、工信部等四部门部署开展智能网联汽车准入和上路通行试点工作 2、北京高院发布《侵犯公民个人信息犯罪审判白皮书》 3、丰田公司确认遭遇美杜莎勒索软件攻击 4、家中设备把数据信息泄露到国外,浙江一男子被罚5000元 5、工银金融勒索案的事件响应服务商M…

IO流-序列化流

一,序列化(把java对象写到对象中去) 二, Object OutputStream(对象字节输出流) 三,案例 package BigDecimal;import java.io.FileOutputStream; import java.io.ObjectOutputStream;public class Main {public static…

【C++】类和对象(3)--初始化列表(再谈构造函数)

目录 一 引入 二 初始化列表概念 三 初始化列表特性 1 引用和const 2 混合使用 3 自定义成员情况 四 初始化列表中的初始化顺序 五 总结 一 引入 构造函数体赋值 class Date { public:Date(int year, int month, int day){_year year;_month month;_day day;} priv…

链表题(4)

本章内容 正文开始前给大家推荐个网站,前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 今天继续给大家带来链表的相关练习题。 相交链表 这道题来自力扣网,链接…