这里就STM32用户咨询到的几个问题,稍加整理分享出来供君参考。
第1问:我目前使用STM32G0B1,代码里有设计BOOT代码,想在跳转前清理各类使用过的外设寄存器。请问STM32有没有复位所有外设寄存器的函数?
答:其实,每个STM32系列都有相关寄存器和应用函数用来针对指定外设或挂在指定总线上的外设进行批量复位,即令其回归到初始复位状态。以STM32G0系列为例,在STM32HAL库里就有类似下面的各种实现函数。
关于这个话题可以参考本公众号另外一篇文章《话说STM32外设复位》,那里有更多详细解读,此处就不再赘述。
第2问:我在使用STM32F730的时候,如果SRAM设置到0x20010000 - 0x2001FFFF之间,DMA传输流程都对,但是SPI输出的数据不对,这是怎么回事?另外,在用USB的bulk传输的时候也是,数据有时是对的,有时候错的。
如果SRAM的缓冲区设置到0x20000000-0x2000FFFF之间的时候,就一切正常。请问这是什么原因?
答:现在问题是,只要代码使用的RAM内存锁定在0x20000000-0x2000FFFF之间时功能都正常,只有使用到0x20010000之后的RAM才有异常。结合他使用的芯片STM32F730,基于ARM Cortex-M7内核的,芯片里有高速L1 Cache。同时,他的代码里还用到了DMA。这样看来,如果他的代码启用了D-Cache,用到2个主设备【CPU和DMA】,如果没有针对D-Cache的使用做合理的配置,就很可能发生数据一致性方面的问题。经用户的进一步反馈,他的代码里也的确使用了D-Cache。
进一步的问题就是,为什么这里不能使用0x20010000之后的区域呢?为探究竟,我们有必要看看STM32F730相关的参考手册。
经查证,0x20000000-0x2000FFFF区间是属于DTCM区,CPU访问它时不使用D-Cache,即CPU每次访问DTCM时都是直接访问,当然DMA是不能使用D-Cache的。这时自然不会产生数据访问的一致性问题。而0x20010000~0x2001FFFF区域是经AXI接口访问的,默认情况下,CPU访问这块区域是可以使用D-Cache的【前提是使能了D-Cache】。
也就是说当我们使用到0x20010000之后的RAM区域时,CPU访问这块可以启用D-Cache。如果DMA也访问这块,若不对该区域做合理存储属性配置或适当操作就可能发生数据一致性问题。此时我们可以对相应RAM区域做MPU配置,将其配置为Shareable 且NonCacheable属性。或在代码里适时地使用针对Cache的清除或无效操作。关于MPU如何配置,这里不做展开,有兴趣的可以进一步了解。本公众号里也有多篇相关文章可供参考阅读。
第3问:在使用STM32 TIMER事件作为触发输出时,那个RESET信号是怎么回事?跟定时器从模式的RESET 模式有什么关系?
答:这里的RESET事件特指通过软件方式对TIMx_EGR寄存器的UG进行置1操作。该操作可以产生1个触发信号给到其它外设,比方ADC,DAC或其它TIMER。同时这个RESET操作对当前定时器会产生更新效果或复位效果,具体点说就是产生更新事件,当前计数器发生重装从新开始计数。
该RESET操作跟定时器RESET从模式有关系吗?没有任何关系,但有相同的现象或效果。即处于RESET从模式的TIMER收到触发信号时,该从定时器也会产生更新事件、计数器进行重装计数。至于给到处于RESET从模式的TIMER的触发信号,可以是源于前级TIMER的更新事件、计数器使能事件、比较事件产生的,也可以是软件RESET操作产生的。
第4问:在使用STM32 ADC多通道转换时,如果不希望一次性转换完成如何操作?
答: 看情况。如果你选择使用的多个ADC通道,平常转换顺序固定,只是不希望基于扫描模式启动后就一次性转换完毕,而是分次分批转换完成。这时我们可以考虑使用ADC的分组转换模式。可以参考本公众号文章《STM32 ADC间断转换模式应用示例》。
如果你选择使用的多个ADC通道,使用过程中转换顺序随机,只是想每次就某个通道做转换,不同时刻可能使用不同的通道。本质上讲,这其实就是单通道转换,在配置时按单通道配置。需要使用哪个通道时,就针对某个通道配置后再做启动。这点可以参考本公众号文章《ADC多通道随机选择性转换应用示例》。
第5问:在使用STM32片内的Vrefint电压是ADC的参考基准吗?它有什么用?
答:STM32片内的Vrefint电压不是ADC模块的参考基准,STM32片内ADC的参考基准可以是Vref,或VDDA【多数时候VDDA跟VDD是接在一起的】,有些系列还可以是VrefBuf电压。注意不要把Vref、Vrefint、VrefBuf搞混了!事实上经常有人弄混。【早期推出的系列STM32片内没有VrefBuf】
Vrefint电压值一般固定在1.2v左右,波动很小。各STM32芯片数据手册有给出参数范围【下图来自STM32G0系列数据手册】:
至于它有什么用,这要看情况。它只是个备用项、可用项。
我经常拿它来验证ADC功能是否正常,因为其电压可知且比较稳定,无须外边引线。有些场合,Vrefint作为相对稳定的AD输入,反过来监测芯片的VDD,此时ADC模块的参考电压VDDA跟VDD是接在一起。有时Vrefint或其分压可用作片内比较器的输入做其它用途。