当前位置: 首页 > news >正文

【51单片机】串口通信原理 + 使用

学习使用的开发板:STC89C52RC/LE52RC
编程软件:Keil5
烧录软件:stc-isp

开发板实图:
在这里插入图片描述

文章目录

  • 串口
    • 硬件电路
    • UART
    • 串口相关寄存器
  • 编码
    • 单片机通过串口发送数据
    • 电脑通过串口发送数据控制LED灯

串口

  • 串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信
  • 单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力
    51单片机内部自带UART(Universal Asynchronous Receiver Transmitter,通用异步收发器),可实现单片机的串口通信

在这里插入图片描述

硬件电路

简单双向串口通信有两根通信线(发送端TXD(Transmit Exchange Data)和接收端RXD(Receive Exchange Date))

TXD和RXD要交叉连接,设备1的TXD连接设备2的RXD,设备1的RXD连接设备2的TXD
在这里插入图片描述
当只要单向传输数据时,可以只有一根通信线

GND是一定要连接的,若两个设备都可以各自供电,则不需要连接VCC

电平标准不一致时,还需要加电平转换芯片


电平标准

电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:

  • TTL电平:+5V表示1,0V表示0,一般用于单片机
  • RS232电平:-3 ~ -15V 表示1,+3 ~ +15V 表示0,一般用于电脑
  • RS485电平:两线压差 +2 ~ +6V 表示1,-2 ~ -6V 表示0(差分信号),一般用于CAN总线

前两个通信距离都较近,一般只有十几米,距离过远传输的数据就很容易出错;而RS485通信距离远,信号可靠性高,传输距离可达1KM以上


相关术语

  • 全双工:通信双方可以在同一时刻互相传输数据

在这里插入图片描述

  • 半双工:通信双方可以互相传输数据,但同时间只能有一段发送,另一端接收,必须分时复用一根数据线

在这里插入图片描述

  • 单工:通信双方只能一方发送到另一方,不能反向传输。比如遥控器控制电视,只能遥控器向电视发送数据
    在这里插入图片描述
  • 异步:通信双方各自约定通信速率
  • 同步:通信双方靠一根时钟线来约定通信速率

数据传输是依靠高低电平的,也就是电平协议。比如如下两个数据
在这里插入图片描述
看电平都是从高电平变为低电平,但是如果通信速率不一样,则获取的数据不一样
在这里插入图片描述
通信速率快,10可能会被解析为1100;通信速率慢,1100也可能会被解析为10。

所以约定好通信速率很重要

  • 总线:连接各个设备的数据传输线路(类似一条马路,把路边的住户连接起来,使住户可以相互交流)

在这里插入图片描述


常见通信接口比较

在这里插入图片描述

  • UART:为本节学习的串口通信接口
  • I2C:板子上的C24C02使用该串口
  • SPI:板子上的DS1302使用非标准SPI
  • 1-Wire:板子上的DS18B20使用该串口

常见的还有CAN总线USB,CAN总线常用于汽车领域


UART

51单片机的UART

STC89C52有1个UART,RXD和TXD分别和P3.0和P3.1这两个I/O口共用同一个引脚
在这里插入图片描述

STC89C52的UART有四种工作模式:
模式0:同步移位寄存器
模式1:8位UART,波特率可变(常用)
模式2:9位UART,波特率固定
模式3:9位UART,波特率可变


串口参数及时序图

  • 波特率:串口通信的速率(发送和接收各数据位的间隔时间)
  • 校验位:用于数据验证,一定程序可以知道数据是否错误,也需要双方提前协商统一校验。常用的校验如01校验奇偶校验9位UART就是多了一位校验位
  • 停止位:用于数据帧间隔,发送多个数据,如何间隔两个数据,就使用停止位
    波特率就是上述异步双方要约定好的如何对数据进行采样

串口收发数据,都是从低位开始
在这里插入图片描述

串口模式图

简单的串口模式图

在这里插入图片描述

UART是集成在单片机内部的,通过TXD引脚发送数据,RXD引脚接收数据

UART可以分为三个部分,中间为定时器T1——控制波特率;左侧绿框的SBUF用于收发数据;右侧为中断系统

SBUF:串口数据缓存寄存器,物理上是两个独立的寄存器,但占用相同的地址。写操作时,写入的是发送寄存器,读操作时,读出的是接收寄存器

完整的串口和中断系统模式图如下:

在这里插入图片描述

下面通过介绍相关寄存器来讲述串口通信的原理

串口相关寄存器

在这里插入图片描述

串行口控制寄存器SCON和PCON

STC89C52系列单片机的串行口设有两个控制寄存器:串行控制寄存器SCON波特率选择特殊功能寄存器PCON

PCON
电源控制寄存器,可能是电源控制还有剩下比特位,所以波特率选择和帧错误控制位也集成其中,减少资源消耗
格式如下:
在这里插入图片描述
我们只要关注SMODSMOD0 即可

  • SMOD:波特率选择位。当软件置SMOD = 1时,使串行通信方式1、2、3的波特率加倍;SMOD = 0,则不加倍。复位时SMOD = 0
  • SMOD0:帧错误检测有效控制位。当SMOD = 1,SCON寄存器中的 SM0/FE 位于 FE(帧错误检测)功能;当SMOD0 = 0,SCON的SM0/FE 用于 和 SM1 组合指定串行口的工作模式。复位时 SMOD0 = 0

SCON
用于选择串行通信的工作方式和某些控制功能,格式如下:
在这里插入图片描述

  • SM0/FE:当PCON寄存器的 SMOD0/FE = 1时,该位用于帧错误检测。当检测到一个无效停止位时,通过UART接收器设置该位,必须由软件清零;当SMOD0/FE = 0,该位和 SM1 组合指定工作模式

在这里插入图片描述

  • REN:允许/禁止串行接收控制位。由软件置位,若REN = 1即允许串行接收数据;REN = 0则禁止接收

  • SM2:允许方式2或方式3多机通信控制位

  • TB8:在方式2或方式3,为要发送的第9位数据,按需要由软件置位或清0。可用作数据的校验位或多机通信中表示地址帧/数据帧的标志位。

  • RB8:在方式2或方式3,是接收到的第9位数据。在方式1,若SM2=0,则RB8是接收到的停止位。方式0不用RB8。

  • TI:发送中断请求标志位。在方式0,当串行发送数据第8位结束时,由内部硬件置TI = 1,向主机请求中断,响应中断后必须用软件复位,即TI = 0。在其他方式中,则在停止位开始发送时由内部硬件置位必须用软件复位TI = 0

  • RI:接收中断请求标志位。在方式0,当串行接收到第8位结束时由内部硬件自动置位 RI = 1 ,向主机请求中断,响应中断后必须用软件复位,即RI=0。在其他方式中,串行接收到停止位的中间时刻由内部硬件置位,即RI=1,必须由软件复位,即RI=0

IE
中断允许寄存器
在这里插入图片描述
其中我们只关注EAES

  • EA:CPU的总中断允许控制位,EA = 1,CPU开放中断;EA = 0,CPU屏蔽所有中断请求
  • ES:串行口中断允许位,ES = 1,允许串行口中断;ES = 0,禁止串行口中断

在这里插入图片描述

注意:接收中断和发送中断共用一个中断,在中断处理函数中还需要通过RITI 的置位判断本次中断是接收中断还是发送中断


最后我们回归模式图,讲解一下串口通信的流程

在这里插入图片描述

发送数据
通过总线将数据写入SBUF,定时器1控制波特率。通过TXD发送数据,当发送数据结束时(方式0为发完8位数据,其他方式为发送停止位时),将 TI = 1,发送中断请求
接收数据
RXD接收数据,通过定时器1控制波特率,对接收数据进行采样,存放在SBUF,当接收数据结束(方式0当串行发送数据第8位结束时,在其他方式中,则在停止位开始发送时由内部硬件置位),将 RI = 1,发出中断请求

注意TIRI 都需要由软件置0

编码

经过上述学习,我们已经对串口有了一定的了解,接下来就是实现串口通信

单片机通过串口发送数据

我们使用UART串口通信,首先要进行初始化,如:选择工作方式,初始化中断系统,设置波特率,初始化定时器

选择工作模式
涉及到SCONPCON

首先是PCON的SMOD0,当 SMOD0 = 0 时,SMOD 的 SM0 才会被用来选择工作方式
其次,我们选择 8位UART,波特率可变模式,即方式1,SCON的SM0 = 0,SM1 = 1
最后,如果要允许串口接收数据,还需要置SCON的REN = 1


初始化中断系统

首先,初始化串口收发数据的中断请求标志位,SCON的 TIRI,由硬件置1,我们初始化时清零即可:TI = 0, RI = 0
到此,SCON的设置就结束了
总结一下,SM0 = 0, SM1 = 1, REN = 1/0, TI = 0, RI = 0,其他默认为0即可,所以SCON = 0x40/0x50

然后是中断开关
在这里插入图片描述

ES = 1, EA = 1

SCON = 0x50;	//选择工作方式 & 允许串口接收数据
PCON |= 0x80;	//使SM0为选择工作方式
//中断开关
ES = 1;			//串口中断开关
EA = 1;			//总中断开关

初始化定时器

初始化定时器可参看【51单片机】定时器
此处定时器1选择工作模式2——8位自动重装

8位自动重装
一次只对TL1或TH1计数加一
当一个溢出后,直接使用另一个计数单元的初值

//设置定时器1
TMOD &= 0x0F;	//高4位清零
TMOD |= 0x20;	//0010,模式3——8位自动重载
TR1 = 1;		//启用定时器T1
ET1 = 0;		//禁止定时器T1中断	
//定时器初值
TL1 = 0xF3;		//设定定时初值
TH1 = 0xF3;		//设定定时器重装值

设置波特率
我们设置波特率为4800
设置波特率需要通过设置定时器1的初始值

TL1 = 0xF3;		//设定定时初值
TH1 = 0xF3;		//设定定时器重装值

讲解一下为什么定时器初值是这个

假设系统频率为12MHz,使用12T模式,则定时器频率为12 / 12 = 1MHz,即每1us,计数单元加1。

使用8位自动重装,256时会溢出,0xF3 = 243,256 - 243 = 13。所以定时器溢出需要13us

溢出率:1 / 13 = 0.07692

使用SMOD = 1,波特率加倍(不除2)
在这里插入图片描述

还需要 0.07692 / 16 = 0.0048076923MHz
转化为Hz:4807.6923Hz,这个就是波特率
会存在一定误差

也可参看如下计算
在这里插入图片描述


到此,串口的初始化就完成了
完整代码如下:

/*** @brief		初始化串口* @parm		无* @retval		无*/
void UART_Init()
{//SCON高4位分别为SM0、SM1、SM2、REN//SM0和SM1控制串口模式,选择01——8位UART,波特率可变//REN接收使能,REN = 0禁止接收,REN = 1允许接收//所以设置0101 0000SCON = 0x50;//PCON包含波特率和电源设置//前两位为SMOD和SMOD0//SMOD = 1波特率加倍,SMOD = 0,波特率不加倍//SMOD0是帧错误的,此处不用//所以设置1000 0000PCON |= 0x80;//设置定时器1TMOD &= 0x0F;	//高4位清零TMOD |= 0x20;	//0010,模式3——8位自动重载TR1 = 1;		//启用定时器T1ET1 = 0;		//禁止定时器T1中断	//定时器初值TL1 = 0xF4;		//设定定时初值TH1 = 0xF4;		//设定定时器重装值//中断开关ES = 1;			//串口中断开关EA = 1;			//总中断开关
}

博主的单片机系统频率为11.0592MHz
可以使用STC-ICP生成波特率设置代码

在这里插入图片描述

注意:配置一定要选择正确;代码中的AUXR寄存器为高版本单片机才有的,低版本不认识这个寄存器,可以直接删掉


串口发送数据通过赋值SBUF,数据发送完后,硬件置位TI = 1,需要我们手动对TI清零
代码如下:

/*** @brief 		通过串口发送一个字节数据* @parm		Byte:要发送字节数据* @retval		无*/
void UART_SendByte(unsigned char Byte)
{SBUF = Byte;while(TI == 0);//数据发送完,硬件置1TI = 0;		//软件置0
}

模块化编程,完整代码如下:

延时模块——控制串口发送数据速率
Delay.h

#ifndef __DELAY_H__
#define __DELAT_H__void Delayms(unsigned int xms);//等待指定毫秒#endif

Delay.c

#include <INTRINS.h>
/*** @brief  延迟一定时间* @parm	延迟的时间,单位是毫秒,范围:0 ~ 65535* @retval	无*/
void Delayms(unsigned int xms)		//@11.0592MHz
{while(xms--){unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i);}	
}

UART串口模块

UART.h

#ifndef __UART_H__
#define __UART_H__void UART_Init();
void UART_SendByte(unsigned char Byte);#endif

UART.c

#include <REGX52.H>
/*** @brief		初始化串口* @parm		无* @retval		无*/
void UART_Init()
{//SCON高4位分别为SM0、SM1、SM2、REN//SM0和SM1控制串口模式,选择01——8位UART,波特率可变//REN接收使能,REN = 0禁止接收,REN = 1允许接收//所以设置0101 0000SCON = 0x50;//PCON包含波特率和电源设置//前两位为SMOD和SMOD0//SMOD = 1波特率加倍,SMOD = 0,波特率不加倍//SMOD0是帧错误的,此处不用//所以设置1000 0000PCON |= 0x80;//设置定时器1TMOD &= 0x0F;	//高4位清零TMOD |= 0x20;	//0010,模式3——8位自动重载TR1 = 1;		//启用定时器T1ET1 = 0;		//禁止定时器T1中断	//定时器初值TL1 = 0xF4;		//设定定时初值TH1 = 0xF4;		//设定定时器重装值//中断开关ES = 1;			//串口中断开关EA = 1;			//总中断开关
}
/*** @brief 		通过串口发送一个字节数据* @parm		Byte 要发送字节数据* @retval		无*/
void UART_SendByte(unsigned char Byte)
{SBUF = Byte;while(TI == 0);//数据发送完,硬件置1TI = 0;		//软件置0
}///**
//  * @brief 		接收数据 模版
//  * @parm			无
//  * @retval		无
//  */
//void UART_Routine() interrupt 4
//{
//	if(RI == 1)//检测是否是接收数据中断
//	{
//		RI = 0;//软件置0
//	}
//}

主程序——每隔一秒通过串口发送递增数据

#include <REGX52.H>
#include "UART.h"
#include "Delay.h"
/*** @brief		通过串口每隔1s发送递增的数据 范围:0 ~ 255* @parm		无* @retval		无*/
void SendIncreasingNum()
{static unsigned char num;UART_SendByte(num++);Delayms(1000);
}void main()
{UART_Init();while(1){SendIncreasingNum();}
}

使用STC-IST串口助手 查看效果

在这里插入图片描述
注意:下面一行的配置要正确

电脑通过串口发送数据控制LED灯

电脑发送数据给单片机需要USB转串口,自带的USB线就已经实现了这一转换,所以我们直接编写单片机通过串口接收数据的逻辑即可。

串口接收数据会存放在SBUF,接收完毕后会将RI置1,发出中断请求,中断号为4,然后需要手动清零RI

代码如下:

void UART_Routine() interrupt 4
{if(RI == 1)//检测是否是接收数据中断{P2 = SBUF;RI = 0;//软件置0}
}

注意P2寄存器用于控制LED亮灭,为0亮起,为1熄灭

还可以将数据重新返回给电脑,同样使用DelayUART 模块,只有main.c不同

main.c

#include <REGX52.H>
#include "UART.h"
#include "Delay.h"
/*** @brief 		接收数据,亮相应的灯,并返回数据* @parm		无* @retval		无*/
void UART_Routine() interrupt 4
{if(RI == 1)//检测是否是接收数据中断{P2 = SBUF;UART_SendByte(SBUF);RI = 0;//软件置0}
}
void main()
{UART_Init();while(1){}
}

效果如下:
我们通过串口助手,发送 0xAA = 1010 1010

在这里插入图片描述

LED灯效果如下:

在这里插入图片描述


以上就是本篇博客的所有内容,感谢你的阅读
如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
在这里插入图片描述

相关文章:

【51单片机】串口通信原理 + 使用

学习使用的开发板&#xff1a;STC89C52RC/LE52RC 编程软件&#xff1a;Keil5 烧录软件&#xff1a;stc-isp 开发板实图&#xff1a; 文章目录 串口硬件电路UART串口相关寄存器 编码单片机通过串口发送数据电脑通过串口发送数据控制LED灯 串口 串口是一种应用十分广泛的通讯接…...

优选算法第五讲:位运算模块

优选算法第五讲&#xff1a;位运算模块 1.常见的位运算总结2.判断字符是否唯一3.丢失的数字4.两整数之和5.只出现一次的数字II6.消失的两个数字 1.常见的位运算总结 2.判断字符是否唯一 链接: link class Solution { public:bool isUnique(string astr) {if(astr.size() >…...

【07】Maven项目多环境打包配置

&#xff08;1&#xff09;Web项目使用Maven进行多模块划分开发之后&#xff0c;面临一个问题&#xff0c;即如何加载不同环境的配置文件打包发布到不同的环境中&#xff1f; &#xff08;2&#xff09;不同的环境有开发环境、测试环境、线上生产环境等。 &#xff08;3&#x…...

嵌入式Linux入门具备:C语言基础与基本驱动学习(2):Linux GIibc IO基础

标准IO 标准 I/O 虽然是对文件 I/O 进行了封装&#xff0c;但事实上并不仅仅只是如此&#xff0c;标准 I/O 会处理很多细节&#xff0c;譬如分配 stdio 缓冲区、以优化的块长度执行 I/O 等&#xff0c;这些处理使用户不必担心如何选择使用正确的块长度。I/O 库函数是构建于文件…...

【微服务】Docker 容器化

一、初识Docker 1. 为什么需要 Docker 大型项目组件较多&#xff0c;运行环境也较为复杂&#xff0c;部署时会遇到一些问题&#xff1a; 依赖关系复杂&#xff0c;容易出现兼容性的问题开发、测试、生产环境有差异 Docker 如何解决依赖的兼容问题 将应用的Libs&#xff08;…...

[前端] 为网站侧边栏添加搜索引擎模块

前言 最近想给我的个人网站侧边栏添加一个搜索引擎模块&#xff0c;可以引导用户帮助本站SEO优化&#xff08;让用户可以通过点击搜索按钮完成一次对本人网站的搜索&#xff0c;从而实现对网站的搜索引擎优化&#xff09;。 最开始&#xff0c;我只是想实现一个简单的百度搜索…...

解决CORS (跨源资源共享) 错误

问题引入 前端代码 <template><div id"hello-vue" class"demo">{{ message }}</div><el-button type"primary" click"handleClick">我是一个按钮</el-button></template><script setup>//加…...

Redis 实现分布式缓存

一、引言 在当今互联网时代&#xff0c;随着业务的不断发展和用户量的持续增长&#xff0c;系统的性能和可扩展性成为了关键挑战。分布式缓存作为一种重要的技术手段&#xff0c;能够有效地缓解数据库压力、提高系统响应速度、增强系统的可扩展性。Redis 作为一种高性能的内存数…...

Chrome与火狐哪个浏览器的移动版本更流畅

在当今的数字化时代&#xff0c;移动设备已经成为我们生活中不可或缺的一部分。而浏览器作为我们访问互联网的重要工具&#xff0c;其性能和用户体验直接影响到我们的使用感受。本文将对比Chrome和火狐&#xff08;Firefox&#xff09;两款主流浏览器的移动版本&#xff0c;探讨…...

7篇Python爬虫实例,直接代码可运行,全网最全,注释超详细(适合收藏)——2、爬取图片信息。

7篇Python爬虫实例&#xff0c;可直接运行&#xff0c;适合收藏 python爬虫7篇实例&#xff0c;分七个文章进行发布&#xff1b;第二篇&#xff1a;爬取图片信息。 爬取图片信息&#xff0c;并将每张图片都下载下来。 爬虫主要三部分&#xff1a; 1、获取数据 2、数据解析 3、…...

25.停车场管理系统(基于web的Java项目)

目录 1.系统的受众说明 2.相关技术与方法 3.系统分析 3.1 可行性分析 3.1.1 技术可行性 3.1.2 经济可行性 3.1.3 操作可行性 3.2 需求分析 3.2.1 系统功能描述 3.2.2 用例图分析 4. 系统设计 4.1 系统类分析 5. 系统详细设计与实现 5.1 用户登录 5.2 系统信…...

展览搭建公司怎么跟展会主办打好交道

与展会主办打好交道的重要性 首先&#xff0c;我们得明白&#xff0c;展览搭建公司为何要跟展会主办打交道。简单地说&#xff0c;展会主办拥有大量的参展商信息。这些参展商是展览搭建公司潜在的客户群体&#xff0c;与主办打好交道&#xff0c;就等于拿到了通向这些客户的 “…...

软件开发方法

软件开发方法是一种用于指导软件开发过程的系统性方法,它涵盖了从需求分析、设计、编码、测试到维护的整个软件生命周期。软件开发方法通常包括一系列的步骤、技术和工具,以确保软件的质量、可维护性和可扩展性。 常见的软件开发方法有瀑布模型、敏捷开发、螺旋模型等。这些…...

「Mac畅玩鸿蒙与硬件24」UI互动应用篇1 - 灯光控制小项目

本篇将带领你实现一个互动性十足的灯光控制小项目&#xff0c;用户可以通过点击按钮来控制灯光的开关。该项目将涉及状态管理、动态图片加载以及按钮交互&#xff0c;是学习鸿蒙应用开发的重要基础。 关键词 UI互动应用状态管理动态图片加载用户交互 一、功能说明 在这个灯光…...

十二:java web(4)-- Spring核心基础

目录 创建项目 Spring 核心基础 Spring 容器 Spring 容器的作用 Spring 容器的工作流程 Bean Bean 的生命周期 IOC&#xff08;控制反转&#xff09;与依赖注入&#xff08;DI&#xff09; 控制反转的概念 依赖注入的几种方式&#xff08;构造器注入、Setter 注入、接…...

new和malloc有什么区别,他们的用法是什么?malloc分配失败会导致什么问题

1) new和malloc的区别&#xff0c;和他们的用法 new 和 malloc 主要有以下区别&#xff1a; 一、性质和来源 new &#xff1a;是 C 的运算符&#xff0c;在操作时会调用构造函数进行对象的初始化。它是 C 语言层面的操作&#xff0c;能更好地与 C 的面向对象特性结合。 malloc …...

了解SQLExpress数据库

SQLExpress&#xff08;Microsoft SQL Server Express&#xff09;是由微软公司开发的一款免费且轻量级的数据库管理系统。以下是关于SQLExpress的详细解释&#xff1a; 一、定义与特点 定义&#xff1a; SQLExpress是Microsoft SQL Server的一个缩减版或基础版&#xff0c;旨在…...

geoserver创建一个根据属性显示不同形状的点样式

geoserver创建一个根据属性显示不同形状的点样式 三角形 -triangle 圆形 - circle 正方形 - square 星形 - star 十字形 - cross 菱形 -diamond 代码&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <StyledLayerDescriptor version"…...

中国遗传学会2024全国学术研讨会在长沙成功召开

2024年11月3日至6日&#xff0c;备受瞩目的中国遗传学会2024全国学术研讨会在长沙盛大召开&#xff0c;此次盛会由中国遗传学会携手湖南省遗传学会共同主办&#xff0c;中南大学与南华大学共同承办。大会以“遗传学&#xff1a;前沿与交叉”为主题&#xff0c;吸引了来自全国各…...

Android Studio 多工程公用module引用

在Android Studio中&#xff0c;如果有多个工程需要共享同一个module&#xff0c;你可以通过以下步骤来实现module的公用&#xff1a; 1.将你想共享的module移动到一个单独的目录&#xff0c;比如一个新建的"libraries"文件夹。 2.修改module的build.gradle文件&am…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...