打印
[AVR单片机]

奇怪,要延时17毫秒以上才能把数据全发出去,为什么?

[复制链接]
3136|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ronanoo|  楼主 | 2007-9-17 16:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以前从来没有遇到过这个怪事。 
使用的上MEGA48V,PB0通过一个反相器控制485的收发。设置485为发,延时1毫秒,发数据,延时1毫秒,设置485为收,却发现总是少两个字节没发出去(监控端口收不到最后两个字节)。把发数据后的延时改为17毫秒及以上,才能完整地把数据发出去。 
MEGA48V的通讯以前也用过,通讯也没有这个问题,这回不知道什么原因,难道是字节发送函数中,每个字节都要17毫秒/2的时间才能发出去,所以不延时17毫秒就会丢数据? 

void send_byte(uchar buf_to_send) //发送采用查询方式  字节发送函数 

        while( !(UCSR0A & (1<<UDRE0)) ); 
        UDR0=buf_to_send; 


void send(void)  /*发送函数*/ 

   uchar i;  
      
    
           //PB0通过一反相器控制485的收发,高经过反相后为低,接收,低,经过反相后为高,发送 
   DDRB |= (1 << PB0);//设置PB0为输出.  
   PORTB &= ~(1 << PB0);//PB0输出低电平 ,485发 
   _delay_ms(1); 
   。 
   。 
   。 
   。 
   。 
   。 
     for(i=0;i<(buf_send[9]+12);i++)/*发送*/ 
     { 
      send_byte(buf_send); 
      } 

  _delay_ms(20);   //最少要延时17及以上,否则为17时,最后一个就不完整,比15少的话会丢数据。   
    
           //PB0通过一反相器控制485的收发,高经过反相后为低,接收,低,经过反相后为高,发送 
   DDRB |= (1 << PB0);//设置PB0为输出.  
   PORTB |= (1 << PB0);//PB0输出高电平 ,485收 
              

原因正在查找中,哪位知道,不妨指点一二。 

相关帖子

沙发
xwj| | 2007-9-17 16:34 | 只看该作者

当然

使用特权

评论回复
板凳
xwj| | 2007-9-17 16:46 | 只看该作者

先说说你的波特率、数据位数

使用特权

评论回复
地板
ronanoo|  楼主 | 2007-9-17 16:47 | 只看该作者

1200,8,1,E

使用特权

评论回复
5
zsmbj| | 2007-9-17 20:18 | 只看该作者

看来你对AVR的串口还不是很了解

AVR的uart除了一个移位寄存器外,还有一个缓冲器用来发送串口数据。而这个udre标志就是指缓冲器的空标志。就是说当你判断这个寄存器空了就可以写入数据了。这个寄存器+发送移位寄存器可以看成是2级的fifo了。

你的程序判断了发送寄存器空即向里写入数据。当最后一个数据写入发送寄存器后,实际这2个数据并没有被发送。而是需要一定时间才能发送完成的。而这时你的程序就把485的发送给关闭了,这样就导致最后2个字节没有被发送。

这个时间是多少呢?
你的波特率是1200bit,8,1,E加上起始和结束一共是11bit,所以发一个字节是11/1200=9.17ms。那么2个字节是18.34ms。
就是你程序的延迟20ms,后再关闭485的发送就没有问题了。

对于485系统,一般可以判断TXC标志,这个标志是指发送的最后一个字节完毕,就是发送移位寄存器里的最后一个bit完成。因为TXC标志不会自动清除,所以需要人工清除(写1清除)

void send_byte(uchar buf_to_send) //发送采用查询方式  字节发送函数 

        while( !(UCSR0A & (1<<TXC0)) ); 
        UCSR0A = (1<<TXC0);
        UDR0=buf_to_send; 

使用特权

评论回复
6
ronanoo|  楼主 | 2007-9-17 20:58 | 只看该作者

有道理,非常感谢zsmbj ,多谢了。

使用特权

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

本版积分规则

3

主题

10

帖子

1

粉丝