網站首頁 編程語言 正文
前言
在嵌入式開發中我們經常會用到串口,串口通信簡單,使用起來方便,且適用場景多,因此串口常常用來輸出調試Log或者跟其他外設進行通訊,也可以用作上位機和下位機之間的通訊。那這一講我就簡單介紹一下如何用Python編寫一個串口收發程序。
1.環境搭建
Python的環境這里就不具體介紹了,網上教程也很多,我主要介紹一下我們這一講用到的類庫以及當前的版本。
package | version |
---|---|
time | 注:python標準庫,無需安裝 |
pyserial | v3.5 |
注:不懂如何安裝庫的同學請自行查閱資料。
特別說明:本文舉的例子皆是基于windows系統下python3來實現的,其他平臺不一定完全適配。
2.硬件準備
我們要通過電腦的USB接口發送串口數據,在硬件上首先得保證有可用的串口設備接入,并且正確的安裝了驅動。
我這里用的是一個CH340的串口轉TTL的模塊來測試的。
可以用兩個這種模塊相互收發,也可以單個模塊自發自收,或者接入其他嵌入式設備也行。
硬件接入之后我們可以在設備管理器看到設備的端口號,如下圖所示:
3.代碼編寫與測試
3.1 簡單測一下串口收發
示例代碼如下:
import serial #導入模塊
try:
# 端口號,根據自己實際情況輸入,可以在設備管理器查看
port = "COM6"
# 串口波特率,根據自己實際情況輸入
bps = 9600
# 超時時間,None:永遠等待操作,0為立即返回請求結果,其他值為等待超時時間(單位為秒)
time = 5
# 打開串口,并返回串口對象
uart = serial.Serial(port, bps, timeout = time)
# 串口發送一個字符串
len = uart.write("hello world".encode('utf-8'))
print("send len: ", len)
# 串口接收一個字符串
str = ''
for i in range(len):
str += uart.read().decode("utf-8")
print("receive data: ", str)
# 關閉串口
uart.close()
except Exception as result:
print("******error******:", result)
運行測試:
我這里是自發自收,如果運行沒有出錯并且成功發送和接收到正確的數據,說明串口通信是走通了,那么接下來就可以繼續完善這個流程。
如果出現其他問題,則需要檢查硬件和軟件,確保所有配置都沒問題才能繼續進行下一步。
3.2 補充細節
1、串口發送各種不同類型的數據。
串口數據常用字符串和十六進制(hex)表示。下面列舉了一些例子,可以作為一種參考。
示例如下:
data1 = "hello world" # 字符串
data2 = b"hello world" # bytes
data3 = "你好" # 中文字符串
data4 = 0x0A # 整形(以16進制表示)
data5 = [0x10, 0x11, 0x12] # 列表/數組(以16進制表示)
len = uart.write(data1.encode('utf-8')) # 發送字符串"hello world"
len = uart.write(data2) # 發送字符串"hello world"
len = uart.write(data3.encode('utf-8')) # 以utf-8編碼方式發送字符串"你好"(6字節)
len = uart.write(data3.encode('gbk')) # 以gbk編碼方式發送字符串"你好"(4字節)
len = uart.write(chr(data4.encode("utf-8")) # 發送16進制數據0x0A(1字節)
for x in data5: # 遍歷列表/數組的所有元素并依次發送
len = uart.write(chr(x).encode("utf-8"))
2、完善串口接收流程
串口接收跟發送一樣,接收數據也是常用字符串和十六進制(hex)表示。
可以根據以下兩種方式接收數據:
str = uart.read(uart.in_waiting).decode("utf-8") # 以字符串接收
str = uart.read().hex() # 以16進制(hex)接收
接收的時間很短,大部分時間其實是在等待接收,所以我們需要加一個死循環或者循環線程來確保串口一直在等待接收。
示例如下:
while True:
if uart.in_waiting:
# str = uart.read(uart.in_waiting).decode("utf-8") # 以字符串接收
str = uart.read().hex() # 以16進制(hex)接收
print(str) # 打印數據
3、掃描端口
在不知道串口端口號的情況下可以先掃描一下可用的端口。
示例如下:
import serial
import serial.tools.list_ports
port_list = list(serial.tools.list_ports.comports())
print(port_list)
if len(port_list) == 0:
print('無可用串口')
else:
for i in range(0,len(port_list)):
print(port_list[i])
3.3 完善整個收發流程
根據上面舉的一些例子,我們把整個流程補充完整。
示例如下:
# 導入模塊
import threading
import time
import serial
import serial.tools.list_ports
# 自定義變量
port = "COM6" # 端口號,根據自己實際情況輸入,可以在設備管理器查看
bps = 9600 # 串口波特率,根據自己實際情況輸入
timeout = 5 # 超時時間,None:永遠等待操作,0為立即返回請求結果,其他值為等待超時時間(單位為秒)
rxdata = '' # 接收的數據
# 掃描端口
def check_uart_port():
port_list = list(serial.tools.list_ports.comports())
# print(port_list)
if len(port_list) == 0:
print('can not fine uart port')
return False
else:
for i in range(0,len(port_list)):
print(port_list[i])
return True
# 打開串口
def open_uart(port, bps, timeout):
try:
# 打開串口,并返回串口對象
uart = serial.Serial(port, bps, timeout=timeout)
return uart
except Exception as result:
print("can not open uart")
print(result)
return False
# 發送數據
def uart_send_data(uart, txbuf):
len = uart.write(txbuf.encode('utf-8')) # 寫數據
return len
# 接收數據
def uart_receive_data(uart):
if uart.in_waiting:
rxdata = uart.read(uart.in_waiting).decode("utf-8") # 以字符串接收
# rxdata = uart.read().hex() # 以16進制(hex)接收
print(rxdata) # 打印數據
# 關閉串口
def close_uart(uart):
uart.close()
# 創建一個線程用來等待串口接收數據
class myThread (threading.Thread): # 繼承父類threading.Thread
def __init__(self, uart):
threading.Thread.__init__(self)
self.uart = uart
def run(self): # 把要執行的代碼寫到run函數里面 線程在創建后會直接運行run函數
while True:
# print("thread_uart_receive")
uart_receive_data(self.uart) # 接收數據
# time.sleep(0.01)
# 主函數
def main():
# 掃描端口
result = check_uart_port()
if(result == False):
return
# 打開串口
result = open_uart(port, bps, timeout)
if (result == False):
return
else:
uart1 = result
# 創建一個線程用來接收串口數據
thread_uart = myThread(uart1)
thread_uart.start()
while True:
# 定時發送數據
txbuf = "hello world"
len = uart_send_data(uart1, txbuf)
print("send len: ", len)
time.sleep(1)
# 啟動主函數
main()
運行測試:
這里還是自發自收,但是改成定時1s循環發送一幀數據,如果是實際使用的話就不要短接TX和RX了,串口是全雙工,收發是可以同步進行的。
原文鏈接:https://blog.csdn.net/ShenZhen_zixian/article/details/127397779
相關推薦
- 2024-01-11 org.apache.commons.collections.MapUtils Map集合工具類
- 2022-06-02 Python學習之迭代器詳解_python
- 2022-07-13 this.static.super關鍵字
- 2024-07-15 Redis 底層數據結構-簡單動態字符串(SDS)
- 2023-01-17 解讀python?cvxpy下SDP問題編程_python
- 2022-07-30 SpringBoot的數據校驗(@Validated注解)、關于validation無法導入的問題解
- 2022-07-11 BeanDefinition的作用 及 new ApplicationContext容器的加載過程
- 2022-10-25 laravel-admin對表單的radio屬性無法進行rule(‘required‘)驗證
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支