【Python】Python实现串口通信(Python+Stm32)

news2024/12/25 3:19:39

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


  • ☆* o(≧▽≦)o *☆~我是小夏与酒🍹
  • 博客主页:小夏与酒的博客
  • 🎈该系列文章专栏:Python学习专栏
  • 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
  • 📜 欢迎大家关注! ❤️
    图标

CSDN

🎉 目录-Python实现串口通信

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

遇见未来

一、实现效果

🥝视频演示:

Python和Stm32实现串口通信演示

🥝图片展示:
PyCharm端发送数据:
效果1
stm32接收数据并回传:
效果2

二、说明

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 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显示屏
oled接口
关于串口,本篇文章使用的是USART1,如下图:
引脚图
引脚PA9是发送端,PA10是接收端,由于是TTL电平,所以需要一个USB转TTL的模块才可以与电脑的USB串口进行连接:
硬件连接2

如果需要这块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);
}

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

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

下面给出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);
	}
}

最后来两张和电脑连接的图片:
展示1
展示2

五、参考文章

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

python实现串口收发。

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

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

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

csdn

🧸结尾


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/735061.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在linux中安装HAProxy

使用xfrp将压缩包上传到linux的opt目录下 1.解压HAProxy安装包 tar -zxvf haproxy-1.8.12.tar.gz 2. 查看点钱的内核及版本: uname -r 3. 根据内核版本选择编译参数 cd haproxy-1.8.12 cat README 4. 编译安装HAProxy make TARGETlinux2628 ARCHx86_64 PREFIX/usr/local…

测试,写用例!真有必要?

今天的文章是想跟所有小伙伴讨论软件测试工作中必不可少的一项工作&#xff1a;写测试用例&#xff0c;但目前还有很多公司并不重视写测试用例&#xff0c;觉得写测试用例是浪费时间&#xff0c;还不如拿这些时间来执行测试&#xff0c;那我们真的有必要写测试用例么&#xff1…

算法与数据结构-递归

文章目录 什么是递归递归需要满足的三个条件递归可能存在的问题堆栈溢出重复计算 总结 什么是递归 递归是一种直接或者间接调用自身函数或者方法的算法&#xff08;或者编程技巧&#xff09;&#xff0c;应用非常广泛。我们举个例子来说明什么是递归&#xff1a; 推荐注册返佣金…

join的作用【A中调用B.join表示 B先完成后A再继续】【b.join 表示b先完成】

★ 2.5 等待一个线程-join() ★★★A中调用B.join表示 B先完成后A再继续 有时&#xff0c;我们需要等待一个线程完成它的工作后&#xff0c;才能进行自己的下一步工作。例如&#xff0c;张三只有等李四转账成功&#xff0c;才决定是否存钱&#xff0c;这时我们需要一个方法明确…

maya粒子碰撞(碰撞几何体索引)

全部下滑了 nParticleShape1.rgbPP<<1,0,0>>; 碰撞层 int $yase nParticleShape1.collisionGeometryIndex; if ($yase 0 ) nParticleShape1.rgbPP<<0,1,0>>; int $yase nParticleShape1.collisionGeometryIndex; if ($yase 0 ) nParticleShape1.…

【Linux】网络基础和网络套接字的概念

文章目录 前言一、网络的发展及其网络中的概念总结 一、网络的发展及其网络中的概念 刚开始的计算机大多处于独立模式&#xff0c;也就是说计算机之间相互独立。等到网络出现的时候就出现了网络互联&#xff0c;多台计算机连接在一起完成数据共享。随着发展计算机越多越多就出…

选购云主机

目录 一、购买云主机 二、SSH连接云主机 三、在云主机上面开放端口 一、购买云主机 云服务商有很多&#xff0c;但是我推荐大家使用腾讯云。之前我讲过阿里云超卖的事情&#xff0c;云主机IO性能非常差劲&#xff0c;我们要在云主机上面安装MySQL、MongoDB这样的数据库&…

TortoiseGit 入门指南01:环境搭建和软件设置

在我的博文Keil MDK环境下Git入门指南的最后&#xff0c;我这样写道&#xff1a; 目前使用 TortoiseGit 管理工程&#xff0c;用 Gitee 作为远程仓库。 命令行 Git 已经不再使用。 当时我并没有介绍软件 TortoiseGit 的使用方法&#xff0c;这个系列补上。如果你还没有看过《Ke…

Linux开发工具【gcc/g++】

Linux开发工具之【gcc/g】 上文我们已经学习了vim编辑器的相关操作和使用&#xff0c;已经可以在Linux下编写代码了&#xff0c;有了代码就需要编译运行&#xff0c;此时就需要用到Linux中的编译工具gcc/g了&#xff0c;其中gcc是C语言的编译器&#xff0c;g是C的编译器&#…

RabbitMQ系列(29)--RabbitMQ搭建Shovel

前言&#xff1a; Federation具备的数据转发功能类似&#xff0c;Shovel能够可靠、持续地从一个Broker中的队列(作为源端&#xff0c;即source)拉取数据并转发至另一个Broker中的交换器(作为目的端&#xff0c;即destination)。作为源端的队列和作为目的端的交换器可以同时位于…

SGM58031与单片机驱动实现

SGM58031与单片机驱动实现 文章目录 SGM58031与单片机驱动实现CUBEIDE设置I2C通讯封装SGM58031通讯实现 CUBEIDE设置 使用硬件I2C与sgm芯片通讯&#xff0c;上面即配置硬件I2C,其他参数默认即可。 I2C通讯封装 封装实现 /*** brief Manages error callback by re-initializ…

【JVM调优】JVM调优工具之Arthas

Arthas的作用 Arthas是一款线上监控诊断产品&#xff0c;通过全局视角实时查看应用 load、内存、gc、线程的状态信息&#xff0c;并能在不修改应用代码的情况下&#xff0c;对业务问题进行诊断&#xff0c;包括查看方法调用的出入参、异常&#xff0c;监测方法执行耗时&#x…

【Elasticsearch】索引库操作

目录 2.索引库操作 2.1.mapping映射属性 2.2.索引库的CRUD 2.2.1.创建索引库和映射 基本语法&#xff1a; 示例&#xff1a; 2.2.2.查询索引库 2.2.3.修改索引库 2.2.4.删除索引库 2.2.5.总结 2.索引库操作 索引库就类似数据库表&#xff0c;mapping映射就类似表的…

[神经网络]Anchor_Free网络(YoloX,CenterNet)

Anchor_Free网络不同于传统的目标检测网络需要先生成很多先验框再从中筛选回归生成预测框。其可以直接从目标的中心点向周围发散一个预测框。这样做有两个好处&#xff1a;①省略了生成大量先验框的过程&#xff0c;可以一定程度增加预测速度&#xff1b;②预测框没有预设长宽比…

魅族新专利:弹开机构及折叠终端,提高便捷性、降低使用难度

珠海市魅族科技有限公司透露新专利&#xff1a;弹开机构及折叠终端&#xff0c;提高展开便捷性、降低使用难度&#xff01; 该专利介绍了一种用于电子设备的弹开机构和折叠终端。该弹开机构由磁吸组和弹开模组组成。磁吸组包括第一磁吸件和第二磁吸件&#xff0c;其中第一磁吸件…

SpringBoot 如何使用 TestRestTemplate 进行 RESTful API 集成测试

SpringBoot 如何使用 TestRestTemplate 进行 RESTful API 集成测试 在使用 SpringBoot 开发 RESTful API 的过程中&#xff0c;我们需要进行集成测试&#xff0c;以确保 API 的正确性和可用性。而 TestRestTemplate 是 Spring Framework 提供的一个工具类&#xff0c;可以用来…

Flink实时任务性能调优

前言 通常我们在开发完Flink任务提交运行后&#xff0c;需要对任务的参数进行一些调整&#xff0c;通常需要调整的情况是任务消费速度跟不上数据写入速度&#xff0c;从而导致实时任务出现反压、内存GC频繁&#xff08;FullGC&#xff09;频繁、内存溢出导致TaskManager被Kill…

【笔记】数字电路基础1 - 门电路

目录 数字电路基础与门电路数电基础基本门电路复合门电路TTL 门电路CMOS 门电路 数字电路基础与门电路 数电基础 数字电路中常将 0 &#xff5e; 1V 范围的电压称为低电平&#xff0c;用“0”表示&#xff1b;而将 3 &#xff5e; 5V 范围的电压称为高电平&#xff0c;用“1”…

【InnoDB 存储引擎】InnoDB 存储引擎的行格式,有 Compact、Redundant、Dynamic 等行格式还有它们配套实验(理论篇)

文章目录 1 InnoDB 行记录格式&#xff08;理论&#xff09;1.1 Redundant 行记录格式1.2 Compact 行记录格式&#xff08;重点&#xff09;1.3 行溢出数据1.4 Compressed 和 Dynamic 行记录格式1.5 CHAR 的行结构存储 2 参考资料 1 InnoDB 行记录格式&#xff08;理论&#xf…