Cortex-M0的BOD中断及重启-掉电检测的可利用性+BOD汇编启动

BOD

Brown-Out Detection,又称掉电检测,一般用来检测单片机电源掉到一定电压之后执行相应操作。

有些产品由于受外围电路的影响,在断电时会存在残余电压,使得单片机仍能运行(一般情况下是外设停止,但内核运行),这样变会出现单片机无法正常复位,更严重点如果电压不稳会导致内核pc指针跑飞,造成程序灾难。

为了避免这个现象,我们可以在单片机程序中加入BOD检测功能,使单片机在检测到掉电到一定电压后,能够执行复位操作。

BOD分为几个等级:如下

#define BOD_INT_RESV    (0 << 2)                                        /* Reserved                     */
#define BOD_INT_LVL1    (1 << 2)                                        /* 2.3 ~2.4                     */
#define BOD_INT_LVL2    (2 << 2)                                        /* 2.6 ~2.7                     */
#define BOD_INT_LVL3    (3 << 2)                                        /* 2.8 ~2.9                     */
                                                                        /* BOD复位电压                  */
#define BOD_RST_RESV    (0 << 0)                                        /* Reserved                     */
#define BOD_RST_LVL1    (1 << 0)                                        /* 2.1 ~2.2                     */
#define BOD_RST_LVL2    (2 << 0)                                        /* 2.4 ~2.5                     */
#define BOD_RST_LVL3    (3 << 0)                                        /* 2.6 ~2.8                     */

我们可以根据自己的需要选择不同的等级,需要考虑的是外设的工作电压,如E2Prom,Flash等。

BOD初始化代码如下,一般放置在main函数的初始进行初始化。笔者用的是NXP的一款芯片。

void BODInit(void)
{
    LPC_SYSCON->BODCTRL = BOD_INT_LVL3 |                                /* BOD中断电压2.8 ~ 2.9         */
                          BOD_RST_LVL2 |                                /* BOD复位电压2.4 ~ 2.5         */
                          BOD_RST_ENABLE;                               /* BOD复位功能使能              */

    NVIC_EnableIRQ(BOD_IRQn);                                           /* 打开BOD中断                  */
}



int main (void)
{
    SystemInit();                                                       /* 初始化目标板,切勿删除       */
    GPIOInit();                                                         /* GPIO初始化                   */
    BODInit();                                                          /* BOD初始化                    */

    if ((LPC_SYSCON->SYSRSTSTAT & BOD_RESET) == BOD_RESET) {            /* 掉电复位,LED闪烁            */
        LPC_SYSCON->SYSRSTSTAT  |= BOD_RESET;                           /* 清除掉电复位标志位           */
        while (1) {
            LPC_GPIO_PORT->PIN[0] &= ~LED;                              /* 点亮LED                      */
            myDelay(100);                                               /* 延时 100ms                   */
            LPC_GPIO_PORT->PIN[0] |=  LED;                              /* 熄灭LED                      */
            myDelay(100);                                               /* 延时 100ms                   */
        }
    } else {
        while (1) {
            LPC_GPIO_PORT->PIN[0] &= ~LED;                              /* 上电复位,点亮LED            */
        }
    }
}

关于BOD汇编启动

既然我们可以在初始化的时候配置BOD的参数,那为什么还需要用汇编启动呢?
考虑之一是单片机内核从启动代码启动到运行到main函数的时候,需要有及ms的延时,虽然时间在ms级,但是对于一些严格要求的程序和产品,芯片在上电时由于电压抖动会导致芯片PC值跑飞,由于此时还没有初始化BOD,因此无法完成复位。

解决办法之一便是在启动代码中增加BOD初始化,使BOD在运行在main函数之前便完成初始化,可防止上电电压抖动造成的不必要的影响。

启动代码中汇编BOD的初始化代码如下。
首先声明BOD初始化程序。

; Cortex-M version
;

        MODULE  ?cstartup

        ;; Forward declaration of sections.
        SECTION CSTACK:DATA:NOROOT(3)

        SECTION .intvec:CODE:NOROOT(2)

        EXTERN  __iar_program_start
        EXTERN  SystemInit
        EXTERN  BODInit      //声明BOD函数
        EXTERN  IRC_Only_SystemInit

        PUBLIC  __vector_table
        PUBLIC  __vector_table_0x1c
        DATA
__vector_table
        DCD     sfe(CSTACK)                 ; Top of Stack
        DCD     Reset_Handler               ; Reset Handler
        DCD     NMI_Handler                 ; NMI Handler
        DCD     HardFault_Handler           ; Hard Fault Handler

然后在程序执行main之前加入执行BODinit的代码段。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Default interrupt handlers.
;;
        THUMB

        PUBWEAK Reset_Handler
        SECTION .text:CODE:REORDER:NOROOT(2)
Reset_Handler
        LDR     R0, =BODInit          //加入BODInit 此函数体在main中
        BLX     R0
        LDR     R0, =SystemInit
        BLX     R0
        LDR     R0, =__iar_program_start
        BX      R0

这样便可完成BOD的汇编启动。

你可能感兴趣的:(嵌入式小技巧)