打印

本人新手,有些问题解决不了,坛子里的高手帮看看。

[复制链接]
1743|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ll_211314|  楼主 | 2009-12-8 13:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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();
   
}
}

相关帖子

沙发
救火车| | 2009-12-8 15:22 | 只看该作者
实在晕,搞这么一堆程序,连个注释都没有。。。怎么看啊

使用特权

评论回复
板凳
ll_211314|  楼主 | 2009-12-8 19:24 | 只看该作者
经版主提醒,加了一些注释。

使用特权

评论回复
地板
xlsbz| | 2009-12-8 19:28 | 只看该作者
把 传送的速度放慢  关100次机, 看有几次有问题?

我感觉是不是..........:dizzy:

使用特权

评论回复
5
ll_211314|  楼主 | 2009-12-9 07:44 | 只看该作者
我关机大概平均三次就出现一次这样的问题,刚开始工控机没接地,几乎每次都这样;后来工控机接地了,就平均三次出现一次。

应该可以肯定有东西通过串口影响了程序,但是本人能力实在有限,加上公司也没什么工具(只有万用表),看不出什么。

使用特权

评论回复
6
84335262| | 2009-12-9 10:06 | 只看该作者
可能是串口接收有啥问题导致直接在里面转悠不出来。加狗是重新启动出来的。如果你觉得显示很重要,可以把显示丢定时器里显示,一进串口中断以后就先开一下中断允许。其实你的显示只要置一下位就可以了,一两个微秒的事,这点时间应该不会影响到下一个字符数据的接收的。这样的话就不需要重新启动。

使用特权

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

本版积分规则

10

主题

38

帖子

0

粉丝