STM32
直播中

辛太励

8年用户 1149经验值
擅长:20153
私信 关注
[问答]

stm8s halt自唤醒长时间搁置Timer出错的原因?

定时器是10mS中断,长时间搁置后,timer变成了200uS的更新中断

相关代码如下:
void sysclk_init(void)
{
        //主时钟选择
    {
        CLK_SWR = 0xE1;     //内部16MHSI为主时钟源
        CLK_ICKR |= 0x05;   //从halt模式唤醒使能、使能HSI时钟
        while((CLK_ICKR   0x02) == 0x00); //等待HSI稳定就绪
    }

    //16MRC时钟1:2输出 即Fmaster = Fhsi / 2 (00-1:1 01-1:2 10-1:4 11-1:8)
    {
        CLK_CKDIVR  = ~(1 << 4);
        CLK_CKDIVR |= (1 << 3);
    }

    //Fcpu = Fmaster = 8M 这个才是真正的供CPU使用的时钟
    CLK_CKDIVR  = ~((1 << 2) | (1 << 1) | (1 << 0));
    //Fcpu = Fmaster / 2 = 4M
        CLK_CKDIVR |= (1 << 0);

        
//                CLK_CKDIVR = 0x00;                //16MHz主频
        CLK_PCKENR1 = 0x00;                //关闭所有外设时钟
        CLK_PCKENR2 = 0x00;
}


void awu_init(void)
{
    CLK_PCKENR2 |= (1 << 2); //使能AWU时钟  

    //唤醒时间2.00S
    AWU_TBR = 0x0D;  
    AWU_APR = 0x3E; //分频Fls
    AWU_CSR1 |= 0x10; //AWU使能


    CLK_ICKR |= (1 << 5); //活跃停机模式(AWU使能情况)下,关闭电压调节器节省功耗  
    FLASH_CR1 |= (1 << 2); //活跃停机模式下Flash掉电,默认只有停机模式才掉电,代价是唤醒时间增加至微秒级别  

}


void tim1_init(void)
{
   CLK_PCKENR1 |= (1 << 7);

    //定时器时钟fck_cnt = Fck_psc / ( PSCR[15:0]+1); Fck_psc  = Fmaster = 8M
    //fck_cnt = 8M / (799 + 1) = 10KHz 周期100us
    TIM1_PSCRH = 0x03;
    TIM1_PSCRL = 0x1F;      //(fCK_CNT)等于fCK_PSC/( PSCR[15:0]+1)。

    // TIM1_CNTR寄存器计数到0x0064(100)为一次溢出:10ms
    TIM1_ARRH = 0x00;      
    TIM1_ARRL = 0x64;  

    TIM1_IER = 0x01;    //允许更新中断

    //重复计数寄存器复位值为0,溢出一次即产生中断
//            TIM1_RCR = 50;      //重复计数寄存器值,这样timer1 2次50ms即100ms产生一次中断

    TIM1_CR1 = 0x01;
}


void main(void)
{
    sysclk_init();
   adc_init();
   timer1_init();
   awu_init();
    while(1)
    {
           //关ADC
           ADC_CR1  = ~(1 << 0);                                            
           //关timer
           TIM1_CR1  = ~0x01;
           CLK_PCKENR1  = ~(1 << 7);        
           asm("halt"); //进入睡眠模式
           asm("nop");
           asm("nop");  
           enter_int();   //关全局中断
            CLK_PCKENR2 |= (1 << 3);
            ADC_CR1  = ~(1 << 0);
            Delay_ms(10);
            ADC_CR1 |= (1 << 0);

            CLK_PCKENR1 |= (1 << 7);
            TIM1_SR1  = ~0x01;//清除中断标志
            TIM1_CR1 = 0x01;
            exit_int(); //开全局中断
    }
}

回帖(1)

算一挂

2024-5-8 17:18:37
根据您提供的代码和描述,问题可能出现在STM8S的时钟配置和定时器设置上。以下是一些可能的原因和解决方案:

1. 时钟源不稳定:在长时间搁置后,可能需要重新配置时钟源以确保其稳定。您已经使用了内部16MHz HSI作为主时钟源,这是一个很好的选择。确保在唤醒过程中,HSI时钟已经稳定。

2. 定时器配置错误:检查定时器的配置,确保其设置为10ms中断。这包括定时器的预分频器、自动重载寄存器和中断使能位。例如,对于STM8S标准外设库,您可以使用以下代码配置定时器:

```c
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_DeInit(TIM1);
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
```

3. 中断服务例程(ISR)问题:确保您的定时器中断服务例程(例如,TIM1_Update_ISR)正确处理中断,并在每次中断中更新定时器的自动重载寄存器。这可以确保定时器在长时间搁置后仍然能够按照预期工作。

4. 唤醒源配置错误:确保您的唤醒源(例如,定时器中断)已正确配置,以便在STM8S从halt模式唤醒时触发中断。

5. 软件问题:检查您的代码,确保没有其他地方修改了定时器的配置或中断使能位。

综上所述,您需要检查时钟配置、定时器设置、中断服务例程和唤醒源配置,以确保STM8S在长时间搁置后能够正确唤醒并按照预期工作。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分