![]() 使用ESP8266或者其它模塊串口AT指令是比較常見,今天我們學(xué)習(xí)如何設(shè)計(jì)和使用AT指令,方案是:?jiǎn)纹瑱C(jī)STM32+串口通訊+AT指令+labview上位機(jī),涉及STM32和Labview代碼的完整串口數(shù)據(jù)通訊流程,具體要求如下: 任務(wù):學(xué)會(huì)使用labview結(jié)合STM32語言實(shí)現(xiàn)AT指令數(shù)據(jù)通訊 要求: 01.STM32串口基本配置、發(fā)送、接收數(shù)據(jù)的語法; 02.構(gòu)建STM32單片機(jī)的AT指令處理體系 03.學(xué)會(huì)C語言的字符串處理函數(shù)strstr、strcmp函數(shù)、atoi函數(shù)使用; 03.實(shí)現(xiàn)AT接收、AT發(fā)送、AT的應(yīng)答、實(shí)現(xiàn)靈活指令; 04.用ESP8266模塊實(shí)現(xiàn)labview數(shù)據(jù)的接收和數(shù)據(jù)的處理; 關(guān)鍵詞:labview、STM32、ESP8266、strcmp函數(shù)、strstr函數(shù)、atoi、VISA 備注1:手機(jī)微信可瀏覽相關(guān)高清圖片; 二、串口通訊原理 06、產(chǎn)品通常需要獲取數(shù)據(jù)和設(shè)置數(shù)據(jù)兩個(gè)操作,而且字符長(zhǎng)度不固定,比如Modbus協(xié)議和AT指令,RTU模式和ASCII模式;
AT指令不固定長(zhǎng)度,串口接收函數(shù)需要獲取到接收的起點(diǎn)終點(diǎn)和長(zhǎng)度,同時(shí)需要有錯(cuò)誤處理、超時(shí)恢復(fù)機(jī)制、超長(zhǎng)恢復(fù)機(jī)制; #include 'stm32f10x.h' #include 'stdio.h' #include 'string.h' //strstr strlen strcmp char USART2_RX_BUF[200]=''; //接收緩沖,最大USART_REC_LEN個(gè)字節(jié). u8 uart2_i=0; u16 USART2_REC_LEN=4; u16 USART2_RX_STA=0; //串口字節(jié)指針 //接收字節(jié)長(zhǎng)度//接收狀態(tài)標(biāo)記 char * user_after(char *instr,char *markstr)//輸入源字符串和目標(biāo)字段,輸出目標(biāo)字段后面的字符 {//剪切處理字符串(指針方法) char *p; int i; if(strstr(instr,markstr)!=NULL){ p=strstr(instr,markstr); i=strlen(markstr); p+=i; return p; } else{ p=NULL; } }
int main(void) { float i=0.0f; 串口初始化(); //串口初始化 while(1) { if(usercmd_en==1) // 需要重新定義 USART2_RX_STA { // usercmd 需要重新定義 USART2_RX_BUF if(strcmp(usercmd,'AT')==0) printf('ok\r\n'); //應(yīng)答測(cè)試指令 if(strcmp(usercmd,'AT+GetADC')==0) printf('CH1=%f \r\n',讀取到的數(shù)據(jù)); //讀取參數(shù)類 if(strstr(USART2_RX_BUF,'AT+SetDAC')!=NULL){ //參數(shù)設(shè)置類 strbuf = user_after(USART2_RX_BUF,'AT+SetDAC='); i0buf=atoi(strbuf); 設(shè)置模擬輸出函數(shù)(i0buf); } usercmd_en=0; } } }
void USART_IRQHandler(void) { u8 r;//串口2中斷服務(wù)程序(正常)字符限制,有結(jié)束字符檢測(cè),未加入超時(shí)清空緩存區(qū) if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)//接收中斷 { r =USART_ReceiveData(USART2);//(USART2->DR); //讀取接收到的數(shù)據(jù) USART2_RX_BUF[uart2_i++]=r; if(uart2_i>200)uart2_i=0; //數(shù)據(jù)超過長(zhǎng)度 if(r=='\n' && USART2_RX_BUF[uart2_i-2]=='\r') //判斷是否回車,可加入CRC { USART2_RX_BUF[uart2_i-2]='\0'; //加結(jié)束符號(hào),將數(shù)據(jù)去掉回車符號(hào) USART2_REC_LEN=uart2_i-2; //記錄字符長(zhǎng)度 USART2_RX_STA=1; //接收到一條未知數(shù)據(jù)需要處理,#define usercmd_en USART2_RX_STA 重定義為 uart2_i=0; //清零索引指針 } } } 五、上位機(jī)串口數(shù)據(jù)對(duì)接 Labview串口讀取最常用的方式是輪詢查詢讀取緩存區(qū)的數(shù)據(jù)(架構(gòu)代碼1),只要將輪詢時(shí)間調(diào)整合適就能實(shí)現(xiàn)正常數(shù)據(jù)接收,只要時(shí)間合適接收就沒問題,時(shí)間合適就可以! 通過架構(gòu)代碼1來分析輪詢讀取串口數(shù)據(jù)的問題: 在現(xiàn)實(shí)應(yīng)用中串口控制通常是不規(guī)定長(zhǎng)度的指令,那么運(yùn)用代碼1模式接收數(shù)據(jù)會(huì)出現(xiàn):短指令正常,長(zhǎng)指令出錯(cuò)的情況。那按照最長(zhǎng)指令計(jì)算等待時(shí)間,會(huì)發(fā)現(xiàn)等待時(shí)間變長(zhǎng)不能滿足響應(yīng)時(shí)間的要求。 01、如何在不影響<實(shí)時(shí)響應(yīng)>性能的情況下<適應(yīng)不同長(zhǎng)度>的指令? 02、按照代碼2的思想是:運(yùn)用上位機(jī)等待中斷方式,獨(dú)立一個(gè)進(jìn)程作為生產(chǎn)者,短時(shí)間接收數(shù)據(jù),然后將相鄰有效數(shù)據(jù)拼接起來驗(yàn)證,接收為空時(shí)清空緩存(可在代碼2中添加驗(yàn)證成功時(shí)清空緩存)。 03、接下來進(jìn)行上位機(jī)的實(shí)例介紹,選擇有成熟協(xié)議的ESP8266無線模塊進(jìn)行上位機(jī)AT指令的對(duì)接: ![]() ![]() 03、可以參考使用該labview結(jié)構(gòu)來設(shè)計(jì)STM32的AT指令對(duì)接上位機(jī),注意事件結(jié)構(gòu)進(jìn)入指定事件一定取消鎖定選項(xiàng)不要鎖定前面板(鎖定后所有前面板局部變量?jī)鼋Y(jié)不再實(shí)時(shí)更新),如果對(duì)應(yīng)事件中用到局部變量數(shù)據(jù),會(huì)有計(jì)算出錯(cuò)現(xiàn)象,還不容易查找錯(cuò)誤點(diǎn),建議盡量多使用數(shù)據(jù)流設(shè)計(jì),減少局部變量的使用; |
|