我正在试图弄清楚如何为我的C8051F020 MCU创建一个定时器。以下代码使用传递给init_Timer2()
的值,其公式如下:
65535-(0.1 /(12/2000000)= 48868。
我将计时器设置为每次执行计数,每10次计数,计数一秒。这是基于上面的公式。 48868传递给init_Timer2
时会产生0.1秒的延迟。每秒需要十个。但是,当我测试计时器时,它有点快。在十秒钟时,计时器报告11秒,在20秒时计时器报告22秒。我想尽可能接近完美的秒。
这是我的代码:
#include <compiler_defs.h>
#include <C8051F020_defs.h>
void init_Clock(void);
void init_Watchdog(void);
void init_Ports(void);
void init_Timer2(unsigned int counts);
void start_Timer2(void);
void timer2_ISR(void);
unsigned int timer2_Count;
unsigned int seconds;
unsigned int minutes;
int main(void)
{
init_Clock();
init_Watchdog();
init_Ports();
start_Timer2();
P5 &= 0xFF;
while (1);
}
//=============================================================
//Functions
//=============================================================
void init_Clock(void)
{
OSCICN = 0x04; //2Mhz
//OSCICN = 0x07; //16Mhz
}
void init_Watchdog(void)
{
//Disable watchdog timer
WDTCN = 0xDE;
WDTCN = 0xAD;
}
void init_Ports(void)
{
XBR0 = 0x00;
XBR1 = 0x00;
XBR2 = 0x40;
P0 = 0x00;
P0MDOUT = 0x00;
P5 = 0x00; //Set P5 to 1111
P74OUT = 0x08; //Set P5 4 - 7 (LEDs) to push pull (Output)
}
void init_Timer2(unsigned int counts)
{
CKCON = 0x00; //Set all timers to system clock divided by 12
T2CON = 0x00; //Set timer 2 to timer mode
RCAP2 = counts;
T2 = 0xFFFF; //655535
IE |= 0x20; //Enable timer 2
T2CON |= 0x04; //Start timer 2
}
void start_Timer2(void)
{
EA = 0;
init_Timer2(48868);
EA = 1;
}
void timer2_ISR(void) interrupt 5
{
T2CON &= ~(0x80);
P5 ^= 0xF0;
timer2_Count++;
if(timer2_Count % 10 == 0)
{
seconds++;
}
if(seconds % 60 == 0 && seconds != 0)
{
minutes++;
}
}
答案 0 :(得分:1)
打开此特定微控制器的数据表并查找时间戳中断。 了解如何每n ms发出一次中断。 通常用于计算的公式取决于时钟速度,并且通常在特定微控制器的数据表/编程指南中进行描述。
答案 1 :(得分:1)
您的代码中可能没有任何内容导致问题。
您假设内部振荡器正好在2Mhz。最有可能的是,你的微观不存在。如果你查看数据表的公差,你会发现当配置为2Mhz时,规格的最小值为1.5Mhz,最大值为2.4Mhz。因此,您可以在预期频率的75%到120%之间运行。 (这通常也随温度而变化......)
因此,您在计数器中看到的10%错误可能只是硬件。
你有第二个micro来刷你的代码吗?它的osc可能以不同的频率运行,可能会给你一种不同的时间感。
旁注:我建议更改
if(seconds % 60 == 0 && seconds != 0)
{
minutes++;
}
到
if(seconds >= 60)
{
seconds = 0;
minutes++;
}
等式检查在周期中比模数更便宜,并且在没有清除{1}的情况下,您报告的秒数在第一分钟后将不正确。
答案 2 :(得分:0)
您正在使用内部振荡器。这是非常不准确的,而不是2 mhz。
答案 3 :(得分:0)
我无法回答这个问题。每个人都贡献了我最终使用22.1184Mhz的外部时钟。以下代码片段是原始邮政编码的部分,已更改为使其起作用:
void init_Clock(void)
{
OSCXCN = 0x67; //External 22.1184Mhz
while ( !(OSCXCN & 0x80) );
OSCICN = 0x88;
}
和
void start_Timer2(void)
{
EA = 0;
//External clock
init_Timer2(47103);
EA = 1;
}
从我的测试来看,这是非常准确的。