使用stm32 通過串口對接一款數據採集終端,對終端發送一條指令,串口會返回不定量的數據,
剛開始使用串口接收中斷的方式處理數據,發現處理速度較慢,出現丟幀情況。
進而改成迴環結構接收數據。
typedef struct
{
short write_point;//寫指針
u8 Reader_RX_Buffer_Second[4096];//存儲空間
short read_point;//讀指針
u8 loop;//如果寫指針到末端的時候,重頭開始寫表示
}READER_UART_REC_STRUCT_T;
串口接收方法:
void DEBUG_Reader_IRQHandler(void)
{
u8_t res;
if(USART_GetITStatus(DEBUG_Reader, USART_IT_RXNE) != RESET)//接收到數據
{
res =USART_ReceiveData(DEBUG_Reader);//;讀取接收到的數據USART2->DR
if(reader_uart_rec_t.loop<1 && reader_uart_rec_t.write_point>=reader_uart_rec_t.read_point)
{
reader_uart_rec_t.Reader_RX_Buffer_Second[reader_uart_rec_t.write_point++] = res;
if(reader_uart_rec_t.write_point == 4095)
{
reader_uart_rec_t.write_point = 0;
reader_uart_rec_t.loop = 1;
}
}else if(reader_uart_rec_t.write_point<reader_uart_rec_t.read_point)
{
reader_uart_rec_t.Reader_RX_Buffer_Second[reader_uart_rec_t.write_point++] = res;
}
USART_ClearITPendingBit(DEBUG_Reader, USART_IT_RXNE);
}
}
數據解析方法:
main()
{
//我的協議最小數據長度爲6
if(reader_uart_rec_t.write_point>(reader_uart_rec_t.read_point+5) || reader_uart_rec_t.loop>0)
{
//數據處理方法
AnalyData(&reader_uart_rec_t);
}
}
typedef struct
{
u8 head;
u8 len;
u8 address;
u8 cmd;
}RECEIVE_EPC_DATA_HEAD_T;
void AnalyData(READER_UART_REC_STRUCT_T* reader_uart_rec)
{
RECEIVE_DATA_HEAD_T head;
if(reader_uart_rec->loop == 1)
{
len = 4095+reader_uart_rec->write_point - reader_uart_rec->read_point;
}else
{
len = reader_uart_rec->write_point - reader_uart_rec->read_point;
}
while(len>0)
{
len--;
if(reader_uart_rec->read_point >= 4096)
{
reader_uart_rec->read_point = 0;
reader_uart_rec->loop = 0;
}
//0xA0 是協議報頭 循環查找報頭,報頭不對則移動指針,正確則判斷符不符合協議頭,然後再處理數據
if(reader_uart_rec->Reader_RX_Buffer_Second[reader_uart_rec->read_point] == 0xA0)
{
memcpy(&head,&reader_uart_rec->Reader_RX_Buffer_Second[reader_uart_rec->read_point],sizeof(RECEIVE_DATA_HEAD_T));
switch(head.cmd)
{
case 0x1:
//處理數據
if((reader_uart_rec->read_point+ head.len+2)>4095)
{
reader_uart_rec->read_point = reader_uart_rec->read_point+ head.len+2-4095;
reader_uart_rec->loop = 0;
}else
{
reader_uart_rec->read_point = reader_uart_rec->read_point+ head.len+2;
}
len = len - head.len-1;
break;
default:
reader_uart_rec->read_point++;//如果協議不在處理範圍,可能是錯誤數據或者出現了丟幀,則read下標後移
break;
}
}else
{
//如果數據不符合包頭則read下標後移繼續找報頭
reader_uart_rec->read_point++;
}
}
}