打印
[其他产品]

atmega128长期工作后程序异常,求助!!

[复制链接]
971|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jcky001|  楼主 | 2025-4-14 16:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
写了一个程序,主要是在定时器1中每20ms监控外界端口IO状态,当IO口状态发生变化时,在定时器内把数据存到数组中,然后作标志位,主程序不停查询该标志位,当标志位为1时,通过串口把数组的数据发送出去。但是在长期工作后(不定时,长达几天几个月都可能)发现程序会出问题,本来串口发送数据只会是在定时器监控的IO口发生变化后才会发生,可是出问题后,主程序会一直往串口发送数据,此时还能进入定时器中断,当IO检测状态改变时,串口数据也改变的。出问题后数据可能是不停地重复发数组内的数据,有时候只会发送数组的一部分数据。下面大概写出程序的内容,不是原代码,求分析可能原因。ISR(time1) //忘记是不是这样了
{
       此处重装初值20ms
       if{PORTA!=pastPORTA}
       {
                for(i=0;i<15;i++)
                        table=某逻辑计算后的值;
               mark=1;
        }
}


int main(void)
{
while(1)
{
        if(mark==1)
       {
              mark=0;
             for{i=0;i<15;i++}
             {
                     Uartsend_oneBit(table);//往串口发送数据
              }
        }
}
}
出问题时现象为串口不停发送table[]的数据,多数为table[0]到table[14]的数据,但有时候没有table[0],是从table[1】开始的,有时候甚至会有乱码。但此时定时器中断能进,加入看门狗在主程序喂狗解决不了该问题,用16M晶振,熔丝位是FE,09,3F.详细程序明天上传。

使用特权

评论回复
沙发
gaoyang9992006| | 2025-4-14 18:55 | 只看该作者
根据您描述的问题现象和代码结构,可能存在以下几个潜在原因:

竞态条件(Race Condition):

mark变量在主循环和中断服务程序(ISR)中被共享访问,但没有保护机制

当主程序正在发送数据时(已将mark置0),如果此时发生中断将mark置1,可能导致状态混乱

改进建议:将mark声明为volatile并使用原子操作或禁用中断保护

数组越界或内存损坏:

如果table数组大小正好是15,而循环使用了i<=15,可能导致内存越界

检查所有数组访问是否在合法范围内

改进建议:使用sizeof(table)/sizeof(table[0])作为循环边界

串口发送阻塞:

如果Uartsend_oneBit是阻塞式发送且没有超时机制,可能在长期运行后因干扰导致卡死

改进建议:实现非阻塞串口发送或添加超时检测

堆栈溢出:

长期运行后可能导致堆栈逐渐增长最终溢出

改进建议:检查堆栈大小设置,增加堆栈溢出检测机制

看门狗复位不彻底:

虽然使用了看门狗,但可能没有完全覆盖所有异常情况

改进建议:在关键位置添加更多的看门狗喂狗点

熔丝位配置问题:

FE 09 3F配置中时钟源为外部晶振,但启动时间设置(默认为16K CK+64ms)可能需要调整

改进建议:检查SUT_CKSEL熔丝位设置是否适合您的硬件

中断嵌套问题:

如果允许中断嵌套,可能在处理串口发送时被其他中断打断

改进建议:在关键代码段禁用中断

使用特权

评论回复
板凳
gaoyang9992006| | 2025-4-14 18:56 | 只看该作者
试试下面的代码
volatile uint8_t mark = 0;  // 添加volatile修饰

ISR(TIMER1_OVF_vect) {
    // 重装初值20ms
    if(PORTA != pastPORTA) {
        uint8_t tmp[15];  // 使用临时缓冲区
        for(uint8_t i=0; i<15; i++) {
            tmp[i] = 某逻辑计算后的值;
        }
        
        // 禁用中断保护临界区
        cli();
        for(uint8_t i=0; i<15; i++) {
            table[i] = tmp[i];
        }
        mark = 1;
        sei();
    }
}

int main(void) {
    while(1) {
        wdt_reset();  // 喂狗
        
        if(mark) {
            cli();
            uint8_t local_mark = mark;
            mark = 0;
            sei();
            
            if(local_mark) {
                for(uint8_t i=0; i<15; i++) {
                    while(!UART_ready_to_send());  // 等待发送就绪
                    Uartsend_oneBit(table[i]);
                    wdt_reset();  // 长循环中喂狗
                }
            }
        }
        
        // 其他任务...
    }
}

使用特权

评论回复
地板
gaoyang9992006| | 2025-4-14 18:56 | 只看该作者
其他排查建议:

添加串口发送完成标志检查

在异常发生时记录状态信息到EEPROM

使用硬件CRC检查关键数据区完整性

考虑增加系统运行时间计数器,定期软复位

检查电源稳定性,劣质电源可能导致MCU异常

使用特权

评论回复
5
dffzh| | 2025-4-15 16:45 | 只看该作者
大概率是上面楼主说的问题:竞态条件(Race Condition)

使用特权

评论回复
6
xinxianshi| | 2025-4-18 15:48 | 只看该作者
也可能是硬件问题。最近我做了个东西,总是烧毁单片机,什么时候烧毁呢,我去动它  时候,不知道怎么暴力碰着了,就烧毁了。我怀疑是什么线的问题,或者板子上有锡膏残渣。

使用特权

评论回复
7
星空魔法师| | 2025-4-21 09:18 | 只看该作者
看起来像是定时器中断服务程序(ISR)中的逻辑问题。检查一下`if{PORTA!=pastPORTA}`的条件判断是否正确,确保`pastPORTA`在每次中断后都被更新。

使用特权

评论回复
8
瞌睡虫本虫| | 2025-4-21 12:23 | 只看该作者
看起来像是定时器中断服务程序中的状态检测逻辑有问题。检查一下`PORTA != pastPORTA`的条件是否正确,可能在某些情况下没有正确地重置`pastPORTA`。

使用特权

评论回复
9
迷雾隐者| | 2025-4-21 14:36 | 只看该作者
看起来像是定时器中断处理过程中的逻辑问题,可能是中断服务例程(ISR)中的代码没有正确处理状态变化,导致标志位`mark`被错误地设置。建议检查`if{PORTA!=pastPORTA}`的条件判断逻辑,确保每次IO状态变化时只设置一次`mark`。

使用特权

评论回复
10
暖茶轻语| | 2025-4-21 19:25 | 只看该作者
看起来你的程序可能存在一些潜在的问题。首先,检查你的定时器中断服务程序(ISR)是否正确地重新装载了初值,以确保定时器能够准确地每20ms触发一次。其次,考虑在中断服务程序中添加一些防抖动逻辑,以确保IO口状态的变化是稳定的。

使用特权

评论回复
11
穷得响叮当侠| | 2025-4-21 19:54 | 只看该作者
看起来像是定时器中断服务程序中存在逻辑错误,导致mark标志位被错误地设置。建议检查定时器中断服务程序中的逻辑,确保只有在IO口状态真正发生变化时才设置mark标志位。

使用特权

评论回复
12
yiyigirl2014| | 2025-4-21 20:47 | 只看该作者
长期工作,这个设定很难排错。

使用特权

评论回复
13
我是一颗胖蘑菇| | 2025-4-21 21:16 | 只看该作者
根据你的描述,可能是由于长时间运行导致某些寄存器或变量的值出现了异常。建议检查是否有可能的硬件问题,比如电源不稳定或者晶振频率漂移。同时,检查代码中是否有可能的逻辑错误或者溢出问题。

使用特权

评论回复
14
暖茶轻语| | 2025-4-21 22:33 | 只看该作者
根据你的描述,可能存在几个问题。首先,检查你的定时器中断服务例程(ISR)是否正确地重新加载了初值,以确保定时器能够以20ms的间隔触发中断。其次,考虑是否存在变量溢出或内存泄漏的问题,这可能会导致程序在长时间运行后出现异常。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1575

主题

5209

帖子

6

粉丝