池州有哪些做网站的,辽宁省建设厅官方网,阿里云oss可以做网站,青海建筑网站建设公司【 声明#xff1a;版权所有#xff0c;欢迎转载#xff0c;请勿用于商业用途。 联系信箱#xff1a;feixiaoxing 163.com】 这种mcu的嵌入式模块理论上都是私有协议#xff0c;因为上位机和下位机都是自己开发的#xff0c;所以只需要自己保证上、下位机可以通讯上…【 声明版权所有欢迎转载请勿用于商业用途。 联系信箱feixiaoxing 163.com】 这种mcu的嵌入式模块理论上都是私有协议因为上位机和下位机都是自己开发的所以只需要自己保证上、下位机可以通讯上没有问题就行。但是现在有一个情况那就是如何实现这个协议。现在我们是选择了ttl作为通信的方式下面要做的就是如何用ttl实现通信协议。 1、上、下位机分开测试 前面准备好了通信的协议各自就可以独立开发了。上位机可以用利用虚拟com进行测试自己写一个假的下位机。而下位机呢则可以通过串口工具来进行测试。一般来说下位机如果测试没有问题了才会去找上位机进行联合调试不然调试的效率就太低了。 对于下位机来说只要串口工具ok了那么上位机不管是qt还是mfc、c# wpf只要按照协议把数据发下来那就应该没问题的。 2、调试的时候一般都是通过16进制调试的 通常来说发送的协议就是8位无符号数据不是字符串。所以这个时候调试的时候不管是接收命令还是发送命令最好都是通过16进制进行调试。 3、上位机一般是主动的那一方 通常来说上位机都是主动的那一方。不管是去读数据还是写数据上位机都是主动发起请求的一方。这个时候对于下位机来说回复好上位机的问题给出相应的答案就可以了。 4、压力测试是一定要的 协议解析的过程有可能出现不对的地方这是很常见的。而且随着开发的进行有可能添加各种不同样的协议内容。所以不管哪一种协议我们在实现和验证的时候一定要进行压力测试即通过串口工具周期性发送一些命令这些都是可以的。单挑发送、多条发送、随机发送一般的上位机工具都会支持这样的测试。 5、使用fsm去解析协议 串口的属性决定了我们是一个、一个去接收数据的。这个时候就要求我们需要根据这些单个的数据来判断它是否符合协议的要求。要做到这一点最好的方法就是用有限状态机fsm去实现。比如说首先是什么状态接收到一个数据应该是什么状态是继续维持还是说继续走向下一个状态。一般来说只要状态机设计好基本上固件都是非常稳定的。
void receiveUartData(void) // receive data and parse data here
{int index 0;if (USART_ReadIntFlag(USART_UX, USART_INT_RXBNE) SET){g_rx_buffer[0] USART_RxData(USART_UX); /* receive one byte data*/switch(uartState){case HEAD_STATE1: // wait 0x55if(g_rx_buffer[0] 0x55){g_usart_rx_buf[0] g_rx_buffer[0];g_usart_rx_sta ;uartState HEAD_STATE2;}else{g_usart_rx_sta 0;}break;case HEAD_STATE2: // wait another 0x55if(g_rx_buffer[0] 0x55){g_usart_rx_buf[1] g_rx_buffer[0];g_usart_rx_sta ;uartState TAIL_STATE1;}else{g_usart_rx_sta 0;uartState HEAD_STATE1;}break;case TAIL_STATE1: // wait 0xaaif(g_usart_rx_sta 32){g_usart_rx_sta 0;uartState HEAD_STATE1;break;}g_usart_rx_buf[g_usart_rx_sta] g_rx_buffer[0];g_usart_rx_sta ;if(g_rx_buffer[0] 0xaa){uartState TAIL_STATE2;}break;case TAIL_STATE2: // wait another 0xaag_usart_rx_buf[g_usart_rx_sta] g_rx_buffer[0];g_usart_rx_sta ;if(g_rx_buffer[0] 0xaa useFlag 0) /* if useFlag 0 or not qualified data, just drop it directly*/{for(index 0; index g_usart_rx_sta; index){transferBuf[index] g_usart_rx_buf[index];}bufLen g_usart_rx_sta;useFlag 1;}g_usart_rx_sta 0;uartState HEAD_STATE1;break;default:break;}USART_ClearIntFlag(USART_UX, USART_INT_RXBNE);}
}6、协议的处理可以放到main里面继续进行 中断部分只是负责数据的接收具体命令的解析可以放到main函数里面继续执行。毕竟接收数据本身是在中断函数处理的这部分花的时间越少越好。而具体的数据解析实时性没那么高慢一点都是没有关系的。
extern uint16_t voltage; // add by feixiaoxing
int parseData() // use app tool to test the data
{unsigned char str[32] {0};if(useFlag 0){return -1;}if(0 bufLen){setFlag();return -1;}if(bufLen 4){setFlag();return -1;}if(transferBuf[0] ! 0x55 || transferBuf[1] ! 0x55){setFlag();return -1;}if(transferBuf[bufLen-2] ! 0xaa || transferBuf[bufLen-1] ! 0xaa){setFlag();return -1;}if(bufLen ! 10) // header length commandid crc tail{setFlag();return -1;}// restore flagsetFlag();// prepare datastr[ 0] 0x55; // headerstr[ 1] 0x55;str[ 2] 0x00; // lengthstr[ 3] 0x08;str[ 4] 0x00; // command id;str[ 5] 0x00;str[ 6] voltage / 1000; // datastr[ 7] voltage % 1000;str[ 8] 0x00; // crcstr[ 9] 0x00;str[10] 0xaa; // tailstr[11] 0xaa;outputData((char*)str, 12);return 0;
}