主要功能将PC端的数据接收下来,分发到不同的设备,也是轮询设备数据读取回来,打包回传到PC端,数据包包头包尾识别,数据校验,接收超时处理,将协议结构化处理,协议的改动不需要改动程序,中断接收一帧完成置标志位交由上层协议程序校验并处理转发
协议格式定义,每一个位都进行了定仪
#ifndef PROTOCOL_H
#define PROTOCOL_H
#include "define.h"
//IO_EMM_31
typedef struct
{
uchar Stx;
uchar Length;
uchar ID;
uchar TollCollectorID[3];
uchar LoginDuration[2];
uchar VehicleClass;
union
{
uchar byte;
struct
{
uchar Payment:4;
uchar Axle:4;
}BIT;
}AxlePaymentDisplay;
union
{
uint word;
uchar byte[2];
}TollFare;
union
{
uchar byte;
struct
{
uchar reserved:1;
uchar Exit_LSS_Rlight:1;
uchar BarrierClose:1;
uchar BarrierOpen:1;
uchar Entry_LSS_Rlight:1;
uchar Entry_LSS_Glight:1;
uchar LaneLog:1;
uchar zero:1;
}BIT;
}TMU_Control1;
union
{
uchar byte;
struct
{
uchar EmergencyAlarm:1;
uchar EvasionAlarm:1;
uchar DiscrepancyAlarm:1;
uchar MisregistrationAlarm:1;
uchar reserved:1;
uchar AxleDectorFault:1;
uchar BoothEquipmentFault:1;
uchar zero:1;
}BIT;
}TMU_Control2;
union
{
uchar byte;
struct
{
uchar EmergencyAlarmRstBut:1;
uchar EvalsionAlarmRstBut:1;
uchar DiscrepancyAlarmRstBut:1;
uchar MisregistrationAlarmRstBut:1;
uchar AxleDetectorOVerride:1;
uchar KeyInOverrideSelect:1;
uchar reserved:1;
uchar zero:1;
}BIT;
}ConStatus1;
union
{
uchar byte;
struct
{
uchar resetved:4;
uchar TMUCommFail:1;
uchar TMUDimmerOverAct:1;
uchar AllSignageDimmming:1;
uchar zero:1;
}BIT;
}ConStatus2;
union
{
uchar byte;
struct
{
uchar reserved:1;
uchar CanopyBeacon:1;
uchar Entry_LSS_Rlight:1;
uchar Entry_LSS_Glight:1;
uchar TPS_Glight:1;
uchar TPS_Rlight:1;
uchar DimmingNormal:1;
uchar zero:1;
}BIT;
}SignageControl;
union
{
uchar byte;
struct
{
uchar TPSCommFail:1;
uchar reserve2:1;
uchar reserve1:1;
uchar TPSTempHigher70:1;
uchar CLSCommFail:1;
uchar CLSPixelFaultDetect:1;
uchar CLSTempHigher70:1;
uchar zero:1;
}BIT;
}TPS_CLSFaultStatus;
union
{
uchar byte;
struct
{
uchar EntryCommFail:1;
uchar ExitCommFail:1;
uchar RlightAspectHigher50:1;
uchar RlightAspectHigher25:1;
uchar TempHigher70:1;
uchar reseved:1;
uchar Rlight:1;
uchar zero:1;
}BIT;
}ExitLSSStatus;
union
{
uchar byte;
struct
{
uchar GlightAspectHigher50:1;
uchar GlightAspectHigher25:1;
uchar RlightAspectHigher50:1;
uchar RlightAspectHigher25:1;
uchar TempHigher70:1;
uchar Glight:1;
uchar Rlight:1;
uchar zero:1;
}BIT;
}EntryLSSStatus;
union
{
uchar byte;
struct
{
uchar ShortDetect:1;
uchar reserved:2;
uchar KickBarAlarm:1;
uchar CabinetOpen:1;
uchar BarrierColse:1;
uchar BarrierOpen:1;
uchar zero:1;
}BIT;
}LocalIOInputStatus;
union
{
uchar byte;
struct
{
uchar Class0:1;
uchar Class1:1;
uchar Class2:1;
uchar Class3:1;
uchar Class4:1;
uchar Class5:1;
uchar Class6:1;
uchar zero:1;
}BIT;
}AutoTollInputStatus1;
union
{
uchar byte;
struct
{
uchar Class7:1;
uchar Class8:1;
uchar Class9:1;
uchar ClassAdd1:1;
uchar LaneOpen:1;
uchar LaneClose:1;
uchar reserved:1;
uchar zero:1;
}BIT;
}AutoTollInputStatus2;
union
{
uchar byte;
struct
{
uchar Axle1:1;
uchar Axle2:1;
uchar Axle3:1;
uchar Axle4:1;
uchar Axle5:1;
uchar Axle6:1;
uchar reserved:1;
uchar zero:1;
}BIT;
}AutoTollInputStatus3;
uchar Checksum;
uchar Etx;
}IO_EMM_31;
//IO_EMM_32
typedef struct
{
uchar Stx;
uchar Length;
uchar ID;
union
{
uchar byte;
struct
{
uchar reserved:1;
uchar Dimmer:3;
uchar Normal:3;
uchar zero:1;
}BIT;
}TPSSetting;
union
{
uchar byte;
struct
{
uchar reserved:1;
uchar Dimmer:3;
uchar Normal:3;
uchar zero:1;
}BIT;
}CLSSetting;
union
{
uchar byte;
struct
{
uchar reserved:1;
uchar Dimmer:3;
uchar Normal:3;
uchar zero:1;
}BIT;
}EntryLSSSetting;
union
{
uchar byte;
struct
{
uchar reserved:1;
uchar Dimmer:3;
uchar Normal:3;
uchar Zero:1;
}BIT;
}ExitLSSSetting;
uchar Checksum;
uchar Etx;
}IO_EMM_32;
//IO_TMU
typedef struct
{
uchar Stx;
uchar Length;
uchar ID;
uchar TollCollectorID[3];
uchar LoginDuration[2];
uchar VehicleClass;
union
{
uchar byte;
struct
{
uchar Payment:4;
uchar Axle:4;
}BIT;
}AxlePaymentDisplay;
union
{
uchar byte;
struct
{
uchar reserved:1;
uchar Exit_LSS_Rlight:1;
uchar BarrierClose:1;
uchar BarrierOpen:1;
uchar Entry_LSS_Rlight:1;
uchar Entry_LSS_Glight:1;
uchar LaneLog:1;
uchar zero:1;
}BIT;
}TMU_Control1;
union
{
uchar byte;
struct
{
uchar EmergencyAlarm:1;
uchar EvasionAlarm:1;
uchar DiscrepancyAlarm:1;
uchar MisregistrationAlarm:1;
uchar reserved:1;
uchar AxleDectorFault:1;
uchar BoothEquipmentFault:1;
uchar zero:1;
}BIT;
}TMU_Control2;
union
{
uchar byte;
struct
{
uchar EmergencyAlarmRstBut:1;
uchar EvalsionAlarmRstBut:1;
uchar DiscrepancyAlarmRstBut:1;
uchar MisregistrationAlarmRstBut:1;
uchar AxleDetectorOVerride:1;
uchar KeyInOverrideSelect:1;
uchar reserved:1;
uchar zero:1;
}BIT;
}ConStatus1;
union
{
uchar byte;
struct
{
uchar resetved:5;
uchar TMUDimmerOverAct:1;
uchar AllSignageDimming:1;
uchar zero:1;
}BIT;
}ConStatus2;
uchar Checksum;
uchar Etx;
}IO_TMU;
//IO_TPS
typedef struct
{
uchar Stx;
uchar Length;
uchar ID;
union
{
uint word;
uchar byte[2];
}TollFare;
union
{
uchar byte;
struct
{
uchar DispPleasePaid:1;
uchar DispThankyou:1;
uchar Rlight:1;
uchar Glight:1;
uchar BrightnessControl:3;
uchar reserved:1;
}BIT;
}LedDisplay;
union
{
uchar byte;
struct
{
uchar TempHigher70:1;
uchar reserved:7;
}BIT;
}Status;
uchar Checksum;
uchar Etx;
}IO_TPS;
//IO_CLS
typedef struct
{
uchar Stx;
uchar Length;
uchar ID;
uchar VehicleClass;
union
{
uchar byte;
struct
{
uchar Axle:3;
uchar reserved1:1;
uchar RelayContactClose:1;
uchar reserved2:3;
}BIT;
}AxleCounterDisplay;
union
{
uchar byte;
struct
{
uchar reserved:4;
uchar Brightness:3;
uchar zero:1;
}BIT;
}BrightnessControl;
union
{
uchar byte;
struct
{
uchar TempHigher70:1;
uchar PixelFaultDetected:1;
uchar reserved:6;
}BIT;
}Status;
uchar Checksum;
uchar Etx;
}IO_CLS;
//IO_LSS
typedef struct
{
uchar Stx;
uchar Length;
uchar ID;
union
{
uchar byte;
struct
{
uchar Rlight:1;
uchar Glight:1;
uchar reserved:6;
}BIT;
}SignalDisp;
union
{
uchar byte;
struct
{
uchar RlightAspectHigher25:1;
uchar RlightAspectHigher50:1;
uchar GlightAspectHigher25:1;
uchar GlightAspectHigher50:1;
uchar BrightnessControl:3;
uchar reserved:1;
}BIT;
}Status1;
union
{
uchar byte;
struct
{
uchar TempHigher70:1;
uchar reserved:7;
}BIT;
}Status2;
uchar Checksum;
uchar Etx;
}IO_LSS;
typedef struct
{
uchar Dimmer;
uchar Normal;
}BRIGHTNESS;
#endif
中断接收与发送
void IntUart0Rx( void ) interrupt 4
{
uchar temp;
static uchar MsgLen;
if( RI_0 )
{
RI_0 = 0;
temp = S0BUF;
Timer1ms[TIMER_COM_DEV].Tick = 10;
Timer1ms[TIMER_COM_DEV].Flg.BIT.Enable = 1;
Timer[TIMER_RESPONSE].Tick = 5;
ACC = temp;
if( P==RB8_0 )
{
if( !DevStrEndFlg )
{
if( temp==0xaa )
{
DevStrEndFlg = 1;
IO2Dev.RecvPtr = 0;
IO2Dev.RecvBuf[IO2Dev.RecvPtr++] = temp;
IO2Dev.Error.byte = 0;
}
}
else
{
if( temp==0xab && IO2Dev.RecvPtr==MsgLen )
{
DevStrEndFlg = 0;
IO2Dev.RecvBuf[IO2Dev.RecvPtr++] = temp;
IO2Dev.Flg.BIT.Recv = 1;
IO2Dev.RecvLen = IO2Dev.RecvPtr;
}/*
else if( temp==0xaa && IO2Dev.RecvPtr!=MsgLen-1 )
{
IO2Dev.RecvPtr = 0;
IO2Dev.RecvBuf[IO2Dev.RecvPtr++] = temp;
}*/
else if( IO2Dev.RecvPtr==2 )
{
IO2Dev.ID = temp;
IO2Dev.RecvBuf[IO2Dev.RecvPtr++] = temp;
switch( IO2Dev.ID )
{
case IO_TMU_ID:
MsgLen = sizeof( IO_TMU )-1;
break;
case IO_TPS_ID:
MsgLen = sizeof( IO_TPS )-1;
break;
case IO_CLS_ID:
MsgLen = sizeof( IO_CLS )-1;
break;
case IO_ELSS_ID:
MsgLen = sizeof( IO_LSS )-1;
break;
case IO_XLSS_ID:
MsgLen = sizeof( IO_LSS )-1;
break;
default:
DevStrEndFlg = 0;
}
}
else if( IO2Dev.RecvPtr<RECVBUF_LEN )
{
IO2Dev.RecvBuf[IO2Dev.RecvPtr++] = temp;
}
else //接收数据溢出
{
DevStrEndFlg = 0;
IO2Dev.RecvPtr = 0;
}
// flg = IO2Dev.RecvPtr;
}
}
else
{
IO2Dev.Error.BIT.Even = 1;
}
}
else if( S0STAT&0x08 )//Framing Error
{
S0STAT &= ~0x08;
IO2Dev.Error.BIT.Framing = 1;
}
else if( S0STAT&0x04 )//Break Detect
{
S0STAT &= ~0x04;
IO2Dev.Error.BIT.BreakDetect = 1;
}
else if( S0STAT&0x02 )//Overrun Error
{
S0STAT &= ~0x02;
IO2Dev.Error.BIT.Overrun = 1;
}
}
//串行口0的发送中断程序
void IntUart0Tx( void ) interrupt 7
{
Uart0SendData();
}
以指针提取数据
#include "Emm2IO.h"
#include "com.h"
#include "protocol.h"
#include "systemtask.h"
#include "IOCheck.h"
IO_EMM_31 IOEmm31;
extern BUF_DEF Emm2IO;
extern IO_TMU IOTmu;
extern IO_TPS IOTps;
extern IO_CLS IOCls;
extern IO_LSS IOEntryLss;
extern IO_LSS IOExitLss;
extern BRIGHTNESS TpsBrightness,ClsBrightness,EntryLssBrightness,ExitLssBrightness;
extern IO_CHECK_DEF IoCheck;
extern TIMER_DEF Timer[TIMER_NUM];
extern uchar flg;
void Emm2IOInit( void )
{
//31
IOEmm31.Stx = 0xaa;
IOEmm31.Length = 0x18;
IOEmm31.ID = 0x20;
IOEmm31.ConStatus1.byte = 0;
IOEmm31.ConStatus2.byte = 0x10;
IOEmm31.TPS_CLSFaultStatus.byte = 0x11;
IOEmm31.ExitLSSStatus.byte = 0x03;
IOEmm31.EntryLSSStatus.byte = 0x00;
IOEmm31.LocalIOInputStatus.byte = 0x00;
IOEmm31.AutoTollInputStatus1.byte = 0x00;
IOEmm31.AutoTollInputStatus2.byte = 0x00;
IOEmm31.AutoTollInputStatus3.byte = 0x00;
IOEmm31.Etx = 0xab;
Emm2IO.Flg.byte = 0;
Emm2IO.SendLen = 0;
Emm2IO.RecvLen = 0;
Emm2IO.SendPtr = 0;
Emm2IO.RecvPtr = 0;
Timer[TIMER_STOP].Flg.BIT.TimeOut = 0;
Timer[TIMER_STOP].Tick = 500;
Timer[TIMER_STOP].Flg.BIT.Enable = 1;
}
//从Emm2IOController31的接收数据中取出需要的内容放到设备缓冲区中
void CopyEmm31ToDev( IO_EMM_31 *IoEmm31Ptr )
{
//TMU
IOTmu.TollCollectorID[0] = IoEmm31Ptr->TollCollectorID[0];
IOTmu.TollCollectorID[1] = IoEmm31Ptr->TollCollectorID[1];
IOTmu.TollCollectorID[2] = IoEmm31Ptr->TollCollectorID[2];
IOTmu.LoginDuration[0] = IoEmm31Ptr->LoginDuration[0];
IOTmu.LoginDuration[1] = IoEmm31Ptr->LoginDuration[1];
IOTmu.VehicleClass = IoEmm31Ptr->VehicleClass;
IOTmu.AxlePaymentDisplay.byte = IoEmm31Ptr->AxlePaymentDisplay.byte;
IOTmu.TMU_Control1.byte = IoEmm31Ptr->TMU_Control1.byte;
IOTmu.TMU_Control2.byte = IoEmm31Ptr->TMU_Control2.byte;
//TPS
IOTps.TollFare.byte[0] = IoEmm31Ptr->TollFare.byte[0];
IOTps.TollFare.byte[1] = IoEmm31Ptr->TollFare.byte[1];
IOTps.LedDisplay.BIT.Glight = IoEmm31Ptr->SignageControl.BIT.TPS_Glight;
IOTps.LedDisplay.BIT.Rlight = IoEmm31Ptr->SignageControl.BIT.TPS_Rlight;
if( (((IoEmm31Ptr->TollFare.byte[0]&0xf0)>>4) == 0x000c) && (IoEmm31Ptr->AxlePaymentDisplay.BIT.Payment == 0x0b) )
{
IOTps.LedDisplay.BIT.DispPleasePaid = 1;
IOTps.LedDisplay.BIT.DispThankyou = 0;
}
else if( (((IoEmm31Ptr->TollFare.byte[0]&0xf0)>>4) == 0x0000c) && (IoEmm31Ptr->AxlePaymentDisplay.BIT.Payment != 0x0b) )
{
IOTps.LedDisplay.BIT.DispPleasePaid = 0;
IOTps.LedDisplay.BIT.DispThankyou = 1;
}
else if( ((IoEmm31Ptr->TollFare.byte[0]&0xf0)>>4) == 0x0000b )
{
IOTps.LedDisplay.BIT.DispPleasePaid = 0;
IOTps.LedDisplay.BIT.DispThankyou = 0;
}
else
{
IOTps.LedDisplay.BIT.DispPleasePaid = 0;
IOTps.LedDisplay.BIT.DispThankyou = 0;
}
//CLS
IOCls.VehicleClass = IoEmm31Ptr->VehicleClass;
if( IoEmm31Ptr->AxlePaymentDisplay.BIT.Axle>0 && IoEmm31Ptr->AxlePaymentDisplay.BIT.Axle<7 )
{
IOCls.AxleCounterDisplay.BIT.Axle = IoEmm31Ptr->AxlePaymentDisplay.BIT.Axle;
}
else
{
IOCls.AxleCounterDisplay.BIT.Axle = 0;
}
IOCls.AxleCounterDisplay.BIT.RelayContactClose = IoEmm31Ptr->SignageControl.BIT.CanopyBeacon;
//EntryLSS
IOEntryLss.SignalDisp.BIT.Rlight = IoEmm31Ptr->SignageControl.BIT.Entry_LSS_Rlight;
if( IoEmm31Ptr->SignageControl.BIT.Entry_LSS_Glight && IOEmm31.LocalIOInputStatus.BIT.BarrierOpen &&
!IOEmm31.LocalIOInputStatus.BIT.BarrierColse )
{
IOEntryLss.SignalDisp.BIT.Glight = 1;
IOEntryLss.SignalDisp.BIT.Rlight = 0;
}
else
{
IOEntryLss.SignalDisp.BIT.Glight = 0;
IOEntryLss.SignalDisp.BIT.Rlight = 1;
}
//ExitLSS
if( IoEmm31Ptr->SignageControl.BIT.DimmingNormal )
{
IOTps.LedDisplay.BIT.BrightnessControl = TpsBrightness.Dimmer;
IOCls.BrightnessControl.BIT.Brightness = ClsBrightness.Dimmer;
IOEntryLss.Status1.BIT.BrightnessControl = EntryLssBrightness.Dimmer;
IOExitLss.Status1.BIT.BrightnessControl = ExitLssBrightness.Dimmer;
}
else
{
IOTps.LedDisplay.BIT.BrightnessControl = TpsBrightness.Normal;
IOCls.BrightnessControl.BIT.Brightness = ClsBrightness.Normal;
IOEntryLss.Status1.BIT.BrightnessControl = EntryLssBrightness.Normal;
IOExitLss.Status1.BIT.BrightnessControl = ExitLssBrightness.Normal;
}
}
//从接收的Emm2IOController31的数据更新Emm31缓冲区
void CopyEmm31ToEmm31Buf( IO_EMM_31 *IoEmm31Ptr )
{
uchar *Sptr,*Dptr,i;
Sptr = (uchar*)IoEmm31Ptr;
Dptr = (uchar*)&IOEmm31;
for( i=0; i<11; i++ )
{
*(Dptr+i+3) = *(Sptr+i+3);
}
*(Dptr+16) = *(Sptr+16);
}
//更新各设备的亮度值
void CopyEmm32ToDev( IO_EMM_32 *IoEmm32Ptr )
{
//TPS
TpsBrightness.Dimmer = IoEmm32Ptr->TPSSetting.BIT.Dimmer;
TpsBrightness.Normal = IoEmm32Ptr->TPSSetting.BIT.Normal;
//CLS
ClsBrightness.Dimmer = IoEmm32Ptr->CLSSetting.BIT.Dimmer;
ClsBrightness.Normal = IoEmm32Ptr->CLSSetting.BIT.Normal;
//EntryLSS
EntryLssBrightness.Dimmer = IoEmm32Ptr->EntryLSSSetting.BIT.Dimmer;
EntryLssBrightness.Normal = IoEmm32Ptr->EntryLSSSetting.BIT.Normal;
//ExitLSS
ExitLssBrightness.Dimmer = IoEmm32Ptr->ExitLSSSetting.BIT.Dimmer;
ExitLssBrightness.Normal = IoEmm32Ptr->ExitLSSSetting.BIT.Normal;
}
//判断是否已从EMM接收完整的数据包,并进行处理
void Emm2IOMain( void )
{
uchar ver,*ptr;
IO_EMM_31 *IoEmm31Ptr;
IO_EMM_32 *IoEmm32Ptr;
if( Emm2IO.Flg.BIT.Recv )
{
Emm2IO.Flg.BIT.Recv = 0;
Timer[TIMER_STOP].Tick = 500;
Timer[TIMER_STOP].Flg.BIT.Enable = 1;
if( Emm2IO.Error.byte == 0 )
{
ver = Checksum( &Emm2IO.RecvBuf[1],Emm2IO.RecvLen-3 );
if( Emm2IO.ID==EMM_IO31_ID )
{
IoEmm31Ptr = (IO_EMM_31 *)Emm2IO.RecvBuf;
if( ver==IoEmm31Ptr->Checksum )
{
CopyEmm31ToDev( IoEmm31Ptr );
CopyEmm31ToEmm31Buf( IoEmm31Ptr );
ptr = (uchar*)&IOEmm31;
ptr++;
// IOEmm31.AutoTollInputStatus3.byte = IoCheck.SaveState.byte[3];
// IOEmm31.LocalIOInputStatus.byte = IoCheck.SaveState.byte[0];
// IOEmm31.AutoTollInputStatus1.byte = IoCheck.SaveState.byte[1];
// IOEmm31.AutoTollInputStatus2.byte = IoCheck.SaveState.byte[2];
// IOEmm31.AutoTollInputStatus3.byte = IoCheck.SaveState.byte[3];
ver = Checksum( ptr,sizeof(IO_EMM_31)-3 );
IOEmm31.Checksum = ver;
CopyToUart1SendBuf( (uchar*)&IOEmm31, sizeof(IO_EMM_31) );
}
}
else if( Emm2IO.ID==EMM_IO32_ID )
{
IoEmm32Ptr = (IO_EMM_32 *)Emm2IO.RecvBuf;
if( ver==IoEmm32Ptr->Checksum )
{
CopyEmm32ToDev( IoEmm32Ptr );
CopyToUart1SendBuf( (uchar*)IoEmm32Ptr, sizeof(IO_EMM_32) );
}
}
}
else
{
Emm2IO.Error.byte = 0;
}
Emm2IO.RecvPtr = 0;
Emm2IO.ID = 0;
}
//When no polling with EMM > 5 seconds.
if( Timer[TIMER_STOP].Flg.BIT.TimeOut )
{
Timer[TIMER_STOP].Flg.BIT.TimeOut = 0;
//TMU
IOTmu.TollCollectorID[0] = 0x0b;
IOTmu.TollCollectorID[1] = 0xbb;
IOTmu.TollCollectorID[2] = 0xbb;
IOTmu.LoginDuration[0] = 0xbb;
IOTmu.LoginDuration[1] = 0xbb;
IOTmu.VehicleClass = 0xbb;
IOTmu.AxlePaymentDisplay.byte = 0xbb;
IOTmu.TMU_Control1.byte = 0x00;
IOTmu.TMU_Control2.byte = 0x40;
//TPS
IOTps.TollFare.word = 0xbbbb;
IOTps.LedDisplay.BIT.Rlight = 1;
IOTps.LedDisplay.BIT.Glight = 0;
IOTps.LedDisplay.BIT.DispPleasePaid = 0;
IOTps.LedDisplay.BIT.DispThankyou = 0;
//CLS
IOCls.VehicleClass = 0xbb;
IOCls.AxleCounterDisplay.byte = 0x00;
//Entry Lss
IOEntryLss.SignalDisp.byte = 0x01;
//Exit Lss
IOExitLss.SignalDisp.byte = 0x01;
}
}
主程序循环,
代码多年前写,基于飞利浦双串口单片机,程序结构是大循环前后台标志,就算现在用上了linux、rtos等的方式,程序接收处理方式差别不大,只是实现起来更简单
下面是完整工程连接
链接:https://pan.baidu.com/s/1bXOrMRH6Gf7kcjra4uANtA?pwd=1234
提取码:1234