anxiaoxiao 发表于 2012-5-21 20:34:48

马潮老师,您好,我的串口中断一直丢包,麻烦帮忙分析

//===============串口初始化=============
void uart0_init(void)
{
UCSR0B = 0x00;   //禁止发送和接收
UCSR0A = 0x00;   //倍速异步模式USX0=0
UCSR0C = 0x06;   //0000 0110,UCSZ01=1,UCSZ00=1;1位起始位,8位字符,1位停止位
UBRR0L = 25;   //设置波特率为19200
UBRR0H = 0;      //
UCSR0B = 0x98;   //使能发送和接收,使能串口中断

asm("sei");//打开全局中断
}

//***************   UART0 FUNCTION************************//
void UartSendHY502(unsigned char *cSendBuffer)
{
         unsigned char i;
         unsigned char cCheckSum = 0;

      UCSR0B &= ~(1<<RXCIE0); //禁止串口接收

      for(i=0;i<30;i++)
          g_cReceBuf = 0;

      while(!(UCSR0A & (1<<UDRE0)));
         UDR0 = 0xAA; //发送包头 0xAA

    while(!(UCSR0A & (1<<UDRE0)));
         UDR0 = 0xBB; //发送包头 0xBB

      for (i=0; i<cSendBuffer; i++)
         {
               cCheckSum ^= cSendBuffer;

                while(!(UCSR0A & (1<<UDRE0)));
               UDR0 = cSendBuffer; //发送长度字、命令字、校验和

                if (cSendBuffer == 0xAA)
               {
                         while(!(UCSR0A & (1<<UDRE0)));
                     UDR0 = 0x00; //在0xAA后加0x00
               }

      }

    while(!(UCSR0A & (1<<UDRE0)));
         UDR0 = cCheckSum; //发送校验字
         
      UCSR0B |= 1<<RXCIE0; //打开串口接收
}

SIGNAL(SIG_USART0_RECV)
{
   unsigned char i;
         unsigned char cReceivedData;
   unsigned char cCheckSum = 0;

      cReceivedData = UDR0;

      if(g_bReceAA)
         {
          g_bReceAA = 0;

         if(cReceivedData == 0xBB )
            g_cReceNum = 0;

         }//不接收包头AA BB

      else
          {
         if (0xAA == cReceivedData)
               g_bReceAA = 1;

          g_cReceBuf = cReceivedData;

          if (g_cReceNum > g_cReceBuf)//代表所有数据已经接收完毕
            {
                  UCSR0B &= ~(1<<RXCIE0); //禁止串口接收,退出中断服务
                  cCheckSum = 0;

               for (i=0; i <= g_cReceBuf; i++)
                        cCheckSum ^= g_cReceBuf;

               if (0 == cCheckSum)
                         {
                           g_bReceCommandOk = 1;//表示数据接收完毕      ,且接收无误                  
                        }
                  g_cReceNum = 0;
                  g_bReceAA = 0;               
               }

          }
}

/************************** main function start here *******************************/
int main(void)
{         
    uchar CardSN[] = {0x02,0x02};
         uchar cStatus;
         uchar *cPa;

      uart0_init();
         
         cPa = CardSN;
         UartSendHY502(cPa);                   //发送指令
         _delay_ms(200);                        // delay for module execution
         cStatus = !g_bReceCommandOk;   
            //一下为显示部分
         if((g_cReceBuf != cPa)|| (cStatus != 0x00))   //判断是否接收完毕,及接收的是否正确
         {
         ……
         }
         else
         {
            ……
         }
}

anxiaoxiao 发表于 2012-5-21 20:35:58

期望马潮老师的回复,大家有经验的过来发表建议哦……

loongsuns 发表于 2012-5-21 20:57:11

你的每帧数据有且只有一个0xaa吗?

还有不要重复发帖子。

anxiaoxiao 发表于 2012-5-21 21:39:02

谢谢回复。

刚才我解决了困扰了两周的问题,不过还是很感谢您。

新手不了解这些规则,而且看马潮老师的那个帖子较晚,就又发了一遍。以后不会再犯这样的错误了。

xiaojiong886 发表于 2012-5-24 11:57:33

关于这一类的帖子哪边有?

anxiaoxiao 发表于 2012-5-24 15:22:01

你可以上网搜下,这方面的问题大家问的很多
{:victory:}

ba_wang_mao 发表于 2012-5-24 17:34:05

应该是你程序的问题。
一个串口通讯方面的老手给你提提意见:

    (1)、我从来不使用查询方式的发送数据
         缺点:响应太慢,占用宝贵的CPU时间
         我一直使用中断方式发送数据
    (2)、我从来不在接收中断里做大量的判断和处理工作
            缺点:可能会造成数据丢失
            我一直在主程序中判断和处理接收的数据。
   下面是我的接收中断代码

#pragma interrupt_handler USART1_RI_ISR:iv_USART1_RX
void USART1_RI_ISR(void)
{
        INT8U ch;
        INT8U status;

        status = UCSR1A;
        ch = UDR1;
        if (USART1_receCount < MSCOMM_BUFFER_LENGTH)
                USART1_mscomm_buffer = ch;
        else
                USART1_receCount = 0;
        if (status & 0x1C)
                USART1_checkoutError = 2;
}



    下面是我的发送中断代码
   
#pragma interrupt_handler USART1_TX_ISR:iv_USART1_TX
void USART1_TX_ISR(void)
{
    if (USART1_sendPosi < USART1_sendCount)
                UDR1 = USART1_send_buffer;
        else
                RS485_RECIVE_enable();
}      



//下面的代码在主程序中执行,用于发送第1个字节,同时开启发送中断
void USART1_Begin_Send(void)
{
        RS485_SEND_enable();
        NOP();                                                //        --------|       
        NOP();                                                //                        |
        NOP();                                                //                        |-----------等待总线释放
        NOP();                                                //                        |
        NOP();                                                //        --------|
    USART1_sendPosi = 0;
        UDR1 = USART1_send_buffer;
}

anxiaoxiao 发表于 2012-5-24 20:54:13

十分感谢高手的建议,我一定谨记在心!
初学者,在这方面没有经验……
谢谢高手让我成长!

cumt_123456 发表于 2012-11-5 22:32:03

谢谢楼上的各位{:victory:}

maimaige 发表于 2012-11-15 20:59:48

mark一下关于串口中断的,有空看看那

maimaige 发表于 2012-11-16 09:00:18

ba_wang_mao 发表于 2012-5-24 17:34 static/image/common/back.gif
应该是你程序的问题。
一个串口通讯方面的老手给你提提意见:



你好,能看到你的这个完整的代码吗,
我主要是想知道你的main函数中是怎么对
USART1_mscomm_buffer[]处理的,
假设你正在处理的过程中,又有新的接收中断到来, USART1_mscomm_buffer[]中的数据又变化了怎么做的

s20101026 发表于 2013-3-28 20:56:17

表示很钦佩!!!!

maimaige 发表于 2013-3-29 08:34:50

mark 今天测试一下

maimaige 发表于 2013-3-29 10:45:37

ba_wang_mao 发表于 2012-5-24 17:34 static/image/common/back.gif
应该是你程序的问题。
一个串口通讯方面的老手给你提提意见:



你好,能够把你的RS485_RECIVE()这个函数是怎么实现的,给看看吗
页: [1]
查看完整版本: 马潮老师,您好,我的串口中断一直丢包,麻烦帮忙分析