在C中实现/模拟具有20Mhz时钟和1024预分频器的16位计数器

时间:2016-03-02 07:59:10

标签: c timer counter atmega

我希望(粗略地)用C模拟Atmega128的T / C1 这是一个16位计数器,时钟频率为20MHz(F_CPU)。我想要一个1024的预分频(CLOCK_PRESCALER)。

我目前的实施如下:

// Simulate 16bit counter with a 16MHz clock and prescale of 1024 (as mega128)
// The counter overflows every 65 536* 1024/20M= 3.3554432s or 3355.4432 ms or 3355443.2us or 3 355 443 200 ns
UInt32 getClock(void){

    UInt32 curr_clock_time_us;
    UInt32 diff;
    UInt32 unscaled_clock;
    UInt32 scaled_clock;
    struct timespec temp;

    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &temp);
    curr_clock_time_us = temp.tv_nsec/1000;

    diff = curr_clock_time_us - prev_clock_time_us;

    //represents timer overflows, which happens every 4194304000 ns.
    if(diff > ((UInt32)3355443)){
        prev_clock_time_us = curr_clock_time_us; // on overflow the counter (here the  diff) should be 0 if we asked it immediately again.
        unscaled_clock = (diff % ((UInt32)3355443));
    } else {
        unscaled_clock = diff;
    }

    //Scale to count value: time
    scaled_clock = unscaled_clock * F_CPU  / CLOCK_PRESCALER * 1/1000 * 1/1000;

    return scaled_clock;
}

Uint32是一个typedef unsigned long。

prev_clock_time_us在board_init()初始化为

    //Starts the clock by registering current time, down to microseconds
struct timespec temp;

clock_gettime(CLOCK_MONOTONIC, &temp);
prev_clock_time_us = temp.tv_nsec/1000;

要测试此代码,我会不断将其打印出来。 我期望或希望看到的是从0开始的时钟 - > 65536 - > 0大约3.355s。

相反,我的打印输出显示的是从0开始的时钟 - > ~20000 - > 0。 这很奇怪。只是打印,例如,curr_clock_time_us似乎该值从0 - >; 1.000.000 - > 0

显示“CLOCKS_PER_SEC需要100万”,但我不确定这是否相关。

所以任何线索我做错了什么?我完全不确定。

1 个答案:

答案 0 :(得分:0)

curr_clock_time_us = tv_nsec / 1000是以微秒为单位的时间,总是<= 1.000.000 us = 1 s

你虽然必须使用tv_sec来计算超过一秒的时差。

#include <iostream>
#include <time.h>
#include <unistd.h>

#define F_CPU 16000000
#define CLOCK_PRESCALER 1024

using namespace std;

time_t prev_clock_time_s;
long prev_clock_time_us;

uint32_t getCounter(void){

    long diff;

    struct timespec temp;

    clock_gettime(CLOCK_REALTIME, &temp);

    diff = ((temp.tv_sec - prev_clock_time_s) * 1000000) + ((temp.tv_nsec/1000) - prev_clock_time_us);

    return (diff % 3355443l) * 65536l / 3355443l;
}

int main()
{
    struct timespec temp;

    clock_gettime(CLOCK_REALTIME, &temp);
    prev_clock_time_s = temp.tv_sec;
    prev_clock_time_us = temp.tv_nsec/1000;
    for (int i = 0; i < 20; i++)
    {
        uint32_t cnt = getCounter();
        std::cout << "counter_value: " << cnt << " time: " << (cnt * 3.3554432 / 65536) << std::endl;
        usleep(300000);
    }
}