在上一篇文章中 STM8单片机低功耗—活跃停机(Active Halt)模式实现-1 没有使用活跃停机(Active Halt)
模式的定时唤醒功能,使用的是外部中断唤醒,这篇文章来演示一下如何使用活跃停机(Active Halt)
的定时自动唤醒功能。
这个活跃停机(Active Halt)
的定时自动唤醒功能中的定时时间指的就是:从单片机进入低功耗模式之后到下一次系统自动唤醒的时间间隔。比如将自动定时的时长设置为1s,当使用HALT命令让单片机进入低功耗模式之后,单片机内部的定时器开始计时,时间到了1s之后,单片机就会自动从低功耗模式中唤醒,如果要再次进入低功耗需要继续执行一次HALT命令。
要使用自动唤醒功能前必须先设置自动唤醒的时间,设置时间需要通过两个寄存器来设置 异步预分频寄存器 (AWU_APR) 和 时基选择寄存器 (AWU_TBR).。
异步预分频寄存器 (AWU_APR)设置对128KHz的内部低速时钟振荡器的分频系数,最小分频值为2,最大分频值为64。
时基选择寄存器 (AWU_TBR)用来设置自动唤醒的时间间隔,它的值从0 到 15,当设置为0时,表示不使用自动唤醒功能。所以唤醒时间的有效值范围从1 到 15 。它的自动唤醒时间范围如下:
最小唤醒时间 0.01ms左右,最大唤醒时间 30.72s,这个唤醒时间是由 异步预分频寄存器 (AWU_APR) 和 *时基选择寄存器 (AWU_TBR)*这两个寄存器的值共同决定的。
具体计算公式如下:
这个0001到1111的值是由时基选择寄存器 (AWU_TBR)的值,这个值不同那么时间的计算公式也不同。每个数字后面跟着的就是相应的计算公式。 APRdiv 这个值是 异步预分频寄存器 (AWU_APR)设置的分频值,fls这个是是内部低速振荡器时钟频率,这里是128Khz的固定值。
根据这个公式就可以计算出自动唤醒的时间了,比如需要设置自动唤醒时间为5s左右,根据上面的时间表格可以看出,自动唤醒时间在5s左右时。时基选择寄存器 (AWU_TBR)中AWUTB[3:0]的值可以是1110或者1111。当值设置为1110时,异步预分频寄存器 (AWU_APR)中APR[5:0]值的设置范围是26到64,当分频值设置为26时,自动唤醒时间就是2.08s,当分频值设置为64时,自动唤醒时间就是5.12s。同样当时基寄存器的值设置为1111时,分频器的值范围为11到64,此时自动唤醒的时间范围就是5.28s到30.72s。
这样时间设置为5s左右,那么尽量是靠近5s。所以这里就设置时基寄存器的值为1110,换算为16进制计算0x0E,设置分频器值为64,这里要注意一点64的十六进制值是0x40,但是给寄存器里面写入的时候需要写入0x3E。需要给16进制值减去2,这是因为分频值是从2开始的,而不是从0开始的。
然后根据时间计算公式计算延时时间。时基值为1110,那么计算公式如下:
APRdiv的值为64,fls的值为128k。 5 * 2^11 * 64 / 128000 = 5.12s,通过公式计算出来的值和上面表格中的值是相符的。
下面就可以开始编写程序了。首先初始化需要用到的外设。
#define LED PB_ODR_ODR5
void LED_GPIO_Init( void )
{
PB_DDR |= ( 1 << 5 ); // 输出 led
PB_CR1 |= ( 1 << 5 ); // 推挽输出
}
//初始化PD2口
void EXTI_GPIO_Init( void )
{
PD_DDR &= ( ~( 1 << 2 ) ); //输入
PD_CR1 &= ( ~( 1 << 2 ) ); //浮空输入
PD_CR2 |= ( 1 << 2 ); //打开外部中断
}
//PD2口为中断输入 低电平触发
void EXTI_Init( void )
{
EXTI_GPIO_Init();
EXTI_CR1 &= ~( 3 << 6 ); //6 7 位清零
EXTI_CR1 |= ( 1 << 6 ); //PD上升沿触发
}
//端口D外部中断 中断号6
#pragma vector = 8 // IAR中的中断号,要在STVD中的中断号上加2
__interrupt void EXTI_PORTC_Handle( void )
{
//外部中断会将单片机从 停机模式唤醒
}
初始化LED口和外部中断。LED灯用来指示单片机运行状态,正常模式下LED灯闪烁,当进入低功耗之后,LED灯停止闪烁。外部中断用于将单片机从低功耗唤醒。
接下来初始化AWU
void AWU_init()
{
CLK_ICKR |= 0x2C; // 活跃停机模式下主电压调节器处于关 打开低速振荡器(128K) 从停机或者活跃停机模式唤醒使能
FLASH_CR1 |= 0x04; // 当MCU在Active-halt 模式时FLASH处于掉电模式
AWU_APR = 0x3E; //设置异步预分频器值 64分频
AWU_TBR = 0x0E; //自动唤醒中断时间 5*2^11*64/128000=5.12s
AWU_CSR1 = 0x30; //使能自动唤醒中断 使能自动唤醒功能
}
#pragma vector = 3 // IAR中的中断号,要在STVD中的中断号上加2
__interrupt void AWU_HALT_Handler( void )
{
AWU_CSR1 = AWU_CSR1; // 通过读AWU_CSR 清除更新中断标志位
}
在AWU中首先设置当系统设置系统进入活跃停机模式时,打开内部低速振荡器。然后设置系统进入活跃停机模式时,FLASH就进入掉电模式。这样可以进一步的降低系统功耗。接下里设置 异步预分频寄存器 (AWU_APR) 和 *时基选择寄存器 (AWU_TBR)*的值,将自动唤醒时间设置为5s左右。最后使能自动唤醒中断功能,在中断中需要清除自动唤醒中断标志,通过读寄存器的值就可以清除自动唤醒标志。如果不清除自动唤醒标志,那么系统只能被唤醒一次,以后就永远进入活跃停机模式,不会自动唤醒了。除非有外部中断信号或者复位信号,系统才会被唤醒。
最后编写主函数
void SysClkInit( void )
{
CLK_SWR = 0xe1; //HSI为主时钟源 16MHz CPU时钟频率
CLK_CKDIVR = 0x00; //CPU时钟0分频,系统时钟0分频
}
void main( void )
{
unsigned int cnt = 0;
__asm( "sim" ); //禁止中断
SysClkInit();
delay_init( 16 );
LED_GPIO_Init();
EXTI_Init();
__asm( "rim" ); //开启中断
AWU_init(); //使能AWU
__asm( "halt" ); //进入 活跃停机(Active Halt)模式 5s 后自动唤醒
while( 1 ) //进入低功耗之前,电流5.5mA
{
LED = !LED;
delay_ms( 500 );
cnt++;
if( cnt > 10 ) //进入低功耗之后,电流160uA
{
cnt = 0; //中断和复位也能随时唤醒
__asm( "halt" ); //再次进入 活跃停机(Active Halt)模式 5S后自动唤醒
}
}
}
首先初始化系统需要用到的外设,然后初始化AWU,这时使用HALt命令,单片机就会进入活跃停机模式,5s之后系统被自动唤醒,然后进入 while循环中,此时LED灯开始闪烁,5s之后再次使用HALT命令让单片机进入活跃停机模式,此时LED灯不再闪烁,5s之后单片机自动被唤醒,LED灯继续闪烁。这样一直循环下去,LED灯就会闪烁5s,停5s,这样一直循环。
当LED灯闪烁时,说明单片机处于正常工作模式,此时用万用表测量单片机的电流为5.5mA,当LED灯停止闪烁时,说明单片机进入到了活跃停机模式中,此时用万用表测量单片机的电流为160uA。
完整工程连接下载地址: STM8单片机低功耗 活跃停机Active Halt模式实现
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://hxydj.blog.csdn.net/article/details/124336588
内容来源于网络,如有侵权,请联系作者删除!