MSP430F5529LP UART 中断函数解析:接收数据并处理校验

本文将详细解析 MSP430F5529LP 单片机 UART 中断函数,重点关注接收数据、处理校验码、解析数据帧以及响应上位机命令的流程。

中断函数代码:

#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
{
  

  unsigned int mpy1,mpy2,mpy3,mpy4,mpy5,mpy6;
  /* 乘法器的寄存器入栈 */
   mpy1=MPY32CTL0;   
   mpy2=RESHI;
   mpy3=RESLO;
   mpy4=OP2;
   if(mpy1&0x0010)
     mpy5=MPYS;
   else   mpy6=MPY;
    
  unsigned char DTU_Rx_Data[100];
  unsigned int int_temp;
  DTU_Rx_Data_Count=0;
  P1OUT ^= BIT1;
  
  if(UCA1STAT&UCRXERR)    
  {

      DTU_Pre_Received=0;
      DTU_Pre_Num = 0;
      return;
  }
  
  DTU_Communication_Error=0x00;
  
  switch(__even_in_range(UCA1IV,4))
  {        
        case 0:break;                             
        case 2:
            while (!(UCA1IFG&UCTXIFG));
            UCA1TXBUF=UCA1RXBUF;
            while (!(UCA1IFG&UCTXIFG));

            //DTU_Rx_Data[DTU_Pre_Num]=UCA1RXBUF;
            //DTU_Pre_Num++;
            if(DTU_Pre_Num==DTU_Rx_Data[4])
            {
                          if(DTU_Rx_Data[0] == (char)0x55&&DTU_Rx_Data[1] == (char)0xFD&&DTU_Rx_Data[2] == (char)0xAA)
                          {
                              DTU_Pre_Received = 1;
                              DTU_Rx_Data_Count = 0;
                              DTU_Pre_Num = 7;

                          }
                              else
                              {  /*接收前导字失败 重新接收*/
                                  DTU_Pre_Num = 0;
                                  DTU_Pre_Received = 0;
                                  DTU_Rceive_OK = 0;
                                  return;
                              }

            }

       /*接收正文*/
            if(DTU_Pre_Received == 1)
          {
            if(DTU_Rx_Data_Count==0)
            {

                int_temp=(unsigned int)DTU_Rx_Data[3];
                DTU_length=int_temp<<8;
                DTU_Rx_Data_Count++;
            }
             if(DTU_Rx_Data_Count==1)

            {

                int_temp=(unsigned int)DTU_Rx_Data[4];
                DTU_length=DTU_length|int_temp;
                DTU_Rx_Data_Count++;
                DTU_Receive_CMD_Count=DTU_length-2;
            }
             if(DTU_Rx_Data_Count==2)
            {

                DTU_Common_Para=DTU_Rx_Data[5];
                DTU_Rx_Data_Buffer[DTU_Rx_Data_Count-2]=DTU_Common_Para;
                DTU_Rx_Data_Count++;
                if(DTU_Common_Para!=0x61)
                {
                    DTU_Pre_Received=0;
                    DTU_Pre_Num = 0;
                    return;
                }                
            }
             if(DTU_Rx_Data_Count==3)
            {

                DTU_Reserve_Para=DTU_Rx_Data[6];
                DTU_Rx_Data_Buffer[DTU_Rx_Data_Count-2]=DTU_Reserve_Para;
                DTU_Rx_Data_Count++;
            }


                switch(DTU_Reserve_Para)
                {
                    case 0x01:  
                    case 0x02:
                    case 0x03:
                    case 0x04:
                    case 0x05:
                    case 0x06:
                    case 0x07:
                    case 0x08: 
                    case 0x09:  
                    case 0xDA:    

                      if(DTU_Rx_Data_Count < 4)
                      {
                          DTU_Pre_Received=0;
                          DTU_Pre_Num = 0;
                          return;
                      }
                      else
                      {
                          unsigned int i=7;
                          while(DTU_Rx_Data_Count<4+DTU_Receive_CMD_Count)
                          {
                              DTU_Rx_Data_Buffer[DTU_Rx_Data_Count-2] = DTU_Rx_Data[i++];//所有接收数据入数组
                              DTU_Rx_Data_Count++;
                          }


                              DTU_Receive_CheckCode = DTU_Rx_Data[i];//保存校验位
                              DTU_Check_Result = DTU_Check_Code(DTU_Rx_Data_Buffer, DTU_Receive_CMD_Count+2);//先校验,再与PC发来的校验码校验,则结果是0
                              if(DTU_Check_Result!=DTU_Receive_CheckCode)
                              {DTU_Communication_Error=0x01;}
                              else {DTU_Communication_Error=0x0;}
                              DTU_Rceive_OK = 1;
                              DTU_Rx_Data_Count=0;
                      }
                      break;
                 
                  default:
                    break;
                } 

  
          if(DTU_Rceive_OK == 1)//响应上位机命名
          {
                _EINT();  //允许中断嵌套
                asm("nop");
              DTU_Pre_Received=0;
              DTU_Pre_Num = 0;  
              DTU_Rx_judge_save();//判断接收数据是否正确、保存修改数据
              DTU_Communicate();
          }
          }

          break;
          case 4:break; 
          default: break;
  }
  
   /* 乘法器的寄存器出栈 */ 
    if(mpy1&0x0010)
     MPYS=mpy5;
    else   MPY=mpy6;
    OP2=mpy4;
    RESLO=mpy3;
    RESHI=mpy2;
    MPY32CTL0=mpy1;
}

代码解析:

  1. 接收数据:
  • 代码通过判断 UCA1STAT 寄存器中的 UCRXERR 位来检查是否有接收错误,如果有则直接返回,不进行处理。
  • 使用 UCA1RXBUF 读取 UART 接收缓冲区中的数据,并将其保存到 DTU_Rx_Data 数组中。
  • 代码使用 DTU_Pre_ReceivedDTU_Pre_Num 变量来记录接收状态和数据个数。
  • 代码通过判断 DTU_Rx_Data 数组中前三个字节是否为 0x55, 0xFD, 0xAA 来判断是否接收到了数据包的开始标志。
  • 代码根据接收到的数据包长度,对数据包进行解析,并保存到 DTU_Rx_Data_Buffer 数组中。
  1. 校验码处理:
  • 代码使用 DTU_Check_Code 函数对接收到的数据进行校验,并与接收到的校验码进行比较,判断数据是否正确。
  1. 数据帧解析:
  • 代码根据数据包类型,对数据进行解析,并根据解析结果进行相应的操作。
  1. 响应上位机命令:
  • 代码使用 DTU_Communicate 函数发送响应数据给上位机。

常见问题排查指南:

  1. 数据长度错误: 确认发送数据时,数据长度是否与实际发送数据长度一致。
  2. 校验码错误: 检查代码中校验码处理是否正确,以及校验码计算逻辑是否与上位机一致。
  3. 数据帧解析错误: 检查数据帧解析逻辑是否正确,以及解析逻辑是否与上位机一致。

总结:

本文详细解析了 MSP430F5529LP 单片机 UART 中断函数,并提供了常见问题排查指南。开发者可以根据本文内容,进一步理解数据传输机制,并更好地处理数据接收和解析过程。

建议:

  • 使用调试工具,查看程序运行过程中的数据流,帮助定位问题。
  • 参考 UART 协议文档,详细了解数据包格式以及校验码计算方式。
  • 通过测试用例,验证代码逻辑是否正确,并确保代码能够正确处理各种情况。
MSP430F5529LP UART 中断函数解析:接收数据并处理校验

原文地址: https://www.cveoy.top/t/topic/jlYk 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录