【STM32单片机】#10 USART串口通信
主要参考学习资料:
B站@江协科技
STM32入门教程-2023版 细致讲解 中文字幕
开发资料下载链接:https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwd=dspb
单片机套装:STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协
实验:
- 串口发送
- 串口发送+接收
目录
- 通信接口
- 串口协议
- 串口通信
- 硬件电路
- 电平标准
- 串口参数及时序
- USART简介
- USART框图
- USART基本结构
- 数据采样
- 波特率发生器
- USB转串口模块
- 函数详解
- USART_DeInit函数
- USART_Init函数
- USART_InitStruct结构体
- USART_StructInit函数
- USART_Cmd函数
- USART_ITConfig函数
- USART_DMACmd函数
- USART_SendData函数
- USART_ReceiveData函数
- 中断标志位函数
- 实验20 串口发送
- 接线图
- 编译器配置
- 串口助手
- 主程序
- 实验21 串口发送+接收
- 查询方式
- 中断方式
通信接口
- 通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统。
- 通信协议:制定通信的规则,通信双方按照协议规则进行数据收发。

上表所列通信协议会在后续逐个深入分析。
全双工:通信双方能够同时进行双向通信,一般有发送和接收两条数据线。
半双工:通信双方只能分时进行双向通信,一般发送和接收共用一条数据线。
单工:数据只能从一个设备到另一个设备,而不能反向传输。
同步:拥有时钟线,接收方在时钟的指引下对数据进行采样。
异步:没有时钟线,双方约定采样频率,并添加帧头帧尾进行采样位置的对齐。
单端:引脚的高低电平是对GND的电压差,通信双方必须共地。
差分:靠两个差分引脚的电压差传输信号,无需GND(除部分USB协议)。使用差分信号可以极大地提高抗干扰特性,所以差分信号一般有较高的传输速度和较长的传输距离。
点对点:只有两个设备相互通信。
多设备:可以在总线上挂载多个设备,需要通过寻址确定通信对象。
串口协议
串口通信
- 串口是一种应用十分广泛的通讯接口,成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
- 单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各种模块互相通信,极大地扩展了单片机的应用范围,增强了单片机系统的硬件实力。
硬件电路

- 简单双向串口通信有两根通信线,TX为发送端,RX为接收端。
- TX与RX交叉连接。
- 当只需单向的数据传输时,可以只接一根通信线。
- 如果两个设备都有独立供电可不接VCC。
- 当电平标准不一致时,需要加电平转换芯片。
电平标准
电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系。串口常用的电平标准有如下三种:
- TTL电平:+3.3V或+5V表示1,0V表示0,是单片机中最常见的电平标准。
- RS232电平:-3~-15V表示1,+3~+15V表示0。
- RS485电平:(差分信号)两线压差+2~+6V表示1,-2~-6V表示0。
本系列基于TTL电平,其他电平使用电平转换芯片即可,在软件层面没有变化。
串口参数及时序

图中为串口发送一个字节的格式,由串口协议规定。串口中每一个字节都装载在一个数据帧里面,每个数据帧都由起始位、数据位和停止位组成。左侧8位数据位代表一个字节的8位,右侧在数据位末尾增加了奇偶校验位,共9位数据位,其中有效载荷为前8位。
- 波特率:串口通信的速率,单位为码元/s,在二进制调制下等于比特率单位bit/s。
- 起始位:标志一个数据帧的开始,固定为低电平。串口的空闲状态为高电平,起始位产生下降沿告诉接收设备数据帧开始。
- 数据位:数据帧的有效载荷,1为高电平,0为低电平,从低位开始发送。
- 停止位:用于数据帧间隔,固定为高电平,恢复空闲状态,为下一个起始位做准备。
- 校验位:用于数据验证,根据数据位计算得来,可以判断数据传输是否正确。如果数据出错,可以选择丢弃或要求重传。
校验方式有无校验、奇校验、偶校验三种,无校验不需要校验位;若使用奇校验,前8位有偶数个1则校验位补1,反之补0,保证1的个数为奇数,接收方在接收数据后会验证数据位和校验位,若1的个数为奇数则认为没有出错,若传输干扰使1的个数变为偶数则认为传输出错;偶校验保证1的个数为偶数,方法同理。
如果两位数据同时出错,则奇偶特性不变,因此奇偶校验的检出率并不高。要求更高的检出率可以了解更为复杂的CRC校验。
串口时序实例(波特率9600)
0xAA,1位停止,无校验:

0x55,1位停止,偶校验:

0x55,2位停止,无校验:

USART简介
- USART(Universal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步收发器
- 相应地,UART为异步收发器。同步功能一般是为了兼容别的协议或特殊用途设计,串口很少使用,因此两者区别不大。
- USART是STM32内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧时序从TX引脚发送,也可自动接收RX引脚的数据帧时序,拼接为一个字节数据存放在数据寄存器中。
- 自带波特率发生器(分频器),最高达4.5Mbits/s。
- 可配置数据位长度(8/9),停止位长度(0.5/1/1.5/2)。
- 可选校验位(无检验/奇校验/偶校验)。
- 支持同步模式、硬件流控制(接收方通过另接线路反馈准备信号,防止因处理慢而导致数据丢失)、DMA和智能卡(刷卡)、IrDA(红外通信)、LIN(局域网)等其他与串口相似的协议。
- STM32F103C8T6 USART资源:USART1(APB2)、USART2/3(APB1)。
USART框图

收发工作部分
左上角TX/RX为发送/接收引脚,其余为智能卡和IrDA协议引脚,包括其编解码模块在内都无需考虑。TX由发送移位寄存器引出,RX通向接收移位寄存器。发送/接收的字节数据存储在发送/接收数据寄存器(TDR/RDR)中,两者共用一个数据寄存器DR的地址,TDR只写,RDR只读,DR自动根据操作是读还是写进行区分。发送移位寄存器将一个字节的数据一位一位移出。
当硬件检测到数据写入TDR时,会检查当前发送移位寄存器是否有数据正在移位,若没有则将TDR的数据全部移动到发送移位寄存器准备发送,并将TXE(TX Empty)标志位置一,此时可以向TDR写入下一个数据。随后发送移位寄存器在发送器控制的驱动下向右移位,将数据一位一位第输出到TX引脚。当数据移位完成后,新的数据会再次从TDR转移到发送移位寄存器中。TDR和移位寄存器的双重缓存可以保证连续发送数据的时候,数据帧之间不会有空闲,提高工作效率。
当数据到达RX引脚时,在接收器控制的驱动下,接收移位寄存器会一位一位地读取RX电平,先放在最高位再向右移。当一个字节的数据移位完成时,该字节的数据会整体转移到RDR中,并将RXNE(RX Not Empty)标志位置一,此时可以读取RDR的数据,接收移位寄存器也能直接接收下一帧数据。
增强部分与控制部分
下方发送器控制控制发送移位寄存器工作,接收器控制控制接收移位寄存器工作。左侧硬件数据流控实现硬件流控制功能,nRTS(Request To Send)为输出脚,告诉对方本设备能否接收,nCTS(Clear To Send)为输入脚,接收其他设备的nRTS信号,二者交叉连接。n指低电平有效,本设备能接收数据时则RTS置低电平请求对方发送,发送时也需通过CTS判断对方能否接收。该功能不常使用,了解即可。
SCLK控制及其引脚用于产生同步的时钟信号,发送移位寄存器每移位一次,同步时钟电平就跳变一个周期。该功能用于兼容其他协议或产生自适应波特率告知接收设备所使用的波特率,不常使用,了解即可。
唤醒单元通过给串口分配一个USART地址实现串口挂载多设备,仅在接收到发送端发送的指定地址时才会唤醒开始工作,否则保持沉默。该功能不常使用,了解即可。
中断控制部分中,中断申请位为SR寄存器中的标志位,其中已经提到过的TXE和RXNE较为重要,其余了解即可。USART中断控制配置中断能否通向NVIC。
波特率发生器部分中,时钟输入为来自APB1/2分频后的 f P C L K 1 / 2 f_{PCLK1/2} fPCLK1/2,挂载在APB2的USART1一般为72MHz,其余挂载在APB1的一般为36MHz。之后该时钟除以USARTDIV分频系数,USARTDIV分为整数部分12位和小数部分4位。分频得到的波特率会再进行16分频(因为后文介绍的数据采样需要16倍频)得到发送器时钟和接收器时钟,通向控制部分。USART_BRR中,TE置一则发送使能(发送器波特率有效),RE置一则接收使能(接收器波特率有效)。
关于图中未详细介绍的寄存器,需要时参见芯片数据手册。
USART基本结构
以下为程序控制USART工作相关的基本结构:

数据采样

当输入电路侦测到一个数据帧的起始位后,就会以波特率的频率连续采样一帧数据。同时,从起始位开始,采样位置就要对齐位的正中间。为了实现上述功能,接收电路会以波特率的16倍频率进行采样。空闲时刻采样为1,采样到0则检测为下降沿,接下来的16次采样若无噪声(全为0)则判断为起始位。但为了包容实际电路可能存在的噪声,接收电路还会检验第3/5/7次采样和第8/9/10次采样,若这两批采样各自至少有2个0则仍判断为起始位,但在2个0和1个1的情况下,接收电路会将NE(Noise Error)噪声标志位置一作为提醒。其余噪声过多的情况下,接收电路将忽略之前的数据,重新开始捕捉下降沿。

如果检测到起始位,则第8/9/10次采样正好对应位的正中间,之后接收每个数据位时都在第8/9/10次进行采样,并按照少数服从多数原则判断该数据位的数据,以此包容噪声,若存在噪声则将NE标志位置一。
波特率发生器

发送器和接收器的波特率由波特率寄存器BRR中的DIV确定,计算公式为
波特率= f P C L K 1 / 2 f_{PCLK1/2} fPCLK1/2/(16*DIV)
USB转串口模块

串口相关实验将通过USB转串口模块连接STM32与电脑实现。
USB端口以UD+和UD-为通信线,通过CH340芯片将USB协议转换为串口协议,输出TXD和RXD。
该模块靠USB端口的VCC+5V供电,并由左上角稳压管电路降压得到VCC+3.3V,与VCC+5V一同通过排针J1第4脚和第6脚引出。第5脚的VCC为CH340的电源输入脚,通过跳线帽与第4脚或第6脚连接,并且TTL电平与供电电平相同。
右下角为PWR电源指示灯和TXD/RXD指示灯,后者会在引脚上有数据传输时闪烁。
函数详解
USART_DeInit函数
简介:恢复缺省配置。
参数:USART名称
USART1/2/3, UART4/5
USART_Init函数
简介:初始化USART。
参数一:USART名称
参数二:USART_InitStruct结构体指针
USART_InitStruct结构体
成员USART_BaudRate:波特率
成员USART_HardwareFlowControl:硬件流控制
USART_HardwareFlowControl_None(不使用)
USART_HardwareFlowControl_RTS(使用RTS)
USART_HardwareFlowControl_CTS(使用CTS)
USART_HardwareFlowControl_RTS_CTS(都使用)
成员USART_Mode:发送/接收模式
USART_Mode_Rx(接收模式), USART_Mode_Tx(发送模式)
若都使用则进行或运算
成员USART_Parity:校验位
USART_Parity_No(无校验)
USART_Parity_Odd(奇校验)
USART_Parity_Even(偶校验)
成员USART_StopBits:停止位
USART_StopBits_0_5, USART_StopBits_1_5
USART_StopBits_1, USART_StopBits_2
成员USART_WordLength:字长(数据位长度)
USART_WordLength_8b(无校验位)
USART_WordLength_9b(使用校验位)
USART_StructInit函数
简介:初始化USART_InitStruct结构体。
参数:USART_InitStruct结构体指针
USART_Cmd函数
简介:USART使能。
参数一:USART名称
参数二:使能/失能
USART_ITConfig函数
简介:USART中断使能。
参数一:USART名称
参数二:USART中断源
USART_IT_TXE
USART_IT_RXNE
其余暂时不用
参数三:使能/失能
USART_DMACmd函数
简介:开启USART到DMA的触发通道。
参数一:USART名称
参数二:DMA请求类型
USART_DMAReq_Tx(发送请求)
USART_DMAReq_Rx(接受请求)
参数三:使能/失能
USART_SendData函数
简介:写DR寄存器(发送)。
参数一:USART名称
参数二:数据
USART_ReceiveData函数
简介:读DR寄存器(接收)。
参数:USART名称
中断标志位函数
USART_GetFlagStatus函数
USART_ClearFlag函数
参数一:USART名称
参数二:USART标志位
USART_FLAG_TXE
USART_FLAG_RXNE
其余暂时不用
USART_GetITStatus函数
USART_ClearITPendingBit函数
参数一:USART名称
参数二:USART中断源
实验20 串口发送
接线图

跳线帽接VCC和3V3,RXD和TXD分别接与USART1对应的TX引脚PA9和RX引脚PA10,GND共地。
编译器配置
本实验部分功能需要对编译器进行配置。
printf函数移植

显示汉字
编译器代码部分输入汉字不报错方法,如下输入–no-multibyte-chars:

将UTF8编码切换为兼容性更好的GB2312编码:

串口助手
验证程序需要用到资料包工具软件中的串口助手。

插入USB转串口模块,串口号与设备管理器中一致,其余配置与程序一致,打开串口即可接收数据。
接收区配置中,HEX模式显示16进制数据,文本模式将16进制数据按ASCII码转换为对应的字符,汉字则通过文本编码选项选择GB2312或UTF8编码。
发送区配置中,HEX模式只能发送两位一组的原始16进制数据,文本模式将发送区内容视作字符,编码为16进制数据发送。
Serial.h
#ifndef __SERIAL_H
#define __SERIAL_H#include <stdio.h>void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);#endif
Serial.c
#include "stm32f10x.h"
//对stdio.h的printf重定向的串口输出方法所需头文件
#include <stdio.h>
//使用可变参数封装sprintf功能的串口输出方法所需头文件
#include <stdarg.h>void Serial_Init(void)
{//开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //初始化TX引脚PA9GPIO_InitTypeDef GPIO_InitStructure;//复用推挽GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化USARTUSART_InitTypeDef USART_InitStructure;//9600波特率USART_InitStructure.USART_BaudRate = 9600;//无流控USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//发送模式USART_InitStructure.USART_Mode = USART_Mode_Tx;//无校验USART_InitStructure.USART_Parity = USART_Parity_No;//1位停止位USART_InitStructure.USART_StopBits = USART_StopBits_1;//8位字长USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1, ENABLE);
}//发送字节函数
void Serial_SendByte(uint8_t Byte)
{//发送数据USART_SendData(USART1, Byte);//等待发送数据寄存器空while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));//TXE在DR写操作自动清零,无需手动清零
}//发送数组函数,Length指定数组长度以判断数组结束
void Serial_SendArray(uint8_t *Array, uint16_t Length)
{uint16_t i;for(i = 0; i < Length; i++){Serial_SendByte(Array[i]);}
}//发送字符串函数
void Serial_SendString(char *String)
{uint8_t i;//可以利用空字符作为结束标志位for(i = 0; String[i] != '\0'; i++){Serial_SendByte(String[i]);}
}//求幂函数,为发送字符串数字函数做准备
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{uint32_t Result = 1;while(Y--){Result *= X;}return Result;
}//发送字符串形式数字函数
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{uint8_t i;for(i = 0; i < Length; i++){//从高位到低位提取数位//ASCII码表中数字从0x30对应的'0'开始Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');}
}//以下为移植printf函数的三种串口输出方法/*
一
如果想使用printf一样的格式化输出功能则可以对其重定向
printf通过其底层函数fputc以字符为单位打印到屏幕
单片机没有屏幕,重定向printf函数的底层fputc到串口
*/
int fputc(int ch, FILE *f)
{Serial_SendByte(ch);return ch;
}//第二种方法为主程序中未封装的sprintf代码/*
三
使用可变参数函数封装sprintf功能
C语言可变参数是较为深入的内容,这里仅展示代码
*/
void Serial_Printf(char *format, ...)
{char String[100];va_list arg;va_start(arg, format);vsprintf(String, format, arg);va_end(arg);Serial_SendString(String);
}
主程序
#include "stm32f10x.h"
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"int main(void)
{OLED_Init();Serial_Init();//不同类型的串口输出函数Serial_SendByte('A');uint8_t MyArray[] = {0x42, 0x43, 0x44, 0x45};Serial_SendArray(MyArray, 4);//通过/r/n换行Serial_SendString("\r\nNum1=");Serial_SendNumber(111, 3);//printf重定向串口输出方式printf("\r\nNum2=%d", 222);//重定向只能被一个串口占用//无需重定向实现格式化输出的sprintf方式char String[100];//sprintf将格式化内容转化到字符串变量中sprintf(String, "\r\nNum3=%d", 333);//再发送字符串Serial_SendString(String);//封装后的sprintf方式Serial_Printf("\r\nNum4=%d", 444);Serial_Printf("\r\n");while(1){}
}
实验21 串口发送+接收
接线保持不变。
查询方式
仅需更改Serial_Init函数:
void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化RX引脚PA10//串口空闲为高电平,选上拉或浮空输入GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//发送/接收模式USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1, ENABLE);
}
主程序:
#include "stm32f10x.h"
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"uint8_t RxData;int main(void)
{OLED_Init();Serial_Init();while(1){//检测是否接收到数据if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE)){//读取数据RxData = USART_ReceiveData(USART1);OLED_ShowHexNum(1, 1, RxData, 2);//RXNE标志位在读取DR时自动清零,无需手动清零}}
}
中断方式
Serial.h
#ifndef __SERIAL_H
#define __SERIAL_H#include <stdio.h>void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);
//新增函数
uint8_t Serial_GetRxFlag(void);
uint8_t Serial_GetRxData(void);#endif
添加两个全局变量,更改Serial_Init函数:
//在驱动中暂存接受数据和接收标志位
uint8_t Serial_RxData;
uint8_t Serial_RxFlag;void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStructure);//开启中断USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//配置NVICNVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;//打开USART1通道NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);USART_Cmd(USART1, ENABLE);
}
添加新函数:
//外接调用接收数据函数
uint8_t Serial_GetRxData(void)
{return Serial_RxData;
}//中断函数实现读取功能
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1, USART_IT_RXNE)){Serial_RxData = USART_ReceiveData(USART1);Serial_RxFlag = 1;USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}
主程序:
#include "stm32f10x.h"
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"uint8_t RxData;int main(void)
{OLED_Init();Serial_Init();OLED_ShowString(1, 1, "RxDara:");while(1){//检测是否接收到数据if (Serial_GetRxFlag()){RxData = Serial_GetRxData();//数据回传功能Serial_SendByte(RxData);OLED_ShowHexNum(1, 8, RxData, 2);//RXNE标志位在读取DR时自动清零,无需手动清零}}
}
相关文章:
【STM32单片机】#10 USART串口通信
主要参考学习资料: B站江协科技 STM32入门教程-2023版 细致讲解 中文字幕 开发资料下载链接:https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 单片机套装:STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协 实验&…...
fastlio用mid360录制的bag包离线建图,提示消息类型错误
我用mid360录制的bag包,激光雷达的数据类型是sensor_msgs::PointCloud2,但是运行fast_lio中的mid360 launch文件,会报错(没截图),显示无法从livox_ros_driver2::CustomMsg转换到sensor_msgs::PointCloud2。…...
二级评论列表-Java实现
二级评论列表是很常见的功能,文章记录了新手用Java实现的具体逻辑。 整体实现逻辑是先用2个sql,分别查出两层数据。然后用java在service中实现数据组装,返给前端。这种实现思路好处是SQL简洁,逻辑分明,便于维护。 一…...
IP检测工具“ipjiance”
目录 IP质量检测 应用场景 对网络安全的贡献 对网络管理的帮助 对用户决策的辅助作用 IP质量检测 检测IP的网络提供商:通过ASN(自治系统编号)识别IP地址所属的网络运营商,例如电信、移动、联通等。 识别网络类型࿱…...
mysql的函数(第二期)
九、窗口函数(MySQL 8.0) 适用于对结果集的子集(窗口)进行计算,常用于数据分析场景。 ROW_NUMBER() 作用:为每一行生成唯一的序号。示例:按分数降序排名 SELECT n…...
Replicate Python client
本文翻译整理自:https://github.com/replicate/replicate-python 文章目录 一、关于 Replicate Python 客户端相关链接资源关键功能特性 二、1.0.0 版本的重大变更三、安装与配置1、系统要求2、安装3、认证配置 四、核心功能1、运行模型2、异步IO支持3、流式输出模型…...
halcon模板匹配(八)alignment_for_ocr_in_semiconductor
目录 一、alignment_for_ocr_in_semiconductor例程目的二、创建训练和查找用于图像对齐三、图像对齐四、在指定区域内查找文本一、alignment_for_ocr_in_semiconductor例程目的 在一个图像中定义两个区域,一个用于图像对齐,在另一个区域内使用文本模板进行匹配。 二、创建训…...
Java读取JSON文件并将其中元素转为JSON对象输出
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Java读取JSON文件并将其中元素转为JSON对象输…...
华为openEuler操作系统全解析:起源、特性与生态对比
华为openEuler操作系统全解析:起源、特性与生态对比 一、起源与发展历程 openEuler(欧拉操作系统)是华为于2019年开源的Linux发行版,其前身为华为内部研发的服务器操作系统EulerOS。EulerOS自2010年起逐步发展,支持华…...
Elasticsearch使用及常见的问题
Elasticsearch作为一款分布式搜索与分析引擎,其核心优势在于高性能搜索能力,依托倒排索引和分布式架构,可快速处理海量数据及复杂查询,支持实时索引与动态扩容,兼具高可用性和扩展性。其丰富的RESTful API与查询语言降…...
Python基础总结(七)之条件语句
文章目录 条件语句if一、Python中的真假二、条件语句格式2.1 if语句格式2.2 if-else语句2.3 if-elif-else语句 三、if语句嵌套 条件语句if 条件语句其实就是if语句,在讲解if语句之前需要知道Python中对于真假的判断。 一、Python中的真假 在Python中非0的都为真&…...
命令update-alternatives
❯ which pip /home/ying/anaconda3/bin/pipying192 ~ [2]> which pip /usr/bin/pip使用update-alternatives对他们进行管理和切换 快捷方式 和 实际路径不可以相同 所以我这边选择了/usr/local/bin目录作为介质存储快捷方式,另外该快捷方式会自己创建我们只需选…...
deekseak 本地windows 10 部署步骤
有些场景需要本地部署,例如金融、医疗(HIPAA)、政府(GDPR)、军工等,需完全控制数据存储和访问权限,避免云端合规风险或者偏远地区、船舶、矿井等无法依赖云服务,关键设施(…...
MySQL中常用函数的分类及示例
概述 以下是 MySQL 中常用函数的分类及示例,涵盖字符串处理、数值计算、日期操作、条件判断等常见场景: 一、字符串函数 1. CONCAT(str1, str2, ...) 拼接字符串。 SELECT CONCAT(Hello, , World); -- 输出: Hello World2. SUBSTRING(str, start,…...
<sql>、<resultMap>、<where>、<foreach>、<trim>、<set>等标签的作用和用法
目录 一. sql 代码片段标签 二. resultMap 映射结果集标签 三. where 条件标签 四. set 修改标签 五. trim 标签 六. foreach 循环标签 一. sql 代码片段标签 sql 标签是 mybatis 框架中一个非常常用的标签页,特别是当一张表很有多个字段多,或者要…...
企业级HAProxy高可用离线部署实战(附Kubernetes APIServer负载均衡配置)
企业级HAProxy高可用离线部署实战(附Kubernetes APIServer负载均衡配置) 摘要:本文深入讲解在离线环境下部署HAProxy 3.1.1的全流程,涵盖源码编译、系统服务封装、K8S APIServer四层负载配置等核心环节,并提供生产级高…...
实现Azure Databricks安全地请求企业内部API返回数据
需要编写一个Databricks在Azure云上运行,它需要访问企业内部的API获取JSON格式的数据,企业有网关和防火墙,API有公司的okta身份认证,通过公司的域账号来授权访问,现在需要创建一个专用的域账号,让Databrick…...
kafka认证部署
首先启动 zookeeper /home/kafka/bin/zookeeper-server-start.sh /home/kafka/config/zookeeper.properties 创建SCRAM证书 /home/kafka/bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config SCRAM-SHA-256[iterations8192,passwordliebe],SCRAM-SHA-512[p…...
【项目】CherrySudio配置MCP服务器
CherrySudio配置MCP服务器 (一)Cherry Studio介绍(二)MCP服务环境搭建(1)环境准备(2)依赖组件安装<1> Bun和UV安装 (3)MCP服务器使用<1> 搜索MCP…...
【LeetCode 热题 100】双指针 系列
📁283. 移动零 对于该题目,需要注意的是两个地方,一是保持非零元素的相对顺序,以及O(1)的空间复杂度。 采用双指针的思路,将数组划分成3个区间,。 [0 , left]:该区间内元素全是非零元素。 [left1 , right…...
【技术派后端篇】 Redis 实现用户活跃度排行榜
在各类互联网应用中,排行榜是一个常见的功能需求,它能够直观地展示用户的表现或贡献情况,提升用户的参与感和竞争意识。在技术派项目中,也引入了用户活跃度排行榜,该排行榜主要基于 Redis 的 ZSET 数据结构来实现。接下…...
模拟算法(一)作业分析及答案
目录 作业1:角谷猜想 解题思路 : 代码实现: 作业2:校门外的树 解题思路 注意事项 代码实现 作业3:乒乓球 编辑 问题重述 解题思路: 作业1:角谷猜想 【描述】 所谓角谷猜想…...
西红柿番茄检测数据集VOC+YOLO格式2320张1类别可用于计数
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2320 标注数量(xml文件个数):2320 标注数量(txt文件个数):2320 …...
企业级实战:将Java服务打包为Docker镜像的两种高效方法
企业级实战:将Java服务打包为Docker镜像的两种高效方法 摘要:本文针对Java服务容器化部署场景,提供 基于容器Commit 和 Dockerfile构建 两种镜像制作方案。重点解决动态库依赖、信号量配置、环境变量注入等企业级痛点问题,并提供…...
专题十六:虚拟路由冗余协议——VRRP
一、VRRP简介 VRRP(Virtual Router Redundancy Protocol)虚拟路由冗余协议通过把几台设备联合组成一台虚拟的设备,使用一定的机制保证当主机的下一跳设备出现故障时,及时将业务切换到备份设备,从而保持通讯的连续性和…...
Java中常见的锁synchronized、ReentrantLock、ReentrantReadWriteLock、StampedLock
在Java中,锁是实现多线程同步的核心机制。不同的锁适用于不同的场景,理解其实现原理和使用方法对优化性能和避免并发问题至关重要。 一、隐式锁:synchronized 关键字 实现原理 基于对象监视器(Monitor):每…...
DDPM(diffusion)原理
DDPM(diffusion)原理 1、DDPM(原理)2、DDPM和 Conditional DDPM(原理解释)2.1. Diffusion Models 原理详解核心思想前向扩散过程(Forward Diffusion)反向去噪过程(Revers…...
《软件设计师》复习笔记(2.2)——效验码、体系结构、指令、流水线
目录 一、校验码 码距 奇偶校验码 循环冗余校验码(CRC) 海明码 真题示例: 二、体系结构 Flynn分类法 三、指令系统 指令组成 指令执行过程 指令的寻址方式 操作数的寻址方式 CISC vs RISC 真题示例: 四、流水线技…...
BT1120 BT656驱动相关代码示例
前些年做视频输出项目的时候用过bt1120 tx与rx模块,现将部分代码进行记录整理。代码功能正常,可正常应用。 1. rx部分: /****************************************************************************** Copyright (C) 2021,All rights …...
2025.04.19-阿里淘天春招算法岗笔试-第一题
📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 01. 字符交换智慧 问题描述 卢小姐有一个长度为 n n n 的字符串...
