??在上一篇文章中使用活跃停机模式实现单片机的定时自动唤醒功能。STM8单片机低功耗—活跃停机(Active Halt)模式实现-2 通过这个实验可以看出,自动唤醒功能和定时器定时功能很类似,那么能不能使用自动唤醒的定时功能实现LED灯的闪烁呢?
??下面就通过这个自动唤醒功能来实现LED灯1s闪烁一次的功能。
??首先初始化用到的外设
#define LED PB_ODR_ODR5
void LED_GPIO_Init( void )
{
PB_DDR |= ( 1 << 5 );
PB_CR1 |= ( 1 << 5 );
}
void EXTI_GPIO_Init( void )
{
PD_DDR &= ( ~( 1 << 2 ) );
PD_CR1 &= ( ~( 1 << 2 ) );
PD_CR2 |= ( 1 << 2 );
}
void EXTI_Init( void )
{
EXTI_GPIO_Init();
EXTI_CR1 &= ~( 3 << 6 );
EXTI_CR1 |= ( 1 << 6 );
}
#pragma vector = 8
__interrupt void EXTI_PORTC_Handle( void )
{
}
?? PB5口用来控制LED灯,用来指示程序运行的状态。PD2口作为外部中断,用于将单片机从低功耗模式唤醒。虽然这个例子中不需要用到外部中断。但是安装常规方法还是把这块也写上了。
?? 接下来初始化AWU
void AWU_init()
{
CLK_ICKR |= 0x2C;
FLASH_CR1 |= 0x04;
AWU_APR = 0x3E;
AWU_TBR = 0x0C;
AWU_CSR1 = 0x30;
CLK_PCKENR2 |= 0x04;
CLK_ICKR |= 0x08;
}
#pragma vector = 3
__interrupt void AWU_HALT_Handler( void )
{
AWU_CSR1 = AWU_CSR1;
}
?? 设置自动唤醒定时时间为1s,然后将设置 外设时钟门控寄存器 2(CLK_PCKENR2) ,将AWU和主时钟连接起来。然后打开内部低速时钟。 其实最后两句配置语句
CLK_PCKENR2 |= 0x04;
CLK_ICKR |= 0x08;
?? 也可以不用写,因为 CLK_PCKENR2 寄存器的复位值为 0xFF,所以再给他或一个0x04,结果并没有发生任何改变。 ?? 而第二行CLK_ICKR 的值初始话第一句的时候,已经将第四位的值设置为1了。这里单独写出来是为了重点提醒对时钟的配置。
?? 这里还需要将自动唤醒中断打开,因为自动唤醒定时时间到了之后,自动唤醒标志位就会被置位,需要将标志位清除之后,下一次自动唤醒功能才会生效,如果不清除标志位,系统第一次进入活跃停机模式之后就不会被自动唤醒了。
?? 下来就可以编写主函数了
void SysClkInit( void )
{
CLK_SWR = 0xe1;
CLK_CKDIVR = 0x00;
}
void main( void )
{
__asm( "sim" );
SysClkInit();
delay_init( 16 );
LED_GPIO_Init();
EXTI_Init();
__asm( "rim" );
AWU_init();
__asm( "halt" );
while( 1 )
{
LED = !LED;
__asm( "halt" );
}
}
?? 首先初始化需要用到的外设和AWU,然后使用HALT指令让单片机进入活跃停机模式,1s钟之后,单片机就会被自动唤醒,然后进入while()循环中,此时将LED的状态取反,然后又进入到活跃停机模式中,1s钟之后单片机再次被自动唤醒。然后继续将LED取反,又进入到活跃停机模式中。这样一直循环。在外面观察时就会发现单片机上的LED灯亮1s灭1s一直循环闪烁。
?? 当不使用低功耗模式时,通过延时函数来实现LED灯的闪烁,用万用表测量单片机的电流为6mA左右。通过活跃停机模式实现LED闪烁时,用万用表测量单片机的电流不到3mA。可以看出同样的LED闪烁功能,低功耗模式的功耗的确比正常模式小很多。如果系统使用的是电池供电的话,使用低功耗模式可以有效地延长电池使用寿命。
|