解決Python串口接收無(wú)標(biāo)識(shí)不定長(zhǎng)數(shù)據(jù)
Python串口接收無(wú)標(biāo)識(shí)不定長(zhǎng)數(shù)據(jù)
python串口讀取數(shù)據(jù)可以使用:
- serial.read(n) n為讀取數(shù)據(jù)個(gè)數(shù),無(wú)參則讀取一個(gè)
- serial.readline() 讀取到\n,讀不到則阻塞直到讀取到\n
在接收不定長(zhǎng)數(shù)據(jù)時(shí),沒有n可以指定,接收數(shù)據(jù)也未必有\(zhòng)n,python又沒有串口空閑中斷,但是可以用延時(shí)來(lái)解決。
import serial from time import sleep ser = serial.Serial(port="COM5",baudrate=9600,timeout=0.5) if ser.isOpen() : print("open") while True : n = ser.inWaiting() if n : sleep(0.1) n = ser.inWaiting() data = ser.read(n) print(data) else: print(" not open") ser.close()
接收可以單開一個(gè)線程,在接收到數(shù)據(jù)后延時(shí)0.1s再查詢當(dāng)前緩沖區(qū)數(shù)據(jù)個(gè)數(shù),第一次查詢并不接收,所以不會(huì)清除緩存。
相當(dāng)于接收到數(shù)據(jù)后,延時(shí)0.1s后再取數(shù)據(jù)。
也就是下位機(jī)發(fā)送的數(shù)據(jù)需要在0.1s內(nèi)發(fā)送完成,發(fā)送間隔大于0.1s。
這個(gè)時(shí)間應(yīng)該根據(jù)下位機(jī)發(fā)送來(lái)定。
注意:
上位機(jī)與下位機(jī)數(shù)據(jù)收發(fā)時(shí)序需考慮
串口接收不定長(zhǎng)數(shù)據(jù)的問題
這個(gè)通用的方法,其實(shí)原理就是傳輸兩個(gè)字節(jié)間是否超過了指定時(shí)間,如果超過了一定的時(shí)間,就認(rèn)為是接收完一幀數(shù)據(jù)了。
首先我們要知道,串口是接收一個(gè)字節(jié),就會(huì)發(fā)生一次中斷,如果一幀數(shù)據(jù)包含10個(gè)字節(jié),就會(huì)發(fā)生10次中斷。
在接收一個(gè)字節(jié)以后,會(huì)緊跟著接收下一個(gè)字節(jié),如果時(shí)間超了一定值,就代表一幀數(shù)據(jù)已經(jīng)發(fā)完了
比如.
波特率為9600,8位(數(shù)據(jù)位)+2位(開始位+停止位)=10位 :每個(gè)串口中斷時(shí)間為10位 *(1000/9600),那么傳一個(gè)字節(jié)1MS左右,
/*----------------------------------*/ /*-------- 定時(shí)器3 操作函數(shù) --------*/ /*----------------------------------*/ void t3int() interrupt 19 using 1 //中斷入口 { if(uart2Ri_start){ uart2Ri_start_time++; if(uart2Ri_start_time>12){ uart2Ri_start=0; uart2Ri_start_time=0; uart2Ri_frame_flat=1; uart2Ri_cnt=0; } } time_ms_pwm++; time500ms_tmp1++; //時(shí)間點(diǎn)切換計(jì)時(shí) //脈沖寬度調(diào)制 if(time_ms_pwm <= pwm){ OE =0; }else{ OE =1; if(time_ms_pwm >= 14 ){ time_ms_pwm =0; OE =1; } } RunLed++; if(RunLed>200){ RunLed=0; RunState=~RunState; } } /*---------------------------- 串口中斷2 中斷服務(wù)程序 -----------------------------*/ #define S2RI 0x01 //S2CON.0 #define S2TI 0x02 //S2CON.1 #define S2RB8 0x04 //S2CON.2 #define S2TB8 0x08 //S2CON.3 char Count=0; int uart1TimeOut=0; char data1; void Uart2() interrupt 8 using 1 { unsigned char dat =0; //暫存接收的數(shù)據(jù) //接收操作 if (S2CON & S2RI){ S2CON &= 0xfe; uart2Ri_start=1; //串口接收開始計(jì)時(shí) if(uart2Ri_cnt<uart2Ri_maxCnt){ rxd_buf[uart2Ri_cnt++]=S2BUF; } else { uart2Ri_cnt=uart2Ri_maxCnt; } uart2Ri_start_time=0; } if (S2CON & S2TI) { S2CON &= ~S2TI; //清除S2TI位 busy = 0; //清忙標(biāo)志 } }
unsigned char time_ms =9; /******************************************************************* * 函數(shù)名 : timer0_init * 描述 : 1毫秒的中斷。 * 參數(shù) : ALL_INT_Enable -- 使能總中斷 ********************************************************************/ void tm0_isr() interrupt 1 using 1 { time_ms++; if(USART2_RX_STA & 0x40){ uart_time_sta++; //接收超時(shí)計(jì)時(shí) if( uart_time_sta >=12){ // rx_cnt =0; USART2_RX_STA =0x80; //這里也清0了允許接收位 // USART2_485_Status_Rx_Tx=1;//接收發(fā)送標(biāo)記位。 } } }
以下是串口的部分,串口接收發(fā)送部分的調(diào)用過
#include "main.h" #include "uart.h" #include "protocol_process.h" #include "stdio.h" #define FOSC 11059200L //系統(tǒng)頻率 #define BAUD 115200 //串口波特率 //#define FOSC 11059200L //系統(tǒng)頻率 //#define BAUD 115200 //串口波特率 #define NONE_PARITY 0 //無(wú)校驗(yàn) #define ODD_PARITY 1 //奇校驗(yàn) #define EVEN_PARITY 2 //偶校驗(yàn) #define MARK_PARITY 3 //標(biāo)記校驗(yàn) #define SPACE_PARITY 4 //空白校驗(yàn) #define PARITYBIT EVEN_PARITY //定義校驗(yàn)位 #define S2RI 0x01 //S2CON.0 #define S2TI 0x02 //S2CON.1 #define S2RB8 0x04 //S2CON.2 #define S2TB8 0x08 //S2CON.3 #define S2_S0 0x01 //P_SW2.0 bit busy; //dong 2019-03-19 //unsigned char rx_max_len =256; xdata unsigned char USART2_RX_BUF_test[ rx_max_len ]; xdata unsigned char USART2_RX_BUF[ rx_max_len ]; xdata unsigned char USART2_TX_BUF[ rx_max_len ]; unsigned char USART2_485_Status_Rx_Tx=0; unsigned char USART2_RX_STA =0; //位[7]-接收成功標(biāo)志,位[6]-允許接收數(shù)據(jù)標(biāo)志(包頭正確標(biāo)志) unsigned char uart_time_sta =0; //用于串口接收計(jì)時(shí) unsigned char rx_cnt =0; void uart2_init(char ALL_INT_Enable) { P_SW2 &= ~S2_S0; //S2_S0=0 (P1.0/RxD2, P1.1/TxD2) //P_SW2 |= S2_S0; //S2_S0=1 (P4.6/RxD2_2, P4.7/TxD2_2) S2CON = 0x50; //8位可變波特率 T2L = (65536 - (FOSC/4/BAUD)); //設(shè)置波特率及重裝值 T2H = (65536 - (FOSC/4/BAUD))>>8; AUXR |= 0x14; //T2為1T模式, 并啟動(dòng)定時(shí)器2 IE2 = 0x01; //使能串口2中斷 if(ALL_INT_Enable){ EA = 1; }else{ EA = 0; } } void UartInit(void) //9600bps@11.0592MHz { P_SW2 &= ~S2_S0; //S2_S0=0 (P1.0/RxD2, P1.1/TxD2) S2CON = 0x50; //8位數(shù)據(jù),可變波特率 AUXR |= 0x04; //定時(shí)器2時(shí)鐘為Fosc,即1T T2L = 0xE0; //設(shè)定定時(shí)初值 T2H = 0xFE; //設(shè)定定時(shí)初值 AUXR |= 0x10; //啟動(dòng)定時(shí)器2 } void SendData(unsigned char dat) { while (busy); //等待前面的數(shù)據(jù)發(fā)送完成 busy = 1; S2BUF = dat; //寫數(shù)據(jù)到UART2數(shù)據(jù)寄存器 } void SendString(unsigned char *s, unsigned char len) { unsigned char i =0; for(i=0; i<len; i++){ SendData(*s++); //發(fā)送當(dāng)前字符 } } /*---------------------------- 發(fā)送串口數(shù)據(jù) ----------------------------*/ void SendData2(char dat) { while (busy); //等待前面的數(shù)據(jù)發(fā)送完成 // ACC = dat; //獲取校驗(yàn)位P (PSW.0) S2BUF = dat; //寫數(shù)據(jù)到UART2數(shù)據(jù)寄存器 busy = 1; } /*---------------------------- 發(fā)送字符串 ----------------------------*/ void SendString2(char *s) { while (*s) //檢測(cè)字符串結(jié)束標(biāo)志 { SendData2(*s++); //發(fā)送當(dāng)前字符 } } //重寫putchar函數(shù) char putchar(char c) { SendData2(c); return c; } //用于485接收完成數(shù)據(jù)后再發(fā)送數(shù)據(jù) void Uart2() interrupt 8 using 1 /* UART2 中斷服務(wù)程序 */ { unsigned char dat =0; //暫存接收的數(shù)據(jù) unsigned char checksum =0; unsigned char offset =0; //接收操作 if ( (S2CON & S2RI) && (USART2_485_Status_Rx_Tx==0 )){ //當(dāng)USART2_STA_RX_TX:0時(shí)為485數(shù)據(jù)線空閑狀態(tài)。 // if ( (S2CON & S2RI) ){ //當(dāng)USART2_STA_RX_TX:0時(shí)為485數(shù)據(jù)線空閑狀態(tài)。 USART2_485_Status_Rx_Tx=1; //S2CON &= ~S2RI; //清除S2RI位 S2CON &= 0xfe; //清除S2RI位 dat = S2BUF; //數(shù)據(jù)包接收是否允許標(biāo)志位檢測(cè) USART2_RX_STA |= 0x40; //完成時(shí)不接收,清0了才能接收數(shù)據(jù),主函數(shù)查詢處理完成后置1,并將接收數(shù)據(jù)緩存清空掉待下次接收。 if( !(USART2_RX_STA & 0x80) ){ uart_time_sta =0x00; //連續(xù)每來(lái)一字節(jié)間隔時(shí)間清0,達(dá)到不過超時(shí)時(shí)間,過了超時(shí)時(shí)間置1 //USART2_RX_STA的第二個(gè)位允許接收數(shù)據(jù)標(biāo)志檢測(cè) if(USART2_RX_STA & 0x40){ if(rx_cnt < rx_max_len){ USART2_RX_BUF[rx_cnt++] =dat; } else { //數(shù)據(jù)包接收完成 // rx_cnt =0; // USART2_485_Status_Rx_Tx=1; //大于最大長(zhǎng)度退出時(shí)接收標(biāo)志位為0:空閑 USART2_RX_STA =0x80; uart_time_sta =12; } } } } //發(fā)送操作 if (S2CON & S2TI){ // S2CON &= ~S2TI; //清除S2TI位 S2CON &= 0xfd; //清除S2TI位 // S2BUF=checksum; busy = 0; //清忙標(biāo)志 } } void clear_rx_buf() { unsigned char i =0; for(i=0; i<rx_max_len; i++){ USART2_RX_BUF[i] =0; } }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
python數(shù)字圖像處理之估計(jì)噪聲參數(shù)
這篇文章主要介紹了python數(shù)字圖像處理之估計(jì)噪聲參數(shù),圖像復(fù)原與重建,想了解圖像處理的同學(xué),一定要好好看看2021-04-04pytorch神經(jīng)網(wǎng)絡(luò)之卷積層與全連接層參數(shù)的設(shè)置方法
今天小編就為大家分享一篇pytorch神經(jīng)網(wǎng)絡(luò)之卷積層與全連接層參數(shù)的設(shè)置方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2019-08-08python爬蟲實(shí)現(xiàn)教程轉(zhuǎn)換成 PDF 電子書
本文給大家分享的是使用python爬蟲實(shí)現(xiàn)把《廖雪峰的 Python 教程》轉(zhuǎn)換成PDF的方法和代碼,有需要的小伙伴可以參考下2017-02-02一文帶你掌握Python?Seaborn數(shù)據(jù)可視化高級(jí)篇
這篇文章主要為大家詳細(xì)介紹了如何使用?Seaborn?創(chuàng)建復(fù)合圖形,如網(wǎng)格圖、因子圖和聚類熱圖等,文中示例代碼講解詳細(xì),感興趣的小伙伴可以學(xué)習(xí)一下2023-07-07關(guān)于python實(shí)現(xiàn)requests接口測(cè)試的問題
requests是一個(gè)很實(shí)用的Python HTTP客戶端庫(kù),Requests是Python語(yǔ)言的第三方的庫(kù),專門用于發(fā)送HTTP請(qǐng)求,這篇文章主要介紹了python實(shí)現(xiàn)requests接口測(cè)試,需要的朋友可以參考下2021-10-10Python使用ctypes調(diào)用C/C++的方法
今天小編就為大家分享一篇關(guān)于Python使用ctypes調(diào)用C/C++的方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01Python?jieba庫(kù)的安裝詳細(xì)圖文教程
jieba庫(kù)的作用主要用于中文分詞,是一種不錯(cuò)的中文分詞組件,下面這篇文章主要給大家介紹了關(guān)于Python?jieba庫(kù)安裝的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-03-03python打包pyinstall的實(shí)現(xiàn)步驟
PyInstaller可將Python代碼打包成單個(gè)可執(zhí)行文件,本文主要介紹了python打包pyinstall的實(shí)現(xiàn)步驟,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10Python語(yǔ)法學(xué)習(xí)之正則表達(dá)式的量詞匯總
通過正則的規(guī)則匹配到的信息都是一個(gè)單獨(dú)的字符存到輸出結(jié)果中的,如何更夠根據(jù)字符串中的詞組進(jìn)行匹配呢?因此本文將帶大家學(xué)習(xí)一下正則表達(dá)式中的量詞符號(hào)與組的概念,感興趣的可以了解一下2022-04-04