【Python】Python实现串口通信(Python+Stm32)
作者:mmseoamin日期:2023-12-14

🎉欢迎来到Python专栏~Python实现串口通信


  • ☆* o(≧▽≦)o *☆嗨~我是小夏与酒🍹
  • ✨博客主页:小夏与酒的博客
  • 🎈该系列文章专栏:Python学习专栏

  • 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
  • 📜 欢迎大家关注! ❤️

    【Python】Python实现串口通信(Python+Stm32),图标,第1张

【Python】Python实现串口通信(Python+Stm32),CSDN,第2张

🎉 目录-Python实现串口通信

  • 一、实现效果
  • 二、说明
  • 三、Python串口通信代码详解
    • 3.1 包下载
    • 3.2 代码详解
    • 四、Stm32串口通信
      • 4.1 硬件部分
      • 4.2 代码部分
      • 五、参考文章

        【Python】Python实现串口通信(Python+Stm32),遇见未来,第3张

        一、实现效果

        🥝视频演示:

        Python和Stm32实现串口通信演示

        🥝图片展示:

        PyCharm端发送数据:

        【Python】Python实现串口通信(Python+Stm32),效果1,第4张

        stm32接收数据并回传:

        【Python】Python实现串口通信(Python+Stm32),效果2,第5张

        二、说明

        Python技能树:Python入门技能树。

        版本:Python 3.10。

        IDE:PyCharm。

        自制Stm32f103原理图与PCB:【stm32开发】stm32+oled最小系统板资料(原理图、PCB、示例代码)【六一】

        需要本文章完整项目文件的话(Python串口通信代码+stm32-oled最小系统板资料+stm32串口通信完整项目),可以从该链接下载:【Python+Stm32串口通信】完整项目资料,或者三连本文章之后私聊我免费领取哦~

        【Python】Python实现串口通信(Python+Stm32),狗头,第6张

        三、Python串口通信代码详解

        3.1 包下载

        直接:

        pip install pyserial
        

        然后等待包的下载和安装完成。

        3.2 代码详解

        先上本次文章的完整代码

        import serial
        from time import sleep
        def recv(serial):
            while True:
                data = serial.read_all()
                if data == '':
                    continue
                else:
                    break
                sleep(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
        

        关于Python实现串口通信的参考文章我都列到文末啦~感谢相关文章的大佬!

        📜代码分析:

        首先是包的导入:

        import serial
        from time import sleep
        

        定义串口接收函数:

        def recv(serial):
            while True:
                data = serial.read_all()
                if data == '':
                    continue
                else:
                    break
                sleep(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显示屏:

        【Python】Python实现串口通信(Python+Stm32),oled接口,第7张

        关于串口,本篇文章使用的是USART1,如下图:

        【Python】Python实现串口通信(Python+Stm32),引脚图,第8张

        引脚PA9是发送端,PA10是接收端,由于是TTL电平,所以需要一个USB转TTL的模块才可以与电脑的USB串口进行连接:

        【Python】Python实现串口通信(Python+Stm32),硬件连接2,第9张

        如果需要这块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 == '':
                    continue
                else:
                    break
                sleep(0.02)
            return data
        

        以十六进制发送和接收的串口通信完整代码:

        import serial
        from time import sleep
        def recv(serial):
            while True:
                data = serial.read_all().hex()
                if data == '':
                    continue
                else:
                    break
                sleep(0.02)
            return data
        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("发送失败!")
        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);
        }
        

        这部分根据实际需求修改和调试即可。

        展示修改后的通信效果,还有一些瑕疵,但是对于普通的项目可以使用了:

        【Python】Python实现串口通信(Python+Stm32),hex,第10张

        下面给出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 
        #include 
        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+Stm32),展示1,第11张

        【Python】Python实现串口通信(Python+Stm32),展示2,第12张

        五、参考文章

        python中串口通信的步骤及实现。

        python实现串口收发。

        详解Python中字符串前“b”,“r”,“u”,“f”的作用。

        Python字符串前缀u、r、b、f含义。

        Python Serial串口的简单数据收发。

        【Python】Python实现串口通信(Python+Stm32),csdn,第13张

        🧸结尾


        • ❤️ 感谢您的支持和鼓励! 😊🙏
        • 📜您可能感兴趣的内容:
        • 【FPGA零基础学习之旅#9】状态机基础知识
        • 【FPGA零基础学习之旅#8】阻塞赋值与非阻塞赋值讲解
        • 【Arduino TinyGo】【最新】使用Go语言编写Arduino-环境搭建和点亮LED灯
        • 【全网首发开源教程】【Labview机器人仿真与控制】Labview与Solidworks多路支配关系-四足爬行机器人仿真与控制

          【Python】Python实现串口通信(Python+Stm32),遇见未来,第14张