详解UART通信协议以及FPGA实现
文章目录
- 一、UART概述
- 二、UART协议帧格式
- 2.1 波特率
- 2.2 奇校验ODD
- 2.3 偶校验EVEN
- 三、UART接收器设计
- 3.1 接收时序图
- 3.2 Verilog代码
- 3.3 仿真文件测试
- 3.4 仿真结果
- 3.5 上版测试
- 四、UART发送器设计
- 4.1 发送时序图
- 4.2 Verilog代码
- 4.3 仿真文件测试
- 4.4 仿真结果
- 4.5 上板测试
- 五、UART回环测试
- 5.1 系统框图
- 5.2 Verilog代码
- 5.3 仿真文件测试
- 5.4 仿真结果
- 5.5 上板测试
- 六、参考
一、UART概述
从《浅谈UART,TTL,RS-232,RS-485的区别》这篇文章,我们知道了UART是一种串行、异步、全双工的通信协议,属于协议层;传输过程一般采用RS-232,RS-485电平标准,将所需传输的数据一位接一位地传输;整体传输框架如下:

串口通信由发送端和接收端构成,两根信号线实现,一根数据发送,一根数据接收。
二、UART协议帧格式
在串口通信过程中,数据接收与发送双方没有共享时钟,因此,双方必须协商好数据传输波特率。根据双方协议好的波特率,接收端即可对发送端的数据进行采样。整个传输流程如下:
- 传输线空闲时为高电平,然后拉低一个码元时间表示起始位
- 接着传输 8 个数据位,先传输低位,再传输高位
- 然后传输一个校验位,用来检测本次传输的数据是否正确
- 最后输出高电平表示停止位,可以是 1 位、1.5 位、2 位的高电平,并且进入空闲状态,等待下一次的数据传输
协议帧格式如下:

2.1 波特率
根据双方协议好的传输速率,接收端即可对发送端的数据进行采样。如果波特率为 9600也就是相当于每秒中划分成了 9600 等份的码元时间。常见的波特率标准为 300bps,600bps,800bps,9600bps,19200bps,38400bps,115200bps 等。通常对串口进行数据采样,采用更高频的时钟。
一个码元的计算方法:例如我们采样时钟为 50M ,所使用的波特率为 115200,传输 1个码元需要的时间( 1 / 115200 ) = 8680ns
2.2 奇校验ODD
使完整编码(有效位和校验位)中的 “1” 的个数为奇数个。如果原来信息中 1 的个数为奇数个,则校验位为 0,这样所有信息中1的个数还是奇数 ;如果原来信息中 1 的个数为偶数个,则校验位为 1,这样所有信息中1的个数还是奇数。
常见的串口通信格式是(8 位数据位+1 位奇数校验位)。以发送字符:10010101和11010101 为例
| 数据第0位 | 数据第1位 | 数据第2位 | 数据第3位 | 数据第4位 | 数据第5位 | 数据第6位 | 数据第7位 | 校验位 |
|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 |
| 1 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 |
2.3 偶校验EVEN
使完整编码(有效位和校验位)中的 “1” 的个数为偶数个。如果原来信息中 1 的个数为奇数个,则校验位为 1,这样所有信息中1的个数还是偶数 ;如果原来信息中 1 的个数为偶数个,则校验位为 0,这样所有信息中1的个数还是偶数。
常见的串口通信格式是(8 位数据位+1 位奇数校验位)。以发送字符:10010101和11010101 为例
| 数据第0位 | 数据第1位 | 数据第2位 | 数据第3位 | 数据第4位 | 数据第5位 | 数据第6位 | 数据第7位 | 校验位 |
|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 |
| 1 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 1 |
三、UART接收器设计
开发平台:vivado2021.1
开发芯片:xc7a100tfgg484-2
3.1 接收时序图
本次实现11500波特率,无奇偶校验位,时钟频率为50M,则每个码元计数次数为50000000/115200=434。时序图如下:

3.2 Verilog代码
`timescale 1ns/1ns
module uart_rx#
(parameter CLK_FREQ = 'd50_000_000, //时钟频率parameter UART_BPS = 'd115200 //波特率
)
(input clk , input rst_n , input rx , //uart_rxoutput reg [7:0] rx_data , //uart_rx_dataoutput reg rx_data_valid //uart_rx_data_valid
);localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS ;//一个码元的长度localparam BAUD_CNT_MAX_div2 = BAUD_CNT_MAX/2 ; reg rx_reg1 ;reg rx_reg2 ;reg rx_reg3 ;reg rx_flag ;reg [23:0] baud_cnt ;reg [3:0] bit_cnt ;reg bit_flag ;//打两拍,消除亚稳态
always @(posedge clk, negedge rst_n) beginif(rst_n == 1'b0)beginrx_reg1 <= 1'b1;rx_reg2 <= 1'b1;endelse beginrx_reg1 <= rx;rx_reg2 <= rx_reg1;end
end//再打一拍用于判断RX下降沿
always @(posedge clk, negedge rst_n) beginif(rst_n == 1'b0)rx_reg3 <= 1'b1;elserx_reg3 <= rx_reg2;end//接收范围
always @(posedge clk, negedge rst_n) beginif(rst_n == 1'b0)rx_flag <= 1'b0;else if (rx_reg3 == 1'b1 && rx_reg2 == 1'b0)rx_flag <= 1'b1;else if(bit_cnt == 'd8 && bit_flag ==1'b1)rx_flag <= 1'b0;elserx_flag <= rx_flag;
end//baud_cnt:波特率计数器计数,从 0 计数到 BAUD_CNT_MAX
always @(posedge clk, negedge rst_n) beginif(rst_n == 1'b0)baud_cnt <= 'd0;else if(baud_cnt == BAUD_CNT_MAX || rx_flag == 1'b0)baud_cnt <= 'd0;else if(rx_flag == 1'b1)baud_cnt <= baud_cnt + 1'b1;elsebaud_cnt <= baud_cnt;
end//bit_flag: baud_cnt 计数器计数到码元中间,时采样的数据最稳定
always @(posedge clk, negedge rst_n) beginif(rst_n == 1'b0)bit_flag <= 1'b0;else if(baud_cnt == BAUD_CNT_MAX_div2)bit_flag <= 1'b1;elsebit_flag <= 1'b0;end//bit_cnt:有效数据计数器, 8 个有效数据(不含起始位和停止位)
always @(posedge clk, negedge rst_n) beginif(rst_n == 1'b0)bit_cnt <= 'd0;else if(bit_cnt == 'd8 && bit_flag == 1'b1)bit_cnt <= 'd0;else if(bit_flag == 1'b1)bit_cnt <= bit_cnt + 1'b1;elsebit_cnt <= bit_cnt;
end//输出数据
always @(posedge clk, negedge rst_n) beginif(rst_n == 1'b0)rx_data <= 'd0;else if(bit_cnt >= 'd1 && bit_flag == 1'b1)rx_data <= {rx_reg3,rx_data [7:1]};elserx_data <= rx_data ;
end//输出数据有效信号,当接受完8个数据位后拉高
always @(posedge clk, negedge rst_n) beginif(rst_n == 1'b0)rx_data_valid <= 1'b0;else if(bit_cnt == 'd8 && bit_flag == 1'b1)rx_data_valid <= 1'b1;elserx_data_valid <= 1'b0;
endendmodule
3.3 仿真文件测试
这次仿真文件使用task任务来模拟uart发送数据
`timescale 1ns/1ns
module tb_uart_rx();reg clk ;reg rst_n ;reg rx ;wire [7:0] rx_data ;wire rx_data_valid ;initial beginclk = 0;rst_n = 0;rx = 1;#100rst_n = 1;end//调用task函数,连续发送八个数据initial begin#300tx_data(8'h6);tx_data(8'h6);tx_data(8'h1);tx_data(8'hA);tx_data(8'hB);tx_data(8'hC);tx_data(8'hD);tx_data(8'hE);tx_data(8'hF);end//定义task函数task tx_data(input [7:0] tx_data);integer i;for (i=0; i<10; i=i+1 ) begincase(i)0: rx <= 1'b0;1: rx <= tx_data[0];2: rx <= tx_data[1];3: rx <= tx_data[2];4: rx <= tx_data[3];5: rx <= tx_data[4];6: rx <= tx_data[5];7: rx <= tx_data[6];8: rx <= tx_data[7];9: rx <= 1'b1;endcase#(434*20);//每发送完一个bit数据后,延迟一个码元的时间endendtaskalways #10 clk = ~ clk;
uart_rx#(.CLK_FREQ ( 'd50_000_000 ),.UART_BPS ( 'd115200 )
)u1_uart_rx
(.clk ( clk ),.rst_n ( rst_n ),.rx ( rx ),.rx_data ( rx_data ),.rx_data_valid ( rx_data_valid )
);endmodule
3.4 仿真结果

由仿真结果可以看出,我们接收到的依次是(661ABCDEF)8个数据,和仿真文件给的一致。
3.5 上版测试
调用ila核,准备抓取rx_data,rx_data_valid信号。通过上位机发送数据,观察rx_data是否正确

上位机没发送数据时候,ila采集不到rx_data_valid信号拉高。

上位机发送一个9F时,ila采集到rx_data_valid信号拉高,并且输出rx_data为9F
四、UART发送器设计
4.1 发送时序图

4.2 Verilog代码
`timescale 1ns / 1ps
module uart_tx#
(parameter CLK_FREQ = 'd50_000_000, //时钟频率parameter UART_BPS = 'd115200 //波特率
)
(input clk ,input rst_n ,input [7:0] tx_data , //发送数据input tx_data_en , //发送数据有效信号output reg tx
);localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS;//待计数的码元周期最大值reg [7:0] tx_data_reg ;reg [23:0] baud_cnt ;reg [3:0] bit_cnt ;reg bit_flag ;reg tx_flag ;//将待发送的数据缓存起来
always @(posedge clk or negedge rst_n) beginif(rst_n == 1'b0)tx_data_reg <= 'd0;else if(tx_data_en == 1'b1)tx_data_reg <= tx_data;elsetx_data_reg <= tx_data_reg;
end//tx_flag拉高时刻
always @(posedge clk or negedge rst_n) beginif(rst_n == 1'b0)tx_flag <= 1'b0;else if(tx_data_en == 1'b1)tx_flag <= 1'b1;else if(bit_cnt == 'd9 && bit_flag == 1'b1)tx_flag <= 1'b0;elsetx_flag <= tx_flag;
end//baud_cnt 计数器
always @(posedge clk or negedge rst_n) beginif(rst_n == 1'b0)baud_cnt <= 'd0;else if(baud_cnt == BAUD_CNT_MAX)baud_cnt <= 'd0;else if(tx_flag == 1'b1)baud_cnt <= baud_cnt + 1'b1;elsebaud_cnt <= 'd0;
end
//bit_flag拉高时刻
always @(posedge clk or negedge rst_n) beginif(rst_n == 1'b0)bit_flag <= 1'b0;else if(baud_cnt == 'd1)bit_flag <= 1'b1;elsebit_flag <= 1'b0;
end//bit_cnt 计数器
always @(posedge clk or negedge rst_n) beginif(rst_n == 1'b0)bit_cnt <= 'd0;else if(bit_cnt == 'd9 && bit_flag == 1'b1)bit_cnt <= 'd0;else if(bit_flag == 1'b1)bit_cnt <= bit_cnt + 1'b1;elsebit_cnt <= bit_cnt;
end//移位data,由低到高发送至tx
always @(posedge clk or negedge rst_n) beginif(rst_n == 1'b0)tx <= 1'b1;else if(bit_flag == 1'b1)case(bit_cnt)0: tx <= 1'b0;1: tx <= tx_data_reg[0];2: tx <= tx_data_reg[1];3: tx <= tx_data_reg[2];4: tx <= tx_data_reg[3];5: tx <= tx_data_reg[4];6: tx <= tx_data_reg[5];7: tx <= tx_data_reg[6];8: tx <= tx_data_reg[7];9: tx <= 1'b1;default:tx <= 1'b1;endcase
endendmodule
4.3 仿真文件测试
模拟两个数据(1A,3B)的输入,让tx模块发送
`timescale 1ns / 1ns
module tb_uart_tx();reg clk ;reg rst_n ;wire tx ;reg [7:0] tx_data ;reg tx_data_en ;initial beginclk = 0;rst_n = 0;tx_data = 8'd0;tx_data_en = 0;#100rst_n = 1;#300tx_data = 8'h1a;tx_data_en = 1;#20 tx_data_en = 0;#(434*20*10+100)//等待10个码元周期时间再等待100nstx_data = 8'h3b;tx_data_en = 1;#20 tx_data_en = 0;#(434*20*10+100)$stop;endalways #10 clk = ~clk;uart_tx#
(.CLK_FREQ ( 'd50_000_000 ),.UART_BPS ( 'd115200 )
)
u1_uart_tx
(.clk ( clk ),.rst_n ( rst_n ),.tx_data ( tx_data ),.tx_data_en ( tx_data_en ),.tx ( tx )
);endmodule
4.4 仿真结果

因为发送数据是(1A:00011010)uart先发送起始位,再发送数据位从低到高,最后拉高一个停止位。理论上tx发送的顺序就是0_01011000_1
从仿真结果来看,tx线上的顺序和理论一致,3B数据同理。
4.5 上板测试
我们创建一个顶层,调用uart_tx模块,在顶层上输入一个数据,让发送模块发出,然后在上位机上接送,观察和我们发送的数据是否一致,代码如下:
`timescale 1ns / 1psmodule uart_top(input clk ,input rst_n ,output tx );reg [7:0] tx_data ;reg tx_data_en ;reg [1:0] cnt ;always @(posedge clk or negedge rst_n) beginif(rst_n == 1'b0)cnt <= 'd0;else if(cnt == 'd3)cnt <= cnt;else cnt <= cnt +1'b1;endalways @(posedge clk or negedge rst_n) beginif(rst_n == 1'b0)begintx_data <= 'd0;tx_data_en <= 1'b0;endelse if (cnt == 'd2)begintx_data <= 8'h6D;tx_data_en <= 1'b1;endelse begintx_data <= 'd0;tx_data_en <= 1'b0;endenduart_tx#
(.CLK_FREQ ( 'd50_000_000 ),.UART_BPS ( 'd115200 )
)
u_uart_tx
(.clk ( clk ),.rst_n ( rst_n ),.tx_data ( tx_data ),.tx_data_en ( tx_data_en ),.tx ( tx )
);endmodule
我们在顶层模块发送了一个 6D数据。

上板后,上位机收到了 6D数据
五、UART回环测试
5.1 系统框图
上面我们测试了UART发送和接收模块都正常,接下来我们将接收模块的输出信号接到发送模块的输入信号,在上位机上面发送数据和接收数据,看是否一致,系统框图如下:

5.2 Verilog代码
`timescale 1ns / 1psmodule uart_top(input clk ,input rst_n ,input rx ,output tx );wire [7:0] rx_data ;wire rx_data_valid ;uart_rx#
(.CLK_FREQ ( 'd50_000_000 ),.UART_BPS ( 'd115200 )
)
u_uart_rx(.clk ( clk ),.rst_n ( rst_n ),.rx ( rx ),.rx_data ( rx_data ),.rx_data_valid ( rx_data_valid )
);uart_tx#
(.CLK_FREQ ( 'd50_000_000 ),.UART_BPS ( 'd115200 )
)
u_uart_tx
(.clk ( clk ),.rst_n ( rst_n ),.tx_data ( rx_data ),.tx_data_en ( rx_data_valid ),.tx ( tx )
);endmodule
5.3 仿真文件测试
我们依然用uart_rx里的测试代码,调用task函数,发送661abcdef
`timescale 1ns / 1ps
module tb_uart_top();reg clk ;reg rst_n ;reg rx ;wire tx ;initial beginclk = 0;rst_n = 0;rx = 1;#100rst_n = 1;end//调用task函数,连续发送八个数据initial begin#300tx_data(8'h6);tx_data(8'h6);tx_data(8'h1);tx_data(8'hA);tx_data(8'hB);tx_data(8'hC);tx_data(8'hD);tx_data(8'hE);tx_data(8'hF);end//定义task函数task tx_data(input [7:0] tx_data);integer i;for (i=0; i<10; i=i+1 ) begincase(i)0: rx <= 1'b0;1: rx <= tx_data[0];2: rx <= tx_data[1];3: rx <= tx_data[2];4: rx <= tx_data[3];5: rx <= tx_data[4];6: rx <= tx_data[5];7: rx <= tx_data[6];8: rx <= tx_data[7];9: rx <= 1'b1;endcase#(434*20);//每发送完一个bit数据后,延迟一个码元的时间endendtaskalways #10 clk =~clk;
uart_top u_uart_top(.clk ( clk ),.rst_n ( rst_n ),.rx ( rx ),.tx ( tx )
);endmodule
5.4 仿真结果

可以看出接收后的数据和发送的数据没问题
5.5 上板测试

可以看到发送和接收都正常
六、参考
UART介绍
相关文章:
详解UART通信协议以及FPGA实现
文章目录 一、UART概述二、UART协议帧格式2.1 波特率2.2 奇校验ODD2.3 偶校验EVEN 三、UART接收器设计3.1 接收时序图3.2 Verilog代码3.3 仿真文件测试3.4 仿真结果3.5 上版测试 四、UART发送器设计4.1 发送时序图4.2 Verilog代码4.3 仿真文件测试4.4 仿真结果4.5 上板测试 五、…...
【算法】删除链表中重复元素
本题来源---《删除链表中重复元素》。 题目描述 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回已排序的链表 。 示例 1: 输入:head [1,1,2] 输出:[1,2]示例 2: 输入…...
mysql防坑指南
1. MySQL连接数问题 MySQL里的max_connections参数代表mysql数据库的最大连接数,参数默认是151,显然不适用于生产,如果请求大于默认连接数,就会出现无法连接数据库的错误,会遇到too many connections的报错信息。 Mys…...
偏微分方程算法之混合边界差分
目录 一、研究对象 二、差分格式 2.1 向前欧拉格式 1. 中心差商 1.1.1 理论推导 1.1.2 算例实现 2. x0处向前差商,x1处向后差商 1.2.1 理论推导 1.2.2 算例实现 2.2 Crank-Nicolson格式 2.2.1 理论推导 2.2.2 算例实现 一、研究对象 这里我们以混合边界…...
中国八大古都,分别是哪8个?
中国历史上统一王朝或者在全局范围内看呈鼎立之势的大的政权的首都,称古都,又称都城、国都等,是古代王朝的政治中心,也是经济和文化中心。 1、西安 西安,古称长安,是中国历史上建都时间最长、建都朝代最多…...
财务信息化与财务软件有何区别与联系?
财务产品与财务信息化,两者究竟有何不同,又有何相通之处?或许,你心中也充满了这样的疑惑。那么,让我用一则小故事,为你揭晓其中的秘密。 想象这样一个场景,长尾狐狸,作为饭团公司的…...
ssm052游戏攻略网站的设计与实现+vue
游戏攻略网站设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本游戏攻略网站就是在这样的大环境下诞生,其可以帮助管理者在短时间内处…...
SAP Credit Memo 到期日设置技巧
当我们用FB60, MIRO或者FB70 记账vendor或者customer 的Credit Memo的时候,我们发现Credit Memo的Due Date不受付款条款的影响,默认为跟baseline date是同一天,并且无法手工更改,那么如果要设置到期日怎么操作呢? 首先…...
软件开发安全设计方案
2.1.应用系统架构安全设计要求 2.2.应用系统软件功能安全设计要求 2.3.应用系统存储安全设计要求 2.4.应用系统通讯安全设计要求 2.5.应用系统数据库安全设计要求 2.6.应用系统数据安全设计要求 软件开发全资料获取:软件开发全套资料_软件开发资料-CSDN博客https://…...
【Zabbix】zabbix 软件监控
使用zabbix监控系统查看服务器状态以及网站流量指标,利用监控系统的数据去了解上线发布的结果,和网站的健康状态 利用一个优秀的监控软件,我们可以: ●通过一个友好的界面进行浏览整个网站所有的服务器状态 ●可以在 Web 前端方便的查看监控…...
Vue Router 路由动态缓存组件
文章目录 一、简介基本用法生命周期钩子 二、定义是否缓存组件三、缓存组件1. 通过 :include 属性实现vue2.x中vue3.x中 2. 通过 v-slot 功能实现3. 通过 v-if 来实现 四、注意事项 一、简介 Vue Router 允许你缓存路由组件,这样在用户导航回之前的页面时ÿ…...
数据结构:线性表————单链表专题
🌈个人主页:小新_- 🎈个人座右铭:“成功者不是从不失败的人,而是从不放弃的人!”🎈 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝 🏆所属专栏࿱…...
多线程(54)JMM中的内存屏障
Java内存模型(JMM)中的内存屏障是一种保证内存可见性、顺序性的底层机制。它们是一组指令,用于在多线程环境中确保内存操作的有序性和可见性。内存屏障主要分为四类:LoadLoad、StoreStore、LoadStore和StoreLoad。 内存屏障的类型…...
什么是流量清洗?
随着网络企业的迅速发展,越来越多的用户都开始关注关于网络流量的问题,同时,随着网络流量的增多,网络上也出现了大量的垃圾信息和恶意攻击,给网络带来了很大的困扰,而流量清洗则能够解决这个问题。 流量清洗…...
淘宝API(通过商品详情接口采集商品页面数据)请求说明文档|可接入测试key
淘宝商品详情数据接口(taobao.item_get)是天猫开放平台提供的一种API接口,旨在帮助开发者获取天猫平台上的商品详情信息。通过调用这个接口,开发者可以获取包括商品ID、标题、价格、库存量、图片等在内的详细数据,从而…...
示例说明闭包函数
示例说明闭包函数 闭包函数是指在一个函数内部定义另一个函数,并且内部函数可以访问外部函数的局部变量,即使外部函数已经执行完毕。 这种功能使得闭包函数可以捕获外部函数的状态,提供了一种保留局部变量值的方式。闭包函数在编程中常用于…...
【自媒体创作利器】AI白日梦+ChatGPT 三分钟生成爆款短视频
AI白日梦https://brmgo.com/signup?codey5no6idev 引言 随着人工智能(AI)技术的快速发展,AI在各个领域都展现出了强大的应用潜力。其中,自然语言处理技术的进步使得智能对话系统得以实现,而ChatGPT作为其中的代表之一…...
把握零碎时间,开启长期副业兼职之旅!在家也能轻松赚钱!
转眼间,2024年已悄然走过三分之一。这一年,外界环境似乎并不那么友好,但对我而言,我的月收入仍然相对稳定。我找到的副业让我每月能赚到3000元以上,这让我深感庆幸。 现实中,只依赖主业工资的日子确实艰辛…...
HarmonyOS开发实例:【数字管家app】
样例简介 数字管家场景需要手机端、设备端和服务端三方协同完成,本文档介绍的demo是数字管家大场景中的手机端应用;用户注册登录后可创建我的家庭并管理家庭成员;可以添加设备(包括智能台灯,智能窗帘,智能…...
人工智能_大模型033_LangChain003_记忆封装Memory上下文控制机制_LCEL表达式语言---人工智能工作笔记0168
## 三、记忆封装:Memory ### 3.1、对话上下文:ConversationBufferMemory from langchain.memory import ConversationBufferMemory, ConversationBufferWindowMemoryhistory = ConversationBufferMemory() history.save_context({"input": "你好啊"}…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
