[牛人杂谈]

M051的欠压电压值设定(BOD)

[复制链接]
1713|15
手机看帖
扫描二维码
随时随地手机跟帖
wahahaheihei|  楼主 | 2017-2-23 21:34 | 显示全部楼层 |阅读模式
NuMicro M051系列微控制器本身有对系统电压进行检测的功能,一旦系统电压低于设定的门限电压后,将自动停止正常运行,并可设置进入复位状态。当系统电压稳定恢复到设定的门限电压之上,将再次启动运行,即相当于一次掉电再上电的复位。
作为一个正式的系统或产品,当系统基本功能调试完成后,一旦进行现场测试阶段,请注意马上改写芯片的配置位,启动内部欠压电压检测功能。NuMicro M051系列微控制器支持宽电压工作范围,但是经常工作在5V3V系统,有必要进行适当的配置。对于5V系统,设置欠压电压为4.5V;对于3V系统,设置欠压电压为2.7V。当允许欠压电压检测时,一旦NuMicro M051系列微控制器的供电电压低于设置的欠压值,它将会进入复位状态,不执行程序,然而当电源恢复到欠压电压值以上时,它才正式执行程序,以保证系统的可靠性。
由于NuMicro M051系列微控制器是宽电压工作的芯片,例如在一个5V的电子系统中,当电压跌至2.3V时,它本身还能工作,还在执行指令程序,但这时出现2个可怕的隐患:
l 2.3V时,外围芯片工作可能已经不正常了,而且逻辑电平严重偏离5V标准,NuMicro M051系列微控制器读取到的信息不正确,造成程序的执行发生逻辑错误(这不是NuMicro M051本身的原因)。
l 当电源下降到一个临界点,如2.1V时,并且在此抖动,这样将使NuMicro M051运行的程序不正常,取指令、读/写数据都可能发生错误,从而造成程序乱飞,工作不稳定。

wahahaheihei|  楼主 | 2017-2-23 21:40 | 显示全部楼层
由于NuMicro M051本身具有对片内Flash写操作指令,在临界电压附近,芯片工作已经不稳定了,硬件的特性也是非常不稳定,所以在这个时候,一旦程序跑飞,就可能破坏Flash中的数据,进而使系统受到破坏。
典型的故障现象如下:
1) Flash中的数据突然被破坏,系统不能正常运行,需要重新下载程序。
2) 电源关闭后立即上电,系统不能运行,而电源关闭后一段时间再上电,系统就可以正常工作。

实际上,任何的单片机都会出现这样的问题,因此在许多系统中,需要使用专门的电源电压检测芯片来防止这样的情况出现。因此,NuMicro M051有必要设置欠压电压值检测,对于系统可靠性的提高绝对是有利无害的,欠压电压值明细表如下表19.8-1

19.8-1 欠压电压值明细表
参数
最小值
典型值
最大值
单位
测试条件
欠压电压 BOV_VL
[1:0] =00b
2.1
2.2
2.3
V
欠压电压 BOV_VL
[1:0] =01b
2.6
2.7
2.8
V
欠压电压 BOV_VL
[1:0] =10b
3.7
3.8
3.9
V
欠压电压 BOV_VL
[1:0] =11b
4.4
4.5
4.6
V
BOD电压迟滞范围
30
-
51
mV
VDD = 2.5V~5.5V


使用特权

评论回复
643757107| | 2017-2-23 23:27 | 显示全部楼层
当允许欠压电压检测时,一旦NuMicro M051系列微控制器的供电电压低于设置的欠压值,它将会进入复位状态,不执行程序,然而当电源恢复到欠压电压值以上时,它才正式执行程序,以保证系统的可靠性。

使用特权

评论回复
598330983| | 2017-2-24 13:46 | 显示全部楼层
要弄清最大值,最小值和典型值的关系。

使用特权

评论回复
734774645| | 2017-2-24 19:39 | 显示全部楼层
一共两个位是用来设置这个的,因此也就4种模式可以选择。

使用特权

评论回复
yiyigirl2014| | 2017-2-24 20:46 | 显示全部楼层
/**
  * @brief      Set Brown-out detector voltage level
  * @param[in]  u32Level is Brown-out voltage level. Including :
  *             - \ref SYS_BODCR_BOD_VL_4_4V
  *             - \ref SYS_BODCR_BOD_VL_3_7V
  *             - \ref SYS_BODCR_BOD_VL_2_7V
  *             - \ref SYS_BODCR_BOD_VL_2_2V
  * @return     None
  * @Details    This macro set Brown-out detector voltage level.
  *             The register write-protection function should be disabled before using this macro.  
  */
#define SYS_SET_BOD_LEVEL(u32Level)     (SYS->BODCR = (SYS->BODCR & ~SYS_BODCR_BOD_VL_Msk) | (u32Level))

使用特权

评论回复
yiyigirl2014| | 2017-2-24 20:58 | 显示全部楼层
上面的定义是在sys的头文件里。规定了这个宏,有四种参数可以选择,参数是用宏替换表示的。方便阅读。

使用特权

评论回复
yiyigirl2014| | 2017-2-24 20:59 | 显示全部楼层
这里给大家个例程看看。
例程序写的不错,还有其他的几个sys应用的例。
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V2.00
* $Revision: 6 $
* $Date: 15/05/22 2:52p $
* @brief    Change system clock to different PLL frequency and output system clock from CLKO pin.
*
* @note
* Copyright (C) 2011 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include "M051Series.h"

#define PLL_CLOCK       50000000

#define SIGNATURE       0x125ab234
#define FLAG_ADDR       0x20000FFC

/*---------------------------------------------------------------------------------------------------------*/
/*  Brown Out Detector IRQ Handler                                                                         */
/*---------------------------------------------------------------------------------------------------------*/
void BOD_IRQHandler(void)
{
    /* Clear BOD Interrupt Flag */
    SYS_CLEAR_BOD_INT_FLAG();

    printf("Brown Out is Detected\n");
}

/*---------------------------------------------------------------------------------------------------------*/
/*  Simple calculation test function                                                                       */
/*---------------------------------------------------------------------------------------------------------*/
#define PI_NUM  256
int32_t f[PI_NUM + 1];
uint32_t piTbl[19] =
{
    3141,
    5926,
    5358,
    9793,
    2384,
    6264,
    3383,
    2795,
    288,
    4197,
    1693,
    9937,
    5105,
    8209,
    7494,
    4592,
    3078,
    1640,
    6284
};

int32_t piResult[19];

int32_t pi(void)
{
    int32_t i, i32Err;
    int32_t a = 10000, b = 0, c = PI_NUM, d = 0, e = 0, g = 0;

    for(; b - c;)
        f[b++] = a / 5;

    i = 0;
    for(; d = 0, g = c * 2; c -= 14,/*printf("%.4d\n",e+d/a),*/ piResult[i++] = e + d / a, e = d % a)
    {
        if(i == 19)
            break;

        for(b = c; d += f[b] * a, f[b] = d % --g, d /= g--, --b; d *= b);
    }
    i32Err = 0;
    for(i = 0; i < 19; i++)
    {
        if(piTbl[i] != piResult[i])
            i32Err = -1;
    }

    return i32Err;
}

void Delay(uint32_t x)
{
    int32_t i;

    for(i = 0; i < x; i++)
    {
        __NOP();
        __NOP();
    }
}

uint32_t g_au32PllSetting[] =
{
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(25) | CLK_PLLCON_NO_4,  /* PLL = 25MHz */
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(29) | CLK_PLLCON_NO_4,  /* PLL = 29MHz */
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(33) | CLK_PLLCON_NO_4,  /* PLL = 33MHz */
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(37) | CLK_PLLCON_NO_4,  /* PLL = 37MHz */
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(41) | CLK_PLLCON_NO_4,  /* PLL = 41MHz */
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(45) | CLK_PLLCON_NO_4,  /* PLL = 45MHz */
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(49) | CLK_PLLCON_NO_4   /* PLL = 49MHz */
};

void SYS_PLL_Test(void)
{
    int32_t  i;

    /*---------------------------------------------------------------------------------------------------------*/
    /* PLL clock configuration test                                                                             */
    /*---------------------------------------------------------------------------------------------------------*/

    printf("\n-------------------------[ Test PLL ]-----------------------------\n");

    for(i = 0; i < sizeof(g_au32PllSetting) / sizeof(g_au32PllSetting[0]) ; i++)
    {
        /* Switch HCLK clock source to HXT and HCLK source divide 1 */
        CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HXT, CLK_CLKDIV_HCLK(1));

        /* Set PLL to power down mode and PLL_STB bit in CLKSTATUS register will be cleared by hardware. */
        CLK_DisablePLL();

        /* Set PLL frequency */
        CLK->PLLCON = g_au32PllSetting[i];

        /* Waiting for PLL clock ready */
        CLK_WaitClockReady(CLK_CLKSTATUS_PLL_STB_Msk);

        /* Switch HCLK clock source to PLL */
        CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_PLL, CLK_CLKDIV_HCLK(1));

        printf("  Change system clock to %d Hz ...................... ", SystemCoreClock);

        /* Output selected clock to CKO, CKO Clock = HCLK / 2^(1 + 1) */
        CLK_EnableCKO(CLK_CLKSEL2_FRQDIV_S_HCLK, 1, 0);

        /* The delay loop is used to check if the CPU speed is increasing */
        Delay(0x400000);

        if(pi())
        {
            printf("[FAIL]\n");
        }
        else
        {
            printf("[OK]\n");
        }

        /* Disable CKO clock */
        CLK_DisableCKO();
    }
}

void SYS_Init(void)
{

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Enable Internal RC 22.1184MHz clock */
    CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

    /* Waiting for Internal RC clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

    /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
    CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));

    /* Enable external XTAL 12MHz clock */
    CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

    /* Waiting for external XTAL clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

    /* Set core clock as PLL_CLOCK from PLL */
    CLK_SetCoreClock(PLL_CLOCK);

    /* Enable UART module clock */
    CLK_EnableModuleClock(UART0_MODULE);

    /* Select UART module clock source */
    CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Set P3 multi-function pins for UART0 RXD , TXD and CKO */
    SYS->P3_MFP &= ~(SYS_MFP_P30_Msk | SYS_MFP_P31_Msk  | SYS_MFP_P36_Msk);
    SYS->P3_MFP |= (SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0 | SYS_MFP_P36_CKO);

}

void UART0_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init UART                                                                                               */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Reset UART0 */
    SYS_ResetModule(UART0_RST);

    /* Configure UART0 and set UART0 Baudrate */
    UART_Open(UART0, 115200);
}

/*---------------------------------------------------------------------------------------------------------*/
/*  Main Function                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void)
{
    uint32_t u32data;

    /* If define INIT_SYSCLK_AT_BOOTING in system_M051Series.h, HCLK will be set to 50MHz in SystemInit(void). */
    /* In end of main function, program issued CPU reset and write-protection will be disabled. */
    if(SYS_IsRegLocked() == 0)
        SYS_LockReg();

    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Init System, peripheral clock and multi-function I/O */
    SYS_Init();

    /* Lock protected registers */
    SYS_LockReg();

    /* Init UART0 for printf */
    UART0_Init();

    printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %dHz\n", SystemCoreClock);

    /*
        This sample code will show some function about system manager controller and clock controller:
        1. Read PDID
        2. Get and clear reset source
        3. Setting about BOD
        4. Change system clock depended on different PLL settings
        5. Output system clock from CKO pin, and the output frequency = system clock / 4
    */

    printf("+---------------------------------------+\n");
    printf("|    M05xx System Driver Sample Code    |\n");
    printf("+---------------------------------------+\n");

    if(M32(FLAG_ADDR) == SIGNATURE)
    {
        printf("  CPU Reset success!\n");
        M32(FLAG_ADDR) = 0;
        printf("  Press any key to continue ...\n");
        getchar();
    }

    /*---------------------------------------------------------------------------------------------------------*/
    /* Misc system function test                                                                               */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Read Part Device ID */
    printf("Product ID 0x%x\n", SYS_ReadPDID());

    /* Get reset source from last operation */
    u32data = SYS_GetResetSrc();
    printf("Reset Source 0x%x\n", u32data);

    /* Clear reset source */
    SYS_ClearResetSrc(u32data);

    /* Unlock protected registers for Brown-Out Detector settings */
    SYS_UnlockReg();

    /* Check if the write-protected registers are unlocked before BOD setting and CPU Reset */
    if(SYS_IsRegLocked() == 0)
    {
        printf("Protected Address is Unlocked\n");
    }

    /* Enable Brown-Out Detector, and set Brown-Out Detector voltage 2.7V */
    SYS_EnableBOD(SYS_BODCR_BOD_INTERRUPT_EN, SYS_BODCR_BOD_VL_2_7V);

    /* Enable BOD IRQ */
    NVIC_EnableIRQ(BOD_IRQn);

    /* Enable Low Voltage Reset function */
    SYS_ENABLE_LVR();

    /* Run PLL Test */
    SYS_PLL_Test();

    /* Write a signature work to SRAM to check if it is reset by software */
    M32(FLAG_ADDR) = SIGNATURE;
    printf("\n\n  >>> Reset CPU <<<\n");

    /* Waiting for message send out */
    UART_WAIT_TX_EMPTY(UART0);

    /* Switch HCLK clock source to Internal RC 22.1184MHz clock and HCLK source divide 1 */
    CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));

    /* Set PLL to Power down mode and HW will also clear PLL_STB bit in CLKSTATUS register */
    CLK_DisablePLL();

    /* Reset CPU */
    SYS_ResetCPU();
}

使用特权

评论回复
zhuotuzi| | 2017-2-25 00:07 | 显示全部楼层
   /* Enable Brown-Out Detector, and set Brown-Out Detector voltage 2.7V */
    SYS_EnableBOD(SYS_BODCR_BOD_INTERRUPT_EN, SYS_BODCR_BOD_VL_2_7V);

    /* Enable BOD IRQ */
    NVIC_EnableIRQ(BOD_IRQn);

    /* Enable Low Voltage Reset function */
    SYS_ENABLE_LVR();
先 通过使能BOD配置工作模式,主要就是中断使能和BOD的门限,然后加入到中断列表,之后系统使能低电压复位。跌破了BOD设置的门限就复位。

使用特权

评论回复
zhuotuzi| | 2017-2-25 00:07 | 显示全部楼层
也不是复位,就是低于这个电压就发生这个中断,电压上来后才恢复供电,激活系统。

使用特权

评论回复
稳稳の幸福| | 2017-2-25 16:08 | 显示全部楼层
BOD也是一种中断的应用

使用特权

评论回复
heisexingqisi| | 2017-2-26 14:54 | 显示全部楼层
我觉得应该设定两个值才比较靠谱吧,要不然如果电压不稳定,刚好在那个阈值上波动,不就开关不停了。
应该设定两个值,a<b。当低于a时候进入欠压停机,当高于b时候进行复位。

使用特权

评论回复
heisexingqisi| | 2017-2-26 14:54 | 显示全部楼层
通过这个区间实现那种抗干扰。

使用特权

评论回复
dongnanxibei| | 2017-2-26 15:07 | 显示全部楼层
欠压复位使用起来比其他的中断容易多了。

使用特权

评论回复
huangcunxiake| | 2017-2-26 17:09 | 显示全部楼层
其实系统考虑到了那个不稳定因素,因此第二次上电后,需要等待若干秒。

使用特权

评论回复
捉虫天师| | 2017-2-26 19:27 | 显示全部楼层
051为Cortex™-M0 32位微控制器系列,其特点为宽电压工作范围2.5V至5.5V与-40℃ ~ 85℃工作温度、内建22.1184 MHz 高精度RC晶振(±1%精确度,25℃ 5V)、并内建Data Flash、欠压检测、丰富周边、整合多种多组串行传输接口、高抗干扰能力(8KV ESD/4KV EFT)、支持在线系统更新(ISP)、在线电路更新(ICP)与在线应用程序更新(IAP),提供封装有QFN33与LQFP48。
可以看出来,实际上只要高于2.5V就可以工作,那么设置这个欠压复位就是为了防止进入危险区,而低压后也是可以工作的,只是稳定性降低了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

197

主题

2975

帖子

12

粉丝