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

2019-03-24 20:19发布

本人写了一个程序,主要是在定时器1中每20ms监控外界端口IO状态,当IO口状态发生变化时,在定时器内把数据存到数组中,然后作标志位,主程序不停查询该标志位,当标志位为1时,通过串口把数组的数据发送出去。但是在长期工作后(不定时,长达几天几个月都可能)发现程序会出问题,本来串口发送数据只会是在定时器监控的IO口发生变化后才会发生,可是出问题后,主程序会一直往串口发送数据,此时还能进入定时器中断,当IO检测状态改变时,串口数据也改变的。出问题后数据可能是不停地重复发数组内的数据,有时候只会发送数组的一部分数据。下面大概写出程序的内容,不是原代码,求分析可能原因。ISR(time1) //忘记是不是这样了
{
       此处重装初值20ms
       if{PORTA!=pastPORTA}
       {
                for(i=0;i<15;i++)
                        table[i]=某逻辑计算后的值;
               mark=1;
        }
}


int main(void)
{
while(1)
{
        if(mark==1)
       {
              mark=0;
             for{i=0;i<15;i++}
             {
                     Uartsend_oneBit(table[i]);//往串口发送数据
              }
        }
}
}
出问题时现象为串口不停发送table[]的数据,多数为table[0]到table[14]的数据,但有时候没有table[0],是从table[1】开始的,有时候甚至会有乱码。但此时定时器中断能进,加入看门狗在主程序喂狗解决不了该问题,用16M晶振,熔丝位是FE,09,3F.详细程序明天上传。
此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
4条回答
Eezzj
1楼-- · 2019-03-25 01:29
原代码来了,里面加入了好多冗余标志位,但没效。
#include<avr/io.h>
#include<avr/iom128.h>
#include<avr/interrupt.h>
#include <avr/wdt.h>
#define CLI() do { __asm__ __volatile__ ("cli"); } while (0)
#define SEI() do { __asm__ __volatile__ ("sei"); } while (0)
#define NOP() do { __asm__ __volatile__ ("nop"); } while (0)
#define uchar unsigned char
#define uint  unsigned int

volatile uchar wdt1=1;
volatile uchar RE_rcorrect[128]; //正确接收到的新码;
volatile uchar wdt2=1;
//------------------------
volatile uchar RD_count;
volatile uchar Rdata;
volatile uchar usart0_Rbuff[128];  //接收缓冲器
volatile uchar usart0_REflag=0;
volatile uchar usart0_RSflag=0;
volatile uchar wdt3=1;
volatile uchar send_flag=0;
volatile uchar send_Tflag=0;
volatile uchar Send_buff[128];  //发送缓冲器
volatile uchar REtime=0;
volatile uchar RecDataBCC=0;
volatile uchar IN_BCC=0;
volatile uchar OUT_BCC=0;
volatile uchar Send_buff[128];  //发送缓冲器
volatile uchar wdt4=1;
volatile   uchar  temA=0;
volatile   uchar  temB=0;
volatile   uchar  temA1=0;
volatile   uchar  temB1=0;
volatile uchar Send_buff[128];  //发送缓冲器
volatile   uchar  PasttemA=0;
volatile   uchar  PasttemB=0;
volatile   uchar  passmark=0;
volatile   uchar  passcount=0;
volatile uchar wdt5=1;
volatile uchar Send_tem[128];  //T发送缓冲器
void usart0_send(uchar sdata);
void String_send(uchar *p,uchar Lenth);

volatile uchar wdt6=1;

volatile uchar  t1=0;
volatile uchar  t2=0;
volatile uchar  t3=0;
volatile uchar  t4=0;
volatile uchar usart0_ST1buff[128];  //T发送缓冲器

volatile uchar send_INmark=0;
volatile uchar send_OUTmark=0;





void timer1_init(void)
{
        TCCR1A=0x00;      //普通模式,不与OCnA相连。
        TCCR1B=0x03;          //Clk/64       
        TCCR1C=0x00;          //不设置强制输出通道
       
        TCNT1H=0xEC;           //定时20ms=次数/每秒次数=(FFFF-初值)/(F_CU/分频)
        TCNT1L=0x77;
       
//        TCNT1H=0xF6;           //定时10ms=次数/每秒次数=(FFFF-初值)/(F_CU/分频)
//        TCNT1L=0x3B;
        TIMSK|=_BV(TOIE1);//使能定时器1;
}


       
ISR(SIG_OVERFLOW1)//定时器1中断
{
                uchar  i=0;
                NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();
                wdt1=0;
                TCNT1H=0xEC;           //定时20ms=次数/每秒次数=(FFFF-初值)/(F_CU/分频)
                TCNT1L=0x77;


       //--------------------------------------
                if(REtime<=0)    //串口接收超时丢弃。
                {
                        usart0_RSflag=0;       
                }
                else
                {
                        REtime--;
                }               
               
               
                 
                temA=PINA;
                temB=PINB&0x0f;
                NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();
                temA1=PINA;
                temB1=PINB&0x0f;
                if((temA==temA1)&&(temB==temB1))
                {
                        IN_BCC=0;
                        Send_tem[0]=0x02;       
                        IN_BCC=0x42;
                    Send_tem[1]=0x42;
                        for(i=0;i<8;i++)
                        {
                                if(((temA>>i)&0x01)==0x01)
                                {
                                        Send_tem[2+i]=0x30;               
                                }
                                else
                                {
                                        Send_tem[2+i]=0x31;       
                                }
                                IN_BCC=IN_BCC^Send_tem[2+i];       
                        }
                        for(i=0;i<4;i++)
                        {
                                if(((temB>>i)&0x01)==0x01)
                                {
                                        Send_tem[10+i]=0x30;               
                                }
                                else
                                {
                                        Send_tem[10+i]=0x31;       
                                }
                                IN_BCC=IN_BCC^Send_tem[10+i];       
                        }
                        Send_tem[14]=IN_BCC;
                        Send_tem[15]=0x03;       
                       
                        if((PasttemA!=temA)||(PasttemB!=temB))
                        {
                       
                                 PasttemA=temA;
                                 PasttemB=temB;       
                 send_Tflag=1; //注销这一行即可取消主动反馈
                                 send_INmark=1;//注销这一行即可取消主动反馈

                        }
                                               
               
                }       
        wdt1=1;                 
}



void usart0_init()
{
        UCSR0B=0x00; //close USART
        UCSR0A=0x00;
        UCSR0C=0x06;
        UBRR0H=0x00;
        UBRR0L=0x67;
        UCSR0B=0xd8;          //open USARTd8       
}

ISR(USART0_TX_vect)
{
        NOP();
        UCSR0A |= (1<<6);                      //发送结束清零
}




void usart0_send(uchar sdata)
{
        NOP();NOP();NOP();NOP();

        if((sdata!=0x02)&&(sdata!=0x30)&&(sdata!=0x31)&&(sdata!=0x42)&&(sdata!=0x43)&&(sdata!=0x44)&&(sdata!=0x45)&&(sdata!=0x03))
        {
                wdt6=0;
    }
    else
        {
                //wdt6=1;
                while(!(UCSR0A&(1<<UDRE0)));
                 UDR0=sdata;
    }
        NOP();NOP();NOP();NOP();
        // while(!(UCSR0A&(1<<TXC0)));
    // UCSR0A |= _BV(TXC0);         
}



ISR(USART0_RX_vect)  //按协议存储除了命令头02和结束03之外的所有数据
{   
       
        NOP();NOP();NOP();NOP();
        wdt2=0;
        if(RXC0)   //接收到数据
        {
          REtime=50;//1没接收完命令将丢弃,定时器中1s后usart0_RSflag=0;
          Rdata=UDR0;         //提取数据         
          if(Rdata==0x02)        //命令头
           {
                 usart0_RSflag=1;//符合协议开始接收
                 RD_count=0;     //接收个数计数
                 RecDataBCC=0;         //初始化BCC校验值       
           }
          else if(usart0_RSflag)       
           {     
                     if((Rdata==0x03)&&(RecDataBCC==0)) //如果收到03并且BCC校验正确
                          {
                                    usart0_RSflag=0;                        //结束接收
                                        if(usart0_Rbuff[0]==0x43)   //输出命令
                                        {
                                            for(uchar i=0;i<14;i++)       
                                                         RE_rcorrect[i]=usart0_Rbuff[i];
                                                usart0_REflag=1;
                                                send_OUTmark=1;                       
                                        }
                                        else if(usart0_Rbuff[0]==0x41) //输入命令
                                        {
                                                send_Tflag=1;
                                                send_INmark=1;               
                                        }
                          }
                          else if((Rdata==0x03)&&(RecDataBCC!=0))//校验不正确
                          {
                                           usart0_RSflag=0;
                                          RD_count=0;     
                                          RecDataBCC=0;                                                   
                          }       
                          else
                          {
                                     usart0_Rbuff[RD_count++]=Rdata;  //存储数据
                                         RecDataBCC=RecDataBCC^Rdata;         //        BCC校验                   
                          }
           }

          if(RD_count>14)  //定长,收到命令头后只存14个数据,超出长度也不符合协议
                  {
                  usart0_RSflag=0;        //重新开始接收
                }
        }
        wdt2=1;
}




void usart0_handle(void)
{
  uchar i;
  wdt3=0;
  switch(RE_rcorrect[0])
   {   
//-----------------------设置码 12路状态设置-------------------------------
        case 0x43:
          switch(RE_rcorrect[1])
           {
            case 0x30: PORTB&=~(1<<PB4);
                          break;
                case 0x31: PORTB|=(1<<PB4);
                          break;
                default:  break;
           }
          switch(RE_rcorrect[2])
           {
            case 0x30: PORTB&=~(1<<PB5);
                          break;                
                case 0x31: PORTB|=(1<<PB5);
                          break;
            default:  break;                                 
           }
          switch(RE_rcorrect[3])
           {
            case 0x30: PORTB&=~(1<<PB6);
                          break;        
                case 0x31: PORTB|=(1<<PB6);
                          break;        
                default:  break;
           }  
          switch(RE_rcorrect[4])
           {
            case 0x30: PORTB&=~(1<<PB7);
                          break;        
                case 0x31: PORTB|=(1<<PB7);
                          break;
                default:  break;
           }
          switch(RE_rcorrect[5])
           {
            case 0x30: PORTC&=~(1<<PC2);
                  break;        
                case 0x31: PORTC|=(1<<PC2);
                  break;        
                default:  break;
           }
          switch(RE_rcorrect[6])
           {
            case 0x30: PORTC&=~(1<<PC3);
                  break;
                case 0x31: PORTC|=(1<<PC3);
                  break;
                default:  break;
           }   
          switch(RE_rcorrect[7])
           {
            case 0x30: PORTC&=~(1<<PC4);
                          break;
                case 0x31: PORTC|=(1<<PC4);
                          break;
                default:  break;
           }
          switch(RE_rcorrect[8])
           {
            case 0x30: PORTC&=~(1<<PC5);
                          break;                
                case 0x31: PORTC|=(1<<PC5);
                          break;
            default:  break;                                 
           }
          switch(RE_rcorrect[9])
           {
            case 0x30: PORTC&=~(1<<PC6);
                          break;        
                case 0x31: PORTC|=(1<<PC6);
                          break;        
                default:  break;
           }  
          switch(RE_rcorrect[10])
           {
            case 0x30: PORTC&=~(1<<PC7);
                          break;        
                case 0x31: PORTC|=(1<<PC7);
                          break;
                default:  break;
           }
          switch(RE_rcorrect[11])
           {
            case 0x30: PORTC&=~(1<<PC0);
                  break;        
                case 0x31: PORTC|=(1<<PC0);
                  break;        
                default:  break;
           }
          switch(RE_rcorrect[12])
           {
            case 0x30: PORTC&=~(1<<PC1);
                  break;
                case 0x31: PORTC|=(1<<PC1);
                  break;
                default:  break;
           }     
                         
         //--------------------------------
       OUT_BCC=0;
           Send_buff[0]=0x02;   
           Send_buff[1]=0x44;
           OUT_BCC=0x44;       
           for(i=0;i<12;i++)
           {
                    Send_buff[i+2]=RE_rcorrect[i+1];
                  OUT_BCC=OUT_BCC^RE_rcorrect[i+1];
       }
           Send_buff[14]=OUT_BCC;
           Send_buff[15]=0x03;                     
          // send_flag=1;
         //-------------------------------                  
  break;

  default:  break;


    }
        wdt3=1;          
}







//------------------------------
//IO
//------------------------------
void IO_iniaitil(void)
{
  DDRE=0xfe; //E口设成输出 11111110
  PORTE=0xff;

  DDRA=0x00;  //A口设成输入
  PORTA=0xff; //
  DDRB=0xF0;  //B口低四位设成输入,高四位为输出
  PORTB=0x0f; //
  
  DDRC=0xff;  //C口设成输出
  PORTC=0x00; //00000000

  wdt1=1;
  wdt2=1;
  wdt3=1;
  wdt4=1;
  wdt5=1;
  wdt6=1;

  
}
           

int main(void)
{  
   CLI();  
   IO_iniaitil();
   timer1_init();
   usart0_init();                 
   SEI();        //开总中断
   wdt_enable(WDTO_250MS); //启动开门狗250ms
   wdt_reset();//开始喂看门狗
   while(1)
    {
                 
                 if((send_Tflag==1)&&(send_INmark==1))//输入
                  {               
                                  wdt4=0;
                                  send_Tflag=0;
                                TIMSK&=~_BV(TOIE1);//关闭定时器中断
                                for(t1=0;t1<16;t1++)
                                {
                                        usart0_ST1buff[t1]=Send_tem[t1];
                }
                                TIMSK|=_BV(TOIE1);//使能定时器1中断;                
                                for(t2=0;t2<16;t2++)
                                {
                                           usart0_send(usart0_ST1buff[t2]);
                }
                                send_INmark=0;
                wdt4=1;               
                  }       


             if((usart0_REflag==1)&&(send_OUTmark==1))//输出       
              {
                             wdt5=0;
                           usart0_REflag=0;
                           usart0_handle();
                           for(t3=0;t3<16;t3++)
                           {
                                           usart0_send(Send_buff[t3]);
               }
                           send_OUTmark=0;
                           wdt5=1;
                  }

                 if((wdt1==1)&&(wdt2==1)&&(wdt3==1)&&(wdt4==1)&&(wdt5==1)&&(wdt6==1))
                 {
                            wdt_reset();//喂看门狗
                 }
   }
}
Eezzj
2楼-- · 2019-03-25 07:18
人呢?
Eezzj
3楼-- · 2019-03-25 12:22
0.0??
dj狂人
4楼-- · 2019-03-25 15:05
代码太长,没仔细看。异常的时候用示波器看看你监测的那个I/O引脚是个什么样的状态

一周热门 更多>