一种用内部高速晶振校准看门狗时钟的方法 8-bit MCU

yuxh 2019-12-21 865

有些用户希望单片机平时保持休眠,用看门狗实现比较准确的定时唤醒。由于看门狗时钟精度比内部高速时钟要低得多,可以用内部高速时钟校准看门狗时钟。本方法适用于于环境温度变化不大或不考虑温飘的场合。



实现思路:

利用定时器如T8P1累加值记录看门狗溢出时间,根据该值来修改看门狗校准寄存器,经过多次迭代后使看门狗的溢出时间满足要求。

主函数中一开始先检测是否是掉电复位,判断的依据是变量CheckData是否不等于0x55AA。若是掉电复位或者不是看门狗复位但是看门狗时钟误差未达到要求,则把看门狗配置成溢出时间8毫秒,T8P1配置成每隔64微秒加1,T8P1值存在变量T8P1_bak中,等待单片机看门狗溢出;若不是看门狗复位且看门狗时钟误差已达到要求,则把看门狗配置成1.024秒。每次看门狗复位后根据T8P1_bak的值修改看门狗校准寄存器。
看门狗校准寄存器最多只修改5次,防止陷入无限循环。



程序流程如下:

如果CheckData不等于0x55AA,表示是掉电复位

       相关变量赋初值。

       T8P1配置成每隔64微秒加1,T8P1寄存器清零。

       关闭看门狗预分频器使看门狗溢出时间是8毫秒,看门狗校准寄存器赋值。

       T8P1定时器开始计数,在while(1)循环中把T8P1值存到变量T8P1_bak中,直到看门狗溢出。

如果CheckData等于0x55AA,表示不是掉电复位
       校准次数加1。

       如果T8P1_bak已达到119~131,即WDT时钟误差已小于正负5%

              把主时钟配置成16MHz,把看门狗溢出时间配置成1.024秒。

       如果WDT时钟误差为达到要求

              用T8P1_bak修正WDTCAL_bak。

              T8P1配置成每隔64微秒加1,T8P1寄存器清零。

              关闭看门狗预分频器使看门狗溢出时间是8毫秒,看门狗校准寄存器赋值。

              T8P1定时器开始计数,若校准次数小于5,则在while(1)循环中把T8P1值存到变量T8P1_bak中,直到看门狗溢出。

完成校准。



以下以HR7P159B为例:

C例程:

#include <hic.h>

unsigned int CheckData;//用于判断是否是掉电复位

unsigned char T8P1_bak;//T8P1值的备份,记录两次看门狗复位之间的时间,T8P1每隔64微秒加1

unsigned char WDTCAL_bak;//WDTCAL的备份,记录看门狗复位前WDTCAL的值

unsigned char CalibratingCounter;//校准次数

sbit PB0_bak;//PB0备份,记录看门狗复位前PB0的电平,用于测试

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

//                          主程序

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

void main() {

         OSCP=0x55;

         OSCC=0xA0;                      //时钟配置成500KHz

         while(!HSOSCF);

         __Asm NOP;

         while(!SW_HS);

         __Asm CWDT;                    //清看门狗

         if(0x55AA!=CheckData){  //是掉电复位

                   CheckData=0x55AA;         //CheckData设初值

                   T8P1_bak=255;

                   WDTCAL_bak=128; //WDTCAL设为中间值,WDTCAL的范围是0~255

                   CalibratingCounter=0;

                   T8P1C=0b00000011;        //配置T8P1每2/500000*16=0.000064加1

                   T8P1=0;

                   WDTC=0x00;             //修改WDTC(禁用预分频,溢出时间8毫秒)

                   CALPROT=0x55;

                   WDTCAL=WDTCAL_bak;

                   CALPROT=0x01;

                   __Asm CWDT;          //清看门狗

                   T8P1E=1;                   //T8P开始计数

                   while(1){                     //等待看门狗溢出复位

                       T8P1_bak=T8P1;

                   }

         }

         else{                                               //不是掉电复位

             CalibratingCounter++;

                   if((T8P1_bak>=119)&&(T8P1_bak<=131)){//WDT误差已小于正负5%。如考虑WDT温飘可再上浮10%

                       OSCP=0x55;

                            OSCC=0xF0;             //时钟配置成16MHz

                            WDTC=0x16;             //修改WDTC(128分频,溢出时间1.024秒)

                            __Asm CWDT;          //清看门狗

                            PB0=PB0_bak;                   //用于测试

                            PBT0=0;                     //用于测试

                            PB0_bak=~PB0_bak;        //用于测试

                   }

                   else{                                               //误差不满足要求,继续调整WDTCAL

                            WDTCAL_bak=WDTCAL_bak+(125-T8P1_bak);

                            T8P1C=0b00000011;        //配置T8P1每2/500000*16=0.000064加1

                            T8P1=0;

                            WDTC=0x00;             //修改WDTC(禁用预分频,溢出时间8毫秒)

                            CALPROT=0x55;

                            WDTCAL=WDTCAL_bak;

                            CALPROT=0x01;

                            __Asm CWDT;          //清看门狗

                            T8P1E=1;                   //T8P开始计数

                       if(CalibratingCounter<5){//最多校准5次

                                     while(1){            //等待看门狗溢出复位

                                               T8P1_bak=T8P1;

                                     }

                            }

                   }

         }

         while(1){

             ;//用户程序

         }

}

 
最新回复 (0)
返回