🎉歡迎來到Python專欄~Python實現串口通信
- ☆* o(≧▽≦)o *☆嗨~我是小夏與酒🍹
- ?博客主頁:小夏與酒的博客
- 🎈該系列文章專欄:Python學習專欄
- 文章作者技術和水平有限,如果文中出現錯誤,希望大家能指正🙏
- 📜 歡迎大家關注! ??
🎉 目錄-Python實現串口通信
- 一、實現效果
- 二、說明
- 三、Python串口通信代碼詳解
- 3.1 包下載
- 3.2 代碼詳解
- 四、Stm32串口通信
- 4.1 硬件部分
- 4.2 代碼部分
- 五、參考文章
一、實現效果
🥝視頻演示:
Python和Stm32實現串口通信演示
🥝圖片展示:
PyCharm端發送數據:
stm32接收數據并回傳:
二、說明
Python技能樹:Python入門技能樹。
版本:Python 3.10。
IDE:PyCharm。
自制Stm32f103原理圖與PCB:【stm32開發】stm32+oled最小系統板資料(原理圖、PCB、示例代碼)【六一】
需要本文章完整項目文件的話(Python串口通信代碼+stm32-oled最小系統板資料+stm32串口通信完整項目),可以從該鏈接下載:【Python+Stm32串口通信】完整項目資料,或者三連本文章之后私聊我免費領取哦~
三、Python串口通信代碼詳解
3.1 包下載
直接:
pip install pyserial
然后等待包的下載和安裝完成。
3.2 代碼詳解
先上本次文章的完整代碼:
import serial
from time import sleepdef recv(serial):while True:data = serial.read_all()if data == '':continueelse:breaksleep(0.02)return datadef send(send_data):if (serial.isOpen()):serial.write(send_data.encode('utf-8')) # 編碼print("發送成功", send_data)else:print("發送失敗!")if __name__ == '__main__':serial = serial.Serial('COM3', 9600, timeout=0.5)if serial.isOpen() :print("open success")else :print("open failed")#這里如果不加上一個while True,程序執行一次就自動跳出了while True:a = input("輸入要發送的數據:")send(a)sleep(0.5) # 起到一個延時的效果data =recv(serial)if data != '' :print("receive : ",data)if data == b'x':print("exit")break
關于Python實現串口通信的參考文章我都列到文末啦~感謝相關文章的大佬!
📜代碼分析:
首先是包的導入:
import serial
from time import sleep
定義串口接收函數:
def recv(serial):while True:data = serial.read_all()if data == '':continueelse:breaksleep(0.02)return data
定義串口發送函數:
def send(send_data):if (serial.isOpen()):serial.write(send_data.encode('utf-8')) # 編碼print("發送成功", send_data)else:print("發送失敗!")
主程序部分:
if __name__ == '__main__':serial = serial.Serial('COM3', 9600, timeout=0.5)if serial.isOpen() :print("open success")else :print("open failed")#這里如果不加上一個while True,程序執行一次就自動跳出了while True:a = input("輸入要發送的數據:")send(a)sleep(0.5) # 起到一個延時的效果data =recv(serial)if data != '' :print("receive : ",data)if data == b'x':print("exit")break
主程序部分的作用就是開啟串口,在while循環中發送或者接收串口的數據,并且在接收到數據x之后,結束程序。
需要注意的是,下面這部分代碼中,9600
為波特率,且需要輸入正確的端口號,不然程序會報錯!
serial = serial.Serial('COM3', 9600, timeout=0.5)
這部分是字符串前綴,前綴b表示該字符串是bytes類型:
if data == b'x':
四、Stm32串口通信
4.1 硬件部分
參考板子的原理圖,連接好OLED顯示屏:
關于串口,本篇文章使用的是USART1,如下圖:
引腳PA9
是發送端,PA10
是接收端,由于是TTL電平
,所以需要一個USB轉TTL
的模塊才可以與電腦的USB串口進行連接:
如果需要這塊stm32的實物開發板的話(低價出),可以聯系我~
4.2 代碼部分
在串口通信中,一般使用hex格式
進行收發,但是在目前的代碼中,我們發送的數據為字符串,所以在stm32的oled顯示中,數據和發送的不一致。
參考文章:Python 串口發送十六進制數據。
修改Python中的發送和接收函數:
#以十六進制的格式發送數據
def send(send_data):send_data_hex = bytes.fromhex(send_data)if (serial.isOpen()):serial.write(send_data_hex) # 編碼print("發送成功", send_data_hex)else:print("發送失敗!")
#以十六進制的格式接收數據
def recv(serial):while True:data = serial.read_all().hex()if data == '':continueelse:breaksleep(0.02)return data
以十六進制發送和接收的串口通信完整代碼:
import serial
from time import sleepdef recv(serial):while True:data = serial.read_all().hex()if data == '':continueelse:breaksleep(0.02)return datadef send(send_data):send_data_hex = bytes.fromhex(send_data)if (serial.isOpen()):serial.write(send_data_hex) # 編碼print("發送成功", send_data_hex)else:print("發送失敗!")if __name__ == '__main__':serial = serial.Serial('COM3', 9600, timeout=0.5)if serial.isOpen() :print("open success")else :print("open failed")#這里如果不加上一個while True,程序執行一次就自動跳出了while True:a = input("輸入要發送的數據:")send(a)sleep(0.5) # 起到一個延時的效果data =recv(serial)if data != '' :print("receive : ",data)
?注意:
本文章中stm32的數據接收和發送格式為:
uint8_t Serial_RxData;
void Serial_SendByte(uint8_t Byte)
{USART_SendData(USART1, Byte);while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
這部分根據實際需求修改和調試即可。
展示修改后的通信效果,還有一些瑕疵,但是對于普通的項目可以使用了:
下面給出stm32的部分代碼:
main.c:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"uint8_t RxData;int main(void)
{OLED_Init();OLED_ShowString(1, 1, "RxData:");Serial_Init();while (1){if (Serial_GetRxFlag() == 1){RxData = Serial_GetRxData();Serial_SendByte(RxData);OLED_ShowHexNum(1, 8, RxData, 2);}}
}
Serial.c:
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>uint8_t Serial_RxData;
uint8_t Serial_RxFlag;void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStructure);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);USART_Cmd(USART1, ENABLE);
}void Serial_SendByte(uint8_t Byte)
{USART_SendData(USART1, Byte);while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}void Serial_SendArray(uint8_t *Array, uint16_t Length)
{uint16_t i;for (i = 0; i < Length; i ++){Serial_SendByte(Array[i]);}
}void Serial_SendString(char *String)
{uint8_t i;for (i = 0; String[i] != '\0'; i ++){Serial_SendByte(String[i]);}
}uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{uint32_t Result = 1;while (Y --){Result *= X;}return Result;
}void Serial_SendNumber(uint32_t Number, uint8_t Length)
{uint8_t i;for (i = 0; i < Length; i ++){Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');}
}int fputc(int ch, FILE *f)
{Serial_SendByte(ch);return ch;
}void Serial_Printf(char *format, ...)
{char String[100];va_list arg;va_start(arg, format);vsprintf(String, format, arg);va_end(arg);Serial_SendString(String);
}uint8_t Serial_GetRxFlag(void)
{if (Serial_RxFlag == 1){Serial_RxFlag = 0;return 1;}return 0;
}uint8_t Serial_GetRxData(void)
{return Serial_RxData;
}void USART1_IRQHandler(void)
{if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET){Serial_RxData = USART_ReceiveData(USART1);Serial_RxFlag = 1;USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}
最后來兩張和電腦連接的圖片:
五、參考文章
python中串口通信的步驟及實現。
python實現串口收發。
詳解Python中字符串前“b”,“r”,“u”,“f”的作用。
Python字符串前綴u、r、b、f含義。
Python Serial串口的簡單數據收發。
🧸結尾
- ?? 感謝您的支持和鼓勵! 😊🙏
- 📜您可能感興趣的內容:
- 【FPGA零基礎學習之旅#9】狀態機基礎知識
- 【FPGA零基礎學習之旅#8】阻塞賦值與非阻塞賦值講解
- 【Arduino TinyGo】【最新】使用Go語言編寫Arduino-環境搭建和點亮LED燈
- 【全網首發開源教程】【Labview機器人仿真與控制】Labview與Solidworks多路支配關系-四足爬行機器人仿真與控制