本帖最后由 Ryanhsiung 于 2011-10-14 17:05 编辑
听说大叔正准备定串口的通信协议,今天我就移植了一个我现在正在用的!注:非商业用途 本程序可随意使用!商业则必须经过本人的同意!!
protocol:
//接收: 0x02 +address + length + command+ data0..n ++ crc8sum
(n>=0)
//发送: 0x02 +address + length +status + (command+ data0..n )+ crc8sum
(n>=0)
大家也可使用9位地址模式,将0x02去除直接,ADDRESS用9位地址传送,剩下的用9位数据传送。
本程序功能:
通过串口接收命令,解析command: 为0 点亮LED1,为1关闭LED1.
下面是流程图!
收码:
void UART0_Int_Handle (uint32_t u32IntStatus)
{
if(u32IntStatus & DRVUART_RDAINT) // 如果是接收中断
{
if(UART0->ISR.RDA_IF==1) // 如果是串口0接收中断,标志会自动清0
{
static uint8_t receive_temp=0; // 临时接收变量 静态 存取速度快
receive_temp = UART0->DATA; // 单字节中断,不用函数了 DrvUART_Read(UART_PORT0,&a_RS232_RecData[RS232_RecCount],1);
if(1 == Flag_Serial_IsRecStatus) // 若没有开始,继续等待开始标识符(SERIAL_START_FLAG)
{
a_Serial_RecData[Serial_RecCount] = receive_temp; // 接收字符
switch(Serial_RecCount)
{
case 0: // 正常不会有0
{
Serial_ReStartReceive();
}break;
case 1: //检测地址是否正确 0就不用检测了
{
if((Serial_Address != receive_temp)&&(SERIAL_BROADCAST_ADDRESS!= receive_temp))
{
Serial_ReStartReceive();
}
}break;
case 2: //记录长度
{
if((receive_temp>SERIAL_MIN_REC_NUM)&&(receive_temp<SERIAL_MAX_REC_NUM)) //判断长度是否法
{
Serial_RecLenth = receive_temp;
}
else
{
Serial_ReStartReceive();
}
}break;
default: //接收内容
{
if(Serial_RecLenth == Serial_RecCount )
{
Flag_Serial_ReceiveOK = 1;
Serial_RecCount = 0;
UART0->IER.RDA_IEN = 0 ; //先不接收,否则可能出错,即还没把数据取出,新的数据就占住了位置
Timer0_En(ENABLE_DIS); //接收完成 T0关
return; //最后一个不计算校验合
}
}break; // 这里用
}
Serial_RecSum = CRC_GetCRC8(Serial_RecSum,receive_temp);// 计算CRC,这样就不用最后一起计算
if( Serial_RecCount++ >= (SERIAL_MAX_REC_NUM-1) ) // 检查接收是否要溢出了
{
Serial_ReStartReceive(); // 并丢掉先前的数据,从新开始
}
}
else
if( SERIAL_START_FLAG == receive_temp )
{//Start to receive
Timer0_En(ENABLE_EN); //使能T0
Serial_RecCount = 1; //个数
Flag_Serial_IsRecStatus =1;
a_Serial_RecData[0] = Serial_RecSum = SERIAL_START_FLAG ;
Serial_RecSum = 0x0e ; // 固定值所以不用CRC_GetCRC8(0x00,SERIAL_START_FLAG); 直接接赋值
}
}
}
}
以下是解码代码
void Serial_Decode(void)
{
if( 1 == Flag_Serial_ReceiveOK )
{
Flag_Serial_ReceiveOK =0;
if( Serial_RecSum == a_Serial_RecData[Serial_RecLenth] ) //
{// 校验合正确,进入下一步
switch(a_Serial_RecData[3])
{
case 0: //灯1亮
{
LED_Control(D_PIN_LED1,D_LED_ON) ;
}break;
case 1: //灯1灭
{
LED_Control(D_PIN_LED1,D_LED_OFF) ;
}break;
default:
{
Serial_AckToPC(0xa0); // 接收成功,解析失败
Serial_ReStartReceive(); // 解析完毕 打开中断 重新准备接收
return;
};
}
Serial_AckToPC(0xaa); // 接收成功,解析成功
Serial_ReStartReceive(); // 解析完毕 打开中断 重新准备接收
}
else
{
Serial_AckToPC(0x00); // 可以进行报错,或者不报,485多主机情况下 最好不要发
Serial_ReStartReceive(); // 打开中断 重新准备接收
}
}
}
|