【IAR工程】STM8S208RB基于ST标准库下自动唤醒(AWU)

【IAR工程】STM8S208RB基于ST标准库下自动唤醒(AWU)


  • 相关篇《【IAR工程】STM8S208RB基于ST标准库下GPIO点灯示例》
  • 《【IAR工程】STM8S208RB基于ST标准库下EXTI外部中断》
  • 基于ST STM8S/A标准外设库:STSW-STM8069,版本号:2.3.1
  • STSW-STM8069官方资源下载地址:https://www.st.com/zh/embedded-software/stsw-stm8069.html
  • IAR编译器版本:IAR Assembler for STMicroelectronics STM8 3.11.1
  • STM8S207/208RBT6最小系统板:https://oshwhub.com/perseverance51/stm8s207rbt6-kai-fa-ban
  • 中断向量表
    【IAR工程】STM8S208RB基于ST标准库下自动唤醒(AWU)_第1张图片

自动唤醒(AWU)

AWU是用来当MCU进入低功耗的活跃停机(Active Halt)模式时提供一个内部的唤醒时间基准。该时间基准的时钟是由内部的低速RC振荡器时钟(LSI)或者通过预分频的HSE晶振时钟来提供的。

  • AWU 时钟框图
    【IAR工程】STM8S208RB基于ST标准库下自动唤醒(AWU)_第2张图片
  • 注意:LS低速时钟源的选择是通过编程CKAWUSEL选项位来实现的。

✅内部低速时钟LSI频率测量

在使用LSI低速内部时钟时,为了确保最好的精度,它的频率可以通过TIM3的输入捕捉1来测定。

  • 代码实现部分;
/**
  * @brief  Measure the LSI frequency using timer IC1 and update the calibration registers.
  * @note   It is recommended to use a timer clock frequency of at least 10MHz in order
	*         to obtain a better in the LSI frequency measurement.
  * @param  None
  * @retval None
  */
uint32_t LSIMeasurment( void )
{

    uint32_t lsi_freq_hz = 0x0;
    uint32_t fmaster = 0x0;
    uint16_t ICValue1 = 0x0;
    uint16_t ICValue2 = 0x0;

    /* Get master frequency */
    fmaster = CLK_GetClockFreq();

    /* Enable the LSI measurement: LSI clock connected to timer Input Capture 1 */
    AWU->CSR |= AWU_CSR_MSR;

#if defined (STM8S903) || defined (STM8S103) || defined (STM8S003) || defined (STM8S001)
    /* Measure the LSI frequency with TIMER Input Capture 1 */

    /* Capture only every 8 events!!! */
    /* Enable capture of TI1 */
    TIM1_ICInit( TIM1_CHANNEL_1, TIM1_ICPOLARITY_RISING, TIM1_ICSELECTION_DIRECTTI, TIM1_ICPSC_DIV8, 0 );

    /* Enable TIM1 */
    TIM1_Cmd( ENABLE );

    /* wait a capture on cc1 */
    while( ( TIM1->SR1 & TIM1_FLAG_CC1 ) != TIM1_FLAG_CC1 );
    /* Get CCR1 value*/
    ICValue1 = TIM1_GetCapture1();
    TIM1_ClearFlag( TIM1_FLAG_CC1 );

    /* wait a capture on cc1 */
    while( ( TIM1->SR1 & TIM1_FLAG_CC1 ) != TIM1_FLAG_CC1 );
    /* Get CCR1 value*/
    ICValue2 = TIM1_GetCapture1();
    TIM1_ClearFlag( TIM1_FLAG_CC1 );

    /* Disable IC1 input capture */
    TIM1->CCER1 &= ( uint8_t )( ~TIM1_CCER1_CC1E );
    /* Disable timer2 */
    TIM1_Cmd( DISABLE );

#else
    /* Measure the LSI frequency with TIMER Input Capture 1 */

    /* Capture only every 8 events!!! */
    /* Enable capture of TI1 */
    TIM3_ICInit( TIM3_CHANNEL_1, TIM3_ICPOLARITY_RISING, TIM3_ICSELECTION_DIRECTTI, TIM3_ICPSC_DIV8, 0 );

    /* Enable TIM3 */
    TIM3_Cmd( ENABLE );

    /* wait a capture on cc1 */
    while ( ( TIM3->SR1 & TIM3_FLAG_CC1 ) != TIM3_FLAG_CC1 );
    /* Get CCR1 value*/
    ICValue1 = TIM3_GetCapture1();
    TIM3_ClearFlag( TIM3_FLAG_CC1 );

    /* wait a capture on cc1 */
    while ( ( TIM3->SR1 & TIM3_FLAG_CC1 ) != TIM3_FLAG_CC1 );
    /* Get CCR1 value*/
    ICValue2 = TIM3_GetCapture1();
    TIM3_ClearFlag( TIM3_FLAG_CC1 );

    /* Disable IC1 input capture */
    TIM3->CCER1 &= ( uint8_t )( ~TIM3_CCER1_CC1E );
    /* Disable timer3 */
    TIM3_Cmd( DISABLE );
#endif /* (STM8S903) || (STM8S103) || (STM8S003) || (STM8S001) */

    /* Compute LSI clock frequency */
    lsi_freq_hz = ( 8 * fmaster ) / ( ICValue2 - ICValue1 );

    /* Disable the LSI measurement: LSI clock disconnected from timer Input Capture 1 */
    AWU->CSR &= ( uint8_t )( ~AWU_CSR_MSR );

    return ( lsi_freq_hz );
}

【IAR工程】STM8S208RB基于ST标准库下自动唤醒(AWU)_第3张图片
.- 通过串口打印信息可以看到,测量到的内部LSI频率。

⛳在使用自动唤醒(AWU)时注意事项

  • ⚡在自动唤醒(AWU)唤醒之后,需要重新对串口进行初始化一次,如果不进行初始化直接调用printf输出函数,串口输出的信息会不完整,其中带一些乱码字符。这一点特别需要特别注意,AWU唤醒后对于其他外设功能最好再进行初始化一次,以免意外发生。

自动唤醒时间配置参数

typedef enum
{
  AWU_TIMEBASE_NO_IT  = (uint8_t)0,    /*!< No AWU interrupt selected */
  AWU_TIMEBASE_250US  = (uint8_t)1,    /*!< AWU Timebase equals 0.25 ms */
  AWU_TIMEBASE_500US  = (uint8_t)2,    /*!< AWU Timebase equals 0.5 ms */
  AWU_TIMEBASE_1MS    = (uint8_t)3,    /*!< AWU Timebase equals 1 ms */
  AWU_TIMEBASE_2MS    = (uint8_t)4,    /*!< AWU Timebase equals 2 ms */
  AWU_TIMEBASE_4MS    = (uint8_t)5,    /*!< AWU Timebase equals 4 ms */
  AWU_TIMEBASE_8MS    = (uint8_t)6,    /*!< AWU Timebase equals 8 ms */
  AWU_TIMEBASE_16MS   = (uint8_t)7,    /*!< AWU Timebase equals 16 ms */
  AWU_TIMEBASE_32MS   = (uint8_t)8,    /*!< AWU Timebase equals 32 ms */
  AWU_TIMEBASE_64MS   = (uint8_t)9,    /*!< AWU Timebase equals 64 ms */
  AWU_TIMEBASE_128MS  = (uint8_t)10,   /*!< AWU Timebase equals 128 ms */
  AWU_TIMEBASE_256MS  = (uint8_t)11,   /*!< AWU Timebase equals 256 ms */
  AWU_TIMEBASE_512MS  = (uint8_t)12,   /*!< AWU Timebase equals 512 ms */
  AWU_TIMEBASE_1S     = (uint8_t)13,   /*!< AWU Timebase equals 1 s */
  AWU_TIMEBASE_2S     = (uint8_t)14,   /*!< AWU Timebase equals 2 s */
  AWU_TIMEBASE_12S    = (uint8_t)15,   /*!< AWU Timebase equals 12 s */
  AWU_TIMEBASE_30S    = (uint8_t)16    /*!< AWU Timebase equals 30 s */
} AWU_Timebase_TypeDef;

自动唤醒配置函数

/*******************************************************************************
**函数名称:void MyAWU_Init()
**功能描述:初始化AWU模块
**入口参数:无
**输出:无
*******************************************************************************/
void MyAWU_Init(void)
{
   	AWU_Init(AWU_TIMEBASE_2S);  //配置自动呼醒为1秒时间呼醒CPU
   	AWU_Cmd(ENABLE);   //使能自动呼醒功能
}

主程序代码

/**************************************************************************************
实验现象:	每间隔1秒自动唤醒CPU,同时使用LED1指示灯亮灭来指示唤醒状态。

接线说明:	1,STM8S单片机-->LED
		   		PC7-->LED1
                                PC6-->LED2

注意事项:1、点击“Download active application”按钮,程序下载完成后,即可运行程序。


***************************************************************************************/

#include "stm8s.h"      /*  添加库函数头文件 */
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "awu.h"
#include "stdio.h"


/*******************************************************************************
**函数名称:void ClockSwitch_HSE()
**功能描述:将系统时钟切换到外部高速晶振时钟
**入口参数:无
**输出:无
*******************************************************************************/
void ClockSwitch_HSE( void )
{
    //启用外部高速晶振,外部晶振1-24MHz

    CLK_HSECmd( ENABLE ); //使能HSE起振
    while( CLK_GetFlagStatus( CLK_FLAG_HSERDY ) == RESET ); //等待HSE准备就绪
    CLK_ClockSwitchCmd( ENABLE ); //使能时钟切换
    CLK_ClockSwitchConfig( CLK_SWITCHMODE_AUTO,    //
                           CLK_SOURCE_HSE,             //选择外部外部晶振(24M晶振)作为系统时钟源
                           DISABLE,                    //不开启时钟切换中断
                           CLK_CURRENTCLOCKSTATE_ENABLE //振荡器使能
                         );

    while( CLK_GetFlagStatus( CLK_FLAG_SWBSY ) != RESET );
    CLK_SYSCLKConfig( CLK_PRESCALER_CPUDIV1 ); //如果切换成功,则设置CPU时钟为1分频,让外部晶振作为系统时钟

    CLK_ClockSwitchCmd( DISABLE );   //关闭切换

    CLK_HSICmd( DISABLE );  //关闭内部高速HSI
}

INTERRUPT_HANDLER(AWU_IRQHandler, 1)
{
	LED1_TOGGLE;   
    USART1_Init( 9600 ); //唤醒后,需要重新初始化一次USART1,否则,串口话打印乱码
        printf("Hello World! \r\n");
        LED2_TOGGLE;
      
  	AWU_GetFlagStatus();  //通过读其状态,清除标志位
}
/* 主函数 */
int main( void )
{

    disableInterrupts();    //关闭系统中断
    //内部时钟为1分频 = 16Mhz
   CLK_SYSCLKConfig( CLK_PRESCALER_HSIDIV1 );
//    ClockSwitch_HSE();      //调用时钟切换函数 设置外部晶振(24MHz)为系统时钟
    
    USART1_Init( 9600 ); //初始化USART1 , 并设置波特率为9600
    printf("Hello World! \r\n");
    LED_Init();
    MyAWU_Init();

    enableInterrupts();     //使能系统中断
    while( 1 )
    {
        halt();  //进入活跃停机模式,等待AWU自动呼醒
    }
}
//是一个宏定义;在固件库中,它的作用就是检测传递给函数的参数是否是有效的参数
void assert_failed( u8* file, u32 line )
{
    while ( 1 )
    {

    }
}

工程源码

  • IAR对中文路径不友好,不要将工程解压在带有中文字符路径的文件夹内直接打开工程编译,这样会导致IAR内部检索文件路径将消耗大量CPU资源。

链接: https://pan.baidu.com/s/1EfAirobJeSyADKLKQ5Lj1w
提取码: 6jxt

你可能感兴趣的:(STM8,#,IAR,for,STM8S208RB,STM8S208RB,STM8S,自动唤醒)