打印

求教高手:PIC16F887的单片机-PC-485通信(有程序))

[复制链接]
6048|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
KF_3C|  楼主 | 2010-5-13 13:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
背景描述:小弟用PIC16F887单片机与电脑通信,因为是485的协议,所以使用了两片芯片SN75176,一片作为接收,一片作为发送。通信协议是,电脑先发送5个字节给单片机,单片机接收并判断正确了,则会置发送标志位,然后向电脑发送数据。
问题描述:现在目前的情况是,在线调试时,发现单片机总是出现接收溢出错误,然后就再也接收不了数据(我们使用中断接收)。如果直接置发送标志位,则可以向电脑发送数据。所以,目前排除了硬件上的问题,认为是软件的问题,但是却找不出来。
请高手指点下,十分感谢!
下面是具体的程序,用在其他单片机PIC16F77,可以成功的通信。

#define     RECV_INIT       0
#define     RECV_ID         1
#define     RECV_STATE      2
#define     RECV_Sum        3
#define     RECV_END        4
#define     RECV_TIMEOUT    50
   /********初始化**************/
void Init_UART(void)
{
    ADCON1=0X07;
    TRISC6=0; // output
    TRISC7=1; // input
    SPBRG=25;                      //9600
    TXSTA=0b00100100;
    RCSTA=0b10010000;
    GIE = 1;
    RCIE=1;
}
   /********如果接收电脑发送的数据,若正确,则置标志位**************/
if(RCIF)    //   放在中断程序里
  {
    ch=RCREG;
    Receive_timeout=RECV_TIMEOUT;
    switch(Receive_state)
    {
        case    RECV_INIT:
                if(ch==0x68)
                {
                    Receive_state=RECV_ID;
                    Receive_timeout=RECV_TIMEOUT;
                }
                else  Receive_timeout=1;
                break;
        case    RECV_ID:
                Receive_state=RECV_STATE;
                Receive_buf[0]=ch;      //uP ionizer ID
       Data_Checksum=ch;
                break;
               
        case    RECV_Sum:
                Receive_state=RECV_END;
                Receive_buf[2]=ch;           // the received checksum
      break;
        case    RECV_END:
                if(ch==0x68)
                {
                     if(Receive_buf[0]==Device_Address)
                     {
        if(Receive_buf[2]==Data_Checksum)
        {
                         Receive_Flag=1;    //receive ok
                        // Run_state=Receive_buf[1];
        }
                     }
                }
        default:
                Receive_timeout=0;
                Receive_state=RECV_INIT;
                break;
    }

   /********如果接收成功,则开始向电脑发送数据**************/
   
    if(Receive_Flag==1)           //  放在main程序里
        {
             //增加通讯指示
            WriteLCDCommand(PageAddress+3,2);
            WriteLCDCommand(50,2);
            for(ch=0;ch<8;ch++)WriteLCDData(0xFF,2);
            //通讯开始,上传状态字 20060314
            Receive_Flag=0;
            RA2=1;         //start to send
    ch=Device_Address;
    TXREG=ch;                          //TXREG:USART Transmit Data Register 20050313
    Data_Checksum=ch;
            while(!TRMT);          //send the id
              ch=temp1&0xff;
              TXREG=ch;
         Data_Checksum+=ch;
            while(!TRMT);       //send the VB3 data low byte
         ch=(temp1>>8)&0xff;
  ch |=0x80;
   TXREG=ch;
   Data_Checksum+=ch;   
               while(!TRMT);       //send the VB3 data high byte
            
              ch=temp2&0xff;
               TXREG=ch;
   Data_Checksum+=ch;
            while(!TRMT);       //send the VB2 data low byte
            ch=(temp2>>8)&0xff;
      ch |=0x80;
        TXREG=ch;
        Data_Checksum+=ch;
              while(!TRMT);             //send the VB2 data low byte
            
           ch=temp3&0xff;
            TXREG=ch;
            Data_Checksum+=ch;
           while(!TRMT);       //send the VB1 data low byte
           ch=(temp3>>8)&0xff;
      ch |=0x80;
      TXREG=ch;
      Data_Checksum+=ch;
           while(!TRMT);       //send the VB1 data high byte

        TXREG=Data_Checksum;
            while(!TRMT);       //send checksum
            RA2=0;               //switch off sending
     }

相关帖子

沙发
KF_3C|  楼主 | 2010-5-13 13:50 | 只看该作者
在网上找到一篇**,解释为什么了出现溢出错误,但是没有指出如何处理。
               
                      PIC单片机的串口 OERR错误
根据883的规格书的介绍,FIFO接收缓冲只有2个字节的存储空间,因此,如果接受时的接收中断执行时间过长,而上位机的数据发送一次超过2个字节,超过FIFO的存储空间,就会造成单片机的FIFO溢出。如果没有对RCREG进行定期在主程序中读取,则错误标志无法清零,单片机的串口通信就会锁死,出现无**常通信的情况。

下图是883在上位机一次连续发送4个字节,在中断中读取RCREG,由于中断执行一次时间超过了发送3个字节的总时间,FIFO的接收缓冲器不能实时被RCREG转取走,造成FIFO溢出。单片机进入接收中断,取走第一次接收到的0x55,但是取走后中断要执行其他程序,不能马上退出中断再进入接收中断,因此后面的3个字节需要存储在FIFO中,造成FIFO的溢出。

C1:上位机发送0x55 4个字节的数据,接单片机RX引脚

C2:单片机执行中断程序,相应接收后的执行返回接收到得上位机数据,由于中断有一个长时间的延时,使单片机在退出第一个接收字节的中断时,已经错过了上位机发送的后3个字节。但是当时仍有2个字节存储在FIFO接收缓冲器中,由于还有3个字节要存储,而FIFO只有2个,造成第二个字节丢失,单片机OERR置位。接收中断响应了后2个存储成功的数据,执行完成后推出接收中断响应,FERR不会自动清零,单片机以后将无法执行接收中断,好比单片机已经进入通信锁死状态。

C3:单片机执行进入中断和退出中断的标志位,为了来查看中断的运行与单片机通信时序的关系。

使用特权

评论回复
板凳
KF_3C|  楼主 | 2010-5-13 13:52 | 只看该作者
本帖最后由 KF_3C 于 2010-5-14 08:19 编辑

上面的图显示不出来,怎么没有高手肯发表下?

使用特权

评论回复
地板
KF_3C|  楼主 | 2010-5-16 11:36 | 只看该作者
这两点在思考,会不会是时钟频率不对呢?

使用特权

评论回复
5
zjswuyunbo| | 2010-5-16 17:37 | 只看该作者
试试检查在主程序或中断中是否发生Oerr,如果有清楚它

使用特权

评论回复
6
KF_3C|  楼主 | 2010-5-17 08:48 | 只看该作者
不大明白,这个OERR是通信溢出错误,现在我们是有这个问题,但如何查在主程序里也有这个错误呢?

使用特权

评论回复
7
KF_3C|  楼主 | 2010-8-19 16:59 | 只看该作者
后来终于把它解决了,还是漏了一个小细节,少检测一个数据位。

使用特权

评论回复
8
molink| | 2011-8-28 14:47 | 只看该作者
很有参考价值!谢谢!

使用特权

评论回复
9
molink| | 2011-8-28 14:51 | 只看该作者
很有参考价值!谢谢!

使用特权

评论回复
10
huihaihuatian| | 2011-8-30 16:13 | 只看该作者
:):handshak:handshake

使用特权

评论回复
11
acetuo| | 2020-10-8 15:11 | 只看该作者
KF_3C 发表于 2010-8-19 16:59
后来终于把它解决了,还是漏了一个小细节,少检测一个数据位。

能把代码贴出来,学习下么

使用特权

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

本版积分规则

15

主题

80

帖子

1

粉丝