【Python】串口通信-与FPGA、蓝牙模块实现串口通信(Python+FPGA)

news2024/11/25 9:56:55

🎉欢迎来到Python专栏~与FPGA、蓝牙模块实现串口通信


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

CSDN

🎉 目录-与FPGA、蓝牙模块实现串口通信

  • 一、效果演示
  • 二、说明
  • 三、Python串口通信代码
  • 四、Python与FPGA实现串口通信
  • 五、Python与蓝牙模块实现串口通信

遇见未来

一、效果演示

Python与FPGA串口通信:

Python与FPGA实现串口通信(USB转TTL)

Python与蓝牙模块串口通信:
在这里插入图片描述

二、说明

Python技能树:Python入门技能树。
版本:Python 3.10。
IDE:PyCharm。
需要使用USB转TTL模块:
模块

三、Python串口通信代码

完整代码:

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)

将代码拆分到不同的文件中,项目文件结构
项目结构

main.py:

import serial
from time import sleep
from DefSerial import defserial

if __name__ == '__main__':
    serial = serial.Serial('COM5', 9600, timeout=0.5)
    if serial.isOpen() :
        print("open success")
    else :
        print("open failed")

    #这里如果不加上一个while True,程序执行一次就自动跳出了
    while True:
        a = input("输入要发送的数据:")
        defserial.send(serial,a)
        sleep(0.5)  # 起到一个延时的效果
        data = defserial.recv(serial)
        if data != '' :
            print("receive : ",data)

defserial.py:

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(serial,send_data):
    send_data_hex = bytes.fromhex(send_data)
    if (serial.isOpen()):
        serial.write(send_data_hex)  # 编码
        print("发送成功", send_data_hex)
    else:
        print("发送失败!")

✨编写完对应的文件之后,记得设置root路径不然将无法使用定义的函数

PyCharm中不同文件之间函数实现调用的设置:【Python】PyCharm中调用另一个文件的函数或类。

四、Python与FPGA实现串口通信

FPGA实现串口通信的参考文章:【FPGA】串口通信讲解-状态机判断数据值。

在这里将各模块代码展示出来:

async_uart_rev.v:

///
//模块介绍:实现异步串口接收功能
///
module async_uart_rev(
	input				rst_n	,//复位信号,低电平有效
	input				clk,//时钟信号,50MHZ
	input				rxd,//串行接收数据
	output	reg	[7:0]	rev_data,//并行数据
	output	reg			rev_dvld //并行数据有效标志
	);
	
	parameter	baud_num	=5207;//1/9600*1000000000/20
	parameter	IDLE		=4'd0;
	parameter	START_ST    =4'd1;
	parameter	STOP_ST     =4'd2;
	
	reg	[12:0]baud_cnt;
	reg			baud_cnt_en;
	wire		sample_en;
	reg	[3:0]	sample_num;
	reg			rxd_ff1;
	reg			rxd_ff2;
	reg	[3:0]	curr_st;
	
	//打两拍操作-第一拍
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			rxd_ff1 <= 1'b0;
		else
			rxd_ff1 <= rxd;
	end
	//打两拍操作-第二拍
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			rxd_ff2 <= 1'b0;
		else
			rxd_ff2 <= rxd_ff1;
	end
	
	//sample_en判断计数器是否到达计数值
	assign sample_en = (baud_cnt == baud_num[12:1])?1'b1:1'b0;
	
	//状态机跳转程序
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			curr_st<=IDLE;
		else case(curr_st)
			IDLE:begin
				if(rxd_ff2==0)
					curr_st<=START_ST;
				else
					;
			end
			START_ST:begin
				if(sample_num==8&&sample_en)
					curr_st<=STOP_ST;
				else
					;
			end
			STOP_ST:begin
				if(rxd_ff2==1&&sample_en)
					curr_st<=IDLE;
				else
					;
			end
			default:;
		endcase
	end
	
	//baud_cnt波特率计数器
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			baud_cnt<=0;
		else if(curr_st==START_ST||curr_st==STOP_ST)begin
			if(baud_cnt==baud_num)
				baud_cnt<=0;
			else 
				baud_cnt<=baud_cnt+1;
		end else
			baud_cnt<=0;
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)	
			sample_num<=0;
		else if(sample_en&&sample_num==9)
			sample_num<=0;
		else if(sample_en)
			sample_num<=sample_num+1;
		else
			;
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			rev_data<=0;
		else if(sample_en)
			case(sample_num)
			1:rev_data[0]<=rxd_ff2;
			2:rev_data[1]<=rxd_ff2;
			3:rev_data[2]<=rxd_ff2;
			4:rev_data[3]<=rxd_ff2;
			5:rev_data[4]<=rxd_ff2;
			6:rev_data[5]<=rxd_ff2;
			7:rev_data[6]<=rxd_ff2;
			8:rev_data[7]<=rxd_ff2;
			default:;
		endcase
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)	
			rev_dvld<=0;
		else if(sample_num==9&&sample_en)
			rev_dvld<=1;
		else
			rev_dvld<=0;
	end
	
endmodule

async_uart_tran.v:

///
//模块介绍:实现异步串口发送功能
///
module async_uart_tran(
	input				rst_n	,//复位信号,低电平有效
	input				clk,//时钟,50MHZ
	input		[7:0]	tran_data,//输入的并行数据
	input				tran_dvld,//输入的并行数据有效标志
	output	reg	txd      //串行输出数据
	);
	
	parameter	baud_num	=5207;//1/9600*1000000000/20
	parameter	IDLE		=4'd0;
	parameter	DATA_ST    	=4'd1;
	parameter	START_ST    =4'd2;
	parameter	STOP_ST     =4'd3;
	
	reg	[12:0]	baud_cnt;
	reg			baud_cnt_en;
	reg	[3:0]	sample_num;
	reg	[3:0]	curr_st;
	
	wire		sample_en;

	assign	sample_en = (baud_cnt==baud_num)?1'b1:1'b0;
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			curr_st<=IDLE;
		else case(curr_st)
			IDLE:begin
				if(tran_dvld==1)
					curr_st<=START_ST;
				else
					;
			end
			START_ST:begin
				if(sample_en==1)
					curr_st<=DATA_ST;
			end
			DATA_ST:begin
				if(sample_en&&sample_num==8)
					curr_st<=STOP_ST;
				else
					;
			end
			STOP_ST:begin
				if(sample_en==1)
					curr_st<=IDLE;
				else
					;
			end
			default:;
		endcase
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			baud_cnt<=0;
		else if(curr_st==START_ST||curr_st==DATA_ST||curr_st==STOP_ST)begin
			if(baud_cnt==baud_num)
				baud_cnt<=0;
			else 
				baud_cnt<=baud_cnt+1;
		end else
			baud_cnt<=0;
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)	
			sample_num<=0;
		else if(curr_st==IDLE)
			sample_num<=0;
		else if(sample_en)
			sample_num<=sample_num+1;
		else
			;
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			txd<=1;
		else if(sample_en)
			case(sample_num)
			0:txd<=1'b0;
			1:txd<=tran_data[0];
			2:txd<=tran_data[1];
			3:txd<=tran_data[2];
			4:txd<=tran_data[3];
			5:txd<=tran_data[4];
			6:txd<=tran_data[5];
			7:txd<=tran_data[6];
			8:txd<=tran_data[7];
			9:txd<=1'b1;
			default:txd<=1;
		endcase
	end
	
endmodule

data.v:

module data(
	input 				clk,
	input 				rst_n,
	input 		[7:0]	rev_data,
	output reg 	[3:0]	led
);

	//定义LED的亮灭
	parameter led_light_all = 8'h11;//全部点亮
	parameter led_close_all = 8'h00;//全部熄灭
	parameter led_light_one = 8'hAA;//点亮led1
	parameter led_close_one = 8'hFF;//关闭led1
	
	localparam 
		IDLE 	 = 4'b0001,
		LIGHTALL = 4'b0010,
		ONELIGHT = 4'b0100,
		ONECLOSE = 4'b1000;
	
	reg [3:0]curr_st;
	
	//状态机主程序
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			curr_st <= IDLE;
		else begin
			case(curr_st)
				IDLE:begin
					if(rev_data == led_light_all)
						curr_st <= LIGHTALL;
					else if(rev_data == led_light_one)
						curr_st <= ONELIGHT;
					else
						;
				end
				LIGHTALL:begin
					if(rev_data == led_close_all)
						curr_st <= IDLE;
					else
						;
				end
				ONELIGHT:begin
					if(rev_data == led_close_one)
						curr_st <= ONECLOSE;
					else
						;
				end
				ONECLOSE:curr_st <= IDLE;
			default:curr_st <= IDLE;
			endcase
		end
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			led <= 4'b1111;
		else begin
			case(curr_st)
				IDLE:	 led <= 4'b1111;
				LIGHTALL:led <= 4'b0000;
				ONELIGHT:led <= 4'b1110;
				ONECLOSE:led <= 4'b0000;
			default:led <= led;
			endcase
		end
	end

endmodule

顶层模块:

///
//模块介绍:顶层模块,例化接收和发送模块,控制LED状态
///
module async_uart_top(
	input		clk		,//时钟,50MHZ
	input		rst_n		,//复位信号,低电平有效
	input		rxd		,//串行接收数据
	output	txd		,//串行发送数据
	output	[3:0] led
	);
	
	wire	[7:0]	rev_data;
	wire			rev_dvld;
	
	async_uart_rev Uasync_uart_rev(
		.rst_n(rst_n),
		.clk(clk),
		.rxd(rxd),
		.rev_data(rev_data),
		.rev_dvld(rev_dvld)
	);
	
	async_uart_tran Uasync_uart_tran(
		.rst_n(rst_n),
		.clk(clk),
		.tran_data(rev_data),
		.tran_dvld(rev_dvld),
		.txd(txd)
	);
	
	data Udata(
		.clk(clk),
		.rst_n(rst_n),
		.rev_data(rev_data),
		.led(led)
	);
	
endmodule

在硬件部分使用USB转TTL模块,将电脑与FPGA的IO口连接:
模块连接
模块连接

注意,这里我们只需连接rxd和txd就可以,因为FPGA和USB转TTL模块都是独立供电,见下图连接:

接口展示
连接展示
注意看data.v模块内部的代码,按照设定值发送即可控制LED的状态:

//定义LED的亮灭
parameter led_light_all = 8'h11;//全部点亮
parameter led_close_all = 8'h00;//全部熄灭
parameter led_light_one = 8'hAA;//点亮led1
parameter led_close_one = 8'hFF;//关闭led1

五、Python与蓝牙模块实现串口通信

使用USB转TTL模块与蓝牙模块连接:
模块连接
注意连接关系:蓝牙模块的TXD接转接模块的RXD,蓝牙模块的RXD接转接模块的TXD。

由于我使用的是BLE模块,所以需要下载BLE调试助手。串口通信成功日志:
APP

csdn

🧸结尾


  • ❤️ 感谢您的支持和鼓励! 😊🙏
  • 📜您可能感兴趣的内容:
  • 【Python】Python实现串口通信(Python+Stm32)
  • 【Verilog HDL】FPGA-testbench基础知识
  • 【Arduino TinyGo】【最新】使用Go语言编写Arduino-环境搭建和点亮LED灯
  • 【全网首发开源教程】【Labview机器人仿真与控制】Labview与Solidworks多路支配关系-四足爬行机器人仿真与控制
    遇见未来

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

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

相关文章

基于Java+SpringBoot+vue前后端分离校园周边美食探索分享平台设计实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

SpringCloud nacos 集成 feign 实例

&#x1f388; 作者&#xff1a;Linux猿 &#x1f388; 简介&#xff1a;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我&#xff0c;关注我&#xff0c;有问题私聊&#xff01; &…

【运维工程师学习七】DNS底层原理及搭建自己的DNS服务器

【运维工程师学习七】DNS底层原理及搭建自己的DNS服务器 0、前言1、域名&#xff08;Domain&#xff09;的由来2、域名&#xff08;Domain&#xff09;的级别3、域名&#xff08;Domain&#xff09;的命名规则4、域名&#xff08;Domain&#xff09;的后缀有哪些5、域名&#x…

[QT编程系列-32]:科学计算 - QT支持的科学计算库

目录 第1章 QT中如何支持科学计算&#xff1f; 1.1 QT没有专门的科学计算库 1.2 QT没有专门的数学运算库 1.3 QT没有数字信号DSP处理库 1.4 QT没有类numpy库 1.5 QT支持的数学运算 第2章 QT数学库详解 2.1 QtMath 2.2 QVector 2.3 QMatrix 第1章 QT中如何支持科学计算…

【数据结构】——LRU Cache

这里写目录标题 什么是LRU CacheLRU Cache的实现LRU Cache的OJ 什么是LRU Cache LRU是Least Recently Used的缩写&#xff0c;意思是最近最少使用&#xff0c;它是一种Cache替换算法。 什么是Cache&#xff1f;狭义的Cache指的是位于CPU和主存间的快速RAM&#xff0c; 通常它不…

【Soft NMS】《Soft-NMS – Improving Object Detection With One Line of Code》

ICCV-2017 文章目录 1 Background and Motivation2 Related Work3 Advantages / Contributions4 Method5 Experiments5.1 Results5.2 Sensitivity Analysis5.3 When does Soft-NMS work better?5.4 Qualitative Results 6 Conclusion&#xff08;own&#xff09; 1 Background…

【Android】Ubuntu20.04编译Android 13并用模拟器运行

前言 一直好奇Android系统是怎么定制的&#xff0c;直到亲自走一遍Android系统编译流程才发现并没想象的复杂。 这就跟app开发一样&#xff0c;Google官方其实都提供了平台、文档、IDE及一些工具&#xff0c;咱们只要按照官方提供的指南来操作就行了。 如果Android没有提供这…

15 QMessageBox消息对话框

错误提示对话框 信息提示对话框 循环对话框 默认是Yes和No&#xff0c;可以修改属性。第5个参数关联回车键 QMessageBox::Save | QMessageBox::Cancel 可以通过捕获按键获取点击结果 警告提示 代码&#xff1a; //QMessageBox 消息对话框//错误提示QMessageBox::critical(th…

11 spring-boot的MVC配置原理

11.1 spring-boot为MVC提供的自动配置 1.ContentNegotiatingViewResolver视图解析器&#xff1b; 2.静态资源或者支持WebJars&#xff1b; 3.自动注册类型转换器&#xff1a;比如说前台提交user的字段&#xff0c;后台自动封装的意思&#xff1b; 4.HttpMessageConverters&…

计算机视觉(一)图像预处理

本章内容 图像显示与存储原理颜色空间RGB颜色空间CMY&#xff08;K&#xff09;颜色空间HSV颜色空间CIE-XYZ颜色空间 图片存储原理主流颜色空间 图像增强的目标图像处理方法点运算&#xff1a;基于直方图的对比度增强直方图 &#xff1a;对数据空间&#xff08;bin&#xff09;…

了解 3DS MAX 3D摄像机跟踪设置:第 1 部分

这是一个关于使用行业标准插件 RayFire 在 3ds Max 中破坏元素的新系列。在本教程的第一部分中&#xff0c;我将向您展示如何在 RayFire 中使用在 3ds Max 中拆除元素的最基本操作和方法。 推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 准备场景 步…

使用Gin框架搭配WebSocket完成实时聊天

文章目录 前言实时聊天聊天功能测试发送信息 前言 在写项目的时候&#xff0c;需要完成实时聊天的功能&#xff0c;于是简单的学习下WebSocket&#xff0c;想知道WebSocket是什么的小伙伴可以去网上别的地方学习一下。 要实现实时聊天&#xff0c;网上的大部分内容都是Spring…

【MI】ModuleNotFoundError: No module named ‘braindecode.datautil.signalproc‘

使用HGD数据集时&#xff0c;需要从braindecode中调用 一直显示ModuleNotFoundError 以为是导入braindecode的版本太新了&#xff0c;于是在braindecode官网上找代码对应版本&#xff0c;一直找不到&#xff0c;最后从github上找到了代码的使用指南 GitHub - braindecode/br…

(学习笔记)HTTP Keep-Alive和TCP Keep-Alive

HTTP的Keep-Alive HTTP协议采用的是[请求-应答]模式&#xff0c;也就是客户端发起请求&#xff0c;服务端才会响应请求&#xff0c;一来一回这个样子。 由于HTTP是基于TCP传输协议实现的&#xff0c;客户端与服务端需要进行HTTP通信前&#xff0c;需要先建立TCP连接&#xff…

redis的常用命令和数据结构

目录 redis的基本特征 Redis操作命令行 redis的数据结构 Redis的基本特征 键值型&#xff0c;value支持多种不同的数据结构&#xff0c;功能丰富 单线程&#xff0c;每个命令具备原子性 低延迟&#xff0c;速快&#xff08;基于内存&#xff0c;IO多路复用&#xff0c;良好…

第 109 场 LeetCode 双周赛

A 检查数组是否是好的 暴力: 排序后遍历判断 class Solution { public:bool isGood(vector<int> &nums) {sort(nums.begin(), nums.end());for (int i 0; i < nums.size() - 1; i)if (nums[i] ! i 1)return false;return nums.back() nums.size() - 1;} };B 将…

npm(基础)

基础-是什么 深度-为什么 #npm基础 - 现代前端开发模式 ##很多年前的前端,是什么样子? ##补充一下 ###Node SDK(software develop kit):Node jdk() IDE(集成dev env):VSCode ####有了npm,我们就可以创建一个工程环境 npm - 理解成一个包管理下载的工具 每一个npm管理…

树莓派刷机和登入

1.打开映像工具 2.选择映像文件写入 3.拔出卡插入树莓派上电 4.树莓派登入 1.HDMI视频线&#xff0c;连接到显示屏幕 2.串口登录 修改系统配置&#xff0c;启用串口登录树莓派 &#xff08;1) 打开SD卡根目录的"config.txt文件"&#xff0c;停止蓝牙&#xff0c;…

Pytorch深度学习------TensorBoard的使用

文章目录 1.什么是TensorBoard2.安装3.启动4.Pytorch 使用 TensorBoard4.1 写入数据4.2 写入图像 1.什么是TensorBoard TensorBoard是一个工具&#xff0c;主要用于数据可视化&#xff0c;用大白话的语言来说就是可以记录在机器学习中表格数据、非表格数据&#xff08;图片、文…

信息与通信工程学科面试准备——通信原理|推免/复试/补充

目录 1. 加性高斯白噪声 加性噪声 白噪声 2. 窄带随机过程 2.1 正弦波加窄带随机过程 3. 信道类型 4.多径传播 5. 频率选择性衰落与相关带宽 6.信道容量&#xff08;连续信道的信道容量&#xff09; 7.调制的目的和分类 7.1 目的 7.2 方式 7.3 作用(正弦波调制) …