STM32单片机入门学习——第22节: [7-2] AD单通道AD多通道

news2025/4/19 0:03:39

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

本文写于:2025.04.07

STM32开发板学习——第22节: [7-2] AD单通道&AD多通道

  • 前言
  • 开发板说明
  • 引用
  • 解答和科普
  • 一、AD单通道
  • 二、AD多通道
  • 问题
  • 总结

前言

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

开发板说明

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

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

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

引用

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

解答和科普

一、AD单通道

在这里插入图片描述
PA0口,PA0到PB1这10个引脚是ADC的10个通道,所以可以任意接。
在这里插入图片描述
第一步,开启RCC时钟,包括ADC和GPIO的时钟,另外这里ADCCLK的分频器,也需要设置一下。
第二步,配置GPIO,把需要用的GPIO配置成模拟输入的模式。
第三步,配置这里的多路开关,把左边的通道接入到右边的规则组列表里,这个就是我们之前说的点菜,把各个通道的菜,列在菜单里。
第四步,配置ADC转换器了,在库函数里,是用结构体来配置的,可以配置这一大块电路的参数,包括ADC是单次转换还是连续转换,扫描还是非扫描、有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。
如果你需要模拟看门狗,那会有几个函数用来配置阈值和监测通道的,如果你想开启中断,那就在中断输出控制里用ITConfig函数开启对应的中断输出,然后再在NVIC中,配置一下优先级,这样就能触发中断了。
第五步,开关控制,调用一下ADC_Cmd函数,开启ADC。这样ADC就配置完成了。
当然在开启ADC的时候,还可以进行校准,这样可以减小误差。

在ADC工作的时候,如果想要软件触发转换,那会有函数可以触发,如果想读取转换结果,那也会有函数可以读取结果。

配置ADCCLK分频器,可以对APB2的72Mhz时钟选择2、4、6、8分频,输入到ADCCLK,这就是这个函数的作用,是在RCC库函数里面,不要忘了配置。

void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);

在这里插入图片描述

void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);

用来给ADC上电的,也就是开关控制;

void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);

开启DMA输出信号的,如果使用DMA转运数据,那就得调用这个函数;

void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);

用于控制某个中断,能不能通向NVIC;

void ADC_ResetCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
void ADC_StartCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);

控制校准

void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);

软件触发

FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);

不能判断是不是转换结束,转换开始后马上清除此位,这个函数是返回SWSTART的状态,由于在转换开始后立刻就清零了,所以这个函数的返回值和转换是否结束,毫无关系。

FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);

判断EOC标志位是否为1,判断转换是否结束;

void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);

间断模式

void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);

给序列的每个组填写指定的通道,就是填写点菜菜单的过程。
在这里插入图片描述

void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);

是否允许外部触发转换;

uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);

ADC获取转换值,就是获取AD转换的数据寄存器,读取转换结果就要使用这个函数,

uint32_t ADC_GetDualModeConversionValue(void);

ADC获取双模式转换值,这个是双ADC模式读取转换结果的函数;

void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);
void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold);
void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);

模拟看门狗配置

void ADC_TempSensorVrefintCmd(FunctionalState NewState);
FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);
void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);

时钟开启

void AD_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);		//开启ADC1的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	//开启GPIOA的时钟
}

配置ADC CLOCK

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);						//分频:72Mhz/6=12Mhz

配置GPIO

	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_InitTypeDef   GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);	

选择规则组的通道

ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);

在这里插入图片描述

现在的配置是:在规则组菜单列表的第一个位置,写入通道0这个通道,就是在序列1的位置,写入通道0,如果你还想在序列2的位置写入其他的通道,那就复制一下这个代码,把这个序列数改为2,然后指定你想要的通道,如果还行继续填充菜单,那就在复制进行配置。

ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_3,2,ADC_SampleTime_55Cycles5);

在这里插入图片描述
结构体初始化ADC

ADC_InitStructure.ADC_ExternalTrigConv=;

在这里插入图片描述
在这里插入图片描述

ADC_InitTypeDef			ADC_InitStructure;
	ADC_InitStructure.ADC_Mode=ADC_Mode_Independent ;					//独立 
	ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;				//右对齐
	ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;	//软件触发没有外部触发	
	ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;					//连续转换还是单词转换
	ADC_InitStructure.ADC_ScanConvMode=DISABLE;							//扫描模式
	ADC_InitStructure.ADC_NbrOfChannel=1;								//通道数目:总共用到几个通道
	ADC_Init(ADC1,&ADC_InitStructure);
	
	ADC_Cmd(ADC1,ENABLE);
	
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1)== SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1)== SET);

获取转换值

uint16_t  AD_GetValue(void)
{
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);							//软件触发,ADC开始转换
	while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)== RESET);				//查看是否转换完成 68个周期 5.6us
		
	return ADC_GetConversionValue(ADC1);			//读取DR寄存器,会自动清理EOC标志位,不需要手动清除了
}

在这里插入图片描述

代码
main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
#include "OLED.h"
#include  "AD.h"

uint16_t ADValue;
float  Voltage;
int main(void)
{
							
	OLED_Init();
	AD_Init();
	
	OLED_ShowString(1,2,"Hello STM32 MCU");
	OLED_ShowString(2,1,"ADValue:");
	OLED_ShowString(3,1,"Voltage:0.00V");
	while(1)
	{
		ADValue=AD_GetValue();
		Voltage=(float) ADValue/4095 *3.3 ;
		OLED_ShowNum(2,9,ADValue,4);
		OLED_ShowNum(3,9,Voltage,1);
		OLED_ShowNum(3,11,(uint16_t)(Voltage*100)%100,2);
		Delay_ms(100);
	}
}

AD.CH

#include "stm32f10x.h"                  // Device header

void AD_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);		//开启ADC1的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	//开启GPIOA的时钟
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);						//分频:72Mhz/6=12Mhz
	
	GPIO_InitTypeDef   GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);	
	
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
	

	ADC_InitTypeDef			ADC_InitStructure;
	ADC_InitStructure.ADC_Mode=ADC_Mode_Independent ;					//独立 
	ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;				//右对齐
	ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;	//软件触发没有外部触发	
	ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;					//连续转换还是单词转换
	ADC_InitStructure.ADC_ScanConvMode=DISABLE;							//扫描模式
	ADC_InitStructure.ADC_NbrOfChannel=1;								//通道数目:总共用到几个通道
	ADC_Init(ADC1,&ADC_InitStructure);
	
	ADC_Cmd(ADC1,ENABLE);
	
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1)== SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1)== SET);
}

uint16_t  AD_GetValue(void)
{
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);							//软件触发,ADC开始转换
	while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)== RESET);				//查看是否转换完成 68个周期 5.6us
		
	return ADC_GetConversionValue(ADC1);			//读取DR寄存器,会自动清理EOC标志位,不需要手动清除了
}

#ifndef    __AD_H
#define    __AD_H

void AD_Init(void);
uint16_t  AD_GetValue(void);

#endif

实验现象

AD单通道

连续模式,非扫描
在这里插入图片描述

ADC_InitTypeDef			ADC_InitStructure;
	ADC_InitStructure.ADC_Mode=ADC_Mode_Independent ;					//独立 
	ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;				//右对齐
	ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;	//软件触发没有外部触发	
	ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;					//连续转换还是单词转换
	ADC_InitStructure.ADC_ScanConvMode=DISABLE;							//扫描模式
	ADC_InitStructure.ADC_NbrOfChannel=1;								//通道数目:总共用到几个通道
	ADC_Init(ADC1,&ADC_InitStructure);
	
	ADC_Cmd(ADC1,ENABLE);
	
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1)== SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1)== SET);


	ADC_SoftwareStartConvCmd(ADC1,ENABLE);	
uint16_t  AD_GetValue(void)
{
				
	return ADC_GetConversionValue(ADC1);			
}

在这里插入图片描述

二、AD多通道

在这里插入图片描述
AO分别接在PA1、PA2、PA3口;

在扫描 模式下,你启动列表之后,它里面每一个单独的通道转换完成之后不会产生标志位,也不会触发中断,你不知道某一个通道是不是转换完成了,它只有在整个列表都转换完成后,才会产生一次EOC标志位,才能触发中断,而这时前面的数据已经被覆盖丢失了。
第二个问题是,AD转换是非常快的,几us,手动转移太高,可以使用间断模式,每转换一个通道就暂停一次,等我们手动转运之后,再继续触发,继续下一次转换;只能通过延迟足够的时间,太蛮烦;

在这里插入图片描述
只需要在每次出发转换之前,手动更改一下列表第一个位置的通道就行了,在转换前,先制定一下通道,再启动转换,就可以实现多通道了。
main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
#include "OLED.h"
#include  "AD.h"

uint16_t AD0,AD1,AD2,AD3;


int main(void)
{
							
	OLED_Init();
	AD_Init();
	
	
	OLED_ShowString(1,1,"AD0:");
	OLED_ShowString(2,1,"AD1:");
	OLED_ShowString(3,1,"AD2:");
	OLED_ShowString(4,1,"AD3:");
	while(1)
	{
		AD0=AD_GetValue( ADC_Channel_0);
		AD1=AD_GetValue( ADC_Channel_1);
		AD2=AD_GetValue( ADC_Channel_2);
		AD3=AD_GetValue( ADC_Channel_3);
		
		OLED_ShowNum(1,5,AD0,4);
		OLED_ShowNum(2,5,AD1,4);
		OLED_ShowNum(3,5,AD2,4);
		OLED_ShowNum(4,5,AD3,4);
		
		Delay_ms(100);
	}
}

AD.ch

#include "stm32f10x.h"                  // Device header

void AD_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);		//开启ADC1的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	//开启GPIOA的时钟
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);						//分频:72Mhz/6=12Mhz
	
	GPIO_InitTypeDef   GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);	
	

	

	ADC_InitTypeDef			ADC_InitStructure;
	ADC_InitStructure.ADC_Mode=ADC_Mode_Independent ;					//独立 
	ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;				//右对齐
	ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;	//软件触发没有外部触发	
	ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;					//连续转换还是单词转换
	ADC_InitStructure.ADC_ScanConvMode=DISABLE;							//扫描模式
	ADC_InitStructure.ADC_NbrOfChannel=1;								//通道数目:总共用到几个通道
	ADC_Init(ADC1,&ADC_InitStructure);
	
	ADC_Cmd(ADC1,ENABLE);
	
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1)== SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1)== SET);
}

uint16_t  AD_GetValue(uint8_t ADC_Channel)
{
	ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5);
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);							//软件触发,ADC开始转换
	while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)== RESET);				//查看是否转换完成 68个周期 5.6us
		
	return ADC_GetConversionValue(ADC1);			//读取DR寄存器,会自动清理EOC标志位,不需要手动清除了
}

#ifndef    __AD_H
#define    __AD_H

void AD_Init(void);
uint16_t  AD_GetValue(uint8_t ADC_Channel);

#endif

实验现象

AD多通道

问题

总结

本节课主要是学习了AD通道的代码配置,如何对每个部分配置:
第一步,开启RCC时钟,包括ADC和GPIO的时钟,另外这里ADCCLK的分频器,也需要设置一下。
第二步,配置GPIO,把需要用的GPIO配置成模拟输入的模式。
第三步,配置这里的多路开关,把左边的通道接入到右边的规则组列表里,这个就是我们之前说的点菜,把各个通道的菜,列在菜单里。
第四步,配置ADC转换器了,在库函数里,是用结构体来配置的,可以配置这一大块电路的参数,包括ADC是单次转换还是连续转换,扫描还是非扫描、有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。
如果你需要模拟看门狗,那会有几个函数用来配置阈值和监测通道的,如果你想开启中断,那就在中断输出控制里用ITConfig函数开启对应的中断输出,然后再在NVIC中,配置一下优先级,这样就能触发中断了。
第五步,开关控制,调用一下ADC_Cmd函数,开启ADC。这样ADC就配置完成了。
当然在开启ADC的时候,还可以进行校准,这样可以减小误差。
最后启动转换,读取转换完成后的值。
多通道是单此转换,把序列1的位置换成要读的通道,实现了AD多通道的读取。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2332609.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Survival Analysis】【机器学习】【1】

前言: 今年在做的一个博士课题项目,主要是利用病人的数据,训练出一个AI模型,做因果分析, 以及个性化治疗。自己一直是做通讯AI方向的,这个系列主要参考卡梅隆大学的教程,以及临床医生的角度 了…

JavaScript---原型和原型链

目录 一、引用类型皆为对象 二、原型和原型链是什么 三、__proto__与prototype 总结 四、原型链顶层 五、constructor 六、函数对象的原型链 一、引用类型皆为对象 原型和原型链都是来源于对象而服务于对象: JavaScript中一切引用类型都是对象,…

离散数学问题集--问题5.9

问题 5.9 综合了计算机组成原理、数字逻辑和离散数学中的关键概念,旨在帮助学生理解二进制算术运算的硬件实现、逻辑门与算术运算的关系,以及如何使用数学方法来验证数字系统的正确性。它强调了从规范到实现再到验证的完整过程。 思想 函数抽象&#xf…

Java—HTML:CSS选择器

今天我要介绍的知识点内容是Java HTML中的CSS选择器; CSS选择器用于定位HTML元素并为其添加样式。它允许我们控制网页的颜色、字体、布局和其他视觉元素。通过分离内容与样式。 下面我将介绍CSS中选择器的使用,并作举例说明; 选择器基本语…

SSM阶段性总结

0 Pojo类 前端给后端:DTO 后端给前端:VO 数据库:PO/VO 业务处理逻辑:BO 统称pojo 1 代理模式 实现静态代理: 1定义接口2实现类3写一个静态代理类4这样在调用时就可以使用这个静态代理类来实现某些功能 实现动态代…

Qt 5.14.2入门(一)写个Hello Qt!程序

目录 参考链接:一、新建项目二、直接运行三、修改代码增加窗口内容1、Qt 显示一个 QLabel 标签控件窗口2、添加按键 参考链接: Qt5教程(一):Hello World 程序 Qt 编程指南 一、新建项目 1、新建一个项目&#xff08…

Jmeter分布式测试启动

代理客户端配置 打开jmeter.properties文件,取消注释并设置端口(如server_port1099), 并添加server.rmi.ssl.disabletrue禁用SSL加密。 (Linux系统)修改jmeter-server文件中的RMI_HOST_DEF为代理机实际IP。…

redis itheima

缓存问题 核心是如何避免大量请求到达数据库 缓存穿透 既不存在于 redis,也不存在于 mysql 的key,被重复请求 public Result queryById(Long id) {String key CACHE_SHOP_KEYid;// 1. redis & mysqlString shopJson stringRedisTemplate.opsFo…

100天精通Python(爬虫篇)——第122天:基于selenium接管已启动的浏览器(反反爬策略)

文章目录 1、问题描述2、问题推测3、解决方法3.1 selenium自动启动浏览器3.2 selenium接管已启动的浏览器3.3 区别总结 4、代码实战4.1 手动方法(手动打开浏览器输入账号密码)4.2 自动方法(.bat文件启动的浏览器) 1、问题描述 使用…

MPP 架构解析:原理、核心优势与对比指南

一、引言:大数据时代的数据处理挑战 全球数据量正以指数级增长。据 Statista 统计,2010 年全球数据量仅 2ZB,2025 年预计达 175ZB。企业面临的核心挑战已从“如何存储数据”转向“如何快速分析数据”。传统架构在处理海量数据时暴露明显瓶颈…

Python设计模式-工厂模式

一、模式定义与核心思想 工厂模式(Factory Pattern)属于创建型设计模式,其核心思想是通过一个"工厂类"来创建对象,而不是直接调用类的构造函数。这种模式将对象的实例化过程封装起来,使系统在实例化对象时能…

彻底解决VS2008编译错误:fatal error C1083 无法打开包括文件“stdint.h“

彻底解决VS2008编译错误:fatal error C1083 无法打开包括文件"stdint.h" 一、错误现象与本质原因 当在Visual Studio 2008中编译包含C99标准整数类型(如int8_t、uint32_t)的代码时,常出现以下编译错误: f…

react从零开始的基础课

全文约5万字。 1.hello,.. // App.jsx import { useState } from react import reactLogo from ./assets/react.svg import viteLogo from /vite.svg import ./App.cssfunction App() {const [count, setCount] useState(0)return (<><Greeting name"world&qu…

算法题型讲解

一.双指针 主要分为俩种类型&#xff1a; 1.左右指针&#xff1a;双指针指向开头&#xff0c;以一定标准移动或交换&#xff0c;对区域进行划分&#xff0c;或找到特殊点的位置 &#xff08;如&#xff1a;快慢指针判断有无环&#xff0c;移动零&#xff09; 2.对撞指针&am…

Redis和数据库一致性问题

操作模拟 1、先更新数据库还是先更新缓存&#xff1f; 1.1先更新缓存&#xff0c;再更新数据库 按并发的角度来说&#xff0c;有两个线程A、B&#xff0c;操作同一个数据&#xff0c;线程A先更新缓存为1&#xff0c;在线程A更新数据库之前&#xff0c;这时候线程B进来&#…

第R8周:RNN实现阿尔茨海默病诊断(pytorch)

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营]中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊]** 本人往期文章可查阅&#xff1a; 深度学习总结 一、准备工作 &#x1f3e1; 我的环境&#xff1a; 语言环境&#xff1a;Python3.1…

C++基础精讲-02

文章目录 1.C/C申请、释放堆空间的方式对比1.1C语言申请、释放堆空间1.2C申请、释放堆空间1.2.1 new表达式申请数组空间 1.3回收空间时的注意事项1.4malloc/free 和 new/delete 的区别 2.引用2.1 引用的概念2.2 引用的本质2.3 引用与指针的联系与区别2.4 引用的使用场景2.4.1 引…

【网络安全】Linux 命令大全

未经许可,不得转载。 文章目录 前言正文文件管理文档编辑文件传输磁盘管理磁盘维护网络通讯系统管理系统设置备份压缩设备管理其它命令前言 在网络安全工作中,熟练掌握 Linux 系统中的常用命令对于日常运维、日志分析和安全排查等任务至关重要。 以下是常用命令的整理汇总,…

C++学习之ORACLE①

目录 1.ORACLE数据库简介 2..ORACLE数据库安装 3..ORACLE体系结构 4..ORACLE基本概念 5..ORACLE基本元素 6..ORACLE数据库启动和关闭 7.SQLPLUS登录ORACLE数据库相关操作 8.SQLPLUS的基本操作 9.oracle中上课使用的方案 10.SQL语言分类 11.SQL中的select语句语法和注…

企业级开发SpringBoost玩转Elasticsearch

案例 Spring Boot 提供了 spring-data-elasticsearch 模块&#xff0c;可以方便地集成 Elasticsearch。 下面我们将详细讲解如何在 Spring Boot 中使用 Elasticsearch 8&#xff0c;并提供示例代码。 1. 添加依赖: 首先&#xff0c;需要在 pom.xml 文件中添加 spring-data-e…