低电压检测器(LVD)适用于监测VDDA电源电压或外部引脚输入电压,当被监测电压与LVD阈值的比较结果满足触发的条件时,LVD将会产生中断或者复位信号,通常用来处理一些紧急任务。 LVD产生的中断或复位标志,只能通过软件程序清零,只有当中断或复位标志被清零后,在再次达到触发条件时,LVD才能再次产生中断或复位信号。 本文以CW32L083为例,介绍LVD的使用方法。 低电压检测器(LVD)的主要特性: 1. 4路监测电压源:VDDA电源电压,PA00、PB00、PB11引脚输入 2. 16阶阈值电压,范围2.02V-3.76V 3. 3种触发条件,可以组合使用 电平触发:电压低于阈值 下降沿触发:电压跌落到阈值以下的下降沿 上升沿触发:电压回升到阈值以上的上升沿 4. 可触发产生中断或复位信号,二者不能同时产生 5. 8阶滤波可配置 6. 支持迟滞功能 7. 支持低功耗模式下运行,中断唤醒MCU 上图为CW32L083低电压检测器(LVD)的功能框图,LVD不仅可以监测VDDA电源电压,也可以监测外部引脚 (PA00、PB00、PB11)输入电压,通过控制寄存器LVD_CR0的SOURCE位域来选择,当使用外部引脚来监测电压时,需将对应的GPIO端口配置为模拟输入模式(GPIOx_ANALOG.PINy = 1)。 LVD的输出结果可以从PA01/PA08/PC12/PE02/PF02引脚输出,需将对应的GPIO口配置为数字输出模式,同时选择功能复用,下面为具体配置 //LVD I/O口初始化 void LVD_PortInit(void) { GPIO_InitTypeDef GPIO_InitStructure = {0};
//打开GPIOA时钟 __RCC_GPIOA_CLK_ENABLE();
//将PA08设置为LVD比较结果输出 GPIO_InitStructure.Pins = GPIO_PIN_8; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_Init(CW_GPIOA, &GPIO_InitStructure); //将PA08复用为LVD比较结果输出 PA08_AFx_LVDOUT(); //将PA00设置为LVD的输入口 PA00_ANALOG_ENABLE(); }
迟滞功能 LVD 内置的电压比较器具有迟滞功能,可避免当 LVD 的被监测电压在阈值电压附近时,电压比较器的输出结果发生频繁翻转,增强系统抗干扰能力。只有当被监测电压高于或低于阈值电压达到20mV时,比较器输出信号才会发生翻转。具体波形如下图所示: LVD的阈值电压根据LVD控制寄存器LVD_CR0的VTH位值决定,有效值0 ~ 15,如下表所示:
数字滤波功能 CW32L083的LVD支持数字滤波功能,以增强系统的鲁棒性,可将LVD电压比较的输出结果信号进行数字滤波,小于滤波宽度的信号被滤除,不会触发中断或复位,如下图所示:
通过设置控制寄存器LVD_CR1的FLTEN位域为1,可使能数字滤波模块。设置控制寄存器 LVD_CR1 的 FLTCLK 位域可以选择数字滤波的时钟: • FLTCLK位为1,选择HSIOSC作为滤波时钟 • FLTCLK位为0,选择内置RC振荡器时钟作为滤波时钟,其频率约150kHz 相关的宏定义如下所示: #define LVD_FilterClk_RC150K ((uint32_t)0x00000000) #define LVD_FilterClk_HSI ((uint32_t)0x00000010)
控制寄存器LVD_CR1的FLTTIME位域用于选择数字滤波的时钟个数,如下表所示: 从LVD状态寄存器LVD_SR的FLTV位域,可以读出经LVD数字滤波后的信号电平;当 GPIO 的功能复用为LVD_OUT时,数字滤波后的信号就可以从GPIO输出,以方便观察测量。
LVD中断 LVD支持在低功耗模式下工作,中断输出可将芯片从低功耗模式下唤醒。当被监测电压与LVD阈值的比较结果满足触发条件时,可产生中断或复位信号。产生中断还是复位信号由控制寄存器LVD_CR0的ACTION位域控制: • ACTION为1,LVD触发产生复位 #define LVD_Action_Reset ((uint32_t)0x00000002) • ACTION为0,LVD触发产生中断 #define LVD_Action_Irq ((uint32_t)0x00000000)
通过设置控制寄存器LVD_CR0的IE位域为1,使能LVD中断,满足触发条件时将产生LVD中断,中断标志位LVD_SR.INTF会被硬件置1,用户可以向INTF位写0,清除中断标志。设置控制寄存器LVD_CR1的LEVEL、FALL、RISE位域,可选择不同的中断或复位触发方式,三者可组合使用: • LEVEL为1,被监测电压低于阈值时触发中断或产生复位 • FALL为1,被监测电压跌落到阈值以下的下降沿触发中断或产生复位 • RISE为1,被监测电压回升到阈值以上的上升沿触发中断或产生复位 相关的寄存器具体位域可参考下表: 根据上述内容,简单介绍配置电压监测例程。LVD的输入通道设置为PA00,输出端口为PA08,门限电压为2.02V,利用LVD的中断实现当LVD输入通道电压低于或者高于门限电压时刻(利用上升沿和下降沿),PC03输出电平翻转一次。
void LVD_PortInit(void) { GPIO_InitTypeDef GPIO_InitStructure = {0};
//打开GPIOA时钟 __RCC_GPIOA_CLK_ENABLE();
//将PA08设置为LVD比较结果输出 GPIO_InitStructure.Pins = GPIO_PIN_8; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_Init(CW_GPIOA, &GPIO_InitStructure); //将PA08复用为LVD比较结果输出 PA08_AFx_LVDOUT(); //将PA00设置为LVD的输入口 PA00_ANALOG_ENABLE(); }
int main(void) { LVD_InitTypeDef LVD_InitStruct = {0}; //LED初始化 LED_Init(); //配置测试IO口 LVD_PortInit(); LVD_InitStruct.LVD_Action = LVD_Action_Irq; //配置中断功能 LVD_InitStruct.LVD_Source = LVD_Source_PA00; //配置LVD输入口为PA00 LVD_InitStruct.LVD_Threshold = LVD_Threshold_2p02V; //配置LVD基准电压为2.02v LVD_InitStruct.LVD_FilterEn = LVD_Filter_Enable; //LVD滤波模块开启 LVD_InitStruct.LVD_FilterClk = LVD_FilterClk_RC150K;//LVD滤波时钟为150KHz LVD_InitStruct.LVD_FilterTime = LVD_FilterTime_4095Clk; LVD_Init(&LVD_InitStruct);
LVD_TrigConfig(LVD_TRIG_FALL | LVD_TRIG_RISE, ENABLE); //LVD中断为上升沿和下降沿触发 LVD_EnableIrq(LVD_INT_PRIORITY); LVD_ClearIrq(); FirmwareDelay(4800); LVD_Enable(); //LVD使能
while (1) { if (gFlagIrq) { PC03_TOG(); gFlagIrq = FALSE; } } }
void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0};
//打开GPIOC时钟 __RCC_GPIOC_CLK_ENABLE();
/* Configure the GPIO_LED pin */ GPIO_InitStructure.Pins = GPIO_PIN_2 | GPIO_PIN_3; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_Init(CW_GPIOC, &GPIO_InitStructure);
//LEDs are off. PC02_SETLOW(); PC03_SETLOW(); }
//LVD中断服务函数 void LVD_IRQHandler(void) { LVD_ClearIrq(); //清除中断标志 gFlagIrq = TRUE; //将gFlagIrq赋值为TURE,使main函数中的if判断语句生效 }
上述例程中的LVD_PortInit()为前文LVD的IO口配置函数,下面例程为通过寄存器配置LVD,具体功能与上述例程一样。 void LVD_PortInit(void) { GPIO_InitTypeDef GPIO_InitStructure = {0};
//打开GPIOA时钟 __RCC_GPIOA_CLK_ENABLE();
//将PA08设置为LVD比较结果输出 GPIO_InitStructure.Pins = GPIO_PIN_8; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_Init(CW_GPIOA, &GPIO_InitStructure); //将PA08复用为LVD比较结果输出 PA08_AFx_LVDOUT(); //将PA00设置为LVD的输入口 PA00_ANALOG_ENABLE(); }
int main(void) { //LED初始化 LED_Init();
//配置测试IO口 LVD_PortInit();
CW_LVD->CR0_f.SOURCE=1; //选择待监测的电压来源为PA00 CW_LVD->CR0_f.VTH=0; //选择阈值电压为2.02V CW_LVD->CR1_f.FLTTIME=7; //选择 LVD 滤波宽度为4095个时钟周期信号 CW_LVD->CR1_f.FLTCLK=0; //选择滤波时钟为150KHz的RC振荡时钟 CW_LVD->CR1_f.FLTEN=1; //使能 LVD 滤波 CW_LVD->CR1_f.RISE=1; //下降沿触发 CW_LVD->CR1_f.FALL=1; //上升沿触发 CW_LVD->CR0_f.ACTION=0; //选择LVD触发为中断 CW_LVD->CR0_f.IE=1; //使能LVD中断 NVIC_ClearPendingIRQ(LVD_IRQn); //使能NVIC中断向量表中的LVD中断 NVIC_SetPriority(LVD_IRQn, 3); NVIC_EnableIRQ(LVD_IRQn); FirmwareDelay(4800); CW_LVD->CR0_f.EN=1; //使能LVD CW_LVD->SR_f.INTF=0; //清除LVD中断标志
while (1) { if (gFlagIrq) { PC03_TOG(); gFlagIrq = FALSE; } } }
/**@brief LED I/O初始化**/ void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0};
//打开GPIOC时钟 __RCC_GPIOC_CLK_ENABLE();
/* Configure the GPIO_LED pin */ GPIO_InitStructure.Pins = GPIO_PIN_2 | GPIO_PIN_3; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_Init(CW_GPIOC, &GPIO_InitStructure);
//LEDs are off. PC02_SETLOW(); PC03_SETLOW(); }
//LVD中断服务函数 void LVD_IRQHandler(void) { LVD_ClearIrq(); //清除中断标志 gFlagIrq = TRUE; //将gFlagIrq赋值为TURE,使main函数中的if判断语句生效 } 上述例程功能为在PA00的输入电压值低于2.02v或高于2.02v的时刻,LVD会产生中断,PC03的输出电平会产生翻转,可利用CW32L083的开发板和数字电源进行测试,将PA00和数字电源连接,调节数字电源输出电压,在升高至门限电压以上或者下降至门限电压以下,LED1的状态会发生翻转。 LVD的相关函数及功能,可参考下述介绍。
1.void LVD_EnableNvic(uint8_t intPriority); //使能NVIC中LVD中断
2.void LVD_DisableNvic(void); //禁止NVIC中LVD中断
3.void LVD_TrigConfig(uint16_t LVD_TRIG, FunctionalState NewState); //配置LVD中断/系统复位触发方式
4.void LVD_EnableIrq(uint8_t intPriority); //使能LVD中断
5.void LVD_DisableIrq(void); //禁止LVD中断
6.void LVD_ClearIrq(void); //清除LVD中断标志
7.boolean_t LVD_GetIrqStatus(void); //获取LVD中断标志
8.FlagStatus LVD_GetFlagStatus(uint16_t LVD_FLAG); //获取LVD指定的状态位
9.boolean_t LVD_GetFilterResult(void); //获取Filter结果
10.void LVD_Init(LVD_InitTypeDef* LVD_InitStruct); //LVD初始化
11.void LVD_DeInit(void); //LVD去初始化
12.void LVD_Enable(void); //使能LVD
13.void LVD_Disable(void); //停止LVD
CW32的LVD的使用介绍到此结束。
|