本帖最后由 ll_211314 于 2009-12-8 19:22 编辑
avr m16的片子,单片机通过485电路接收从工控机发过来的数据,再把接收到的数据动态显示到led上。平时都挺正常,就是工控机关机的时候,原来视觉上一起显示的数变成了“跑马灯”的形式,把单片机复位了才好,也不是每次关机都这样。我怀疑是工控机关机时某种“干扰”使程序“跑飞”了,于是加了看门狗(下面的程序时已经加了看门狗的)。现在没有“跑马灯”的现象了,取而代之的复位,然后可以正常使用。现在在公司看情况还行,我怕到现场之后有持续的“干扰”就完蛋了。自己能力有限,所以请大家帮忙看看是什么造成了“跑马灯”的现象,如果是干扰的话,有帮忙看看程序的就更好了。
第一次弄,写的不好,嘴下留情。
除了void uart0_rx_isr(void)、void pwm(void)和void display(void)以外都是初始化。
//ICC-AVR application builder : 2009-12-8 8:58:49
// Target : M16
// Crystal: 4.8000Mhz
#include <iom16v.h>
#include <macros.h>
unsigned char temp,check,datadisp[4];
unsigned char num_code[20]={0XBF,0X86,0XDB,0XCF,0XE6,0XED,0XFD,0X87,0XFF,0XEF};
unsigned char receivedata[5];
unsigned char counter= 0;
unsigned char light;
void delay_ms(void)
{
unsigned int cnt;
for(cnt=0;cnt<255;cnt++);
}
void port_init(void)
{
PORTA = 0xFC;
DDRA = 0x00;
PORTB = 0x00;
DDRB = 0xFF;
PORTC = 0x00; //m103 output only
DDRC = 0x00;
PORTD = 0xFF;
DDRD = 0xFF;
}
//Watchdog initialize
// prescale: 16K
void watchdog_init(void)
{
WDR(); //this prevents a timout on enabling
WDTCR = 0x18;
WDTCR = 0x08; //WATCHDOG ENABLED - dont forget to issue WDRs
}
void uart0_init(void)
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = BIT(URSEL) | 0x26;
UBRRL = 0xF9; //set baud rate lo
UBRRH = 0x00; //set baud rate hi
UCSRB = 0x90;
}
//下面这段是串口接收中断,上位机发过来的数据是0c打头,后面是四个0-9的数。
先是校验,通过校验之后,数据通过单片机的缓冲区共单片机处理。
#pragma interrupt_handler uart0_rx_isr:12
void uart0_rx_isr(void)
{
//uart has received a character in UDR
unsigned char i;
check = UCSRA & 0X04; //校验。
if(!check)
{
temp = UDR; //读串口寄存器数据。
if(temp == 0x0c)
{
counter = 0;
receivedata[counter] = temp;
counter++;
}
else if((temp<=9)&&receivedata[0]==0x0c)
{
receivedata[counter]= temp;
counter++;
}
else
counter = 0;
if(counter == 5)
{
datadisp[0] = receivedata[1];
datadisp[1] = receivedata[2];
datadisp[2] = receivedata[3];
datadisp[3] = receivedata[4];
for(i=0;i<5;i++)
{
receivedata=0x00;
}
}
}
}
void timer2_init(void)
{
TCCR2 = 0x00; //stop
ASSR = 0x00; //set async mode
TCNT2 = 0x01; //setup
OCR2 = 0xFF;
TCCR2 = 0x69; //start
}
void spi_init(void)
{
SPCR = 0x50; //setup SPI
SPSR = 0x00; //setup SPI
}
//下面这段程序是通过 pwm调 led的亮度。
void pwm(void)
{
unsigned char switch1,switch2;
switch1 = PINA & 0X01;
switch2 = PINA & 0X02;
if((switch1==0)&&(switch2==0))
light = 0Xdf;
else if((switch1==0)&&(switch2!=0))
light = 0X9f;
else if((switch1!=0)&&(switch2==0))
light = 0X4f;
else
light = 0X0f;
}
void display(void)
{
unsigned char pp,p,q,j;
for(pp=0;pp<4;pp++)
{
p = datadisp[pp];
q = num_code[p] ;
OCR2 = 0XFF;
//CLEAR 595reg
PORTB &= ~BIT(6);//PORTB6的清零和置位是为spi提供上升沿。
delay_ms();
PORTB |= BIT(6);
//end clear 595reg
SPDR = q; //数据送给spi。
while(!(SPSR & 0X80));
PORTB &= ~BIT(4);//PORTB4的清零和置位是为spi提供上升沿。
delay_ms();
PORTB |= BIT(4);
OCR2 = light;
PORTB |= BIT(pp);//开 led的位选。
for(j=0;j<2;j++)
delay_ms();
PORTB &= 0Xf0;//关 led的位选。
}
}
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
watchdog_init();
uart0_init();
spi_init();
timer2_init();
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x00; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void main(void)
{
init_devices();
pwm();
while(1)
{
display();
WDR();
}
} |