1

我想弄清楚如何为我的 C8051F020 MCU 创建一个计时器。以下代码使用通过init_Timer2()以下公式传递给的值:

65535-(0.1 / (12/2000000)=48868。

我将计时器设置为每次执行时计数,每计数 10 次,计数一秒。这是基于上面的公式。传递给 48868 时init_Timer2会产生 0.1 秒的延迟。每秒需要十个。但是,当我测试计时器时,它有点快。在 10 秒时计时器报告 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++;
        }
}
4

4 回答 4

1

打开此特定微控制器的数据表并查找计时中断。了解如何每 n ms 发出一次中断。通常计算公式取决于时钟速度,并且通常在特定微控制器的数据表/编程指南中进行描述。

于 2012-10-17T07:41:05.057 回答
1

您的代码中可能没有任何内容导致问题。

您假设内部振荡器正好是 2Mhz。很可能,您的微信不存在。如果您查看数据表的容差,您会看到配置为 2Mhz 时,指定的最小值为 1.5Mhz,最大值为 2.4Mhz。因此,您可以在预期频率的 75% 到 120% 之间的任何地方运行。(这通常也会随着温度而变化......)

因此,您在计数器中看到的 10% 错误可能只是硬件。

你有第二个微可以将你的代码刷入吗?它的 osc 可能以不同的频率运行,并且可能会给您不同的时间感。

旁注:我建议更改

if(seconds % 60 == 0  && seconds != 0)
{
    minutes++;
}

if(seconds >= 60)
{
    seconds = 0;
    minutes++;
}

相等性检查的周期比模数更便宜,并且在第一分钟后不清除seconds您报告的秒数将是不正确的。

于 2012-10-17T13:28:45.740 回答
0

您正在使用内部振荡器。这是非常不准确的,而不是 2 mhz。

于 2012-10-17T16:56:58.320 回答
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;
}

从我的测试来看,这是非常准确的。

于 2012-10-17T21:00:04.660 回答