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

STM32单片机入门学习——第27节: [9-3] USART串口发送串口发送+接收

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难,但我还是想去做!

本文写于:2025.04.08

STM32开发板学习——第27节: [9-3] USART串口发送&串口发送+接收

  • 前言
  • 开发板说明
  • 引用
  • 解答和科普
  • 一、串口发送
  • 二、发送+接收
  • 问题
  • 总结

前言

   本次笔记是用来记录我的学习过程,同时把我需要的困难和思考记下来,有助于我的学习,同时也作为一种习惯,可以督促我学习,是一个激励自己的过程,让我们开始32单片机的学习之路。
   欢迎大家给我提意见,能给我的嵌入式之旅提供方向和路线,现在作为小白,我就先学习32单片机了,就跟着B站上的江协科技开始学习了.
   在这里会记录下江协科技32单片机开发板的配套视频教程所作的实验和学习笔记内容,因为我之前有一个开发板,我大概率会用我的板子模仿着来做.让我们一起加油!
   另外为了增强我的学习效果:每次笔记把我不知道或者问题在后面提出来,再下一篇开头作为解答!

开发板说明

   本人采用的是慧净的开发板,因为这个板子是我N年前就买的板子,索性就拿来用了。另外我也购买了江科大的学习套间。
   原理图如下
1、开发板原理图
在这里插入图片描述
2、STM32F103C6和51对比
在这里插入图片描述
3、STM32F103C6核心板
在这里插入图片描述

视频中的都用这个开发板来实现,如果有资源就利用起来。另外也计划实现江协科技的套件。

下图是实物图
在这里插入图片描述

引用

【STM32入门教程-2023版 细致讲解 中文字幕】
还参考了下图中的书籍:
STM32库开发实战指南:基于STM32F103(第2版)
在这里插入图片描述
数据手册
在这里插入图片描述

解答和科普

一、串口发送

在这里插入图片描述
这是USB转串口模块,这里有个跳线帽,说过这个跳线帽要接在VCC和3.3V上,因为VCC是给CH340芯片供电,选择通信的TTL电平为3.3V, 然后通信引脚TXD和RXD要接在STM32的PA9和PA10口,为什么是这两个口呢,看一下引脚定义表,计划用USART1进行通信,所以选择这两个引脚。TX和RX交叉连接,不要接错了。在接线图里,接A9(TX)接的就是串口模块的RXD(接受), 然后串口模块的TXD(发送)要接在STM32的PA10(RX接收)。然后,两个设备之间要把负极接在一起,进行共地,一般多个系统之间互联,都要进行共地,这样电平才能有高低的参考。最后这个串口和STlink都要插在电脑上,这样STM32和串口模块都要独立供电,所以这里通信的电源正极就不需要接了,直接3根线就行了。
在这里插入图片描述
初始化流程:
在这里插入图片描述
第一步,开启时钟,把需要用的USART和GPIO的时钟打开;
第二部,GPIO初始化,把TX配置成复用输出,RX配置成输入;
第三步,配置USART,直接使用一个结构体,就可以把这里所有参数都配置好了;
第四步,如果你只需要发送的功能,就直接开启USART,初始化就结束了,如果你需要接受的功能,可能还需要配置中断,那就在开启USART之前,再加上ITConfig和NVIC的代码就行了。
那初始化完成之后,如果要发送数据,调用一个发送函数就行了,如果要接受数据,就调用接受的函数,如果要获取发送和接受的状态,就调用获取标志位的函数,这就是USART外设的使用思路。

void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct);
void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct);

配置同步时钟输出的,包括时钟是不是要输出,时钟的极性相位等参数,因为参数比较多,也是用结构体配置的;

void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState);

开启USART到DMA的触发通道;

void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);

这两个函数,在我们发送和接收的时候会用到;写和读DR寄存器,DR寄存器内部有4个寄存器,控制发送与接收,执行细节上一节已经分析过了,写DR就是发送,读DR就是接收,至于怎么产生波形。怎么判断输入,软件不管;

FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

标志位相关函数

首先引脚模式:TX引脚是USART外设控制的输出脚,所以要选用复用推挽输出;
RX引脚是USART外设数据输入脚,所以要选择输入模式,输入模式并不分什么普通输入、复用输入,一根线只能有一个输出,但可以有多个输入,所以输入脚外设和GPIO都可以同时用,一般RX配置是浮空输入或者上拉输入,因为串口波形空闲状态时高电平,所以不使用下拉输入,引脚模式不清楚的话,还是可以看一下手册,GPIO那一节有个推荐的配置表,可以参考一下;目前只需要数据发送,所以只初始化TX就行了,引脚模式这里,选择AF_PP;

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);	

这样就是把PA9配置为复用推挽输出,供USART1的TX使用,那引脚就初始化好了;
配置USART

USART_InitTypeDef   USART_InitStructure;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;	//无校验位USART_InitStructure.USART_StopBits=USART_StopBits_1;	//停止位1位USART_InitStructure.USART_WordLength=USART_WordLength_8b;	//数据位8位USART_Init(USART1,&USART_InitStructure);USART_Cmd(USART1,ENABLE);			//开启

第一个参数波特率:可以直接写个9600就行,写完之后,这个Init函数内部会自动算好9600对应的分频系数,然后写入到BRR寄存器;
第二个参数是硬件流控制:我们不使用所以选择None;
第三个参数是串口模式:我们放到这里,这里可以选择TX发送模式和RX接收模式,如果你继续要发送有需要接收,那就用或符号把TX和RX或起来,
第四个参数是校验位:
第五个参数是停止位;
第六个参数哦是8位数据;

发送一个字节

void Serial_SendByte(uint8_t Byte)		//发送一个字节
{USART_SendData(USART1,Byte);while (USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);}

main.C

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
#include "OLED.h"
#include "Serial.h"int main(void)
{OLED_Init();Serial_Init();Serial_SendByte(0x66);OLED_ShowString(1,2,"Hello STM32 MCU");while(1){}
}

Serial

#include "stm32f10x.h"                  // Device headervoid 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);	USART_InitTypeDef   USART_InitStructure;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;	//无校验位USART_InitStructure.USART_StopBits=USART_StopBits_1;	//停止位1位USART_InitStructure.USART_WordLength=USART_WordLength_8b;	//数据位8位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)==RESET);}
#ifndef __SERIAL_H
#define __SERIAL_Hvoid Serial_Init(void);
void Serial_SendByte(uint8_t Byte);#endif

实验现象
在这里插入图片描述
在这里插入图片描述
HEX模式:只能显示一个个的十六进制数,不能显示文本0x41;
文本模式;以原始数据编码后的形式显示 0x41对应A;
在这里插入图片描述
UFT8
在这里插入图片描述

Serial_SendByte('A');也是发送0x41

发送数组

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]);}}

在这里插入图片描述

	Serial_SendString("Hello STM32 MCU\r\n");

这个可以执行换行:\r\n,
在这里插入图片描述

发送数字

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++){Serial_SendByte(Number/Serial_Pow(10,Length-i-1)%10+'0');}}

在这里插入图片描述
使用printf函数

在这里插入图片描述
printf函数默认输出到屏幕,我们单片机没有屏幕,所以要进行重定向:
在串口模块里加上#include <stdio.h>

int fputc(int ch,FILE *f)
{Serial_SendByte(ch);return ch;
}
printf("Num= %d\r\n",666);

那么重定向fput跟printf有什么关系呢:fputc是printf函数的底层,printf函数在打印的时候,就是不断调用fput函数一个个打印的,我们把fputc函数重定向到了串口,那printf自然就输出到串口了,这样printf就移植好了。
这种方法只能重定向一个,你定向到串口1了,那串口2再用就没有用了,如果多个串口都想用printf怎么办呢,这时候就可以用Sprintf,可以把格式化字符输出到一个字符串里,所以这里可以先定义一个字符串:

	char String[100];sprintf(String,"Num= %d\r\n",666);Serial_SendString(String);

定义字符串,打印字符串;再发送字符串。我们要是能封装这个过程,就再好不过了。
封装Sprintf;可变参数

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);}
	Serial_Printf("Num= %d\r\n",666);

在这里插入图片描述
显示汉字
1、UTF8都是(加上–no-multibyte-chars)
在这里插入图片描述
Serial_Printf(“你好,世界”);
在这里插入图片描述2、GB2312
在这里插入图片描述
然后再写汉字,选择GBK编码,复位也可以显示了。

二、发送+接收

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_InitStructure.USART_Mode=USART_Mode_Tx |USART_Mode_Rx;	

可以选择查询或者中断,如果使用查询,那初始化就结束了,如果使用中断,那还需要在这里开启中断,配置NVIC;
查询:
查询的流程是,在主函数里不断判断RXNE标志位,如果置1了,就说明收到数据了, 那再调用ReceiveData,读取DR寄存器,这样就行了。主函数演示不封装了,
在这里插入图片描述

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.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)== SET)	//收到数据{RxData=USART_ReceiveData(USART1);}OLED_ShowHexNum(1,1,RxData,2);//清除标志位}
}

中断方法
首先,初始化这里,要加上开启中断的代码:

	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef	NVIC_InitStructure;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);

这里RXNE标志位一但置1了,就会向NVIC申请中断,之后我们可以在中断函数里接收数据;
要不要清楚标志位呢,如果你读取了DR,就可以自动清除,如果没读取DR,就可以手动清除。
其实在中断里,只是进行了数据转存一下,最终还是要扫描查询这个RxFlag,来接收数据的;对于单字节接收来说,可能转存一下意义不大,主要展示一下中断接收的写法和多字节数据包接收;
在各自的函数中分别用了;

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);}}
uint8_t  Serial_GetRxFlag(void)
{if(Serial_RxFlag == 1){Serial_RxFlag=0;return  1;}return 0;	
}uint8_t  Serial_GetRxData (void)
{return Serial_RxData;
}

main.C

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
#include "OLED.h"
#include "Serial.h"uint8_t RxData;
int main(void)
{OLED_Init();Serial_Init();OLED_ShowString(1,1,"Hello STM32 MCU");OLED_ShowString(2,1,"RxData:");while(1){if(Serial_GetRxFlag()==1)	//收到数据{RxData=Serial_GetRxData();Serial_SendByte(RxData);}OLED_ShowHexNum(2,8,RxData,2);//清除标志位}
}

Serial.ch

#include "stm32f10x.h"                  // Device header
#include "stdio.h"
#include "stdarg.h"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;	//停止位1位USART_InitStructure.USART_WordLength=USART_WordLength_8b;	//数据位8位USART_Init(USART1,&USART_InitStructure);USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef	NVIC_InitStructure;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);			//开启
}void Serial_SendByte(uint8_t Byte)		//发送一个字节
{USART_SendData(USART1,Byte);while (USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);}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++){Serial_SendByte(Number/Serial_Pow(10,Length-i-1)%10+'0');}}int fputc(int ch,FILE *f)
{Serial_SendByte(ch);return ch;
}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);}uint8_t  Serial_GetRxFlag(void)
{if(Serial_RxFlag == 1){Serial_RxFlag=0;return  1;}return 0;	
}uint8_t  Serial_GetRxData (void)
{return Serial_RxData;
}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);}}

现象
在这里插入图片描述

问题

1、只是发送和接收一个字节,如何接收大量数据;

总结

本节课主要学会了如何用串口进行接收和发送,在串口模式可以|起了,发送和接收,然后本次只完成了单字节的接收和发送。

相关文章:

STM32单片机入门学习——第27节: [9-3] USART串口发送串口发送+接收

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难&#xff0c;但我还是想去做&#xff01; 本文写于&#xff1a;2025.04.08 STM32开发板学习——第27节: [9-3] USART串口发送&串口发送接收 前言开发板说…...

python 3.9 随机生成 以UTF-8 编码 的随机中文

理论实践 因为python3的默认编码为UTF-8&#xff0c;我们将‘浪’的utf8\u6d6a进行打印测试 print(\u6d6a) >>浪 中文匹配范围有两种 [\u4e00-\u9fa5]和[\u2E80-\u9FFF]&#xff0c;后者包括了日韩地区的汉字 由于utf采用16进制&#xff0c;则需要进行一个进制的变换&a…...

数字电子技术基础(四十)——使用Digital软件和Multisim软件模拟显示译码器

目录 1 使用Digital软件模拟显示译码器 1.1 原理介绍 1.2 器件选择 1.3 电路运行 1.4 结果分析 2 使用Multisim软件模拟显示译码器 2.1 器件选择 2.2 电路运行 1 使用Digital软件模拟显示译码器 1.1 原理介绍 7448常用于驱动7段显示译码器。如下所示为7448驱动BS201A…...

第十四届蓝桥杯大赛软件赛国赛C/C++研究生组

研究生C国赛软件大赛 题一&#xff1a;混乘数字题二&#xff1a;钉板上的正方形题三&#xff1a;整数变换题四&#xff1a;躲炮弹题五&#xff1a;最大区间 题一&#xff1a;混乘数字 有一点像哈希表&#xff1a; 首先定义两个数组&#xff0c;拆分ab和n 然后令n a*b 查看两个…...

innodb如何实现mvcc的

InnoDB 实现 MVCC&#xff08;多版本并发控制&#xff09;的机制主要依赖于 Undo Log&#xff08;回滚日志&#xff09;、Read View&#xff08;读视图&#xff09; 和 隐藏的事务字段。以下是具体实现步骤和原理&#xff1a; 1. 核心数据结构 InnoDB 的每一行数据&#xff08…...

多模态大语言模型arxiv论文略读(四)

A Survey on Multimodal Large Language Models ➡️ 论文标题&#xff1a;A Survey on Multimodal Large Language Models ➡️ 论文作者&#xff1a;Shukang Yin, Chaoyou Fu, Sirui Zhao, Ke Li, Xing Sun, Tong Xu, Enhong Chen ➡️ 研究机构: 中国科学技术大学、腾讯优图…...

空对象模式(Null Object Pattern)在C#中的实现详解

一 、什么是空对象模式 空对象模模是靠”空对孔象式是书丯一种引施丼文行为,行凌,凌万成,个默疤"空象象象象来飞䛿引用用用用电从延盈盈甘仙丿引用用用职从延务在仅代砷易行行 」这种燕式亲如要目的片片 也说媚平父如如 核心思烟 定义一个人 派一个 &#xfffd; 创建…...

在kotlin的安卓项目中使用dagger

在 Kotlin 的 Android 项目中使用 ​​Dagger​​&#xff08;特别是 ​​Dagger Hilt​​&#xff0c;官方推荐的简化版&#xff09;进行依赖注入&#xff08;DI&#xff09;可以大幅提升代码的可测试性和模块化程度。 1. 配置 Dagger Hilt​​ ​​1.1 添加依赖​​ 在 bu…...

(三)链式工作流构建——打造智能对话的强大引擎

上一篇&#xff1a;&#xff08;二&#xff09;输入输出处理——打造智能对话的灵魂 在前两个阶段&#xff0c;我们已经搭建了一个基础的智能对话&#xff0c;并深入探讨了输入输出处理的细节。今天&#xff0c;我们将进入智能对话的高级阶段——链式工作流构建。这一阶段的目…...

python三大库之---pandas(二)

python三大库之—pandas&#xff08;二&#xff09; 文章目录 python三大库之---pandas&#xff08;二&#xff09;六&#xff0c;函数6.1、常用的统计学函数6.2重置索引6.3 遍历6.3.1DataFrame 遍历6.3.2 itertuples()6.3.3 使用属性遍历 6.4 排序6.4.1 sort_index6.4.2 sort_…...

php7.4.3连接MSsql server方法

需要下载安装Microsoft Drivers for PHP for SQL Server驱动&#xff0c; https://download.csdn.net/download/tjsoft/90568178 实操Win2008IISphp7.4.3连接SqlServer2008数据库所有安装包资源-CSDN文库 适用于 SQL Server 的 PHP 的 Microsoft 驱动程序支持与 SQL Server …...

Flask返回文件方法详解

在 Flask 中返回文件可以通过 send_file 或 send_from_directory 方法实现。以下是详细方法和示例: 1. 使用 send_file 返回文件 这是最直接的方法,适用于返回任意路径的文件。 from flask import Flask, send_fileapp = Flask(__name__)@app.route("/download")…...

JS中的Promise对象

基本概念 Promise 是 JavaScript 中用于处理异步操作的对象。它代表一个异步操作的最终完成及其结果值。Promise 提供了一种更优雅的方式来处理异步代码&#xff0c;避免了传统的回调地狱。 Promise 有三种状态 Pending&#xff08;等待中&#xff09;&#xff1a;初始状态&…...

macOS设置定时播放眼保健操

文章目录 1. ✅方法一&#xff1a;直接基于日历2. 方法二&#xff1a;基于脚本2.1 音乐文件获取(ncm转mp3)2.2 创建播放音乐任务2.3 脚本实现定时播放 1. ✅方法一&#xff1a;直接基于日历 左侧新建一个日历&#xff0c;不然会和其他日历混淆&#xff0c;看起来会有点乱 然后…...

Python 小练习系列 | Vol.14:掌握偏函数 partial,用函数更丝滑!

&#x1f9e9; Python 小练习系列 | Vol.14&#xff1a;掌握偏函数 partial&#xff0c;用函数更丝滑&#xff01; 本节的 Python 小练习系列我们将聚焦一个 冷门但高能 的工具 —— functools.partial。它的作用类似于“函数的预设模板”&#xff0c;能帮你写出更加灵活、优雅…...

记录学习的第二十三天

老样子&#xff0c;每日一题开胃。 我一开始还想着暴力解一下试试呢&#xff0c;结果不太行&#x1f602; 接着两道动态规划。 这道题我本来是想用最长递增子序列来做的&#xff0c;不过实在是太麻烦了&#xff0c;实在做不下去了。 然后看了题解&#xff0c;发现可以倒着数。 …...

Web品质 - 重要的HTML元素

Web品质 - 重要的HTML元素 在构建一个优秀的Web页面时,HTML元素的选择和运用至关重要。这些元素不仅影响页面的结构,还直接关系到页面的可用性、可访问性和SEO表现。本文将深入探讨一些关键的HTML元素,并解释它们在提升Web品质方面的重要性。 1. <html> 根元素 HTM…...

SpringBoot整合sa-token,Redis:解决重启项目丢失登录态问题

SpringBoot整合sa-token&#xff0c;Redis&#xff1a;解决重启项目丢失登录态问题 &#x1f525;1. 痛点直击&#xff1a;为什么登录状态会消失&#xff1f;2.实现方案2.1.导入依赖2.2.新增yml配置文件 3.效果图4.结语 &#x1f600;大家好&#xff01;我是向阳&#x1f31e;&…...

Python 字典和集合(子类化UserDict)

本章内容的大纲如下&#xff1a; 常见的字典方法 如何处理查找不到的键 标准库中 dict 类型的变种set 和 frozenset 类型 散列表的工作原理 散列表带来的潜在影响&#xff08;什么样的数据类型可作为键、不可预知的 顺序&#xff0c;等等&#xff09; 子类化UserDict 就创造自…...

npm fund 命令的作用

运行别人的项目遇到这个问题&#xff1a; npm fund 命令的作用 npm fund 是 npm 提供的命令&#xff0c;用于显示项目依赖中哪些包需要资金支持。这些信息来自包的 package.json 中定义的 funding 字段&#xff0c;目的是帮助开发者了解如何支持开源维护者。 典型场景示例 假…...

ES:账号、索引、ILM

目录 笔记1&#xff1a;账号权限查看、查看账号、创建账号等查看所有用户查看特定用户验证权限修改用户权限删除用户 笔记2&#xff1a;索引状态和内容的查看等查看所有索引查看特定索引内容查看索引映射查看索引设置查看索引统计信息查看ILM策略 笔记1&#xff1a;账号权限查看…...

哈希表(开散列)的实现

目录 引入 开散列的底层实现 哈希表的定义 哈希表的扩容 哈希表的插入 哈希表查找 哈希表的删除 引入 接上一篇&#xff0c;我们使用了闭散列的方法解决了哈希冲突&#xff0c;此篇文章将会使用开散列的方式解决哈希冲突&#xff0c;后面对unordered_set和unordered_map的…...

#在docker中启动mysql之类的容器时,没有挂载的数据...在后期怎么把数据导出外部

如果要导出 Docker 容器内的 整个目录&#xff08;包含所有文件及子目录&#xff09;&#xff0c;可以使用以下几种方法&#xff1a; 方法 1&#xff1a;使用 docker cp 直接复制目录到宿主机 适用场景&#xff1a;容器正在运行或已停止&#xff08;但未删除&#xff09;。 命…...

[蓝桥杯] 挖矿(CC++双语版)

题目链接 P10904 [蓝桥杯 2024 省 C] 挖矿 - 洛谷 题目理解 我们可以将这道题中矿洞的位置理解成为一个坐标轴&#xff0c;以题目样例绘出坐标轴&#xff1a; 样例&#xff1a; 输入的5为矿洞数量&#xff0c;4为可走的步数。第二行输入是5个矿洞的坐标。输出结果为在要求步数…...

Johnson算法 流水线问题 java实现

某印刷厂有 6项加工任务J1&#xff0c;J2&#xff0c;J3&#xff0c;J4&#xff0c;J5&#xff0c;J6&#xff0c;需要在两台机器Mi和M2上完 成。 在机器Mi上各任务所需时间为5,1,8,5,3,4单位; 在机器M2上各任务所需时间为7,2,2,4,7,4单位。 即时间矩阵为&#xff1a; T1 {5, …...

远程监控系统项目里练习

1、项目目标 设备端&#xff1a; &#xff08;1&#xff09;基于stm32mp157开发板&#xff0c;裁剪linux5.10.10&#xff0c;完成ov5640摄像头移植&#xff1b; &#xff08;2&#xff09;完成用户层程序&#xff0c;完成对摄像头的控制及与云端服务的数据交互。 云端&…...

安装并配置Maven

如图所示&#xff0c;解压安装包&#xff0c;配置环境变量&#xff0c;在bin目录那个界面新建文件夹repository&#xff0c;写上安装路径的坐标&#xff0c;修改Maven仓库镜像&#xff0c;输入cmd验证是否安装成功 <mirror><id>alimaven</id><mirrorOf>…...

PlatformIO 自定义脚本选择编译库源文件 - 设置只用于C++ 的编译选项

PlatformIO 只支持以文件夹为单位选择要编译的源文件&#xff0c;不像Keil 或者CMake&#xff0c;可以手动控制每一个源文件。而且默认只会将库的src 文件夹下的源文件全部加入编译。比如&#xff0c;某个库的文件结构如下&#xff1a; libx src include mem| a.c| b.c| c.c…...

dolphinscheduler单机部署链接oracle

部署成功请给小编一个赞或者收藏激励小编 1、安装准备 JDK版本:1.8或者1.8oracle版本&#xff1a;19Coracle驱动版本&#xff1a;8 2、安装jdk 下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/#java8 下载后上传到/tmp目录下。 然后执行下面命…...

MongoDB常见面试题总结(上)

MongoDB 基础 MongoDB 是什么&#xff1f; MongoDB 是一个基于 分布式文件存储 的开源 NoSQL 数据库系统&#xff0c;由 C 编写的。MongoDB 提供了 面向文档 的存储方式&#xff0c;操作起来比较简单和容易&#xff0c;支持“无模式”的数据建模&#xff0c;可以存储比较复杂…...