You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ATtiny 402 Timer 0中断周期异常问题排查求助

ATtiny402定时器中断周期不符问题排查

问题根源分析

你的实测周期与理论值不符,核心是时钟配置错误,具体如下:

1. 熔丝配置误解

ATtiny402的OSCCFG熔丝仅支持选择1/2/4/8MHz内部时钟,无法通过熔丝设置16/20MHz。你设置的OSCCFG = 0x02实际对应4MHz时钟,而非你认为的20MHz。20MHz时钟必须通过寄存器配置启用。

2. 主时钟配置错误

你的clk_conf()函数中:

CLKCTRL.MCLKCTRLA = 0b00000000 ;

该设置会让主时钟遵循熔丝OSCCFG的配置(即4MHz),而非20MHz。要启用20MHz内部时钟,需将CLKCTRL.MCLKCTRLA的FREQSEL位设为0101(对应20MHz),正确代码为:

CLKCTRL.MCLKCTRLA = 0x50; // 二进制01010000,FREQSEL=0101对应20MHz

3. 定时器时钟源配置错误

你的timer0_init()函数中:

TCA0.SINGLE.CTRLA = 0b00000001 ;

TCA0.SINGLE.CTRLA的bit3-1是CLKSEL时钟选择位,当前设置为000,对应无时钟输入,定时器本应停止运行。要选择主时钟作为定时器时钟源,需将CLKSEL设为001(对应CLK_PER主时钟),正确代码为:

TCA0.SINGLE.CTRLA = 0b00000011; // ENABLE=1,CLKSEL=001(主时钟)

4. 冗余代码(不影响周期,但可优化)

ISR中的TCA0.SINGLE.CNT = 0是多余操作:定时器溢出后会自动将CNT寄存器清零,无需手动设置。

修正后代码

#include <avr/io.h>
#include <avr/interrupt.h>

FUSES = {
    .WDTCFG = 0x00, // WDTCFG {PERIOD=OFF, WINDOW=OFF}
    .BODCFG = 0x00, // BODCFG {SLEEP=DIS, ACTIVE=DIS, SAMPFREQ=1KHz, LVL=BODLEVEL0}
    .OSCCFG = 0x00, // 熔丝设为1MHz,后续通过寄存器切换为20MHz
    .TCD0CFG = 0x00, // TCD0CFG {CMPA=CLEAR, CMPB=CLEAR, CMPC=CLEAR, CMPD=CLEAR, CMPAEN=CLEAR, CMPBEN=CLEAR, CMPCEN=CLEAR, CMPDEN=CLEAR}
    .SYSCFG0 = 0xC4, // SYSCFG0 {EESAVE=CLEAR, RSTPINCFG=UPDI, CRCSRC=NOCRC}
    .SYSCFG1 = 0x07, // SYSCFG1 {SUT=64MS}
    .APPEND = 0x00, // APPEND {APPEND=User range:  0x0 - 0xFF}
    .BOOTEND = 0x00, // BOOTEND {BOOTEND=User range:  0x0 - 0xFF}
};

LOCKBITS = 0xC5; // {LB=NOLOCK}


void io_set(void){
    PORTA.DIR = 0b01000000 ;   // PA6设为输出
    PORTA.PIN1CTRL = 0b0001000  ;  // PA1上拉(无关配置)
}

void clk_conf(void){
    CLKCTRL.MCLKCTRLA = 0x50 ;  // 启用20MHz内部时钟
    CLKCTRL.MCLKCTRLB = 0b00000000 ;  // 禁用主时钟预分频器
}

void timer0_init(){
    TCA0.SINGLE.CTRLA = 0b00000011 ;// 启用定时器,时钟源为主时钟CLK_PER
    TCA0.SINGLE.CTRLB = 0b00000000 ;// 普通模式
    TCA0.SINGLE.PER    = 30000;    // TOP值设为30000
    TCA0.SINGLE.INTCTRL = 0b00000001; // 启用溢出中断
}

void en_global_int(){
    sei(); // 直接用sei()启用全局中断,无需操作SREG
}

int main(void)
{
    clk_conf() ; 
    io_set() ; 
    en_global_int() ; 
    timer0_init() ;
    while (1){

    }
}


ISR(TCA0_OVF_vect){
    TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm; // 清除中断标志
    PORTA.OUT ^= 0b01000000 ; // 翻转PA6输出
}

验证修正效果

修正后,主时钟为20MHz,定时器时钟源为20MHz,TOP=30000,理论中断周期为:
30000 * (1/20000000) = 1.5ms
与你的预期一致,示波器实测值应接近该数值。

内容的提问来源于stack exchange,提问作者BeamString

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 21:39:18