Attiny204 上意外的定时器/计数器 B 中断频率

问题描述 投票:0回答:1

我正在尝试使用 Microchip studio 中的定时器/计数器 B 在 Attiny204 上实现计时系统,但根据我的寄存器和熔丝设置,我得到了非常意外的中断频率。

我将

OSCCFG.FREQSEL
保险丝设置为 20Mhz 时钟,我正在使用以下两行初始化时钟控制器,这应该给我一个 20Mhz
CLK_CPU
和 312.5Khz
CLK_PER

CLKCTRL.MCLKCTRLA = CLKCTRL_CLKSEL_OSC20M_gc; //Select internal 20Mhz oscillator
CLKCTRL.MCLKCTRLB = CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm; //Set peripheral clock to 1/64th of CPU clock

我正在使用以下几行初始化计时器/计数器 B 模块:

TCB0.CCMP = MATCH_VALUE; //Some value such that we get 1000 interrupts per second
TCB0.CTRLB = TCB_CNTMODE_INT_gc; //Periodic interrupt mode
TCB0.EVCTRL = TCB_CAPTEI_bm; //Enable input capture event (probably not needed)
TCB0.CTRLA = TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm; //Use CLK_PER not CLK_PER/2 and enable timer
TCB0.INTCTRL = TCB_CAPT_bm; //Enable interrupt

根据我在数据表中读到的内容,在周期性中断模式下,计时器计数直到其值与

TCB0.CCMP
匹配,然后触发中断,并从零开始再次计数。中断处理程序只是增加主时间戳
uint16_t
并打开和关闭引脚,以便我可以使用逻辑分析仪读取中断频率,并清除中断标志。

ISR(TCB0_INT_vect){
    if(++master & 1)
        VPORTA.OUT &= ~_BV(4);
    else
        VPORTA.OUT |= _BV(4);
    TCB0_INTFLAGS = TCB_CAPT_bm; //Clear the flag that triggered this interrupt
}

根据我的理解,

MATCH_VALUE
的正确值应该是20000000/64/1000,大约是312,但是这个值给我的中断频率约为10.6Khz。

我从实验中发现 3360 (0xD20) 给了我几乎完全相同的 1Khz 信号,但我无法根据设置弄清楚这在数学上有何意义。

我最初以为我的微控制器已损坏,时钟速度错误,但我在新芯片上尝试了固件并得到了相同的行为。

我的代码或数学有什么问题?使用我的实验价值是否安全,或者我是否做了一些会导致其他问题的事情?

c avr-gcc atmelstudio attiny
1个回答
0
投票

我错过了数据表中的一部分,其中提到

CLKCTRL.MCLKCTRLA
CLKCTRL.MCLKCTRLB
是写保护的,因此写入这些寄存器会被 CPU 默默忽略,默认的
CLK_CPU
->
CLK_PER
预分频器值为 6正在使用而不是我的数学计算所基于的预期值 64。

CPU_CCP = 0xD8; //Unprotect CLKCTRL.MCLKCTRLA
CLKCTRL.MCLKCTRLA = CLKCTRL_CLKSEL_OSC20M_gc; //Select internal 20Mhz oscillator
CPU_CCP = 0xD8; //Unprotect CLKCTRL.MCLKCTRLB
CLKCTRL.MCLKCTRLB = CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm; //Set peripheral clock to 1/64th of CPU clock

插入这两行之后,频率就达到了我的预期。

© www.soinside.com 2019 - 2024. All rights reserved.