在 ATtiny85 上的 Timer0 上启用 CTC 模式中断时出现奇怪的行为

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

我正在使用 ATtiny85 进行一个基于 C 构建的简单红外项目(用于 DSLR 相机的红外遥控器)。我在 CTC 模式下使用定时器 0 生成了一个 38.4 kHz 方波信号,并设置输出在每次定时器达到最大值时切换 PB0

OCRA
。我想使用定时器 0 比较单元生成的中断来计算它生成的周期数,因为计数器达到最大值两次以生成 38.4 kHz 方波的完整周期,对两个中断进行计数应指示完整的循环。 问题:我注意到每次调用
sei()
函数来启用全局中断时,生成的方波都会变形,并且永远不会调用关联的ISR。我使用示波器检查了 PB0 上生成的波形:

  • 在设置过程中不调用 sei() 函数: 生成的方波看起来符合预期。

  • 在设置过程中调用 sei(): 生成的方波有一些较长的脉冲。

我如何测试这个?

我实现了以下测试代码,如前所述配置定时器 0,并在每次检测到与定时器 0 的比较单元相关的中断时切换 PB1:

  • main.h
#ifndef MAIN_H
#define MAIN_H

#define __AVR_ATtiny85__
#define F_CPU 8000000UL

#endif
  • main.c
#include "main.h"
#include <avr/io.h>
#include <avr/interrupt.h>

int main(void)
{
    cli();
    DDRB |= _BV(PB0) | _BV(PB1);
    PORTB &= ~_BV(PB1);
    // Set general register to sync mode for configuration
    GTCCR |= _BV(TSM) | _BV(PSR0);
    // Default registers
    TCCR0A = 0; 
    TCCR0B = 0;
    TCNT0 = 0;
    TCCR0A |= _BV(COM0A0) | _BV(WGM01); // Set toggle on match and CTC mode
    TCCR0B |= _BV(CS00); // internal clock no-prescaling
    OCR0A |= 12; // For app 38,8kHz
    TIMSK |= _BV(OCIE0A);
    // Enable timer
    GTCCR &= ~_BV(TSM) & ~_BV(PSR0);
    // Enable global interrupts
    sei();  
    while(1);

}
// Demo interrupt service routine
ISR(TIMER0_COMPA_vect){
    PORTB ^= _BV(PB1);
}

编译我使用的代码

avr-gcc
,如下所示:

avr-gcc main.c -o main.elf -Wall -Wextra

编译器没有发出任何警告。然后我使用

avr-objcopy
来获取十六进制文件:

avr-objcopy -O ihex -j .text -j .data main.elf main.hex

最后我使用avrdude对IC进行了编程:

avrdude -p t85 -c usbtiny -B 125kHz -U flash:w:main.hex

保险丝是:

avrdude: safemode: Fuses OK (E:FF, H:DF, L:62)

我尝试了什么?

- 手动设置 SREG 寄存器:

sei()
行替换为:

SREG |= 1 << 7;

做了一些事情,但仍然不起作用。生成的方波看起来更好,但不符合预期,并且 ISR 没有对 PB1 执行任何操作。

- 替换 ISR 操作: 我虽然可能端口操作花费了很多时间,但是用

_NOP();
替换它对生成的方波的奇怪行为没有影响。

-尝试过其他 IC: 我有另一个 ATtiny85,并且表现相同。也许我有两个有缺陷的IC?

我不知道是否我配置错误,或者当我使用

sei()
启用中断时,IC 受到中断的轰炸而无法正常工作?

预先感谢您的任何提示或回复!

c microcontroller interrupt avr attiny
1个回答
0
投票

#define __AVR_ATtiny85__

不要摆弄工具链的内部宏。相反...

avr-gcc main.c -o main.elf -Wall -Wextra

...用

-mmcu=attiny85
进行编译和链接。如果缺少该选项,链接阶段将不会链接到启动代码
crtattiny85.o
,并且设置一些宏也无法解决该问题。

此外,如果没有

-mmcu=
,编译器将使用错误的 AVR 架构:在 avr-gcc 中,ATtiny85 是
avr25
,而默认值(没有
-mmcu=
)是
avr2
。请参阅 avr-gcc 机器相关选项

也可能是设备总是被watchdog定时器重置并从头开始的情况。因此,请检查 watchdock 是否正在服务或已停用(通过配置或熔断器)。

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