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

10天学会嵌入式技术之51单片机-day-7

第十六章 UART通信

16.1 UART 概述

16.1.1 前置基础

想要理解和使用 UART,需要先了解一些通讯领域的术语,如下 。

(1)串行通讯和并行通讯

串行通讯和并行通讯是数据传输的两种主要方式,两者的区别如下。

(2)单工通讯和双工通讯

单工和双工是通讯领域中用于描述数据传输方向的术语,它们定义了两个设备之间的
数据通信方式。

单工通信,只允许数据在一个方向上传输,即数据只能从发送端传输到接收端,接收
端无法向发送端传输数据。简单来说,就是一种“单向”通信模式,可以类比电视广播。

双工通信,允许数据在两个方向上传输,其下又分为两种类型:半双工和全双工 。

半双工通信允许数据在两个方向上传输,但不能同时进行。在任何时刻,数据只能在
一个方向上传输。这意味着通信的两端可以轮流发送和接收数据,但不能同时进行。可以
类比对讲机。

全双工通信允许数据同时在两个方向上传输。这种通信方式最为高效,因为它允许通
信双方同时发送和接收数据,可以类比电话。

(3)同步通讯和异步通讯

同步通讯和异步通讯的区别在于发送方和接收方如何对数据进行协调统一,详细内容
如下图所示。

16.1.2 UART 定义

UART(Universal Asynchronous Receiver/Transmitter)是一种异步、全双工的串行通信
接口,常用于微控制器与计算机、其他微控制器或外部设备之间的数据交换,下图是
UART 通信所需的信号线,其中 Tx 用于发送数据,Rx 用于接受数据。

16.1.3 UART 通讯协议

16.1.3.1 数据格式

在 UART 通信中,数据是逐帧(Frame)发送的,每个数据帧通常包括起始位、数据
位、校验位(可选)和停止位,具体结构如下图所示。

(1)空闲状态
协议规定,在空闲状态下,也就是没有数据传输时,应为高电平。
(2)起始位
起始位表示一个数据帧的开始,起始位为低电平(区别于空闲状态)。
(3)数据位
传输的主体内容,位于起始位之后,长度可以是 5 到 9 位,一般都是 8 位。低电平表
示 0,高电平表示 1。
(4)校验位(可选)
用于校验当前帧的正确性,校验算法可以是奇校验或偶校验,该算法的思想如下。
奇校验(odd parity):如果数据位中 1 的数目是偶数,则校验位为 1,如果 1 的数目
是奇数,校验位为 0,目的是保证数据位+校验位中的 1 的总个数是奇数。
偶校验(even parity):如果数据为中 1 的数目是偶数,则校验位为 0,如果 1 的数目
为奇数,校验位为 1,目的是保证数据位+校验位中的 1 的个数是偶数。
(5)停止位
停止位表示数据帧的结束,通常为 1 位或 2 位,停止位为高电平。

16.1.3.2 发送方和接收方的约定

为保证 UART 通信能够正常工作,发送方和接收方必须提前做好如下约定。

(1)波特率
波特率(Baud Rate)用于表示数据的传输速率,发送方和接收方必须约定好传输速率,
才能保证数据被正确的发送和接收。
需要注意波特率(Baud Rate)和比特率(Bit Rate)的区别,比特率表示每秒传输的位
(bit)数,而波特率表示每秒传输的符号(symbol)数。但是串口通信中,只有 0 和 1 这
两个符号,因此 1 个符号用 1 位就能表示,所以此处的波特率和比特率是等价的。
(2)数据位
发送方和接收方需要明确数据位的位数。
(3)校验位
发送方和接收方需要明确是否有校验位,如果有,需要明确校验算法是哪个。
(4)停止位
发送方和接收方需要明确停止位的位数。


16.2 单片机 UART 使用说明

STC89C52 系列单片机内部集成了一个功能强大的全双工串行通信口,以下是相关引
脚。

该通信口具有四种工作模式,如下。

其中模式 0 为同步通讯,该模式下,TxD 引脚会作为时钟信号线,RxD 作为数据信号
线,该模式下只能实现半双工通讯。

模式 1、2、3 为经典的 UART 通讯,三者的区别在与是否有校验位,以及波特率
是否可变。

模式 1 的一个数据帧包含 1 个起始位,8 个数据位和 1 个停止位。
模式 2 和模式 3 的一个数据帧包含 1 个数据位,8 个数据位,1 个校验位和 1 个停止位。
另外模式 1 和模式 3 的波特率可由定时器 1 进行配置,因而可以自由设置,而方式 2
的波特率直接由系统时钟决定,因而不可自由配置。
下面以方式 1 为例,介绍该串行通信口的用法。

16.2.1 设置工作模式

工作模式需要通过 SCON(Serial Control,串行口控制)寄存器中的 SM0 和 SM1 两
个控制位进行设置,如下图所示。

16.2.2 设置波特率

方式 1 的波特率会受到两个因素的影响,分别是 SMOD 控制位和定时器 1 的溢出频率,
具体作用如下图所示。

UART 常用的波特率有 4800、9600、19200、38400、57600、115200 等,此处以 9600
为例。

(1)设置 SMOD 控制位

SMOD 控制位位于 PCON(Power Control,电源控制)寄存器,如下图所示。

(2)设置定时器 1

由于定时器 1 当前的作用仅仅是为串口提供时钟信号,因此可不开启定时器中断,只
需完成以下配置即可。

(1)选择定时器工作模式

定时器 1 的工作模式需要通过 TMOD 寄存器中的 C/T 控制位,以及 M1 和 M0 两个控
制位进行设置,如下图所示。

C/T 用于设置计数/定时的工作方式,此处应选择定时模式,因此需将 C/T 设置为 0。
M1 和 M0,用于配置具体的工作模式,相关配置如下。

由于没有启用定时器中断,因此无法在中断中重新设置定时器脉冲计数器的初始值,
所以此处选择模式 2(8 位自动重装载)最为合理。

(2)设置脉冲计数器初始值

模式 2 的最大计数为 28=256,因此定时器 1 的溢出频率等于 SYSclk / 12 /(256 - TH1)
或者是 SYSclk / 6 /(256 - TH1),假如当前 MCU 工作在 12T 模式,所以溢出频率就等于
SYSclk / 12 /(256 - TH1)。

(3)启动定时器
定时器 1 的启动也无需外部引脚控制,因此应将 GATE 控制位设置为 0,并将 TR1 控
制位设置为 1。

16.2.3 发送数据

STC89C52 的串口的发送模块示意图如下。

数据发送的大致流程如下:
开发者将待发送的 8 位数据写入发送缓冲器(SBUF),此时发送控制器(Tx Control)
就会开始工作,它会自动为数据添加起始位和结束位,从而构成一个完整的 UART 数据帧,
然后逐位通过 TxD 引脚输出出去。当完成一个数据帧的输出之后,发送控制器会将发送中
断控制位 TI 置 1,向 CPU 请求中断,CPU 检测到中断请求后就执行相应的中断服务程序。
总结:发送数据只需要将待发送的数据写入 SBUF 即可。

16.2.4 接收数据

STC89C52 的串口的接收模块示意图如下。

默认情况下,串口并不会接收数据。如需接收数据,需要先将 REN(Receive Enable)
控制位置为 1,REN 控制位位于 SCON 寄存器,如下图所示。

REN 置为 1 后,上图中的 1 到 0 跳变检测器(1-To-0 Transition Detector)就会开
始工作,具体来讲就是不断检测 RxD 引脚的起始位。当检测到 1 到 0 的跳变后,就会启动
接收控制器(Rx Control),接收控制器会将接收到数据逐位移入到输入移位寄存器
(Input Shift REG),直到接收到停止位,就算完成了一帧数据的接收。
正常情况下,接下来,接收控制器会将输入移位寄存器(Input Shift REG)中的数据
加载到读取缓冲器(SBUF)中,并将读取中断控制位 RI 置 1,向 CPU 请求中断,CPU 检
测到中断请求后就执行相应的中断服务程序,开发者就能在中断服务程序中读取 SBUF 获
取当前帧的数据了。
但是上述操作(加载数据到 SBUF 和 RI 置位)的执行是有条件的,满足条件才会执行,
不满足,那么当前数据帧就会被丢弃,具体条件如下:

(1)结束位正常

开发者可以配置是否检测停止位的有效性(高电平有效)。是否检测是由 SCON 寄存
器中的 SM2 控制位来决定的。SM2=1 时,接收控制器就会检测控制停止位,当 SM2=0 时,
则不会检测停止位,建议将 SM2 设置为 0。

2)读取中断标志位为复位状态

读取中断标志位 RI 必须等于 0,也就说要保证上一帧数据已经被读取或处理完毕,才
能处理当前帧。

总结:接收数据需要先使能接收,也就是将 REN 控制位置 1,然后开启串口中断,并
在中断服务程序中读取 SBUF。

16.2.5 串口中断注意事项

根据前文的描述,当使用串口发送完一帧数据后,会将发送中断标志位 TI 置 1;当串
口接收到一帧数据后,会将接收中断标志位 RI 置 1。需要注意的是两个控制位请求的是同
一个中断——串口中断(中断号为 4)。

也就是说发送完一帧数据和接收完一帧数据之后,执行的都是串口中断的中断服务程
序,因此,再编写该中段服务程序时,需要注意判断当前中断到底是由发送操作触发的,
还是由接收操作触发的,代码示例如下。

/*
* 串口中断的中断号为 4
*/
void Dri_UART_Handler() interrupt 4
{
/* 检查接收中断标志位 RI,如果为 1,表示有一帧数据接收完成 */if (RI == 1) {}
/* 检查发送中断标志位 TI,如果为 1,表示有一帧数据发送完成 */if (TI == 1) {}
}

另外 RI 和 TI 标志位,只能由软件复位,也就是需要在中断服务程序中将其设置为 0,
如下

/*
* 串口中断的中断号为 4
*/
void Dri_UART_Hander() interrupt 4
{
/* 检查接收中断标志位 RI,如果为 1,表示有一帧数据接收完成 */if (RI == 1) {RI = 0;}
/* 检查发送中断标志位 TI,如果为 1,表示有一帧数据发送完成 */if (TI == 1) {TI = 0;}
}

16.3 需求描述

使用 UART 与 PC 进行通信,通过 PC 向单片机发送命令,控制 LED 的亮灭。

16.4 硬件设计

当前需求是实现 PC 单片机的串口通讯,但是现在的 PC 基本都不再提供串口,因此需
要使用一个 USB 转串口的芯片来实现 PC 与单片机的通讯,如下图所示。
 

16.5 软件设计:单字节命令

16.5.1 具体要求

当 PC 向单片机发送字符 A 时,单片机需要令 LED 亮起,并向 PC 回复:Ok: LED is
on。

当 PC 向单片机发送字符 B 时,单片机需要令 LED 熄灭,并向 PC 回复:Ok: LED is
off。

当 PC 向单片机发送其他字符时,单片机不做任何操作,只需向 PC 回复:Error:
Unknown command。

16.5.2 实现思路

实现当前需求,需要先对串口进行初始化,具体操作如下。

(1)选择串口工作模式

本案例选择模式 1,因此需要将 SM0 和 SM1 做出如下配置。

SM0 = 0;
SM1 = 1;

(2)设置波特率

本案例波特率选用 9600,需要做如下配置。
(1)SMOD 控制位
按照前文的计算,将 SMOD 设置为 0 即可,由于 SMOD 不可进行位寻址,因此我们
需要对其所在的寄存器 PCON 进行整体赋值,如下。

PCON &= 0x7F;

(2)定时器 1

按照前文的计算,定时器 1 应工作在模式 2(8 位自动重装载),每次重装载的初始值
应为 253。具体设置如下。

// 定时器 1 工作模式
TMOD &= 0x0F;
TMOD |= 0x20;
// 定时器 1 的初值
TH1 = 0xFD;
TL1 = 0xFD;
// 启动定时器 1
TR1 = 1;

(3)串口接收相关配置

串口默认不接收数据,因此需要先使能接受,另外还需将 SCON 寄存器中的 SM2 控制
位设置为 0,表示接受数据时不校验数据帧的停止位。

REN = 1;
SM2 = 0;

(4)启动串口中断

// 开启中断
EA = 1;
// 开启串口中断
ES = 1;
// 复位中断标志位
RI = 0;
TI = 0

完成串口的初始化之后,根据需求编写响应的业务逻辑即可。

16.5.3 完整代码

(1)Dri_UART.h

#ifndef __DRI_UART_H__
#define __DRI_UART_H__
#include <STC89C5xRC.H>
#include "Util.h"
/**
* @brief 串口初始化方法,需要先调用
*
*/
void Dri_UART_Init();
/**
* @brief 通过串口发送一个字符串
*
* @param ch 要发送的字符串
*/
void Dri_UART_SendStr(char *str);
/**
* @brief 通过串口接收一个字符
*
* @param p_ch 要接收的字符指针
*
* @return 0 为读取失败,1 为读取成功
*/
bit Dri_UART_RecvChar(char *p_ch);
#endif

(2)Dri_UART.c

#include "Dri_UART.h"
#define BAUD_RATE 9600
#define T2TEMP 256 - (FOSC / NT / 32 / BAUD_RATE)
char buffer;
// 发送状态,1:正在发送,0:未在发送
static bit is_sending;
void Dri_UART_Init()
{
// 1.设置串口工作模式SM0 = 0;SM1 = 1;
// 2.设置波特率
// 2.1 设置 SMOD 控制位PCON &= ~0x80;
// 2.2 设置定时器 1TMOD &= 0x0F;TMOD |= 0x20;TH1 = 0xFD;TL1 = 0xFD;TR1 = 1;
// 3.串口接收相关配置REN = 1;SM2 = 0;
// 打开中断总开关和串口中断开关EA = 1;ES = 1;TI = 0;RI = 0;is_sending = 0;buffer = 0;
}void Dri_UART_SendChar(char ch)
{
// 如果有数据在发送,等待发送完成while (is_sending);is_sending = 1;SBUF = ch;
}void Dri_UART_SendStr(char *str)
{while (*str) {Dri_UART_SendChar(*str);str++;}
}bit Dri_UART_RecvChar(char *p_ch)
{
// 如果缓冲区有数据,则将值符传给 p_ch,并清空缓冲区if (buffer) {*p_ch = buffer;buffer = 0;return 1;} else {return 0;}
}/**
* @brief 串口中断函数,进入这个函数有两个触发条件:发送完成和接收完成
*
*/
void Dri_UART_Func() interrupt 4
{
// 收到命令,将数据放入缓冲区if (RI == 1) {buffer = SBUF;RI = 0;}
// 发送完成,将发送状态置为 0if (TI == 1) {is_sending = 0;TI = 0;}
}

(3)main.c

#include <STC89C5xRC.H>
#include "Dri_UART.h"
void main()
{char command;Dri_UART_Init();while (1) {if (Dri_UART_RecvChar(&command)) {if (command == 'A') {// 点亮 LEDP0 = 0x00;Dri_UART_SendStr("Ok:LED is on");} else if (command == 'B') {// 熄灭 LEDP0 = 0xFF;Dri_UART_SendStr("Ok:LED is off");} else {// 报错Dri_UART_SendStr("Error:Unknown command");}}}
}

16.6 软件设计:多字节命令

16.6.1 具体要求

当 PC 向单片机发送字符串 on 时,单片机需要令 LED 亮起,并向 PC 回复:Ok: LED
is on

当 PC 向单片机发送字符串 off 时,单片机需要令 LED 熄灭,并向 PC 回复:Ok: LED
is off

当 PC 向单片机发送其他字符串时,单片机不做任何操作,只需向 PC 回复:Error:
Unknown command

16.6.2 完整代码

1)Dri_UART.h

#ifndef __DRI_UART_H__
#define __DRI_UART_H__
#include <STC89C5xRC.H>
#include "Util.h"
/**
* @brief 串口初始化
*
*/
void Dri_UART_Init(void);
/**
* @brief 发送字符串
*
* @param str 待发送字符串
*/
void Dri_UART_SendStr(char *str);
/**
* @brief 接收字符串
*
* @param str 用于接收字符串的数组
* @return bit 0 为读取失败,1 为读取成功
*/
bit Dri_UART_ReceiveStr(char str[]);
#endif /* __DRI_UART_H__ */

2)Dri_UART.c

#include "Dri_UART.h"
#include "Dri_Timer0.h"
#define BAUD_RATE 9600
#define T2TEMP 256 - (FOSC / NT / 32 / BAUD_RATE)
#include <STDIO.H>
/ 0:未在发送 1:正在发送
static bit s_is_sending = 0;
static char s_buffer[10] = {0};
static u8 s_index = 0;
static bit s_is_complete = 0;
static u8 s_idle_count = 0;
void Dri_UART_Timer0Callback()
{s_idle_count++;if (s_index > 0 && s_idle_count >= 10) {s_is_complete = 1;s_idle_count = 0;}
}
void Dri_UART_Init()
{// 1.选择工作模式SM0 = 0;SM1 = 1;// 2.波特率// 2.1 SMODPCON &= 0x7F;// 2.2 Timer1// 2.2.1 工作模式TMOD &= 0x0F;TMOD |= 0x20;// 2.2.2 初始值TH1 = 0xFD;TL1 = 0xFD;// 2.2.3 开启TR1 = 1;// 3.接受相关REN = 1;SM2 = 0;// 4. 中断相关EA = 1;ES = 1;RI = 0;TI = 0;// 5. 注册空闲监测回调Dri_Timer0_RegisterCallback(Dri_UART_Timer0Callback);
}
void Dri_UART_SendChar(char c)
{while (s_is_sending == 1);s_is_sending = 1;SBUF = c;
}
void Dri_UART_SendStr(char *str)
{while (*str != 0) {Dri_UART_SendChar(*str);str++;}
}
bit Dri_UART_ReceiveStr(char *cmd)
{u8 i;if (s_is_complete) {for (i = 0; i < s_index; i++) {cmd[i] = s_buffer[i];}cmd[s_index] = '\0';s_index = 0;s_is_complete = 0;return 1;} else {return 0;}
}
void Dri_UART_Handler() interrupt 4
{if (RI == 1) {// 接收数据的逻辑s_idle_count = 0;s_buffer[s_index++] = SBUF;RI = 0;}if (TI == 1) {// 发送数据的逻辑s_is_sending = 0;TI = 0;}
}

(3)main.c

#include "Dri_UART.h"
#include <STRING.H>
void main()
{char command[10] = {0};Dri_UART_Init();while (1) {if (Dri_UART_ReceiveStr(command)) {if (strcmp(command, "on") == 0) {P0 = 0x00;Dri_UART_SendStr("Ok:LED is on");} else if (strcmp(command, "off") == 0) {P0 = 0xFF;Dri_UART_SendStr("Ok:LED is off");} else {Dri_UART_SendStr("Error:Unhnown command");}}}
}

相关文章:

10天学会嵌入式技术之51单片机-day-7

第十六章 UART通信 16.1 UART 概述 16.1.1 前置基础 想要理解和使用 UART&#xff0c;需要先了解一些通讯领域的术语&#xff0c;如下 。 &#xff08;1&#xff09;串行通讯和并行通讯 串行通讯和并行通讯是数据传输的两种主要方式&#xff0c;两者的区别如下。 &#xff…...

w~视觉~合集3

我自己的原文哦~ https://blog.51cto.com/whaosoft/12327888 #几个论文 Fast Charging of Energy-dense Lithium-ion Batteries Real-time Short Video Recommendation on Mobile Devices Semantic interpretation for convolutional neural networks: What makes a ca…...

AI在论文评审中的应用与工具推荐

一、AI在论文评审中的核心应用场景 内容质量评估与逻辑校验 • 核心论点识别&#xff1a;AI可快速定位论文核心创新点&#xff0c;并验证其与文献综述、实验数据的逻辑一致性&#xff08;如知网研学的“文献矩阵分析”功能&#xff09;。 • 方法论合理性检测&#xff1a;自动识…...

怎样记忆Precision、Recall?

首先&#xff0c;明确符号&#xff1a; TP(True Posive)&#xff1a;标签为正&#xff0c;预测为正 TN(True Negative)&#xff1a;标签为负&#xff0c;预测为负 FP(False Positive)&#xff1a;标签为负&#xff0c;预测为正 FN(False Negative)&#xff1a;标签为正&#xf…...

【刷题】第三弹——二叉树篇(上)

文章目录 一.相同的树二. 另一棵树的子树三. 翻转二叉树四. 对称二叉树五. 平衡二叉树六. 二叉搜索树七. 二叉树的遍历 一.相同的树 检查两棵树是否相同 思路: 1.先比较结构 结构不一样直接false 2.结构一样,在比较值 public boolean isSameTree(TreeNode p, TreeNode q) {if…...

【Canvas与标志】红黄渐变阴影太极图

【成图】 120*120的png图标 大小图&#xff1a; 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>红黄渐变阴影太极图 Draft1&l…...

express的中间件,全局中间件,路由中间件,静态资源中间件以及使用注意事项 , 获取请求体数据

Express 中间件系统 的详细讲解&#xff0c;包括全局中间件、路由中间件、静态资源中间件、请求体解析中间件&#xff0c;以及使用注意事项&#x1f447; &#x1f310; 一、什么是中间件&#xff08;Middleware&#xff09;&#xff1f; 中间件是 函数&#xff0c;在请求到达…...

大数据去重

实验4 大数据去重 1.实验目的 通过Hadoop数据去重实验&#xff0c;学生可以掌握准备数据、伪分布式文件系统配置方法&#xff0c;以及在集成开发环境Eclipse中实现Hadoop数据去重方法。 2.实验要求 了解基于Hadoop处理平台的大数据去重过程&#xff0c;理解其主要功能&…...

高功率激光输出稳定性不足?OAS 光学软件来攻克

法布里珀罗干涉仪设计案例 简介 法布里珀罗干涉仪作为一种高分辨率光学仪器&#xff0c;基于多光束干涉原理构建。其核心结构由两块高度平行的反射镜组成谐振腔&#xff0c;当光进入该谐振腔后&#xff0c;会在镜面间进行多次反射。在这一过程中&#xff0c;透射光会形成干涉条…...

基于大模型的结肠癌全病程预测与诊疗方案研究

目录 一、引言 1.1 研究背景与意义 1.2 研究目的与创新点 二、结肠癌概述 2.1 流行病学特征 2.2 发病机制与危险因素 2.3 临床症状与诊断方法 三、大模型技术原理与应用现状 3.1 大模型的基本原理 3.2 在医疗领域的应用情况 3.3 在结肠癌预测中的潜力分析 四、术前…...

【Hive入门】Hive查询语言(DQL)完全指南:从基础查询到高级分析

目录 1 Hive查询执行架构全景 2 SELECT基础查询详解 2.1 基本查询结构 2.2 条件查询流程图 3 聚合函数与GROUP BY实战 3.1 聚合执行模型 3.2 GROUP BY数据流 4 排序操作深度解析 4.1 ORDER BY执行流程 4.2 排序算法对比 5 高级技巧与注意事项 5.1 嵌套查询与CTE 5.…...

【学习笔记】文件包含漏洞--相关习题

第一关 伪协议 用代码执行命令查看目录所含文件&#xff0c;发现flag.php 法一 题目代码含有include&#xff0c;写入文件包含指令&#xff1a; php://filter/readconvert.base64-encode/resourceflag.php 解码即可得到flag。 法二 法三 法二可以用php&#xff1a;//input&…...

蓝桥杯 20. 压缩变换

压缩变换 原题目链接 题目描述 小明最近在研究压缩算法。他知道&#xff0c;压缩时如果能够使数值很小&#xff0c;就能通过熵编码得到较高的压缩比。然而&#xff0c;要使数值变小是一个挑战。 最近&#xff0c;小明需要压缩一些正整数序列&#xff0c;这些序列的特点是&a…...

BY免费空间去掉?i=1

BY免费空间去掉?i1 使用说明 支持域名&#xff1a;tae.dpdns.org 前提绑定主机&#xff0c;申请主机–控制面板选择–子域名&#xff0c;绑定xxx.tae.dpdns.org子域名 默认开启DDoS防御&#xff0c;无防火墙规则&#xff0c;建议用.htaccess来防御 默认去掉访问统计?i1 …...

中篇:深入剖析 L2CAP 与 ATT 协议模块(约5000字)

引言 在 BLE 协议栈中,L2CAP 与 ATT 承担了关键的数据分发、协议复用与属性访问职责。对多协议并存和大数据场景的应用,深入理解这两层协议的分片重组、流控机制、MTU/MTU 协商和 ATT 操作流程,对于提升系统性能与稳定性至关重要。本篇将全面拆解 L2CAP 与 ATT 的原理与实战…...

【C语言】C语言结构体:从基础到高级特性

前言 在C语言的世界里&#xff0c;结构体是一种强大而灵活的自定义数据类型&#xff0c;它能够将不同类型的数据组合在一起&#xff0c;形成一个逻辑上的整体。从简单的数据聚合到复杂的内存对齐优化&#xff0c;再到高效的位段操作&#xff0c;结构体在系统编程、嵌入式开发和…...

电控---JTAG协议

一、物理层架构与信号特性 1. 引脚定义与电气规范 核心引脚&#xff1a; TCK&#xff08;测试时钟&#xff09;&#xff1a;频率范围0.1MHz至50MHz&#xff08;如Xilinx Spartan-6支持25MHz&#xff09;&#xff0c;上升沿采样数据。TMS&#xff08;测试模式选择&#xff09;…...

FreeRTOS【3】任务调度算法

重要概念 在运行的任务&#xff0c;被称为"正在使用处理器"&#xff0c;它处于运行状态。在单处理系统中&#xff0c;任何时间里只能有一个任务处于运行状态。 非运行状态的任务&#xff0c;它处于这 3 中状态之一&#xff1a;阻塞(Blocked)、暂停(Suspended)、就绪…...

高德地图API + three.js + Vue3基础使用与使用 + 标记不显示避坑

three.js小白的学习之路。 最近闲来无事&#xff0c;突然想起来之前好像项目有需求说是要将模型放在地图上。加上在浏览别的大佬写的博客时&#xff0c;也找到了一些大佬写的相关文章。基本上都是使用的高德地图开放平台的JS API。我也随之开启了自己的学习之路。 先简单学习…...

书籍推荐:《价值心法》一姜胡说

书名 &#xff1a;《价值心法》一姜胡说 摘录 每天问问自己&#xff0c;如果今天只做一件事&#xff0c;这件事是什么&#xff1f;找到它。拿出2—3个小时&#xff0c;专门处理这件事。其他所有事全部排在那2—3个小时之外。 集中一段时间用来做最重要的事。这段时…...

Linux GPIO驱动开发实战:Poll与异步通知双机制详解

1. 引言 在嵌入式Linux开发中&#xff0c;GPIO按键驱动是最基础也最典型的案例之一。本文将基于一个支持poll和异步通知双机制的GPIO驱动框架&#xff0c;深入剖析以下核心内容&#xff1a; GPIO中断与防抖处理环形缓冲区设计Poll机制实现异步通知(SIGIO)实现应用层交互方式 …...

x-cmd install | brows - 终端里的 GitHub Releases 浏览器,告别繁琐下载!

目录 核心功能与优势安装适用场景 还在为寻找 GitHub 项目的特定 Release 版本而苦恼吗&#xff1f;还在网页上翻来覆去地查找下载链接吗&#xff1f;现在&#xff0c;有了 brows&#xff0c;一切都将变得简单高效&#xff01; brows 是一款专为终端设计的 GitHub Releases 浏览…...

一天学完Servlet!!!(万字总结)

文章目录 前言Servlet打印Hello ServletServlet生命周期 HttpServletRequest对象常用api方法请求乱码问题请求转发request域对象 HttpServletResponse对象响应数据响应乱码问题请求重定向请求转发与重定向区别 Cookie对象Cookie的创建与获取Cookie设置到期时间Cookie注意点Cook…...

c#-命名和书写规范

文章目录 1. 接口名称以大写 I 开头2. 属性类型以单词 Attribute 结尾3. 枚举类型对非标记使用单数名词,对标记使用复数名词4. 标识符不应包含两个连续下划线(__)字符5. 对变量、方法和类使用有意义的描述性名称6. 将 PascalCase 用于类名和方法名称7. 对方法参数和局部变量…...

【双指针】和为s的两个数字

57. 和为target的两个数字 剑指 Offer 57. 和为s的两个数字 ​ 输入一个递增排序的数组和一个数字target&#xff0c;在数组中查找两个数&#xff0c;使得它们的和正好是target。如果有多对数字的和等于target&#xff0c;则输出任意一对即可。 示例 1&#xff1a; 输入&…...

【Vue】TypeScript与Vue3集成

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Vue 文章目录 1. 前言2. 环境准备与基础搭建2.1. 安装 Node.js 与 npm/yarn/pnpm2.2. 创建 Vue3 TypeScript 项目2.2.1. 使用 Vue CLI2.2.2. 使用 Vite&#xff08;推荐&#xff09;2.2.3. 目录结构简述 3. Vue3 TS 基础语法整…...

win11中wsl在自定义位置安装ubuntu20.04 + ROS Noetic

wsl的安装 环境自定义位置安装指定ubuntu版本VsCodeROS备份与重载备份重新导入 常用命令参考文章 环境 搜索 启用或关闭 Windows 功能 勾选这2个功能&#xff0c;然后重启 自定义位置安装指定ubuntu版本 从网上找到你所需要的相关wsl ubuntu版本的安装包&#xff0c;一般直…...

【数据可视化-29】食物营养成分数据可视化分析

&#x1f9d1; 博主简介&#xff1a;曾任某智慧城市类企业算法总监&#xff0c;目前在美国市场的物流公司从事高级算法工程师一职&#xff0c;深耕人工智能领域&#xff0c;精通python数据挖掘、可视化、机器学习等&#xff0c;发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…...

手动实现legend 与 echarts图交互 通过js事件实现图标某项的高亮 显示与隐藏

通过html实现legend的样式 提供调用echarts的api实现与echarts图表交互的效果 实现饼图element实现类似于legend与echartstu表交互效果 效果图 配置代码 <template><div style"height: 400px; width: 500px;background-color: #CCC;"><v-chart:opti…...

C语言编程--16.删除链表的倒数第n个节点

题目&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a…...

centos7使用certbot完成nginx ssl证书续期

没有废话纯干货 yum源配置&#xff08;配置好的可以跳过&#xff09; #到/etc/yum.repos.d/下mkdir bak&#xff0c;将所用东西mv到bak下 cd /etc/yum.repos.d/ mkdir bak mv ./* bak/ wget https://mirrors.aliyun.com/repo/Centos-7.repo 没有安装nginx的话&#xff0c;配…...

ECharts学习之 toolbox 工具栏

toolbox: {show: true,feature: {//数据视图工具&#xff0c;可以展现当前图表所用的数据dataView: {title: "数据视图",readOnly: false, //是否不可编辑&#xff0c;即只读lang:[数据视图,关闭,刷新] //数据视图上有三个话术},magicType: {type: ["line"…...

修改el-select背景颜色

修改el-select背景颜色 /* 修改el-select样式--直接覆盖默认样式&#xff08;推荐&#xff09; */ ::v-deep .el-select .el-input__inner {background-color: #1d2b72 !important; /* 修改输入框背景色 */color: #fff; } ::v-deep .el-select .el-input__wrapper {background-…...

Qt 使用 MySQL 数据库的基本方法

在 Qt 中&#xff0c;使用 MySQL 数据库的基本方法主要是通过 QSqlDatabase、QSqlQuery 等类来进行数据库的连接、查询和数据操作。以下是 Qt 中连接和操作 MySQL 数据库的基本步骤。 1. 安装 MySQL 驱动 首先&#xff0c;确保您的 Qt 环境已经配置了 MySQL 驱动。通常&#…...

BLIP 系列论文(BLIP、BLIP-2、InstructBLIP)

BLIP BLIP 是 Salesforce 团队在多模态领域中的经典工作&#xff0c;影响力巨大&#xff0c;BLIP 系列包括&#xff1a;BLIP、BLIP-2、InstructBLIP。 BLIP 在多模态大模型之前&#xff0c;多模态领域中最流行的是视觉-语言预训练&#xff08;Vision-Language Pre-training,…...

【玩转全栈】—— 无敌前端究极动态组件库--Inspira UI

目录 Inspira UI 介绍 配置环境 使用示例 效果&#xff1a; Inspira UI 学习视频&#xff1a; 华丽优雅 | Inspira UI快速上手_哔哩哔哩_bilibili 官网&#xff1a;https://inspira-ui.com/ Inspira UI 介绍 Inspira UI 是一个设计精美、功能丰富的用户界面库&#xff0c;专为…...

Java24新增特性

Java 24&#xff08;Oracle JDK 24&#xff09;作为Java生态的重要更新&#xff0c;聚焦AI开发支持、后量子安全、性能优化及开发者效率提升&#xff0c;带来20余项新特性和数千项改进。以下是核心特性的分类解析&#xff1a; 一、语言特性增强&#xff1a;简化代码与模式匹配 …...

Git多人协作与企业级开发模型

目录 1.多人协作一 2.多人协作二 3.远程分⽀删除后&#xff0c;本地gitbranch-a依然能看到的解决办法 4.企业级开发模型 4.1.Git的重要性 4.2.系统开发环境 4.3.Git 分⽀设计规范 1.多人协作一 ⽬前&#xff0c;我们所完成的⼯作如下&#xff1a; 基本完成Git的所有本…...

Android学习总结之扩展基础篇(一)

一、IdleHandler工作原理 1. IdleHandler 接口定义 IdleHandler 是 MessageQueue 类中的一个接口&#xff0c;定义如下&#xff1a; public static interface IdleHandler {/*** 当消息队列空闲时会调用此方法。* return 如果返回 true&#xff0c;则该 IdleHandler 会保留在…...

C语言教程(十六): C 语言字符串详解

一、字符串的表示 在C语言中&#xff0c;字符串是由一系列字符组成&#xff0c;并且以空字符 \0 作为结束标志。字符串通常用字符数组来表示。例如&#xff1a; char str[] {H, e, l, l, o, \0};也可以使用字符串字面量来初始化字符数组&#xff1a;char str[] "Hello&…...

Redis LFU 策略参数配置指南

一、基础配置步骤‌ 设置内存上限‌ 在 redis.conf 配置文件中添加以下指令&#xff0c;限制 Redis 最大内存使用量&#xff08;例如设置为 4GB&#xff09;&#xff1a; maxmemory 4gb选择 LFU 淘汰策略‌ 根据键的作用域选择策略&#xff1a; # 所有键参与淘汰 maxmemory-…...

Pikachu靶场-unsafe upfileupload

不安全的文件上传漏洞防御与对抗方式对照表 防御方式 防御实现 攻击者对抗方式 对抗原理 文件类型白名单验证 仅允许指定扩展名&#xff08;如 .jpg, .png&#xff09; if (!in_array($ext, [jpg, png])) { die(); } 伪造文件类型&#xff1a; 1. 修改文件头&#xff08;…...

Python基础语法:查看数据的类型type(),数据类型转换,可变和不可变类型

目录 查看数据类型type() 使用type()语句查看数据的类型 变量无类型而数据有类型 数据类型转换 在字符串&#xff0c;整型&#xff0c;浮点数之间相互转换 可变类型和不可变类型 查看数据类型type() 使用type()语句查看数据的类型 Python中使用type(被查看数据的类型)语…...

高防IP是如何防护DDoS攻击和CC攻击的

高防IP是一种针对网络攻击&#xff08;如DDoS和CC攻击&#xff09;设计的防护服务&#xff0c;其核心原理是通过流量调度、智能清洗和分布式防护节点等技术&#xff0c;将恶意流量拦截在目标服务器之外。以下是其防护DDoS和CC攻击的具体机制&#xff1a; 一、防御DDoS攻击的机制…...

从认证到透传:用 Nginx 为 EasySearch 构建一体化认证网关

在构建本地或云端搜索引擎系统时&#xff0c;EasySearch 凭借其轻量、高性能、易部署等优势&#xff0c;逐渐成为众多开发者和技术爱好者的首选。但在实际部署过程中&#xff0c;如何借助 Nginx 为 EasySearch 提供高效、稳定且安全的访问入口&#xff0c;尤其是在身份认证方面…...

利用deepseek快速生成甘特图

一、什么是甘特图 甘特图&#xff08;Gantt Chart&#xff09;是一种直观的项目管理工具&#xff0c;广泛应用于多个领域&#xff0c;主要用于​​时间规划、任务分配和进度跟踪​​。 直观性​​&#xff1a;时间轴清晰展示任务重叠或延迟。 ​​灵活性​​&#xff1a;支持…...

突破厚铜PCB阻抗控制难题:多级阻抗实现方法

随着电子技术的发展&#xff0c;电子设备对电路板的性能要求越来越高。其中&#xff0c;阻抗控制是电路板设计中的一个重要环节&#xff0c;尤其是对于高频、高速的电子设备。厚铜电路板由于其优良的导电性能和机械强度&#xff0c;被广泛应用于各种高端电子设备中。然而&#…...

JCP官方定义的Java技术体系组成部分详解

JCP官方定义的Java技术体系组成部分详解 1. Java平台规范&#xff08;Java Platform Specifications&#xff09; 定义&#xff1a;由JCP制定的Java平台核心规范&#xff0c;包括Java SE&#xff08;标准版&#xff09;、Java EE&#xff08;企业版&#xff0c;现为Jakarta EE…...

如何在 Windows上安装 Python 3.6.5?

Windows 系统安装步骤 下载安装包 安装包下载链接&#xff1a;https://pan.quark.cn/s/9294ca0fd46a 运行安装程序 双击下载的 .exe 文件&#xff08;如 python-3.6.5.exe&#xff09;。 勾选 Add Python 3.6 to PATH&#xff08;重要&#xff01;这将自动配置环境变量&…...

OpenHarmony 开源鸿蒙北向开发——hdc工具使用及常用命令(持续更新)

hdc&#xff08;OpenHarmony Device Connector&#xff09;是为开发人员提供的用于设备连接调试的命令行工具&#xff0c;该工具需支持部署在 Windows/Linux/Mac 等系统上与 OpenHarmony 设备&#xff08;或模拟器&#xff09;进行连接调试通信。简单来讲&#xff0c;hdc 是 Op…...