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

【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串口通信

主要参考学习资料&#xff1a; B站江协科技 STM32入门教程-2023版 细致讲解 中文字幕 开发资料下载链接&#xff1a;https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 单片机套装&#xff1a;STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协 实验&…...

goc命令大全

颜色0黑1红2蓝3浅绿4浅蓝5淡黄6棕7深蓝8灰9粉10深绿11紫12蓝绿13黄14橙15白 绘图命令功能pen笔.fd()前进.rt()右转.c()颜色.up()抬笔.o(,)圆.e(,)椭圆.r(,,)长方形.picL(,)调图片.text(,,)文字.hide()隐藏.moveTo(,)移动wait();等待.soundL()调声音pause();暂停 绘图命令功能…...

Linux | 软件仓库管理

一. 软件包 1.1 软件包的分类 DEB&#xff1a;主要用于基于 Debian 的系统&#xff0c;如 Ubuntu。这种软件包格式具有良好的依赖管理机制&#xff0c;方便用户安装、升级和卸载软件。RPM&#xff1a;广泛应用于 Red Hat、CentOS、Fedora 等系统。RPM 包将软件打包成一个文件…...

Python实现对目标Word文档进行自动化排版【4万字精讲】(14)

前言 本文是该专栏的第14篇,后面会持续分享Python办公自动化干货知识,记得关注。 注意:本文涵盖4万字以及实战操作代码的精讲攻略,带你轻松掌握一键式“文档自动化排版”程序功能。 如果说当你在工作项目中,遇到这样的需求,需要如何处理——假设,现在有大批量的docx格…...

LeetCode每日一题4.19

2563. 统计公平数对的数目 题目 问题分析 输入&#xff1a;一个整数数组 nums 和两个整数 lower 和 upper。 输出&#xff1a;返回满足条件的公平数对的数目&#xff0c;即对于所有 0 < i < j < n&#xff0c;lower < nums[i] nums[j] < upper 的数对 (i, j)…...

Spring AI 开发 - 快速入门

先看效果 项目搭建 Spring AI 是 Spring 推出的一个项目&#xff0c;目标是提供统一的API抽象层&#xff0c;屏蔽不同AI模型和服务的底层差异&#xff0c;实现跨平台兼容性。 演示使用的模型是阿里的 qwq-32b。 环境要求&#xff1a; JDK &#xff1a;17以上&#xff08;包括…...

leetcode哈希表(六)-三数相加

题目 15. 三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复…...

Photoshop安装与配置--简单攻略版

下载地址:Photoshop软件工具下载 安装完成后&#xff0c;即可运行Photoshop.exe&#xff1b;打开工具页面后&#xff0c;按照下面简单配置即可 1.编辑-》首选项-》常规 或者直接快捷键CtrlK 暂存盘&#xff1a;一定要设置为非C盘 2.性能 3.文件处理 以上配置比较基础&#xf…...

一个 CTO 的深度思考

今天和一些同事聊了一会&#xff0c;以下是我的观点 我的观点&#xff0c;成年人只能筛选&#xff0c;不能培养在组织中&#xff0c;应该永远向有结果的人看齐。不能当他站出来讲话的时候&#xff0c;大家还要讨论讨论&#xff0c;他虽然拿到结果了&#xff0c;但是他就是有一…...

Java:使用Maven构建项目无src解决方案

创建箭头所指的包和类以及yml文件&#xff1a; 类中&#xff1a; package com.itheima;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;SpringBootApplication public class BigEventApplication …...

Git 命令速查手册

听说用美图可以钓读者&#xff1f; 一、基础操作核心命令 1. 仓库初始化与克隆 命令作用示例git init创建新仓库git init my-projectgit clone克隆远程仓库git clone [https://github.com/user/repo.git](https://github.com/user/repo.git)git remote add关联远程仓库git re…...

office软件中word里面的编号库和列表库功能

在Microsoft Word中,编号库和列表库是两大核心排版工具,分别服务于不同层级的文档结构化需求。以下从功能定义、核心差异、应用场景及操作技巧等维度进行详细解析: 一、编号库(Numbering Library) 1. 定义与功能 编号库是Word中预设或用户自定义的有序列表格式集合,用于…...

C++入门七式——模板初阶

目录 函数模板 函数模板概念 函数模板格式 函数模板的原理 函数模板的实例化 模板参数的匹配原则 类模板 类模板的定义格式 类模板的显式实例化 当面对下面的代码时&#xff0c;大家会不会有一种无力的感觉&#xff1f;明明这些代码差不多&#xff0c;只是因为类型不…...

Python+Selenium+Pytest+POM自动化测试框架封装(完整版)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、测试框架简介 1&#xff09;测试框架的优点 代码复用率高&#xff0c;如果不使用框架的话&#xff0c;代码会显得很冗余。可以组装日志、报告、邮件等一…...

matlab 处理海洋数据并画图的工具包--ocean_data_tools

matlab 处理海洋数据并画图的工具包–ocean_data_tools matlab 处理海洋数据并画图的工具包–ocean_data_tools ocean_data_tools 简化了提取、格式化和可视化免费可用的海洋学数据的过程。虽然可以在线访问大量海洋学数据&#xff0c;但由于获取这些数据并将其格式化为可用数据…...

软件开发指南——GUI 开发方案推荐

1. LVGL (Light and Versatile Graphics Library) 适用场景&#xff1a;嵌入式设备、资源受限环境 优势&#xff1a; 专为嵌入式设计的开源 GUI 库&#xff0c;内存占用极小&#xff08;最低仅需 64KB RAM&#xff09;支持触摸屏、硬件加速&#xff08;如 STM32 的 LTDC&…...

JDK8 HashMap的实现原理

一 HashMap底层存储结构 HashMap底层结构采用&#xff08;数组&#xff09;&#xff08;链表 or 红黑树&#xff09;的形式来存储节点。 首先HashMap是一个数组&#xff0c;而且数组里面每个位置可以放入多个元素&#xff0c;形象一点&#xff0c;咱们把数组的这些个位置称为桶…...

YOLO拓展-锚框(anchor box)详解

一.锚框&#xff08;anchor box&#xff09;概述 1.1什么是锚框 锚框就是一种进行预测的像素框&#xff0c;通过遍历输入图像上所有可能的像素框&#xff0c;然后选出正确的目标框&#xff0c;并对位置和大小进行调整就可以完成目标检测任务。 对于yolo锚框的建设须基于实际…...

U-Boot(Universal Bootloader)简介

U-Boot 是一种开源的、高度可定制的 引导加载程序&#xff08;Bootloader&#xff09;&#xff0c;专为嵌入式系统和特定硬件平台设计。它负责在设备上电后初始化硬件、加载操作系统内核&#xff0c;并将控制权移交给操作系统&#xff0c;是嵌入式设备启动过程中不可或缺的核心…...

turtle库绘制进阶图形

要求&#xff1a; 1.绘制嵌套彩色五角星&#xff08;大小逐层递减&#xff09; 2. 设计函数绘制自定义正多边形&#xff08;边数与颜色参数化&#xff09; 3. 扩展&#xff1a;实现动态旋转花瓣图案 代码&#xff1a; import turtledef draw_nested_star():colors ["…...

[matlab]南海地形眩晕图代码

[matlab]南海地形眩晕图代码 请ChatGPT帮写个南海地形眩晕图代码 图片 图片 代码 .rtcContent { padding: 30px; } .lineNode {font-size: 12pt; font-family: "Times New Roman", Menlo, Monaco, Consolas, "Courier New", monospace; font-style: n…...

3. 进程概念

目录 1. 冯诺依曼体系结构 2. 操作系统 3. 理解进程的一般思路 4. 查看进程 5. fork初识 6. 进程状态 6.1 一般操作系统 6.2 Linux系统是怎么维护进程状态的 7. 进程优先级 先谈硬件-再谈软件-最后谈进程。 1. 冯诺依曼体系结构 我们常见的计算机&#xff08;笔记本电…...

yolov8的数据处理lableimg的安装以及使用

视频数据集准备 video cv2.VideoCapture("./BVN.mp4") num 0 # 计数器 save_step 30 # 间隔帧 while True:rel, frame video.read()if not ret:breaknum 1if num % save_step 0:cv2.imwrite("./demo images/" str(num) ".jpg", frame)l…...

小刚说C语言刷题——1035 判断成绩等级

1.题目描述 输入某学生成绩&#xff0c;如果 86分以上(包括 86分&#xff09;则输出 VERY GOOD &#xff0c;如果在 60到 85之间的则输出 GOOD (包括 60和 85)&#xff0c;小于 60 的则输出 BAD。 输入 输入只有一行&#xff0c;包括 1个整数。 输出 输出只有一行&#xf…...

Spring 依赖冲突解决方案详解

引言 在Spring框架中&#xff0c;依赖管理是一个核心功能&#xff0c;它使得开发者能够轻松地管理应用程序中的各种组件和服务。然而&#xff0c;随着项目的增长和复杂度的增加&#xff0c;依赖冲突问题也变得日益常见。本文将详细介绍Spring中不同类型的依赖冲突及其解决方法…...

P11299 [NOISG 2021 Finals] Fraud 题解

题目背景 你被任命为第 24 届全国信息学奥林匹克竞赛的负责人&#xff01; 题目描述 本次竞赛共有 N 名参赛者和 2 轮比赛。第 i 名参赛者在第一轮获得了分&#xff0c;在第二轮获得了 分。 每轮比赛分别有一个正整数权重 X 和 Y。第 i 名参赛者的最终得分​ 计算公式为&a…...

AI时代下 你需要和想要了解的英文缩写含义

在AI智能时代下&#xff0c;越来愈多的企业都开始重视并应用以及开发AI相关产品&#xff0c;这个时候都会或多或少的涉及到英文&#xff0c;英文还好&#xff0c;但是如果是缩写&#xff0c;如果我们没有提前了解过&#xff0c;我们往往很难以快速Get到对方的意思。在这里&…...

大数据平台简介

一、分布式系统基础架构 &#xff08;一&#xff09;定义与核心特征 分布式系统是由多台计算机&#xff08;节点&#xff09;通过网络协作组成的系统&#xff0c;对外表现为一个统一整体。其核心特征包括&#xff1a; 去中心化&#xff1a;节点平等或分角色协作&#xff08;如…...

电脑端移植至手机平板:攻克难题,仙盟架构显神通——仙盟创梦IDE

在将电脑端应用移植到手机和平板的过程中&#xff0c;常面临诸多棘手问题。像 1.x 号关闭按钮因位置设计欠佳&#xff0c;难以被用户精准点击&#xff0c;字体过小导致阅读与操作不便等。未来之窗仙盟创梦凭借创新的仙盟架构&#xff0c;巧妙且高效地化解了这些困扰开发者与用户…...

基于Python的中国象棋小游戏的设计与实现

基于Python的中国象棋小游戏的设计与实现 第一章 绪论1.1 研究背景1.2 研究意义 第二章 需求分析2.1 需求分析2.1.1核心功能需求2.1.2 用户体验需求2.1.3 衍生功能需求 2.2 可行性分析2.2.1 技术可行性2.2.2 经济可行性2.2.3 市场可行性2.2.4 法律与合规性 第三章 概要设计3.1 …...

HCIP --- OSPF综合实验

一、拓扑图 二、实验要求 1&#xff0c;R5为ISP&#xff0c;其上只能配置IP地址;R4作为企业边界路由器&#xff0c;出口公网地址需要通过PPP协议获取&#xff0c;并进行chap认证。 2&#xff0c;整个0SPF环境IP基于172.16.0.8/16划分。 3&#xff0c;所有设备均可访问R5的环…...

【OpenGL】OpenGL学习笔记-1:VS2019配置OpenGL开发环境

在Visual Studio 2019中可以通过手动配置库文件或NuGet包管理器快速安装的方法配置OpenGL环境&#xff0c;详细步骤如下&#xff1a; 一、打开VS2019&#xff0c;创建新的控制台项目 二、方法一&#xff1a;手动配置GLEW/GLFW/GLAD库 GLFW是窗口管理和输入事件的基础设施&…...

GWAS_LD

局部LDblock 绘图 1. 查看显著位点附近基因情况 链接pvalue显著位点文件 ln -s ~/yiyaoran/GWAS/my_GWAS_J/P3.GWAS/01.tassel/mlm_output.manht_figure.sigSite.out . #也可以自己筛选awk $2 9 && $4 < 0.000028481 mlm_output.manht_input>368_GWAS.snpsnp两…...

WinForms开发基础:实现带X按钮的ClearableTextBox控件

前言 我们经常看到这样的带X按钮的输入框 如果使用WinForms开发中&#xff0c;该如何进行设计&#xff0c;普通的TextBox控件如何进行改造&#xff1f;为了提升用户体验&#xff0c;在TextBox文本框内添加一个“x”按钮&#xff0c;方便用户一键清除内容。本文将介绍如何通过继…...

直线轴承常规分类知多少?

直线轴承的分类方式多样&#xff0c;以下是从材质、结构形状和常规系列三个维度进行的具体分类&#xff1a; 按主要材质分类 外壳材质&#xff1a;常见的有不锈钢&#xff0c;具有良好的耐腐蚀性&#xff0c;适用于一些对环境要求较高、易受腐蚀的工作场景&#xff1b;轴承…...

算法期末复习

算法期末复习 1.单选题 \1. 二分搜索算法是利用( A)实现的算法。 A. 分治策略 B. 动态规划法 C. 贪心法 D. 回溯法 \2. 回溯法解旅行售货员问题时的解空间树时( C ) 。 A. 子集树 B. 深度优先生成树 C. 排序树 D. 广度优先生成树 \3. 下列算法中通常以自底向上的方式求解最…...

LeetCode 5:最长回文子串

1、题目描述 给你一个字符串 s&#xff0c;找到 s 中最长的 回文 子串。 示例 1: 输入&#xff1a;s "babad" 输出&#xff1a;"bab" 解释&#xff1a;"aba" 同样是符合题意的答案。 示例 2: 输入&#xff1a;s "cbbd" 输出&#…...

2025年4月19日 记录大模型出现的计算问题

2025年4月19日 记录大模型出现的计算问题&#xff0c;用了四个大模型计算json的数值&#xff0c;3个错误&#xff0c;1个正确 问题 Class Train Val answer 2574 853 screen 5025 1959 blackBoard 7847 3445 teacher 8490 3228 stand…...

Python语法系列博客 · 第3期 数据结构入门(列表、元组、字典、集合)

上一期小练习解答&#xff08;第2期回顾&#xff09; ✅ 练习1&#xff1a;判断一个数是正数、负数还是零 num float(input("请输入一个数&#xff1a;")) if num > 0:print("正数") elif num < 0:print("负数") else:print("零&q…...

【对Linux文件权限的深入理解】

Linux文件权限 Linux下权限概念概念相关命令 Linux的文件权限管理1.文件访问者的分类&#xff08;⼈&#xff09;文件类型和访问权限&#xff08;事物属性&#xff09;文件权限值的表示方法⽂件访问权限的相关设置方法目录的权限&#xff08;比较重要&#xff09;粘滞位 Linux下…...

2025.04.19【Spider】| 蜘蛛图绘制技巧精解

Basic multi-group radar chart Start with a basic version, learn how to format your input dataset Radar chart with ggradar A Spider chart made using the ggradar package and a lot of customization.A work by Tuo Wang 文章目录 Basic multi-group radar chartRa…...

AtCoder ABC402 A~D 题解

A - CBC 题目大意 给点字符串 S S S&#xff0c;输出其中所有大写字母。 思路 根据题意模拟即可。 代码 #include <cstdio> #include <iostream> #include <algorithm> using namespace std;int main() {string s;cin >> s;for (int i 0; i &l…...

双指针算法(部分例题解析)

快慢指针左右指针 前言 双指针&#xff0c;它通过设置两个指针来遍历数据&#xff0c;从而实现高效的查找、排序、去重等操作。双指针算法的核心在于通过合理地移动这两个指针&#xff0c;减少不必要的遍历&#xff0c;提高算法的效率。 283. 移动零 - 力扣&#xff08;LeetCo…...

PHP怎样判断浏览器类型和浏览器语言?

获取浏览器类型 $_SERVER[HTTP_USER_AGENT]包含了用户代理字符串&#xff0c;该字符串包含了浏览器、操作系统等信息。通过分析这个字符串&#xff0c;可以大致判断用户使用的浏览器类型。 <?phpfunction getBrowserType() {$userAgent $_SERVER[HTTP_USER_AGENT];$brow…...

利用 i2c 快速从 Interface 生成 Class

利用 i2c 快速从 Interface 生成 Class&#xff08;支持 TS & ArkTS&#xff09; 在日常 TypeScript 或 ArkTS 开发中&#xff0c;需要根据 interface 定义手动实现对应的 class&#xff0c;这既重复又容易出错。分享一个命令行工具 —— interface2class&#xff0c;简称…...

Vue+Notification 自定义消息通知组件 支持数据分页 实时更新

效果图&#xff1a; message.vue 消息组件 子组件 <template><div class"custom-notification"><div class"content"><span click"gotoMessageList(currentMessage.split()[1])">{{ currentMessage.split()[0] }}</…...

机械设计【】技术要求(实际使用)

目录 台板技术要求加工件技术要求钣金件技术要求工装型腔技术要求铝型材框架技术要求装配体技术要求焊接件技术要求1(外形尺寸≥1500mm)焊接件技术要求2(外形尺寸<1500mm)焊接件技术要求3(不锈钢)其他要求台板技术要求 1.台板下表面周边不倒角,其余未注倒角C0.5; 2.去…...

遨游科普:防爆平板是指什么?有哪些应用场景?

在石油开采平台的炽热甲板、化工园区的反应釜旁、矿井巷道的瓦斯弥漫区&#xff0c;总能看到一群手持特殊设备的作业人员。他们手中的平板并非寻常消费电子产品&#xff0c;而是专门应对极端环境的防爆平板。防爆平板承载着工业安全的核心诉求&#xff0c;其技术演进与应用拓展…...

【GCC】gcc编译学习

文章目录 1. 过程2. 常用命令选项3. 多个源文件编译参考内容 1. 过程 step1 : 预处理&#xff0c;生成.i文件&#xff08;预处理器cpp&#xff09; gcc -E [源文件] -o [生成的.i文件] gcc -E test.c -o test.istep2 : 汇编&#xff0c;将预处理后的文件转换为汇编语言生成.s…...

不确定与非单调推理的可信度方法

可信度方法是肖特里菲(E.H.Shortliffe)等人在确定性理论(Theoryof Comfirmation)的基础上,结合概率论等提出的一种不确定性推理方法,首先在专家系统MYCIN中得到了成功的应用。由于该方法比较直观、简单,而且效果也比较好,因而受到人们的重视。目前,许多专家系统都是基于…...