Arduino自定義通訊協議解析
阿新 • • 發佈:2019-01-02
編譯執行上傳到板子上以後,在串列埠除錯助手中除錯結果如下圖:/* 自定義的庫函式: 協議解析器 V1.0 解析的資料格式: 協議首部-指令長度-控制指令-校驗和 "控制指令"格式: 裝置型別-裝置號-埠號 */ #include<stdlib.h> #include<string.h> //#pragma warning(disable:4996) #define BUFFER_SIZE 128//假定接收資料的最大長度為128 class ProtocolParser { public: ProtocolParser(char *header); ~ProtocolParser(); void Append(char *data); void AppendChar(char ch);//將從串列埠接收到的字元存到buffer size_t GetDeviceType();//獲取裝置型別 size_t GetDeviceNumber();//獲取裝置號 size_t GetPort();//獲取裝置所連線的埠號 private: bool m_bInCmd;//標誌位,標識一條控制指令是否接收完畢 char *m_pHeader;//協議首部 size_t m_nCmdLength;//指令長度 char *m_pCtrlCmd;//控制指令 size_t m_nCheckSum;//校驗和 char buffer[BUFFER_SIZE];//接收的資料暫時存在buffer中 size_t m_nRecvDataIndex;//記錄接收資料的索引 char GetHeader(size_t index);//獲取協議首部指定索引的字元 size_t GetCmdLength();//獲取控制指令長度 size_t GetRecvDataLength();//獲取接收到的一條控制指令的長度 size_t GetCheckSum();//獲取實際接收到的校驗和 }; //建構函式初始化,header為協議首部 ProtocolParser::ProtocolParser(char *header) { m_bInCmd = false; //strcpy(m_pHeader, header); m_pHeader = header; m_nCmdLength = 0; m_nCheckSum = 0; m_nRecvDataIndex = 0; m_pCtrlCmd = NULL; buffer[0] = '\0'; } ProtocolParser::~ProtocolParser() { } char ProtocolParser::GetHeader(size_t index) { int headerLength = strlen(m_pHeader); return m_pHeader[index]; } //獲取“控制指令”欄位的長度,通過接收到的資料的第2、3位的值獲取 size_t ProtocolParser::GetCmdLength() { int len = strlen(buffer); if (len >= 2) { m_nCmdLength=(buffer[0] - '0') * 16 + (buffer[1] - '0') * 1; } return m_nCmdLength; } //獲取實際接收到的校驗和 size_t ProtocolParser::GetCheckSum() { //int len = strlen(buffer); m_nCheckSum = (buffer[GetCmdLength() * 2 + 2] - '0') * 16 + (buffer[GetCmdLength() * 2 + 3] - '0') * 1; return m_nCheckSum; } //從buffer中解析出裝置型別 size_t ProtocolParser::GetDeviceType() { //int len = strlen(buffer); return (buffer[2] - '0') * 16 + (buffer[3] - '0') * 1; } //從buffer中解析出裝置號 size_t ProtocolParser::GetDeviceNumber() { //int len = strlen(buffer); return (buffer[4] - '0') * 16 + (buffer[5] - '0') * 1; } //從buffer中解析出埠號 size_t ProtocolParser::GetPort() { //int len = strlen(buffer); return (buffer[6] - '0') * 16 + (buffer[7] - '0') * 1; } //將從串列埠接收的字串存入buffer中 void ProtocolParser::AppendChar(char ch) { size_t bufferLength = strlen(buffer); switch (m_nRecvDataIndex) { case 0: case 1://接收到的資料的索引值為0或者1,表示接收到的是首部 m_bInCmd = true; buffer[0] = 0; m_nRecvDataIndex++; return; break; case 2: case 3://接收到的資料的索引值為2或者3,表示接收到的是"指令長度"部分 buffer[m_nRecvDataIndex - 2] = ch; buffer[m_nRecvDataIndex - 1] = '\0'; m_nRecvDataIndex++; return; break; default: break; } if (m_nRecvDataIndex==(GetCmdLength()*2+5))//達到了索引值 { buffer[bufferLength] = ch; buffer[bufferLength + 1] = '\0'; size_t chksum = 0; //計算根據接收的資料得到的校驗和 for (size_t i = 0; i < GetCmdLength()*2;++i) { chksum ^= buffer[i + 2]; } if (chksum==GetCheckSum())//判斷實際接收到的校驗和跟計算出來的校驗和是否相等 { Serial.println("DeviceType:"); Serial.println(GetDeviceType(),DEC); Serial.println("DeviceNumber:"); Serial.println(GetDeviceNumber(),DEC); Serial.println("Port:"); Serial.println(GetPort(),DEC); //GetDeviceNumber(); //GetPort(); //解析buffer的各個欄位的含義 //cout << "DeviceType:" << GetDeviceType() << endl; //cout << "DeviceNumber:" << GetDeviceNumber() << endl; //cout << "Port:" << GetPort() << endl; } else//不相等說明出錯了 { Serial.println("Error"); //cout << "Error" << endl; } buffer[0] = '\0'; m_bInCmd = false; m_nRecvDataIndex = 0; m_nCheckSum = 0; } else if (m_bInCmd)//指令未接收完畢 { buffer[bufferLength] = ch; buffer[bufferLength + 1] = '\0'; m_nRecvDataIndex++; } } void ProtocolParser::Append(char *data) { for (size_t i = 0; i < strlen(data);++i) { AppendChar(data[i]); } } //int led=13; char value; ProtocolParser protocolParser(170); void setup() { // put your setup code here, to run once: Serial.begin(9600); //Serial.println("Parser:"); //pinMode(led,OUTPUT); } void loop() { // put your main code here, to run repeatedly: while(Serial.available()>0){ value=Serial.read(); //Serial.print(value); protocolParser.AppendChar(value); //Serial.println(protocolParser.getPort()); } }