MSP430F5529LP UART 中断函数解析:接收数据并处理校验
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;
}
代码解析:
- 接收数据:
- 代码通过判断
UCA1STAT寄存器中的UCRXERR位来检查是否有接收错误,如果有则直接返回,不进行处理。 - 使用
UCA1RXBUF读取 UART 接收缓冲区中的数据,并将其保存到DTU_Rx_Data数组中。 - 代码使用
DTU_Pre_Received和DTU_Pre_Num变量来记录接收状态和数据个数。 - 代码通过判断
DTU_Rx_Data数组中前三个字节是否为0x55,0xFD,0xAA来判断是否接收到了数据包的开始标志。 - 代码根据接收到的数据包长度,对数据包进行解析,并保存到
DTU_Rx_Data_Buffer数组中。
- 校验码处理:
- 代码使用
DTU_Check_Code函数对接收到的数据进行校验,并与接收到的校验码进行比较,判断数据是否正确。
- 数据帧解析:
- 代码根据数据包类型,对数据进行解析,并根据解析结果进行相应的操作。
- 响应上位机命令:
- 代码使用
DTU_Communicate函数发送响应数据给上位机。
常见问题排查指南:
- 数据长度错误: 确认发送数据时,数据长度是否与实际发送数据长度一致。
- 校验码错误: 检查代码中校验码处理是否正确,以及校验码计算逻辑是否与上位机一致。
- 数据帧解析错误: 检查数据帧解析逻辑是否正确,以及解析逻辑是否与上位机一致。
总结:
本文详细解析了 MSP430F5529LP 单片机 UART 中断函数,并提供了常见问题排查指南。开发者可以根据本文内容,进一步理解数据传输机制,并更好地处理数据接收和解析过程。
建议:
- 使用调试工具,查看程序运行过程中的数据流,帮助定位问题。
- 参考 UART 协议文档,详细了解数据包格式以及校验码计算方式。
- 通过测试用例,验证代码逻辑是否正确,并确保代码能够正确处理各种情况。
原文地址: https://www.cveoy.top/t/topic/jlYk 著作权归作者所有。请勿转载和采集!