1、接收部分
身份证模块串口接收解析:
#define CRC_16_CCITT 0x1021
unsigned short CRC16_CCITT(unsigned char* pchMsg, unsigned short wDataLen) // 1. MSB
{
unsigned char i, chChar;
unsigned short wCRC = 0;
while (wDataLen–)
{
chChar = *pchMsg++;
wCRC ^= (((unsigned short)chChar) << 8);
for (i = 0; i < 8; i++)
{
if (wCRC & 0x8000)
wCRC = (wCRC << 1) ^ CRC_16_CCITT;
else
wCRC <<= 1;
}
}
return wCRC;
}
uint32_t Dispose_Uart1RecData(void)
{
#define frame_head 0x7E
volatile static uint8_t rec_number = 0;
volatile static uint8_t state_machine = 0; //这里每接收一个字节,进入一个中断
volatile static uint8_t rcvcou_temp = 0;
volatile static uint8_t lencnt = 0;
volatile static uint8_t m_ucData[20] = {0};
volatile static uint8_t rec_dat = 0;
volatile static uint8_t rec_temp = 0;
volatile static uint8_t rec_len = 0;
volatile static uint8_t len2cnt = 0;
volatile static uint8_t rcv2cou = 0;
volatile static uint16_t rev_crc = 0;
volatile static uint8_t crc_h = 0;
volatile static uint8_t crc_l = 0;
rec_dat = (uint8_t)(huart1.Instance->DR); //中断接收到的单个数据;
if(state_machine == 0)
{
if(rec_dat == frame_head)
{
lencnt = 0;
rcvcou_temp = 3; // 第一个数据长度
rec_data[rec_number] = rec_dat; //rec_data保存接收到的数据
state_machine = 1;
rec_number++;
}
else
{
state_machine = 0;
rec_number = 0;
}
}
else if(1 == state_machine)
{
m_ucData[lencnt++] = rec_dat; // m_ucData数据暂时不用,lencnt需要自加
if(lencnt == rcvcou_temp) // 已接收了第一个数据长度的数据
{
state_machine = 2;
rec_data[rec_number] = rec_dat;
rcv2cou = rec_data[3];
len2cnt = 0;
rec_number++;
}
else
{
rec_data[rec_number] = rec_dat;
rec_number++;
}
}
else if(2 == state_machine)
{
m_ucData[len2cnt++] = rec_dat;
if(2 == rcv2cou)
{
state_machine = 4;
rec_data[rec_number] = rec_dat;
rec_number++;
rev_crc = CRC16_CCITT(rec_data+1,rec_number-2); //计算crc16
crc_h = (uint8_t)(rev_crc & 0xff);
crc_l = (uint8_t)((rev_crc >> 8) & 0xff);
}
else
{
if(len2cnt == (rcv2cou-2))
{
state_machine = 3;
rec_data[rec_number] = rec_dat;
rec_number++;
rev_crc = CRC16_CCITT(rec_data+1,rec_number-1); //计算crc16
crc_h = (uint8_t)(rev_crc & 0xff);
crc_l = (uint8_t)((rev_crc >> 8) & 0xff);
}
rec_data[rec_number] = rec_dat;
rec_number++;
}
}
else if(state_machine == 3)
{
if(crc_h == rec_dat)
{
state_machine = 4;
rec_data[rec_number] = rec_dat;
rec_number++;
}
else
{
state_machine = 0;
rec_number = 0;
}
}
else if(state_machine == 4)
{
if(crc_l == rec_dat) // 判断异或校验和是否相等
{
rec_data[rec_number] = rec_dat;
HAL_UART_Transmit(&huart1,rec_data,sizeof(rec_data),1000); //测试用
//HAL_UART_Transmit(&huart1,&rec_dat,1,1000);
Parse_UartsDatas();
uart1_rev_finish_flag = 1; //一帧数据接收完成标志;
len2cnt = 0;
state_machine = 0; // 状态机复位
rec_number = 0;
}
else
{
state_machine = 0;
rec_number = 0;
}
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)&rec_temp, 1); //重新使能串口接收中断
return 0;
}
2、发送部分总结:
对于不定长数据帧,结构体中帧尾和校验就不能有,直接是data[]数据,校验后计算给出帧尾和校验。
3、通信协议:(见自定义的—身份证模块通讯协议)
1、协议说明
串口设置:115200,8 数据位、1 停止位、无校验
协议构成
帧头 功能码 子功能码 数据长度 命令数据 校验位
1Byte 1Byte 1Byte 1Byte nByte(n>0) 2Byte
帧头:十六进制表示;固定为7E。
数据长度:十六进制表示;功能码、子功能码、命令数据的长度之和。
功能码:功能码用于标识执行不同的功能,长度为1个字节,可以根据需要完成的功能来进行相应的定义。
子功能码:
子功能码是对功能码的细化,长度为1个字节。其中子功能码的最高位0表示发送的请求,最高位1表示返回的响应。
命令数据:多字节时低字节在前,高字节在后。
校验位: 2字节。根据数据包(从“功能码”计算到“命令数据”)生成CRC校验值。校验单元采用CRC校验,生成多项式为CCITT推荐的16位的0x11021。发送方生成2字节的CRC校验(传输时低字节在前,高字节在后);同样,接收方收到完整的数据包后,生成新的CRC校验值。如果所计算出的CRC值和收到的校验值相等则表明该校验值有效,否则认为该包在传输过程中产生了差错。对校验出错的命令,接收方不处理也不返回任何的应答。
注1:命令数据中的数据大于1Byte的数据采用小端模式(低字节在前,高字节在后)。所有均需主机下发指令读取,从机不会主动上报任何数据。
注2:一包发送数据的总长度不得超过 250 Byte。
2、功能码与子功能码
表2-1功能码与子功能码
3、功能码表
4、指令详细说明
4.1 查询系统板状态(0x01)
控制板发送命令如下:
7E 01 01 02 43 24 (对系统板1的查询);
系统板返回命令示例如下:
7E 81 01 03 01 CE D9(系统板1在线)
(系统板1不在线,将无响应数据)
控制板发送命令如下:
7E 01 02 02 10 71 (对系统板2的查询,对另3个系统板查询子功能码参考表2-1功能码与子功能码);
系统板返回命令示例如下:
7E 81 02 02 01 AF B3(系统板2在线)
(系统板2不在线,将无响应数据)
4.2 开始系统板测试(0x02)
控制板发送命令如下:
7E 02 01 02 13 7D (对系统板1的开始测试命令,对另4个系统板开始测试子功能码参考表2-1功能码与子功能码);
系统板返回命令示例如下:
7E 82 01 02 49 46(及时响应命令)
7E 82 01 06 01 01 01 01 AB 21(4路身份证模块测试完成后,响应的测试结果命令,测试正常为01,测试失败为00);
4.3 重启系统板(0x03)
控制板发送命令如下:
7E 03 00 02 12 79(无子功能码时候,默认为00)
系统板返回命令示例如下:
7E 83 00 02 48 42
4.4 读取系统板软件版本号(0x04)
控制板发送命令如下:
7E 04 00 02 82 FC(无子功能码时候,默认为00)
系统板返回命令示例如下:(V01.03.01.201230)
7E 84 00 12 56 30 31 2E 30 33 2E 30 31 2E 32 30 31 32 33 30 FC 98
4.5 停止USB测试(0x05)暂时不用
控制板发送命令如下:
7E 05 00 02 B2 CB
系统板返回命令示例如下:
7E 85 00 02 E8 F0