12 ABC串口接收原理与思路
1. 串口接收原理

基本原理:通过数据起始位判断要是否要开始接收的数据,通过采样的方式确定每一位数据是0还是1。
如何判断数据起始位到来:通过边沿检测电路检测起始信号的下降沿
如何采样:一位数据采多次,统计得到高电平出现的次数,次数多的就是该位的电平值


2. 自己写的代码(不完善)
设计代码
module uart_byte_rx(clk,rstn,uart_byte_rx,blaud_set,data,rx_done
);input clk;input rstn;input uart_byte_rx;input blaud_set;output reg [7:0] data;output reg rx_done;//Blaud_set = 0时,波特率 = 9600;//Blaud_set = 1时,波特率 = 19200;//Blaud_set = 2时,波特率 = 38400;//Blaud_set = 3时,波特率 = 57600;//Blaud_set = 4时,波特率 = 115200;reg[17:0] bps_dr;always@(*)case(blaud_set)0: bps_dr = 1000000000/9600/20;1: bps_dr = 1000000000/19200/20;2: bps_dr = 1000000000/38400/20;3: bps_dr = 1000000000/57600/20;4: bps_dr = 1000000000/115200/20;endcasereg [1:0] test;reg get_en;always@(posedge clk or negedge rstn) //边沿检测,使能后续的采样if(!rstn) begindata <= 0;test <= 0;get_en <= 0;rx_done <= 0;endelse begintest[0] <= uart_byte_rx;test[1] <= test[0];if((test[0] ==0 )&&(test[1] == 1))get_en <= 1;rx_done <= 0;endreg [17:0] div_cnt;reg [3:0] counter;reg [3:0] tx_counter;always@(posedge clk or negedge rstn) //计数时钟,一个计数周期代表一位数据if(!rstn) div_cnt <= 0;else if(get_en)beginif(div_cnt == 434 - 1)div_cnt <= 0;elsediv_cnt <= div_cnt + 1'd1;end wire bps_clk;assign bps_clk = (div_cnt == 1);always@(posedge clk or negedge rstn) //数据段,包含起始位和终止位,共十段if(!rstn) tx_counter <= 0;else if(get_en)beginif(tx_counter == 11)tx_counter <= 0;else if(div_cnt == 1)tx_counter <= tx_counter + 1'd1;end always@(posedge clk or negedge rstn) //数据采样,每段数据采样8次。if(!rstn)counter <= 0;else if(div_cnt == 3)counter <= 0;else if((div_cnt == 1*433/8 - 10)||(div_cnt == 2*433/8 - 10)||(div_cnt == 3*433/8 - 10)||(div_cnt == 4*433/8 - 10)||(div_cnt == 5*433/8 - 10)||(div_cnt == 6*433/8 - 10)||(div_cnt == 7*433/8 - 10)||(div_cnt == 8*433/8 - 10))counter <= counter + uart_byte_rx;always@(posedge clk or negedge rstn) //if(!rstn) counter <= 0;else if(div_cnt == 2)case(tx_counter)2:if(counter > 4 )data[0] <= 1; else if(counter <4) data[0] <= 0;3:if(counter > 4 )data[1] <= 1; else if(counter <4) data[1] <= 0; 4:if(counter > 4 )data[2] <= 1; else if(counter <4) data[2] <= 0; 5:if(counter > 4 )data[3] <= 1; else if(counter <4) data[3] <= 0; 6:if(counter > 4 )data[4] <= 1; else if(counter <4) data[4] <= 0; 7:if(counter > 4 )data[5] <= 1; else if(counter <4) data[5] <= 0; 8:if(counter > 4 )data[6] <= 1; else if(counter <4) data[6] <= 0; 9:if(counter > 4 )data[7] <= 1; else if(counter <4) data[7] <= 0;11:begin rx_done <= 1; get_en <= 0; div_cnt <= 0; enddefault: begin rx_done <= 0; data <= data; endendcase
endmodule
仿真波形

3. 看完视频后写的代码(完善)
设计代码
3.1 需学习的点:
1.将div_cnt划分为最小时间段
2.某些判断信号直接用assign利用,而不需要利用寄存器
3.仿真代码中task的使用
module uart_byte_rx1(clk,rstn,blaud_set,uart_rx,data,rx_done
);input clk;input rstn;input [2:0]blaud_set;input uart_rx;output reg [7:0] data;output rx_done;reg [8:0] bps_dr;always@(*)case(blaud_set)0:bps_dr = 1000000000/9600/16/20;1:bps_dr = 1000000000/19200/16/20;2:bps_dr = 1000000000/38400/16/20;3:bps_dr = 1000000000/57600/16/20;4:bps_dr = 1000000000/115200/16/20;default : bps_dr = 1000000000/9600/16/20;endcase//边沿信号检测reg [1:0] uart_rx_r; //用两位寄存器分别存储两个时间沿的uart_rx信号always@(posedge clk) beginuart_rx_r[0] <= uart_rx;uart_rx_r[1] <= uart_rx_r[0];end//将两位寄存器的值直接通过导线输出进行判断(不需要再使用寄存器)wire nedge_uart_rx; //掌握一下这个方法,之前一直使用的是寄存器//法一://assign nedge_uart_rx = ((uart_rx_r[0] == 0)&&(uart_rx_r == 1));//法二:assign nedge_uart_rx = (uart_rx_r == 2'b10);reg rx_en;always@(posedge clk or negedge rstn)if(!rstn)rx_en <= 0;else if(nedge_uart_rx)rx_en <= 1;else if(rx_done)rx_en <= 0;//周期计数器reg [8:0] div_cnt;always@(posedge clk or negedge rstn)if(!rstn)div_cnt <= 0;else if(rx_en) beginif(div_cnt == bps_dr - 1)div_cnt <= 0;elsediv_cnt <= div_cnt + 1'd1;endelsediv_cnt <= 0;wire [3:0]bps_clk_16x; //(一定要记得加位宽)采样信号,这种写法很灵活assign bps_clk_16x = bps_dr/2; //采样每一段的中点值,同时也可以用它来计数。//发送一字节的数据有需要十个数据位,每位数据有16个小段供采样,共160reg [7:0]bps_cnt;always@(posedge clk or negedge rstn)if(!rstn)bps_cnt <= 0;else if(rx_en) beginif(bps_cnt == 159)bps_cnt <= 0;else if(div_cnt ==bps_clk_16x)bps_cnt <= bps_cnt + 1'd1; endelse bps_cnt <= 0;reg[2:0] r_data[7:0];//二维数据,代表八个r_data,每个r_data有3位寄存器存储数值。reg[2:0] sta_data;reg[2:0] sto_data;always@(posedge clk or negedge rstn)if(!rstn)beginsta_data <= 0;sto_data <= 0;r_data[0] <= 0; //语法规定,二维数组赋值要分开赋值r_data[1] <= 0; r_data[2] <= 0;r_data[3] <= 0; r_data[4] <= 0; r_data[5] <= 0; r_data[6] <= 0; r_data[7] <= 0; endelse if(div_cnt == bps_clk_16x - 1)case(bps_cnt) //下面合在一起的写法是允许的0:beginr_data[0] <= 0; r_data[1] <= 0; r_data[2] <= 0;r_data[3] <= 0; r_data[4] <= 0; r_data[5] <= 0; r_data[6] <= 0; r_data[7] <= 0;end 5,6,7,8,9,10,11: sta_data <= sta_data + uart_rx;21,22,23,24,25,26,27: r_data[0] <= r_data[0] + uart_rx;37,38,39,40,41,42,43: r_data[1] <= r_data[1] + uart_rx;53,54,55,56,57,58,59: r_data[2] <= r_data[2] + uart_rx;69,70,71,72,73,74,75: r_data[3] <= r_data[3] + uart_rx;85,86,87,88,89,90,91: r_data[4] <= r_data[4] + uart_rx;101,102,103,104,105,106,107: r_data[5] <= r_data[5] + uart_rx;117,118,119,120,121,122,123: r_data[6] <= r_data[6] + uart_rx;133,134,135,136,137,138,139: r_data[7] <= r_data[7] + uart_rx;149,150,151,152,153,154,155: sto_data <= sto_data + uart_rx;default:;endcase reg rx_done;always@(posedge clk or negedge rstn)if(!rstn)rx_done <= 0;else if(bps_cnt == 159) beginrx_done <= 1;endelserx_done <= 0;//数据接收完成后赋值给data输出always@(posedge clk or negedge rstn)if(!rstn)data <= 0;else if(rx_done)begindata[0] <= (r_data[0] >= 4 ) ? 1 : 0; //可换种写法,写法如下data[1] <= (r_data[1] >= 4 ) ? 1 : 0;data[2] <= (r_data[2] >= 4 ) ? 1 : 0;data[3] <= (r_data[3] >= 4 ) ? 1 : 0;data[4] <= (r_data[4] >= 4 ) ? 1 : 0;data[5] <= (r_data[5] >= 4 ) ? 1 : 0;data[6] <= (r_data[6] >= 4 ) ? 1 : 0;data[7] <= (r_data[7] >= 4 ) ? 1 : 0;end// data[1] <= r_data[1][2]// 0:3'd000// 1:3'd001// 2:3'd010// 4:3'd100// 5:3'd101// 6:3'd110// 7:3'd111 利用第3位的区别给data赋值endmodule
仿真代码
`timescale 1ns/1nsmodule uart_byte_rx1_tb();reg clk;reg rstn;reg uart_rx;wire [2:0]blaud_set;wire [7:0]data;wire rx_done;uart_byte_rx1 uart_byte_rx_inst1(.clk(clk),.rstn(rstn),.blaud_set(blaud_set),.uart_rx(uart_rx),.data(data),.rx_done(rx_done));assign blaud_set = 3'd4;initial clk = 1;always #10 clk = ~clk;initial beginrstn = 0;uart_rx = 1;#201;rstn = 1;#200;uart_tx_byte(8'h5a);@(posedge rx_done)#5000;uart_tx_byte(8'ha5);@(posedge rx_done)#5000;uart_tx_byte(8'h86);@(posedge rx_done)#5000;$stop;endtask uart_tx_byte;input [7:0] tx_data;beginuart_rx = 1;#20;uart_rx = 0;#8680;uart_rx = tx_data[0];#8680;uart_rx = tx_data[1];#8680;uart_rx = tx_data[2];#8680;uart_rx = tx_data[3];#8680;uart_rx = tx_data[4];#8680;uart_rx = tx_data[5];#8680;uart_rx = tx_data[6];#8680;uart_rx = tx_data[7];endendtaskendmodule
仿真波形

相关文章:
12 ABC串口接收原理与思路
1. 串口接收原理 基本原理:通过数据起始位判断要是否要开始接收的数据,通过采样的方式确定每一位数据是0还是1。 如何判断数据起始位到来:通过边沿检测电路检测起始信号的下降沿 如何采样:一位数据采多次,统计得到高…...
leetcode(二分查找)34.在排序数组中查找元素的第一个和最后一个位置(C++详细解释)DAY11
文章目录 1.题目示例提示 2.解答思路3.实现代码结果 4.总结 1.题目 给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target,返回 [-1, -1]。 你必须设计…...
算法刷题框架
前言:最近积累了一些算法题量,正在刷东神的算法笔记,监督自己记录下读后启发,顺便帮助道友们阅读 数据结构 这一部分老生常谈,数据的存储方式只有顺序存储和链式存储。 最基本的数组和链表对应这两者,栈…...
跟着cherno手搓游戏引擎【24】开启2D引擎前的项目总结(包括前置知识汇总)
前置技术: c动态链接和静态链接: 隐藏的细节:编译与链接_哔哩哔哩_bilibili 【底层】动态链接库(dll)是如何工作的?_哔哩哔哩_bilibili 预编译,编译,汇编,链接 预编译头文件: 为…...
石子合并+环形石子合并+能量项链+凸多边形的划分——区间DP
一、石子合并 (经典例题) 设有 N 堆石子排成一排,其编号为 1,2,3,…,N。 每堆石子有一定的质量,可以用一个整数来描述,现在要将这 N 堆石子合并成为一堆。 每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,…...
IMX6ULL移植U-Boot 2022.04
目录 目录 1.编译环境以及uboot版本 2.默认编译测试 3.uboot中新增自己的开发板 3.编译测试 4.烧录测试 5.patch文件 1.编译环境以及uboot版本 宿主机Debian12u-boot版本lf_v2022.04 ; git 连接GitHub - nxp-imx/uboot-imx: i.MX U-Boot交叉编译工具gcc-arm-10.3-2021.0…...
ES实战-高级聚合
多桶型聚合 1.词条聚合–terms 2.范围聚合–range 3,直方图聚合–histogram/日期直方图 4.嵌套聚合 5.地理距离聚合 include(包含)exclude(不包含) GET /get-together/_search?pretty {"size": 0,"aggs": {"tags": {"terms": {"…...
网络安全产品之认识蜜罐
文章目录 一、什么是蜜罐二、蜜罐的主要类型三、蜜罐的主要功能四、蜜罐的主要组成及核心技术五、蜜罐的优缺点六、蜜罐如何与其他安全工具协同工作?七、什么是“蜜网”?与蜜罐的联系和区别是什么? 蜜罐的概念首次由Clifford Stoll在其1988年…...
推荐《架构探险:从零开始写Java Web框架》
版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl 春节读了《架构探险:从零开始写Java Web框架》,一本大概10年前的好书。 本书的作者是阿里巴巴架构师黄勇。黄勇对分布式服务架构与大数据技术有深入…...
Go教程-Go语言简介
这篇文章我们来聊聊Go语言。 Go语言发展历史 以下是Go语言发展的几个里程碑节点: Go一开始是Google内部的一个项目,由三位大佬Rob Pike、Robert Griesemer、Ken Thompson早2007年发起。在2009年11月,Go语言正式对外开源。在2010年…...
React + SpringBoot + Minio实现文件的预览
思路:后端提供接口,从minio获取文件的预览链接,返回给前端,前端使用组件进行渲染展示 这里我从minio获取文件预览地址用到了一个最近刚开源的项目,挺好用的,大伙可以试试,用法也很简单 官网&am…...
心法利器[107] onnx和tensorRT的bert加速方案记录
心法利器 本栏目主要和大家一起讨论近期自己学习的心得和体会,与大家一起成长。具体介绍:仓颉专项:飞机大炮我都会,利器心法我还有。 2023年新一版的文章合集已经发布,获取方式看这里:又添十万字-CS的陋室2…...
AcWing 122 糖果传递(贪心)
[题目概述] 有 n 个小朋友坐成一圈,每人有 a[i] 个糖果。 每人只能给左右两人传递糖果。 每人每次传递一个糖果代价为 1。 求使所有人获得均等糖果的最小代价。 输入格式 第一行输入一个正整数 n,表示小朋友的个数。 接下来 n 行,每行一个…...
unity的重中之重:组件
检查器(Hierarchy)面板中的所有东西都是组件。日后多数工作都是和组件打交道,包括调参、自定义脚本组件。 文章目录 12 游戏的灵魂,脚本组件13 玩转脚本组件14 尽职的一生,了解组件的生命周期15 不能插队!…...
Linux释放内存
free -m是Linux上查看内存的指令,其中-m是以兆(MB)为单位,如果不加则以KB为单位。 如下图表示,(total)总物理内存是809MB,(used)已使用167MB,&…...
Python算法题集_翻转二叉树
Python算法题集_翻转二叉树 题226:翻转二叉树1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【DFS递归】2) 改进版一【BFS迭代,节点循环】3) 改进版二【BFS迭代,列表循环】 4. 最优算法 本文为Python算法题集…...
Git快速掌握,通俗易懂
Git分布式版本控制工具 介绍 Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。Git是由Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Git可以帮助开发者们管理代码的版本,避免代码冲突&#…...
PHP毕业设计图片分享网站76t17
图片分享网站主要是为了提高工作人员的工作效率和更方便快捷的满足用户,更好存储所有数据信息及快速方便的检索功能,对系统的各个模块是通过许多今天的发达系统做出合理的分析来确定考虑用户的可操作性,遵循开发的系统优化的原则,…...
代码随想录 Leetcode45. 跳跃游戏 II
题目: 代码(首刷看解析 2024年2月15日): class Solution { public:int jump(vector<int>& nums) {if (nums.size() 1) return 0;int res 0;int curDistance 0;int nextDistance 0;for (int i 0; i < nums.size(); i) {nex…...
【C语言】socketpair 的系统调用
一、 Linux 内核 4.19socketpair 的系统调用 SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,int __user *, usockvec) {return __sys_socketpair(family, type, protocol, usockvec); } 这段代码定义了一个名为 socketpair 的系统调用。系统调用是操作…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
