首先我知道这个低功耗的32k时钟十分不准,但还是想不加晶振的情况下,尽可能的利用这个做一些东西。现在想获取他在某一时刻的准确值。
我的思路是使用rtc的秒中断,设置一个100us一次的定时器,中断时记录计数值。准确频率值应该是(32768/计数值)x10000。
但是我发现,计算值,和用主时钟输出,示波器/另一个单片机pwm测量值不相同,比如计算值是24983Hz,示波器或pwm测量是25370Hz。
我想问下,这两者之间哪个较为准确,如果计算值不准确,能否看看是哪里的问题。万分感谢
附上主要代码
- #include "config.h"
- #include "STC8G_H_GPIO.h"
- #include "STC8G_H_UART.h"
- #include "STC8G_H_Delay.h"
- #include "STC8G_H_NVIC.h"
- #include "STC8G_H_Switch.h"
-
- bit f_1s;
- u16 timeCnt, lastCnt, fwt;
- float tmp;
- u8 st;
-
- void GPIO_config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure; //结构定义
-
- P0M0 = 0x00;
- P0M1 = 0x00;
- P1M0 = 0x00;
- P1M1 = 0x00;
- P2M0 = 0x00;
- P2M1 = 0x00;
- P3M0 = 0x00;
- P3M1 = 0x00;
- P4M0 = 0x00;
- P4M1 = 0x00;
- P5M0 = 0x00;
- P5M1 = 0x00;
-
- GPIO_InitStructure.Pin = GPIO_Pin_0 | GPIO_Pin_1; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
- GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
- GPIO_Inilize(GPIO_P3, &GPIO_InitStructure); //初始化
- }
-
- /*************** 串口初始化函数 *****************/
- void UART_config(void)
- {
- COMx_InitDefine COMx_InitStructure; //结构定义
-
- COMx_InitStructure.UART_Mode = UART_8bit_BRTx; //模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
- COMx_InitStructure.UART_BRT_Use = BRT_Timer1; //选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
- COMx_InitStructure.UART_BaudRate = 115200ul; //波特率, 一般 110 ~ 115200
- COMx_InitStructure.UART_RxEnable = ENABLE; //接收允许, ENABLE或DISABLE
- COMx_InitStructure.BaudRateDouble = DISABLE; //波特率加倍, ENABLE或DISABLE
- UART_Configuration(UART1, &COMx_InitStructure); //初始化串口1 UART1,UART2,UART3,UART4
- NVIC_UART1_Init(ENABLE, Priority_1); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
-
- UART1_SW(UART1_SW_P30_P31); //UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
- }
-
-
- /**********************************************/
-
- void Timer0_Init(void) //100微秒@24.000MHz
- {
- AUXR |= 0x80; //定时器时钟1T模式
- TMOD &= 0xF0; //设置定时器模式
- TL0 = 0xA0; //设置定时初始值
- TH0 = 0xF6; //设置定时初始值
- TF0 = 0; //清除TF0标志
- ET0 = 1;
- TR0 = 1; //定时器0开始计时
- }
-
- void Timer0Proc() interrupt 1
- {
- timeCnt++;
- }
-
- //rtc
- void RTC_Isr() interrupt 13//RTC_VECTOR
- {
- if(RTCIF & 0x08) //秒中断
- {
- RTCIF &= ~0x08;
- lastCnt = timeCnt;
- timeCnt = 0;
- f_1s = 1;
- }
- }
-
- void RTC_Init()
- {
- //使用内部时钟
- IRC32KCR = 0x80;
- while(!(IRC32KCR & 0x01));
- RTCCFG |= 0x02;
- INIYEAR = 23; //Y:23
- INIMONTH = 02; //M:02
- INIDAY = 21; //D:19
- INIHOUR = 23; //H:23
- INIMIN = 00; //M:45
- INISEC = 00; //S:55
- INISSEC = 0; //S/128:0
- RTCCFG |= 0x01;
-
- RTCIF = 0;
- RTCIEN = 0x08; //秒中断
- timeCnt = 0;
- RTCCR = 1; //启动
-
- }
-
- void main(void)
- {
- u8 i;
-
- EAXSFR(); /* 扩展寄存器访问使能 */
- GPIO_config();
- UART_config();
- EA = 1;
- Timer0_Init();
- RTC_Init();
-
- fwt = CHIPID9 << 8 | CHIPID10;
- st = 0;
- MCLKOCR = 0x01; //主时钟输出到P5.4口
- while (1)
- {
- if(st == 10)
- {
- st++;
- //关闭rtc
- RTCIEN = 0;
- timeCnt = 0;
- RTCCR = 0;
- //切换主时钟
- CLKDIV = 0x00; //时钟不分频
- CLKSEL = 0x03; //选择内部32K
- }
-
- if(f_1s)
- {
- f_1s = 0;
- tmp = 32768.0 / lastCnt * 10000.0;
- printf("b=%huHz Cnt=%hu calc=%fHz\r\n", fwt, lastCnt, tmp);
- st++;
- }
- }
- }
复制代码
输出示例 b=30070Hz Cnt=13116 calc=24983Hz
|