之前写了一篇Python与STM32F103通信的文章,但是存在一定的问题,比如说有时串口接收不到返回的数据,还有就是接收数据接收的不全,感觉有可能是读取的时候用serial.read_all()这个方法和正点原子例程中串口缓冲区的发送有矛盾,所以参考了一下其他文章,写一篇新文章记录一下。
上一篇文章链接:(29条消息) 使用Python与Stm32进行通信_def__init__1923的博客-CSDN博客_stm32单片机 pythonhttps://blog.csdn.net/weixin_47428902/article/details/126296318?spm=1001.2014.3001.5501
方法:利用python的serial函数库与STM32进行通信。
没有安装serial库的话请先安装,terminal输入指令:
pip install serial
将Stm32用USB串口连接到电脑,打开设备管理器查看端口,端口为COM4。
在Pycharm中写下Python程序:
import serial
# 串口打开函数
def open_ser():
port = 'COM4' # 串口号
baudrate = 115200 # 波特率
try:
global ser
ser = serial.Serial(port, baudrate, timeout=2)
if ser.isOpen() == True:
print("串口打开成功")
except Exception as exc:
print("串口打开异常", exc)
# 数据发送
def send_msg():
try:
send_datas = input("请输入要发送的数据:\n")
ser.write(str(send_datas+'\r\n').encode("gbk"))
print('-' * 80)
print("已发送数据:")
print(send_datas)
print('-' * 80)
# send_datas1 = 875
# ser.write(str(send_datas1).encode("gbk"))
# print("已发送数据:", send_datas1)
except Exception as exc:
print("发送异常", exc)
# 接收数据
def read_msg():
try:
print("等待接收数据......")
while True:
data = ser.read(ser.in_waiting).decode('gbk')
if data != '':
break
print('-' * 80)
print("已接受到数据:")
print(data)
print('-' * 80)
except Exception as exc:
print("读取异常", exc)
# 关闭串口
def close_ser():
try:
ser.close()
if ser.isOpen():
print("串口未关闭")
else:
print("串口已关闭")
except Exception as exc:
print("串口关闭异常", exc)
if __name__ == '__main__':
ser = None
open_ser() # 打开串口
while 1:
print('----------请选择你要进行的操作----------')
print('---1:发送数据--2:接收数据--3:关闭串口---')
op = input('请输入:')
if op == '1':
send_msg() # 写数据
if op == '2':
read_msg() # 读数据
if op == '3':
close_ser() # 关闭串口
break
先讲解一下代码:第一部分,打开串口。port选择您的端口号,波特率选择115200,保持跟您STM32串口通信的波特率一致即可。serial.Serial()函数的参数timeout代表超时时间,可选择参数:1.timeout = None: 长时间等待 2.timeout = 0: 不阻塞形式 (读完之后就返回) 3.timeout = x: x秒后超时 (float allowed)。
# 串口打开函数
def open_ser():
port = 'COM4' # 串口号
baudrate = 115200 # 波特率
try:
global ser
ser = serial.Serial(port, baudrate, timeout=2)
if ser.isOpen() == True:
print("串口打开成功")
except Exception as exc:
print("串口打开异常", exc)
接下来是第二部分:数据发送部分。首先先输入要发送的输入,写入串口时进行gbk编码,然后再进行发送。注意看,send_datas后面写了+'\r\n',这是因为正点原子串口通信那个例程代码写的协议是接收数据要以'\r\n'结尾,所以加上了这两个字符,否则STM32认为接收数据无效。
# 数据发送
def send_msg():
try:
send_datas = input("请输入要发送的数据:\n")
ser.write(str(send_datas+'\r\n').encode("gbk"))
print('-' * 80)
print("已发送数据:")
print(send_datas)
print('-' * 80)
# send_datas1 = 875
# ser.write(str(send_datas1).encode("gbk"))
# print("已发送数据:", send_datas1)
except Exception as exc:
print("发送异常", exc)
再下来是第三部分:数据接收部分。使用ser.read(ser.in_waiting)这个方法来接收数据,测试后尝试没有数据接收不全的情况,所以最好就采用这种方法吧。接收后进行gbk解码,解码完成后打印接收到的数据。
# 接收数据
def read_msg():
try:
print("等待接收数据......")
while True:
data = ser.read(ser.in_waiting).decode('gbk')
if data != '':
break
print('-' * 80)
print("已接受到数据:")
print(data)
print('-' * 80)
except Exception as exc:
print("读取异常", exc)
再下来是第四部分:串口关闭部分。这部分不需要解释,大家应该都能看懂。
# 关闭串口
def close_ser():
try:
ser.close()
if ser.isOpen():
print("串口未关闭")
else:
print("串口已关闭")
except Exception as exc:
print("串口关闭异常", exc)
最后讲解一下主程序。先打开串口,然后进入死循环,通过input方法来做进一步决定:发送数据、接收数据、关闭串口。如果输入1,则代表发送数据;如果输入2,则代表接收数据;如果输入3,则代表关闭串口退出。下面是主程序。。。。。。。
if __name__ == '__main__':
ser = None
open_ser() # 打开串口
while 1:
print('----------请选择你要进行的操作----------')
print('---1:发送数据--2:接收数据--3:关闭串口---')
op = input('请输入:')
if op == '1':
send_msg() # 写数据
if op == '2':
read_msg() # 读数据
if op == '3':
close_ser() # 关闭串口
break
接下来请看演示部分。
运行程序,弹出以下部分。
输入1,开始发送数据。
再输入2,接收数据。弹出以下部分。
再输入3,关闭串口,程序结束。
STM32F103的程序用正点原子的例程即可,代码如下。
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
/************************************************
ALIENTEK精英STM32开发板实验4
串口 实验
技术支持:www.openedv.com
淘宝店铺:http://eboard.taobao.com
关注微信公众平台微信号:"正点原子",免费获取STM32资料。
广州市星翼电子科技有限公司
作者:正点原子 @ALIENTEK
************************************************/
int main(void)
{
u16 t;
u16 len;
u16 times=0;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LED_Init(); //LED端口初始化
KEY_Init(); //初始化与按键连接的硬件接口
while(1)
{
if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
printf("你发送的消息是:\r\n\r\n");
delay_us(10);
for(t=0;t
每隔一段时间打印一下的那部分注释掉,比较烦人。
内容基本上就是这些,希望能够给您带来帮助,有问题的话欢迎讨论。