微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 ATmega48PA 中断时的未定义行为

如何解决使用 ATmega48PA 中断时的未定义行为

我正在构建一个简单的定时器/计数器应用程序,它使用 Atmel 的 ATmega48PA 中的正常模式产生延迟,使用 Timer1,以恒定时间间隔切换 LED。使用中断时会发生什么情况,LED 切换一定时间,然后切换效果停止,保持 LED 始终亮起! 我相信 sei() 函数或在 SREG 中启用全局中断是有问题的,因为我之前在使用中断时在同一个微控制器上遇到过这种行为。

这是我的问题提供的代码片段,尽管任何人都会认为此代码非常正常并且必须正常工作!

#include <avr/io.h>
#include <atmel_start.h>
#include <util/delay.h>
#include <math.h>
#include <clock_config.h>
#include "avr/iom48pa.h"

#define LOAD_VALUE      49911UL

#define SET_BIT( REG,BIT )                 REG |= ( 1 << BIT )
#define CLR_BIT( REG,BIT )                 REG &= ~( 1 << BIT )
#define TOG_BIT( REG,BIT )                 REG ^= ( 1 << BIT )

void Timer16_Init( void );
void Timer16_DelayMS( unsigned short delayMS );

unsigned short delayMS = 50;

ISR( TIMER1_OVF_vect ){
    disable_global_interrupt();
    TOG_BIT( PORTC,2 );
    TOG_BIT( PORTC,3 );
    TCNT1 = ( ( 4194304 - delayMS ) * 1000 ) / 64;
    Enable_global_interrupt();
}

int main( void ){
    
    /* Initializes MCU,drivers and middle ware */
    atmel_start_init();
     
     /* configure pin 2 and pin 3 in PORTC as output */
     SET_BIT( DDRC,3 );
     SET_BIT( DDRC,2 );
     
     Enable_global_interrupt();
     Timer16_Init();
     TCNT1 = ( ( 4194304 - delayMS ) * 1000 ) / 64;

    while( 1 ){
        
    }
}
void Timer16_Init( void ){
    SET_BIT( TCCR1B,CS10 );
    SET_BIT( TCCR1B,CS12 );
    SET_BIT( TimsK1,TOIE1 );
}

我只想知道,这里到底发生了什么?!

解决方法

乍一看,你的代码没有什么特别的问题。因此,让我们检查一下可能性:

首先您已经完成了一些 32 位长的计算并将结果放入 16 位寄存器:

TCNT1 = ( ( 4194304 - delayMS ) * 1000 ) / 64; 它会导致一个不可预测的值被输入到寄存器中。所以我建议您使用适当的值或在您的代码中使用 (long) 和 (int) 以防止数据溢出。

第二您没有输入正确的数据行顺序:

Enable_global_interrupt();
Timer16_Init();
TCNT1 = ( ( 4194304 - delayMS ) * 1000 ) / 64;

您启用中断,然后初始化计时器,然后应用计时器的值。这是不正确的,因为计时器运行并能够进行中断,但尚未设置其值。顺序必须是这样的:

TCNT1 = ( ( 4194304 - delayMS ) * 1000 ) / 64;    
Enable_global_interrupt();
Timer16_Init();

第三您在正常模式下使用了定时器,进入溢出中断并在中断例程中设置定时器值。我强烈建议您改用比较模式,因为它不需要在中断例程中设置定时器值。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。