
1 STM32库函数里的回调函数是什么,有何用? ! [0 N% d# y+ S" }1 E* g; u 0 k, \) \9 w7 R# }! @ 回调函数终究乃用户所编写,是用户基于特定事件和应用需求而编写的功能模块,与其他函数并无本质区别。形式上讲,STM32库预先为用户做了回调函数的弱定义或基于事件的函数指针的定义。因基于特定条件发生后被调用执行而被冠以回调称号。 ' ?& l6 g6 u, v% \# ?! v* ^8 o严格来讲,库函数里没有完整的回调函数,只有基于各类事件的弱定义的不具备实际功能的空回调函数,或者是针对各类事件而定义的各种用于调用回调函数的函数指针。我们的程序监测相应条件或事件往往是有的放矢,当相应事件出现时我们需要做相应的处理,这正是回调函数要实现的功能,也是其功用所在。 7 L4 [3 y7 M+ h$ \ P2 STM32工程里的回调函数与中断函数有什么区别? * @+ n- L5 a9 V. \# C& l4 k9 K0 XSTM32外设库里的回调函数的确多数时候跟中断事件及中断服务程序息息相关,往往在中断服务程序中基于特定事件调用相应的用户回调函数。很多时候,我们完全可以将用户回调函数看成中断函数的一个调用模块或延伸。 一个中断服务程序里可以因不同事件而调用不同的回调函数,即一个中断服务程序里可能包含多个不同的回调函数。比方,我们在定时器中断服务程序里可以涉及多个事件及相应的用户回调函数,定时器中断服务程序可能涉及更新事件、不同通道的比较事件或捕获事件,相应的用户回调函数往往因应用场景而异。 1 [# x- H% d+ v% Z当然,回调函数的调用还可以是中断事件以外的其他事件触发调用,比方可以基于初始化操作来调用相应初始化回调函数。当然,在库里对某个外设的初始化可能有些默认操作,但这个默认操作很难是放之四海而皆准的操作,这时我们就得根据实际应用针对性编写初始化代码,即初始化型回调函数。 " e- E' x i, Z$ K, m# E3 STM32库函数里的回调函数是否可以不用? * D% w8 A3 p) j/ n3 _' h6 CSTM32库函数里的回调机制是库设计者为了便于软件框架清晰、减少开发者工作量等因素事先准备的函数声明及接口,用户使用时只需根据具体应用编写相关函数体。当然,你如果不想理睬这些回调函数声明及定义也是可以的,你根据具体应用自行组织代码完全可行。 : t: U- L5 H& Q* c& v2 n4 STM32库函数里似乎存在着类似半成品的库回调函数? : z P% } l' c7 M5 ^% F& KSTM32库函数里的确准备了一些包含用户回调函数的由库定义的回调函数,是库设计者基于各类特定事件而准备的回调函数,它会针对特定事件做一些基本而必要的操作,比方状态的检查、标志监测及清除,但它没有办法彻底写完整,因为它无法知道该事件发生后用户的真实需求是什么,该如何操作,所以它终究还是需要调用真正的用户回调函数。这样做的目的还是为了给开发者减少开发工作量、以及减少出错等。 $ ?) y1 m3 }) k7 k# P我们不妨具体看个实例。下面的回调函数采样的指针注册方式,我们看看UART的DMA传输完成中断里传输完成的回调函数的调用过程。 8 h' b1 G" H" o# F c! o+ G- g首先,在UART的DMA启动函数HAL_UART_Transmit_ DMA()里有这样一部分内容: ![]() 库里就DMA传输事件准备了几个回调函数【传输完成、半完成、出错】,即上图中红线标示出来的。其实这几个回调函数还不算完整的用户回调函数,是库定义的并会做一些在它看来用户必定需要完成的一些操作,它事先帮助完成,之后才调用最终的用户回调函数。我们以传输完成事件为例来看看,上图星号所标的函数。 ![]() 在这个库定义的UART_DMATransmitCplt()函数里,它对DMA的传输模式做了判断,如果是Normal模式,就将UART的传输数据长度设置为0,禁止DMA后续传输功能,使能UART传输完成中断的使能。然后才来调用用户回调函数【上图中箭头所指】。如果DMA工作在循环模式,代码进到UART_DMATransmitCplt()函数后就直接调用最终的用户回调函数。也就说这些库定义的回调函数在用户回调函数的基础上做了些必要操作,用户回调函数可以看成这类库回调函数的子集。 3 B7 H* v( K8 B. t5 基于STM32库来组织用户回调函数要注意什么? k0 p, ^0 P7 e前面提过了,用户回调函数主要基于初始化事件或中断事件而组织的代码。那些中断事件的回调函数的调用基本都是在中断服务程序里发生的。所以,我们在编写回调函数时要结合具体情况灵活地组织代码。要考虑中断优先级、具体事件响应的实时性等。具体点说,我们在组织回调函数时,要考虑是否一定要一股脑地全写在中断服务程序里,会不会影响别的中断响应。对于有些不紧急而又耗时的事件响应代码,可以考虑只在回调函数里设置相应标志,真正的处理代码放到主循环去完成。 8 g: H/ T' o$ f. a5 ^' @5 H0 s还提醒一点,STM32库设计者主动给我们准备了弱定义回调函数或基于各个事件的回调函数指针,尽管很丰富了,但未必能包罗万象,必要时我们可能还得根据具体情况来额外组织些类似回调函数的事件/中断响应代码。 转载自STM32公众号 1 M( M [3 w- e: X + C1 R7 o& c: O3 X- t6 P |
要是初始化GPIO引脚为输出模式,怎么把引脚状态为高电平或低电平可以讲讲 |
拷打cubemx【003】——找不到的芯片包
新版STM32Cube for Visual Studio Code开发体验
【STM32N6570-DK评测】3.CubeMX关于DCMIPP和CSI的BUG整理及摄像头使用
经验分享常被误解的开、关总中断
【STM32C0测评】Nucleo-C092开发板功耗测试
【STM32C0测评】Nucleo-C092开发板IIC通信测试(硬件IIC)
【STM32C0测评】Nucleo-C092开发板IIC通信测试(软件IIC)
【STM32C0测评】Nucleo-C092开发板IIC通信测试(硬件软件IIC一网打尽)
【STM32C0测评】Nucleo-C092开发板USART串口测试
【STM32C0测评】Nucleo-C092开发板使用PWM控制板载LED呼吸灯