跳转至

0625——ClassB 踩坑

ClassB 软件自检

IEC60730 标准定义了A、B、C三类功能,分别关注于设备的使用便利性、安全性和特殊危险预防。这些分类帮助设计人员确保设备在各种操作条件下能够安全可靠地运行,为用户提供了更高的操作安全和舒适体验。

A类功能是指那些用于一般自动控制目的的设备,这些设备的主要目标是提高使用便利性和效率,而不直接涉及到设备的基本安全保障。A类功能的设计通常关注设备的操作舒适性和用户友好性。如智能家居系统中的智能灯光控制,可以通过定时器或传感器自动调节室内灯光。家用洗衣机的洗涤程序控制提供选择不同的洗涤模式,如快速洗、节能洗等。

B类功能是指那些直接涉及到设备安全的自动控制功能。这些功能的主要目标是防止设备在使用过程中出现可能导致用户受伤或设备损坏的情况。比如烤箱或电热水壶的热切断装置,防止烤箱或电热水壶等设备过热,当温度超过设定值时自动切断电源,以避免火灾或设备损坏。

C类功能是指那些用于防止特殊危险、或更高风险的自动控制功能,特别是在可能出现爆炸、火灾等严重事故的环境中。如热水器的压力保护装置,实时监控热水器内部的压力,防止因压力过高而导致的爆炸或水箱损坏。电动窗帘的安全装置,在窗帘升降过程中,如果感应到障碍物,自动停止或反向操作以防止夹伤等等。

Class B主要针对家用电器,如果家用电器中使用了MCU,并且MCU承担了部分或者全部的安全保护功能,那就需要进行软件评估;而如果MCU仅仅实现产品的功能,安全保护由硬件进行,那这类家电不需要进行软件评估。软件评估是对软件运行时的风险控制措施进行评估,目的是为了确保电器的使用安全。软件评估的内容并不是单独地看软件本身,它需要从软件整体的角度来分析系统存在的风险和软件相关的风险,所以它包括了对系统设计、硬件结构和软件结构的综合检查,还包括对整个软件开发过程的评估。

Class B软件库的结构:

启动时的自检(启动时在进行系统初始化之前,会对所有用到的片上资源做一个整体检测,包括看门狗自检、CPU寄存器自检、FLASH功能自检、系统时钟自检、控制流自检。)

运行时的自检。

FLASH存储校验——CRC32

ADC准确性测试

测试方法

每10ms检测一次检测到的内部 参考电压(VREF) 的AD值。如果连续30次内部参考电压的AD值与理论值的差值超过±10%,则确定ADC采样出现故障。此时显示故障代码。

配置VREFINT通道

很好,测试方法中提到了,检查参考电压的AD值,意味着我们需要配置ADC,DMA的底层来实现读取VREF

ADC,DMA一切都配置好了,但是需要再取一个VREFINT,即参考电压输入通道。

如何增加呢?既然是配置底层,那么一定先找到VREF相关寄存器

翻阅STM32F030RC datasheet(硬件参考):

3.10.2 Internal voltage reference (VREFINT)

The internal voltage reference (VREFINT) provides a stable (bandgap) voltage output for the 
ADC. VREFINT is internally connected to the ADC_IN17 input channel. The precise voltage 
of VREFINT is individually measured for each part by ST during production test and stored in 
the system memory area. It is accessible in read-only mode

VREF与ADC_IN17相连接,所以应当配置ADC_IN17的转换通道

寄存器相关,翻阅reference manual(软件参考):

找到了转换通道相关的寄存器 ADC channel selection register (ADC_CHSELR)

Bits 17:0 CHSELx: Channel-x selection
    These bits are written by software and define which channels are part of the sequence of channels 
    to be converted. 
    0: Input Channel-x is not selected for conversion
    1: Input Channel-x is selected for conversion
    Note: The software is allowed to write this bit only when ADSTART = 0 (which ensures that no 
    conversion is ongoing).

    ADC_CHSELR——bit 标识了该通道是否选定AD转换。


以为这就结束了? 全文搜索中,还出现了另一个寄存器 ADC common configuration register (ADC_CCR)

Bit 22 VREFEN: VREFINT enable
    This bit is set and cleared by software to enable/disable the VREFINT.
    0: VREFINT disabled
    1: VREFINT enabled

    注意到该Bit22标识了通道VREFINT是否使能。

好,相关寄存器齐全了,可以进行配置,由于项目是别人使用LL库写的,我只负责ClassB的移植。所以我需要使用LL函数来开启VREF通道

向ADC初始化函数内添加如下语句。

LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_VREFINT);
LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_VREFINT);

别忘了搬运ADC的DMA配置

就当我以为配置已经结束时,进行调试,并没有在ADC_Buffer[]中看见我想要的VREF数据,由于对LL库不熟悉,没办法快速定位问题。

我只能去阅读ADC和DMA配置的语句细节,这导致我耗费了一下午时间,但苍天不负有心人,我注意到了

__STATIC_INLINE void LL_DMA_SetDataLength(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t NbData)

它是这么描述的 ————@brief  Set Number of data to transfer.

是的,在我新增一个VREFINT转换通道后,代表我也新增了一项需要DMA搬运的数据。

为了让VREFINT数据转换出来,我需要让原语句的LL_DMA_SetDataLengthNbData+1

再修改转换的数据个数即NbData后,ADC_Buffer[]中,就多了一行数值,我确定是VREFINT

VREF是准确的1.2V!

解决了一切,但VREF的值很奇怪,在12bit分辨率的ADC下,即最大值0xffffff = 4096 = 3.3v(VDD)

若VREF是精确的1.2V,那么ADC取到的值就应该是4096*(1.2/3.3) = 1489 上下浮动,实际确实1200上下浮动。

很纳闷,是底层配置不对?还是VREF根本不准确?冷静思考后,我想应该排查单片机的供电电压是否准确,即VDD是否是3.3V

由于调试时单片机是JLINK供电的,那么VDD只会与JLINK相关,拆开JLINK外壳,发现给单片机供电的跳线帽是5V的选项,不是3.3V

真是一关又一关。但是必须关关过。跳回3.3V后我重新调试,得到了1500上下浮动的VREF。一切圆满。