STM32基础教程——串口收发
目录
前言
字长设置 编辑
停止位
起始位侦测
波特率
1. UART波特率的基本原理
2. 为什么需要先除以分频因子(USARTDIV)?
(1)PCLK频率太高
(2)分频因子的作用
3. 为什么还需要再除以16?
(1)过采样技术
(2)波特率公式
4. 分数波特率发生器
5. 总结:为什么要先除以分频因子再除以16?
示例计算
技术实现
连线图
代码实现
技术要点
串口引脚
GPIO引脚配置
USART初始化
开启USART中断
配置NVIC
发送1位数据
串口中断数据接收
串口打印
可变参数类型
作用
问题记录
前言
串口,是一种应用范围十分广泛的通信接口,串口的成本较低,容易使用,通信线路简单,可以实现两个设备之间的通信。单片机的串口可以实现单片机与单片机,单片机与电脑,单片机与其他设备的通信,极大地扩展了单片机的应用范围,增强了单片机的硬件实力。
USART即通用同步/异步收发器,USART是STM32内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧时序,从TX引脚发送出去,也可自动接收RX引脚的数据帧时序,拼接为一个字节数据,存放在数据寄存器里。
USART的部分主要特性
- 全双工,异步通信
- 分数波特率发生器系统,发送和接受共用的可编程波特率,最高打4.5Mbits/s。
- 可编程数据字节长度(8位或9位)
- 可配置的停止位——支持1或2个停止位
- 单独的发送器和接收器使能位
- 检测标志
——接收缓冲器满
——发送缓冲器空
——传输结束标志位
- 校验控制
——发送校验位
——对接收数据进行校验
USART部分功能概述
任何USART双向通信至少需要两个脚,接收数据输入(RX)和发送数据输出(TX)。
- 总线在发送或接收前应处于空闲状态
- 一个起始位
- 一个数据字(8位或9位)
- 最低有效位在前
- 0.5,1,1.5,2个的停止位,由此表明数据帧的结束
USART框图
字长设置 
字长可通过编程USART_CR1寄存器中的M位,选择8位或9位。在起始位期间,TX脚处于低电平,在停止位期间处于高电平。
停止位
起始位侦测
起始位侦测,在空闲状态下,串口通信线路保持高电平,接收线路以波特率的16倍频率对信号进行采样,持续检测线路的状态。
当采样检测到从高电平(1)到低电平(0)的变化时,说明可能出现了起始位的下降沿。为了确保这不是噪声引起,接收电路会进一步确认。
在检测到下降沿之后,接收电路会在接下来的采样周期中继续采样,确认是否是起始位。接收电路会在第3次,第5次,第7次采样一批数据,并在第8次,第9次,第10采样一批数据。如果这两批采样结果都满足“每三次采样中至少有两个0”,则认为检测到了有效起始位。如果不满足条件,则认为是噪声干扰,重新回到空闲状态等待新的下降沿。
一旦确认起始位有效,接收电路会将第8,9,10次采样的位置对齐到数据位的中间位置,这样可以确保每个后续每个数据位的采样都在位的正中间,从而提高了数据接收的准确性。
如果有一次三个采样点上仅有2个时‘0’,那么起始位有效,但会设置NE噪声标志位。
波特率
发送器和接收器的波特率都由波特率寄存器BBR里的DIV值来确定。
这里的fck是外设的时钟,PCLK1用于USART2,3,4,5,PCLK2用于USART1.
1. UART波特率的基本原理
- 波特率表示每秒传输的符号数(通常为比特数),它决定了数据传输的速度。
- 在UART通信中,波特率是由时钟信号通过分频来生成的。
- STM32的UART模块使用一个波特率发生器,通过分频系统时钟(PCLK)来生成所需的波特率。
2. 为什么需要先除以分频因子(USARTDIV)?
(1)PCLK频率太高
- STM32的外设时钟(PCLK)通常是一个较高的频率,例如72 MHz、36 MHz等。
- 直接用如此高的时钟频率去驱动UART会导致难以生成低速的波特率(如9600 bps)。因此,必须对PCLK进行分频。
(2)分频因子的作用
- 分频因子(USARTDIV)是一个可编程值,用于将PCLK分频到一个适合生成波特率的频率范围。
- 公式如下:
UART时钟=PCLK/USARTDIV
- USARTDIV的值可以通过计算得出,确保最终的UART时钟接近所需的波特率。
3. 为什么还需要再除以16?
(1)过采样技术
- STM32的UART模块采用16倍过采样技术,即每个数据位的时间宽度被分为16个采样点。
- 这种过采样技术可以提高数据接收的精度和抗噪声能力。
- 因此,UART的实际波特率是基于“分频后的时钟再除以16”来生成的。
(2)波特率公式
- 综合上述两步,波特率的计算公式为:
波特率=PCLK /(USARTDIV×16)
- 通过这种方式,可以更精细地调整波特率,使其更接近目标值。
4. 分数波特率发生器
- 在某些情况下,即使使用整数分频因子(USARTDIV),也可能会导致波特率存在一定的误差。
- 为了解决这个问题,STM32引入了分数波特率发生器,允许对USARTDIV的小数部分进行调整。
- 分数部分的精度通常是1/16,这样可以进一步减小波特率误差。
5. 总结:为什么要先除以分频因子再除以16?
分频因子(USARTDIV)的作用:
- 将高频的PCLK分频到一个较低的频率范围,便于生成目标波特率。
16倍过采样的作用:
- 通过对分频后的时钟再除以16,实现高精度的数据采样和抗噪声能力。
- 这种设计使得UART可以在不同的波特率下保持稳定性和可靠性。
灵活性和精度:
- 结合分频因子和16倍过采样,STM32可以灵活地支持各种波特率,并通过分数波特率发生器进一步提高精度。
示例计算
假设:
- PCLK = 72 MHz
- 目标波特率 = 9600 bps
根据公式:
USARTDIV=PCLK波特率×16USARTDIV=波特率×16PCLK
代入数值:
USARTDIV=72,000,0009600×16=468.75USARTDIV=9600×1672,000,000=468.75
- 整数部分为468,小数部分为0.75。
- 配置USARTDIV寄存器时,将整数部分写入DIV_Mantissa,小数部分写入DIV_Fraction。
通过这种方式,STM32可以精确生成9600 bps的波特率。
过采样技术:
- STM32使用波特率的16倍频率对输入信号进行过采样。这意味着在一个比特时间内,会进行16次采样。
- 过采样的好处是可以更精确地定位起始位、数据位和停止位,并且有助于识别可能的噪声干扰。
技术实现
连线图
代码实现
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h" //延时函数
#include "OLED.h"
#include "Serial.h"int main(void)
{/*初始化*/OLED_Init();Serial_Init();while(1){//查询方法
// while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET);
// Dat = USART_ReceiveData(USART1);//中断方法if(Serial_ITFlag() == 1){OLED_ShowHexNum(1,1,Serial_ReceiveData(),2);}}
}
Serial.h
#ifndef SERIAL_H
#define SERIAL_H#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h> //Variable parametersvoid Serial_Init(void);
uint8_t Serial_ITFlag(void);
uint16_t Serial_ReceiveData(void);
void Serial_Printf(const char *format,...);
void Serial_SendArray(uint8_t* Array,uint16_t Length);
void Serial_SendByte(uint8_t Byte);
void Serial_SendNum(uint32_t Num, uint8_t Length);
void Serial_SendString(char *String);#endif
Serial.c
#include "Serial.h"uint8_t Serial_RxFlag = 0;
uint16_t Serial_RxData;/*** @brief Initialize the USART peripheral* @param None* @retval None*/
void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//GPIOGPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);USART_InitTypeDef USART_InitStruct;USART_InitStruct.USART_BaudRate = 9600; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_InitStruct.USART_Parity = USART_Parity_Odd; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_WordLength = USART_WordLength_9b; USART_Init(USART1,&USART_InitStruct);//串口中断USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;NVIC_Init(&NVIC_InitStruct);USART_Cmd(USART1,ENABLE);
}/*** @brief Send a byte via serial port* @param Byte: Data byte to be transmitted* @retval None*/
void Serial_SendByte(uint8_t Byte)
{USART_SendData(USART1,Byte); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
}/*** @brief Send data via serial port* @param Data parameters:* @arg Array: Data buffer to be transmitted* @arg Length: Number of bytes to transmit* @retval None*/
void Serial_SendArray(uint8_t *Array,uint16_t Length)
{uint16_t i;for(i=0;i<Length;i++){Serial_SendByte(Array[i]); }
}/*** @brief Send a string via serial port* @param String: Pointer to the null-terminated string to transmit* @retval None*/
void Serial_SendString(char *String)
{while((*String) != '\0'){Serial_SendByte(*String);String++;}
}/*** @brief Calculate X raised to the power of Y (X^Y)* @param X: Base number (must be positive if Y=0)* @param Y: Exponent (must be non-negative)* @retval Result of X^Y*/
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{uint32_t Result = 1;while(Y--){Result *= X;}return Result;
}/*** @brief Send string via serial port* @param String: Pointer to null-terminated string* @retval None*/
void Serial_SendNum(uint32_t Num, uint8_t Length)
{uint8_t i;for(i=0;i<Length;i++){Serial_SendByte(Num / Serial_Pow(10,Length-i-1) % 10 + '0');}
}///**
// *@brief fputc
// *@param None
// *@retval None
//**/
//int fputc(int ch,FILE *f)
//{
// Serial_SendByte(ch);
// return ch;
//}/***@brief Brief description of the function or code*@param None*@retval None*@note parmN is format.The actual parameter passed to this parameter is the number of parameters represented bythe ellipsis part.
**/
void Serial_Printf(const char *format,...)
{char buffer[128];va_list args; //Declear an object that store parametersva_start(args, format); //Initialize args as parameters listvsnprintf(buffer, sizeof(buffer), format, args);va_end(args); //Clearing workSerial_SendString(buffer);
}/***@brief Detect the interrupt flag bit of the serial port.*@param None*@retval Where to enter the interrupt flag state
**/
uint8_t Serial_ITFlag(void)
{if(Serial_RxFlag == 1){Serial_RxFlag = 0;return 1;}return 0;
}/***@brief Return the data received through the serial port.*@param None*@retval The value of DR register.
**/
uint16_t Serial_ReceiveData(void)
{return Serial_RxData;
}/***@brief Serial port interrupt*@param None*@retval None
**/
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET){Serial_RxData = USART_ReceiveData(USART1);Serial_RxFlag = 1;USART_ClearITPendingBit(USART1,USART_IT_RXNE); //读取DR寄存器会自动将USART_CR1寄存器中的RXNEIE位清除}
}
OLED部分代码参照文章《STM32基础教程——OLED显示》http://【STM32基础教程 ——OLED显示 - CSDN App】https://blog.csdn.net/2301_80319641/article/details/145837521?sharetype=blog&shareId=145837521&sharerefer=APP&sharesource=2301_80319641&sharefrom=link
技术要点
串口引脚
USART1的TX和RX引脚分别为PA9和PA10的复用功能引脚。
GPIO引脚配置
//GPIOGPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);
PA9作为复用Tx引脚,应设置为复用推挽输出(GPIO引脚的行为取决于所选的复用功能,由特定的外设控制)。
PA10作为复用Rx引脚,设置为上拉输入(没有复用输入是因为引脚作为输入功能只被动的接收或采集信号而不产生驱动信号)(因为数据信号在空闲状态保持高电平,不能使用下拉输入,可选浮空输入。)
USART初始化
USART_InitTypeDef USART_InitStruct;USART_InitStruct.USART_BaudRate = 9600; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_InitStruct.USART_Parity = USART_Parity_Odd; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_WordLength = USART_WordLength_9b; USART_Init(USART1,&USART_InitStruct);
波特率的设置不需要自己计算,只需将想要设置的波特率赋值给USART_BaudRate成员,本实验设置波特率为9600,不使用硬件流控制,USART_Mode同时启用收发功能,数据帧采用奇校验,一个停止位,数据字节长度设置为9。
开启USART中断
//串口中断USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
配置NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;NVIC_Init(&NVIC_InitStruct);
优先级分组选择第2组,中断通道选择USART中断通道。
发送1位数据
/*** @brief Send a byte via serial port* @param Byte: Data byte to be transmitted* @retval None*/
void Serial_SendByte(uint8_t Byte)
{USART_SendData(USART1,Byte); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
}
调用USART_SendData()函数发送一位数据,然后while循环等待数据发送完成后TXE标志位被置1,再次发送输入即向USART_DR寄存器写入数据时会自动将该标志位清0。
串口中断数据接收
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET){Serial_RxData = USART_ReceiveData(USART1);Serial_RxFlag = 1;USART_ClearITPendingBit(USART1,USART_IT_RXNE); //读取DR寄存器会自动将USART_CR1寄存器中的RXNEIE位清除}
}
每接收到一个数据就会触发一次串口中断,如果检测到USART_SR寄存器中的RXNE标志位被置1,说明接受到的数据已经从移位寄存器全部转移到额数据接收寄存器中,然后将数据接收寄存器USART_DR的值赋给变量,并将中断数据接收标志位(自己定义的)置1,最后清除读数据接受寄存器的标志位。
串口打印
/***@brief Brief description of the function or code*@param None*@retval None*@note parmN is format.The actual parameter passed to this parameter is the number of parameters represented bythe ellipsis part.
**/
void Serial_Printf(const char *format,...)
{char buffer[128];va_list args; //Declear an object that store parametersva_start(args, format); //Initialize args as parameters listvsnprintf(buffer, sizeof(buffer), format, args);va_end(args); //Clearing workSerial_SendString(buffer);
}
基于C库的printf函数的原理实现的串口打印函数。该函数定义了一个128个字节的缓冲区,va_start()初始化可变参数类型变量args,使其指向第一个可变参数(即format后的第一个参数),
vsnprintf()函数将格式化字符串写入缓冲区buffer,va_end函数完成清理args的工作,完成对可变参数列表的使用。
在C语言中,处理函数的可变参数(variadic arguments)需要用到标准库中的
<stdarg.h>
头文件。这个头文件提供了处理不定数量参数所需的功能和宏定义。下面详细解释可变参数类型以及如何使用指向这些参数的变量。可变参数类型
va_list
类型:
- 这是一个特殊的类型,用于声明一个变量,该变量将被用来遍历函数调用时传递的所有额外参数。
- 它本质上是一个指向参数列表的指针或类似结构体,但其具体实现是编译器相关的,通常对用户是不透明的。
宏定义:
va_start
:初始化一个va_list
类型的变量,使其指向第一个可变参数。需要传入两个参数:一个是va_list
类型的变量,另一个是指向固定参数列表中的最后一个已知参数的标识符(通常是省略号前的那个参数)。va_arg
:获取当前指针位置的参数值,并根据提供的类型向前移动指针到下一个参数。需要传入两个参数:一个是va_list
类型的变量,另一个是你想要获取的参数的数据类型。va_end
:清理工作,释放由va_start
初始化的资源。虽然在现代系统上这可能不是严格必要的,但它是一种良好的编程实践。作用
当你有一个函数接受不定数量的参数时(比如
printf
),你可以使用va_list
类型的变量来遍历所有额外参数。具体步骤如下:
- 首先,使用
va_start
初始化你的va_list
变量,告诉它从哪里开始查找额外参数。- 然后,使用
va_arg
来依次提取每个参数的值,并根据需要处理它们。- 最后,在完成所有参数处理之后,调用
va_end
来进行必要的清理。
问题记录
1.对可变参数相关知识理解较浅。
2.USART波特率基本原理倍率采样理解反了。
相关文章:
STM32基础教程——串口收发
目录 前言 字长设置 编辑 停止位 起始位侦测 波特率 1. UART波特率的基本原理 2. 为什么需要先除以分频因子(USARTDIV)? (1)PCLK频率太高 (2)分频因子的作用 3. 为什么还需要再除以…...
Matlab 步进电机传递函数模糊pid
1、内容简介 Matlab 210-步进电机传递函数模糊pid 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略...
unordered_map、unordered_set详解
深入理解C中的 unordered_map 和 unordered_set 在C标准库中,unordered_map 和 unordered_set 是两个基于哈希表(Hash Table)实现的高效容器。它们以O(1)的平均时间复杂度实现快速查找、插入和删除操作,特别适合需要高频…...
详解trl中的GRPOTrainer和GRPOConfig
引言 在大型语言模型(LLM)的强化学习微调领域, Group Relative Policy Optimization (GRPO) 算法因其高效性和资源友好性受到广泛关注。Hugging Face的 TRL (Transformer Reinforcement Learning) 库通过GRPOTrainer和GRPOConfig提供了该算法的开箱即用实现。本文将深入解析…...
【C++】多态 - 从虚函数到动态绑定的核心原理
📌 个人主页: 孙同学_ 🔧 文章专栏:C 💡 关注我,分享经验,助你少走弯路 文章目录 1. 多态的概念2. 多态的定义及实现2.1 多态的构成条件2.1.1实现多态还有两个必须重要条件:2.1.2 虚…...
项目预期管理:超越甘特图,实现客户价值交付
引言 在项目管理实践中,许多项目经理习惯于将注意力集中在甘特图的进度条上,关注任务是否按时完成、里程碑是否达成。然而,这种以计划管理为中心的方法往往忽略了项目管理的核心目标:满足客户预期,交付真正的价值。项…...
FISCO 2.0 安装部署WeBASE与区块链浏览器(环境搭建)
FISCO BCOS 2.0 安装部署WeBASE与区块链浏览器-对应的官网地址: WeBASE平台:https://webasedoc.readthedocs.io/zh-cn/latest/docs/WeBASE/install.html 区块链浏览器:https://fisco-bcos-documentation.readthedocs.io/zh-cn/latest/docs/br…...
xss学习3之服务端session
一、服务端的Session 1. cookie和session 1)cookie和session对比 cookie: 保存在客户端,包含所有key-value信息,浏览器访问多个网站时会积累大量cookie,占用存储空间,并在每次请求时携带所有cookie,增加…...
23种设计模式-结构型模式之适配器模式(Java版本)
Java 适配器模式(Adapter Pattern)详解 🔌 什么是适配器模式? 适配器模式用于将一个类的接口转换成客户端所期望的另一种接口,让原本接口不兼容的类可以协同工作。 📦 就像插头转换器,让不同…...
【2025计算机网络-面试常问】http和https区别是什么,http的内容有哪些,https用的是对称加密还是非对称加密,流程是怎么样的
HTTP与HTTPS全面对比及HTTPS加密流程详解 一、HTTP与HTTPS核心区别 特性HTTPHTTPS协议基础明文传输HTTP SSL/TLS加密层默认端口80443加密方式无加密混合加密(非对称对称)证书要求不需要需要CA颁发的数字证书安全性易被窃听、篡改、冒充防窃听、防篡改…...
使用安全继电器的急停电路设计
使用安全继电器的急停电路设计 一,急停回路的设计1,如何将急停接到线路当中?2,急停开关 如何接到安全继电器中 一,急停回路的设计 急停是每一个设备必不可少的部分,因为关乎安全,所以说所以说他…...
SpringCloud概述和环境搭建
SpringCloud概述和环境搭建 一.微服务的引入1.单体架构2.集群和分布式架构3.集群和分布式4.微服务架构4.微服务的优缺点 二.微服务解决方案-SpringCloud1.Spring Cloud简介2.Spring Cloud版本3.Spring Cloud实现方案4.Spring Cloud Alibaba 三.环境搭建1.安装JDK172.Ubantu上下…...
System.out 详解
System.out 详解 System.out 是 Java 提供的标准输出流(PrintStream 类型),默认关联控制台(Console),用于向终端打印文本信息。它是 Java 中最常用的输出方式之一,尤其在调试和命令行程序开发中。 1. 核心知识点 (1)System.out 的本质 类型:PrintStream(字节流,但…...
每天学一个 Linux 命令(28):ln
可访问网站查看,视觉品味拉满: http://www.616vip.cn/28/index.html ln 是 Linux 中用于创建文件或目录链接的命令,主要生成硬链接(Hard Link)和符号链接(Symbolic Link,软链接)。链接常用于文件共享、快捷访问或版本管理。 命令格式 ln [选项] 源文件 目标链接链…...
【微知】服务器如何获取服务器的SN序列号信息?(dmidecode -t 1)
文章目录 背景命令dmidecode -t的数字代表的字段 背景 各种场景都需要获取服务器的SN(Serial Number),比如问题定位,文件命名,该部分信息在dmi中是标准信息,不同服务器,不同os都能用相同方式获…...
4.20刷题记录(单调栈)
第一部分:简单介绍 单调栈我的理解是在栈中存储数字出现的位置,然后通过遍历比较当前栈顶元素与当前元素的大小关系,从而确定逻辑相关顺序。 第二部分:真题讲解 (1)739. 每日温度 - 力扣(Lee…...
Opencv图像处理:模板匹配对象
文章目录 一、模板匹配1、什么是模板匹配?2、原理 二、单模板匹配(代码实现)1、预处理2、 开始模板匹配并绘制匹配位置的外接矩形 三、多模板匹配(代码实现)1、读取图片和模板2、模板匹配3、设置阈值1)阈值…...
Web3.0热门领域NFT项目实战课程
课程大小:3.8G 课程下载:https://download.csdn.net/download/m0_66047725/90616383 更多资源下载:关注我 深度掌握Solidity合约开发,助力成为抢手的Web3.0开发工程师 深入Web3.0技术的人才,一将难求。本课程由We…...
DAY 50 leetcode 1047--栈和队列.删除字符串中的所有相邻重复项
题号1047 给出由小写字母组成的字符串 s,重复项删除操作会选择两个相邻且相同的字母,并删除它们。 在 s 上反复执行重复项删除操作,直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。 import java.util.Ar…...
单例模式与消费者生产者模型,以及线程池的基本认识与模拟实现
前言 今天我们就来讲讲什么是单例模式与线程池的相关知识,这两个内容也是我们多线程中比较重要的内容。其次单例模式也是我们常见设计模式。 单例模式 那么什么是单例模式呢?上面说到的设计模式又是什么? 其实单例模式就是设计模式的一种。…...
微信小程序通过mqtt控制esp32
目录 1.注册巴法云 2.设备连接mqtt 3.微信小程序 备注 本文esp32用的是MicroPython固件,MQTT服务用的是巴法云。 本文参考巴法云官方教程:https://bemfa.blog.csdn.net/article/details/115282152 1.注册巴法云 注册登陆并新建一个topicÿ…...
QML、Qt Quick 、Qt Quick Controls 2
一、概念 基本关系 QML 是声明式语言,用于描述用户界面。声明式语法(类似JSON+JavaScript),定义UI结构和行为。 Qt Quick 是 QML 的标准库,提供基本类型和功能。提供QML语言运行时的基础能力,相当于QML的"标准模板库(STL)"。 Quick Controls 2 是基于 Qt Quic…...
基于maven-jar-plugin打造一款自动识别主类的maven打包插件
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
利用 HEMT 和 PHEMT 改善无线通信电路中的增益、速度和噪声
本文要点 高电子迁移率晶体管 (High electron mobility transistors ,HEMTs) 和应变式异质接面高迁移率晶体管(pseudomorphic high electron mobility transistors ,PHEMTs) 因其独特的、可提高性能的特点而…...
探秘C#用户定义类型:突破预定义的边界
在C#的编程世界里,除了系统提供的16种预定义类型,开发者还拥有强大的自主能力——创建自己的用户定义类型。这大大拓展了编程的灵活性和可扩展性,让开发者能根据具体需求定制数据结构和功能。 六种用户定义类型 类类型(class&am…...
idea中导入从GitHub上克隆下来的springboot项目解决找不到主类的问题
第一步:删除目录下的.idea和target,然后用idea打开 第二步:如果有需要,idea更换jdk版本 原文链接:https://blog.csdn.net/m0_74036731/article/details/146779040 解决方法(idea中解决)&#…...
北理工宫某的瓜ppt下载地址
关于“北理工宫某瓜”PPT下载地址相关技术探讨 摘要:本文围绕“北理工宫某瓜”事件中PPT下载地址相关情况展开分析,探讨了网络资源传播的技术机制、涉及的网络安全问题以及围绕此类资源分享应遵循的规范和注意事项,旨在从技术角度对这类网络…...
[论文阅读]Making Retrieval-Augmented Language Models Robust to Irrelevant Context
Making Retrieval-Augmented Language Models Robust to Irrelevant Context [2310.01558v2] Making Retrieval-Augmented Language Models Robust to Irrelevant Context 检索增强语言模型(RALMs),它包含一个检索机制,以减少将…...
论文阅读:2023 arxiv A Survey of Reinforcement Learning from Human Feedback
A Survey of Reinforcement Learning from Human Feedback https://arxiv.org/pdf/2312.14925 https://www.doubao.com/chat/3506943124865538 速览 这篇论文是关于“从人类反馈中进行强化学习(RLHF)”的综述,核心是讲如何让AI通过人类反…...
【图像处理基石】什么是去马赛克算法?
RAW数据的Demosaic算法(去马赛克算法)是图像处理中的关键技术,主要用于将图像传感器(如数码相机、手机摄像头)采集的原始马赛克数据恢复为完整的RGB三通道图像。 1. RAW数据的特性 马赛克结构:图像传感器…...
transformer注意力机制
单头注意力机制 import torch import torch.nn.functional as Fdef scaled_dot_product_attention(Q, K, V):# Q: (batch_size, seq_len, d_k)# K: (batch_size, seq_len, d_k)# V: (batch_size, seq_len, d_v)batch_size: 一次输入的句子数。 seq_len: 每个句子的词数。 d_mo…...
Ubuntu 22.04 更换 Nvidia 显卡后启动无法进入桌面问题的解决
原显卡为 R7 240, 更换为 3060Ti 后, 开机进桌面时卡在了黑屏界面, 键盘有反应, 但是无法进入 shell. 解决方案为 https://askubuntu.com/questions/1538108/cant-install-rtx-4060-ti-on-ubuntu-22-04-lts 启动后在开机菜单中(如果没有开机菜单, 需要按shift键), 进入recove…...
ROS机器人开发实践->机器人建模与仿真
前言: 这篇博客知识一个整体性的了解对于机器人建模和仿真,更多详细的细节,见 6.4.2 Xacro_语法详解 Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 一、整体框架 机器人模型分为两个部分具体的形状和插件。有了这个具体的形状…...
中国占全球工业机器人装机量的52%,国产机器人崛起加速洗牌,拆分机器人业务独立上市,软硬件协同增强,AI工业机械臂催生业务再增长
一、内部战略优化:聚焦核心业务与释放增长潜力 业务协同效应有限 ABB的机器人业务(全球市场份额第二)与集团其他业务(如电气化、过程自动化)的协同性较低。机器人业务专注于柔性制造和智能自动化,而其他业务更偏向能源效率和大型工业系统。分拆后,ABB集团可更聚焦于电气…...
C#森林中的兔子(力扣题目)
C#森林中的兔子(力扣题目) 题目介绍 森林中有未知数量的兔子。提问其中若干只兔子 “还有多少只兔子与你(指被提问的兔子)颜色相同?” ,将答案收集到一个整数数组 answers 中,其中 answers[i] 是第 i 只兔子的回答。 给你数组…...
OSPF特殊区域
四种特殊区域 1、stub 2、完全stub 3、nssa 4、完全nssa 作用:用于优化OSPF的LSDB空间 stub: [R2-ospf-1-area-0.0.0.1]stub //配置一个区域为stub区域 只在ABR上配置的话会导致OSPF邻居关系断开,因为此时Option选项中Nbit和Ebit置位不一致所…...
深入理解 CICD 与 Jenkins 流水线:从原理到实践
前言:在当今数字化飞速发展的时代,软件开发行业的竞争日益激烈。为了能够快速响应市场需求,及时交付高质量的软件产品,开发团队们不断探索和采用新的开发模式与工具。CICD(持续集成、持续交付 / 部署)作为一…...
1.Vue自动化工具安装(Vue-cli)
目录 1.node.js 安装: 2 npm 安装 3 安装Vue-cli 4总结: 一般情况下,单文件组件,我们运行在 自动化工具vue-CLI中,可以帮我们编译单文件组件。所以我们在学习时一般需要在系统中先搭建vue-CLI工具 下面就是一些我…...
前端亮点:大文件上传技术详解及问题解析
大片文件上传 文件上传 大片文件上传需考虑问题 一、核心实现步骤 分片唯一标识计算 (优化比较时间) • Hash生成:使用SparkMD5或crypto.subtle.digest计算文件整体Hash(秒传依据)及分片Hash(断点续传依据)。 • 优化:通过Web Worker多线程计算,避免主线程阻塞(如…...
每日一题——最小测试用例集覆盖问题
最小测试用例集覆盖问题(C语言实现) 问题描述 假设我们有一系列测试用例,每个测试用例会覆盖若干个代码模块。 我们使用一个二维数组来表示这些测试用例的覆盖情况: 如果某个测试用例 i 能覆盖代码模块 j,则数组中…...
React 文章 分页
删除功能 携带路由参数跳转到新的路由项 const navigate useNavigate() 根据文章ID条件渲染...
【技术派后端篇】Redis实现统计计数
在互联网项目中,计数器有着广泛的应用场景。以技术派项目为例,诸如文章点赞数、收藏数、评论数以及用户粉丝数等都离不开计数器的支持。在技术派源码中,提供了基于数据库操作记录实时更新和基于 Redis 的 incr 特性实现计数器这两种方案&…...
NHANES指标推荐:RFM
文章题目:Higher relative fat mass was associated with a higher prevalence of gallstones in US adults DOI:10.1186/s12876-025-03715-3 中文标题:在美国成年人中,相对脂肪质量越高,胆结石患病率就越高 发表杂志&…...
嵌入式人工智能应用-第三章 opencv操作 4 灰度处理
嵌入式人工智能应用 嵌入式人工智能应用-第三章 opencv操作 4 灰度处理 嵌入式人工智能应用1 灰度处理2 算法2.1 均值方法2.2 最大值法2.3 分量法2.4 加权平均法(Weighted Average Method)2.5 系统自带方法 3 总结 1 灰度处理 图像灰处理即是将一幅彩色…...
AI Agent破局:智能化与生态系统标准化的颠覆性融合!
Hi!好久不见 云边有个稻草人-个人主页 热门文章_云边有个稻草人的博客-本篇文章所属专栏~ 目录 一、引言 二、AI Agent的基本概念 2.1 定义与分类 2.2 AI Agent的工作原理 2.3 示例代码:AI Agent的基本实现 三、AI Agent在企业数字化转型中的应用 …...
UniFlash以串口方式烧录MSPM0G3507(无需仿真器)
材料:MSPM0G3507黑钢版,只要有UART的其他版本亦可(PA14需接LED) 下载软件:UniFlash 9.1.0.5175,网址:UNIFLASH 软件编程工具 | 德州仪器 TI.com.cn 测试文件:MSPM0G30…...
坐标轴刻度QCPAxisTicker
一、QCPAxisTicker 概述 QCPAxisTicker 是 QCustomPlot 中控制坐标轴刻度生成和显示的基类,负责计算刻度位置和生成刻度标签。 二、主要派生类 类名描述QCPAxisTickerFixed固定步长的刻度生成器QCPAxisTickerLog对数坐标刻度生成器QCPAxisTickerPi专门显示π倍数…...
Spring Boot 版本与对应 JDK 版本兼容性
Spring Boot 版本与对应 JDK 版本兼容性 以下是 Spring Boot 主要版本与所需 JDK 版本的对应关系,以及长期支持(LTS)信息: 最新版本对应关系 (截至2024年) Spring Boot 版本发布日期支持的 JDK 版本备注3.2.x (最新)2023-11JDK 17-21推荐使用 JDK 173…...
【MySQL】MySQL的基础语法及其语句的介绍
1、基础语法 mysql -h【主机名】 -u【用户名】 -p //登录MySQL exit或quit; //退出MySQL show database; //查看MySQL下的所有数据库 use 【数据库名】; //进入数据库 show tables; //查看数据库下的所有表名 *MySQL的启动和关闭 &am…...
《汽车理论》第四章作业MATLAB部分
1.计算并绘制利用附着系数曲线和制动效率曲线 clc close all %空载(no load)-1 ;满载(full load)-2 m14080; m29290; hg10.845; hg21.170; L3.950; a12.100; a22.950; b1L-a1; b2L-a2; beta0.38; %利用附着系数与制动强度的关系曲线 z0:0.01:1; phi_f1L*beta.*z./(b1z*hg1);%前…...