Implementing/simulating 具有 20Mhz 时钟和 1024 C 预分频器的 16 位计数器

Implementing/simulating 16bit counter with 20Mhz clock and 1024 prescaler in C

我正在寻找(粗略地)在 C 中模拟 Atmega128 的 Timer/Counter1 这是一个 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.355 秒。

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

查看发现 "CLOCKS_PER_SEC is required to be 1 million" 但我不确定这是否相关。

所以有什么线索是我做错了什么吗?我不确定。

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);
    }
}