本人写了一个程序,主要是在定时器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.详细程序明天上传。
此帖出自
小平头技术问答
#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();//喂看门狗
}
}
}
一周热门 更多>