23:【stm32】ADC模数转换器

ADC模数转换器

  • 1、ADC的简介
  • 2、逐次逼近型ADC
  • 3、采样时间和转换时间
  • 4、STM32中ADC模块
  • 5、编程案列
    • 5.1、AD单通道
    • 5.2、AD多通道

1、ADC的简介

ADC就是一个模数转换器,将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁。说的直观一点就是一个电压表,用于测量电压的片上外设。其中转换电压的范围0~3.3v

在这里插入图片描述
其中这些传感器在有外界的刺激的情况下,将会改变自身电阻的大小(如下图N1电阻),进而改变输出电压的大小。而电压的大小通过模拟输出口AO口输出。单片机可以通过ADC获取外部模块的电压值,进而做出一些动作。
在这里插入图片描述
那么单片机是怎样通过ADC进行对外部电压的测量并转换为数字量保存在内存中喃?

答案:比较器将ADC的结果寄存器里面的数据(DAC转换)和模拟信号进行比较,
①若ADC的结果寄存器里面的数据<模拟信号,则增加ADC的结果寄存器里面的数据。
②若ADC的结果寄存器里面的数据>模拟信号,则减小ADC的结果寄存器里面的数据。
③若ADC的结果寄存器里面的数据=模拟信号,则将数据保存到DMA中。

STM32F103C8T6有2个ADC,假如ADC的结果寄存器是2位,那么分辨率是多少喃?如下图
在这里插入图片描述
若结果寄存器是4位喃?是8位喃?

在这里插入图片描述

2、逐次逼近型ADC

我们先来了解一下ADC的工作原理,如下图所示:
在这里插入图片描述

如图:当闭合采样开关,模拟信号输入,对电容充电。当充满电后,断开采样开关,比较器通过比较来给结果寄存器增加数据/减少数据,直到和模拟信号的值相差到规定的数值以内,然后将数据保存并转换。如下图为模拟信号为2.21v。

在这里插入图片描述
则结果寄存器的数据最后为1010。

3、采样时间和转换时间

采样时间就是对电容充满电所需要的时间,而转换时间就是通过比较,确定结果寄存器里面的数值的时间。
而ADC挂载在APB2总线上,但是ADC的特性规定,ADC的时钟<14MHz。所以APB2时钟出来后还要被分频才能够给ADC通过时钟源。

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

  • 转换时间 = 12.5的时钟周期。

在这里插入图片描述

  • 采样时间 = 电容充电的时间
    电容充电的时间越长,采样的数据就越精确,误差就越小。
    在这里插入图片描述但是ADC的精度本来就是有限的,只要我们采样的误差<1/4*ADC分辨率即可。
    在这里插入图片描述电容充电的时间由电路中的电阻决定的,电阻越大,电流越小,充电时间越长,采样时间越长。
    在这里插入图片描述
    假设ADC的时钟源频率为14MH在,则
    在这里插入图片描述但是在编程中采样时间是规定了8个挡位的,所以我们只能选择和采样时间相近的那个挡位。挡位>采样时间,数据越精确。挡位<采样时间,数据变化的越快

问:最理想的情况下ADC每砂最多执行多少次转换

在这里插入图片描述
所以:理想情况下1us转换1次数据,则1s转换1000000次。

4、STM32中ADC模块

STM32F103C8T6单片机中有2个ADC模块:ADC1、ADC2,结果寄存器都为12位。也就是将3.3v的电压分为了4095份。且每个ADC片上外设都有10外部测量通道和2个内部信号源。我们可以通过外部通道测量外部模块的电压
在这里插入图片描述
这么多的通道是怎样管理的喃?
答案是:通过规则组(常规序列)和注入组(注入序列)进行管理

在这里插入图片描述

+如上图所示:规则组和注入组就像是一个盒子(用来存放需要测量的物件),ADC就像是一个工人。
① 规则组:规则组里面最多能对16个通道采集转换(盒子里面最多能放16个物件等待被测量),而存放采集转换的数据的盒子只有一个。所以只有等第一个的数据被DMA挪走后,第二个数据才能放入盒子里面
② 注入组:注入组里面最多能对4个通道采集转换,而又有4个盒子专门存放数据。
③触发控制:让ADC开始采集转换的信号(让工人开始测量),如下图所示,有定时器启动和软件启动。而软件启动就是就是给寄存器置1
在这里插入图片描述

在这里插入图片描述

规则组的转换模式:
①单次转换非扫描模式
在这里插入图片描述
在此模式下,规则组只有第一个盒子里面的通道才有效(即序列1),我们可以在序列1的盒子里面放入我们需要转换的通道,然后给规则组一个触发信号,开始采集转换,转换完成后数据保存在数据寄存器里面,同时给ECO置1。需要进行第二次转换,那么需要在启动一次触发信号,开启转换。

②连续转换非扫描模式
在这里插入图片描述
和单次转换非扫描模式不同的是,给规则组一个触发信号,在第一次转换完成后立马进入第二次转换,不断的进行下去。单片机需要获取数据,只需要读取数据寄存器里面的数据即可

③单次转换扫描模式

在这里插入图片描述
在规则组里面的多个盒子里面放入我们需要转换的通道,然后告诉ADC有多少个盒子,转换完成后依次存放在数据寄存器里面。ECO置1,需要第二次转换则需要启动触发信号。

④连续转换扫描模式
在这里插入图片描述

数据对齐:
ADC转换后的数据是12位的,而数据寄存器是16位的,所以数据寄存器有4个空出来的位置补零。一般的情况下使用右对齐即可
在这里插入图片描述

数据校准
校准都是固定的,只需要在初始化后加上校准代码即可,不用理解。
在这里插入图片描述

5、编程案列

与之相关的标准库编程接口:
在这里插入图片描述

5.1、AD单通道

ADC.c文件的代码如下;

/*ADC单通道实验,通过通道1(PA0)对自身输出电压进行采集,通过电位器改变电压变化,最终在OLED上面显示出来
*/
#include "stm32f10x.h"                  // Device headervoid AD_Init(void)
{//1.开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//2.对ADC时钟进行分频RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72MHZ/6 = 12MHz//3.对通道1(PA0)进行配置GPIO_InitTypeDef GPIOInitStruct;GPIOInitStruct.GPIO_Mode = GPIO_Mode_AIN;//模拟输入模式,ADC的专属模式GPIOInitStruct.GPIO_Pin = GPIO_Pin_0;GPIO_Init(GPIOA,&GPIOInitStruct);//4.对ADC规则组进行配置ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//ADC几,通道,序列,采样时间//5.初始化ADCADC_InitTypeDef ADC_InitStruct;ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//工作模式:独立模式/双ADC模式,这里的独立模式ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//ADC触发选择,选择软件触发ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//连续/单次模式,这里选择单次ADC_InitStruct.ADC_ScanConvMode = DISABLE;//扫描/非扫描,这里选择非扫描ADC_InitStruct.ADC_NbrOfChannel = 1;//在扫描模式下的盒子数目ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据对齐,右对齐ADC_Init(ADC1,&ADC_InitStruct);//6.开启ADC电源ADC_Cmd(ADC1,ENABLE);//7.校准ADC_ResetCalibration(ADC1);//将校准复位,给CR2_RSTCAL置1,进行复位while(ADC_GetResetCalibrationStatus(ADC1) == SET);//复位完成,硬件置0ADC_StartCalibration(ADC1);//开始校准,给CR2_CAL置1while(ADC_GetCalibrationStatus(ADC1) == SET);//校准完成,硬件置0}uint16_t AD_GetValue(void)//获取数据寄存器里面的数据
{ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//等待ECO置1,代表转换完成return ADC_GetConversionValue(ADC1);//获取ADCx->DR里面的数据,ECO自动清除
}

【注】如果使用连续非扫描模式那么ADC.c文件的代码如下:

#include "stm32f10x.h"                  // Device headervoid AD_Init(void)
{//1.开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//2.对ADC时钟进行分频RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72MHZ/6 = 12MHz//3.对通道1(PA0)进行配置GPIO_InitTypeDef GPIOInitStruct;GPIOInitStruct.GPIO_Mode = GPIO_Mode_AIN;//模拟输入模式,ADC的专属模式GPIOInitStruct.GPIO_Pin = GPIO_Pin_0;GPIO_Init(GPIOA,&GPIOInitStruct);//4.对ADC规则组进行配置ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//ADC几,通道,序列,采样时间//5.初始化ADCADC_InitTypeDef ADC_InitStruct;ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//工作模式:独立模式/双ADC模式,这里的独立模式ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//ADC触发选择,选择软件触发ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;//连续/单次模式,这里选择单次ADC_InitStruct.ADC_ScanConvMode = DISABLE;//扫描/非扫描,这里选择非扫描ADC_InitStruct.ADC_NbrOfChannel = 1;//在扫描模式下的盒子数目ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据对齐,右对齐ADC_Init(ADC1,&ADC_InitStruct);//6.开启ADC电源ADC_Cmd(ADC1,ENABLE);//7.校准ADC_ResetCalibration(ADC1);//将校准复位,给CR2_RSTCAL置1,进行复位while(ADC_GetResetCalibrationStatus(ADC1) == SET);//复位完成,硬件置0ADC_StartCalibration(ADC1);//开始校准,给CR2_CAL置1while(ADC_GetCalibrationStatus(ADC1) == SET);//校准完成,硬件置0ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//等待ECO置1,代表转换完成}uint16_t AD_GetValue(void)//获取数据寄存器里面的数据
{
//	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发
//	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//等待ECO置1,代表转换完成return ADC_GetConversionValue(ADC1);//获取ADCx->DR里面的数据,ECO自动清除
}

主程序文件的代码如下:

/*ADC单通道的简单使用
*/#include "stm32f10x.h"                 
#include "OLED.h"
#include "ADC.h"
#include "Delay.h"uint16_t Value;
float Voltage;				//定义电压变量int main(void)
{AD_Init();OLED_Init();OLED_Clear();OLED_ShowString(1,1,"Value:");OLED_ShowString(2,1,"Voltage:0.00V");while(1){Value = AD_GetValue();//获取数据Voltage = (Value * 3.3) / 4095;//转换为电压值OLED_ShowNum(1,7,Value,4);//显示数据OLED_ShowNum(2,9,Voltage,1);//显示电压值的整数部分OLED_ShowNum(2,11,(uint16_t)(Voltage*100) % 100,2);//显示电压值的小数部分Delay_ms(100);}
}

5.2、AD多通道

我们还没有学习DMA,使用如果不使用DMA对多通道转换的数据进行挪动的话,那么会出现数据的覆盖。我们通过单次转换非扫描模式模拟单次扫描模式。就是在第一次转换完成后,将第一序列的盒子里面的通道通过手动修改。
ADC.c文件的代码如下:

#include "stm32f10x.h"                  // Device headervoid AD_Init(void)
{//1.开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//2.对ADC时钟进行分频RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72MHZ/6 = 12MHz//3.对通道1(PA0)进行配置GPIO_InitTypeDef GPIOInitStruct;GPIOInitStruct.GPIO_Mode = GPIO_Mode_AIN;//模拟输入模式,ADC的专属模式GPIOInitStruct.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;GPIO_Init(GPIOA,&GPIOInitStruct);//4.对ADC规则组进行配置
//	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//ADC几,通道,序列,采样时间//5.初始化ADCADC_InitTypeDef ADC_InitStruct;ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//工作模式:独立模式/双ADC模式,这里的独立模式ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//ADC触发选择,选择软件触发ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//连续/单次模式,这里选择单次ADC_InitStruct.ADC_ScanConvMode = DISABLE;//扫描/非扫描,这里选择非扫描ADC_InitStruct.ADC_NbrOfChannel = 1;//在扫描模式下的盒子数目ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据对齐,右对齐ADC_Init(ADC1,&ADC_InitStruct);//6.开启ADC电源ADC_Cmd(ADC1,ENABLE);//7.校准ADC_ResetCalibration(ADC1);//将校准复位,给CR2_RSTCAL置1,进行复位while(ADC_GetResetCalibrationStatus(ADC1) == SET);//复位完成,硬件置0ADC_StartCalibration(ADC1);//开始校准,给CR2_CAL置1while(ADC_GetCalibrationStatus(ADC1) == SET);//校准完成,硬件置0
}uint16_t AD_GetValue(uint8_t ADC_Channel)//获取数据寄存器里面的数据,指定通道
{ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5);//ADC几,通道,序列,采样时间ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//等待ECO置1,代表转换完成return ADC_GetConversionValue(ADC1);//获取ADCx->DR里面的数据,ECO自动清除
}

主程序文件的代码如下:

/*ADC单通道的简单使用
*/#include "stm32f10x.h"                 
#include "OLED.h"
#include "ADC.h"
#include "Delay.h"uint16_t Value1,Value2,Value3,Value4;int main(void)
{AD_Init();OLED_Init();OLED_Clear();OLED_ShowString(1,1,"Value1:");OLED_ShowString(2,1,"Value2:");OLED_ShowString(3,1,"Value3:");OLED_ShowString(4,1,"Value4:");while(1){Value1 = AD_GetValue(ADC_Channel_0);//获取通道1数据,手动修改第一序列的通道Value2 = AD_GetValue(ADC_Channel_1);//获取通道2数据Value3 = AD_GetValue(ADC_Channel_2);//获取通道3数据Value4 = AD_GetValue(ADC_Channel_3);//获取通道4数据OLED_ShowNum(1,8,Value1,4);OLED_ShowNum(2,8,Value2,4);OLED_ShowNum(3,8,Value3,4);OLED_ShowNum(4,8,Value4,4);Delay_ms(100);}
}

【注】此方法不能在连续非扫描情况下模拟连续扫描模式。
因为:连续非扫描模式下,只需要一次的触发信号,如果模拟连续扫描模式,则需要手动修改通道,而修改通道后没有触发信号来进行触发。

#include "stm32f10x.h"                  // Device headervoid AD_Init(void)
{//1.开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//2.对ADC时钟进行分频RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72MHZ/6 = 12MHz//3.对通道1(PA0)进行配置GPIO_InitTypeDef GPIOInitStruct;GPIOInitStruct.GPIO_Mode = GPIO_Mode_AIN;//模拟输入模式,ADC的专属模式GPIOInitStruct.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;GPIO_Init(GPIOA,&GPIOInitStruct);//4.对ADC规则组进行配置
//	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//ADC几,通道,序列,采样时间//5.初始化ADCADC_InitTypeDef ADC_InitStruct;ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//工作模式:独立模式/双ADC模式,这里的独立模式ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//ADC触发选择,选择软件触发ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;//连续/单次模式,这里选择单次ADC_InitStruct.ADC_ScanConvMode = DISABLE;//扫描/非扫描,这里选择非扫描ADC_InitStruct.ADC_NbrOfChannel = 1;//在扫描模式下的盒子数目ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据对齐,右对齐ADC_Init(ADC1,&ADC_InitStruct);//6.开启ADC电源ADC_Cmd(ADC1,ENABLE);//7.校准ADC_ResetCalibration(ADC1);//将校准复位,给CR2_RSTCAL置1,进行复位while(ADC_GetResetCalibrationStatus(ADC1) == SET);//复位完成,硬件置0ADC_StartCalibration(ADC1);//开始校准,给CR2_CAL置1while(ADC_GetCalibrationStatus(ADC1) == SET);//校准完成,硬件置0ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//等待ECO置1,代表转换完成
}uint16_t AD_GetValue(uint8_t ADC_Channel)//获取数据寄存器里面的数据
{ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5);//ADC几,通道,序列,采样时间
//	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发
//	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//等待ECO置1,代表转换完成return ADC_GetConversionValue(ADC1);//获取ADCx->DR里面的数据,ECO自动清除
}

上面的代码为连续非扫描情况下模拟连续扫描模式的ADC.c文件的代码,需要手动修改通道的在软件触发之后,这是不允许的,因为等规则组里面的配置完整后,在给触发信号这样正确。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

春秋云镜(ZZCMS 2023)·CVE-2023-50104

漏洞参考说明&#xff1a;GitHub - zzq66/cve4 漏洞复现&#xff1a; 1、访问 URL/3/E_bak5.1/upload/index.php 2、使用默认账户密码admin/admin登录 3、上传恶意语句 修改tablename字段为eval($_POST[1]) POST /3/E_bak5.1/upload/phomebak.php HTTP/1.1 Host: eci-2zehp12…

华为云征文 | 华为云Flexus云服务器X实例之Docker环境下部署JmalCloud个人网盘

华为云征文 | 华为云Flexus云服务器X实例之Docker环境下部署JmalCloud个人网盘 前言一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 Flexus云服务器X实例特点1.3 Flexus云服务器X实例使用场景 二、JmalCloud介绍2.1 JmalCloud简介2.2 JmalCloud优点2.3 JmalCloud使…

阿里云身份证二要素详细使用

初步&#xff1a; 先登录阿里云&#xff08;找官网链接&#xff09; 2、云市场搜索身份证二要素 看个人需求选择 3、我选择的是下边这个 4、接下来看文档具体调用&#xff08;在请求示例中有选择语言的代码 我选择的就是java&#xff09; 5、在控制台看appcode码 放入代码中…

揭秘难以复现Bug的解决之道:堆栈分析实战

目录 引言 友情提示难以复现的Bug之痛 寄存器(SP、LR)详解 SP寄存器&#xff1a;堆栈的指路明灯LR寄存器&#xff1a;函数调用与异常处理的桥梁 问题分析与解决流程揭秘 保存现场分析堆栈数据 堆栈结构入栈顺序 案例 J-Link工具 常用命令保存RAM数据到本地 分析栈基本信息 分…

全国大学生数据建模比赛——深度学习

全国大学生数学建模比赛中&#xff0c;深度学习可以成为解决复杂问题的有力手段。 一、深度学习的优势在比赛中的体现 强大的模式识别能力&#xff1a;深度学习模型&#xff0c;如卷积神经网络&#xff08;CNN&#xff09;和循环神经网络&#xff08;RNN&#xff09;&#xff0…

如何在 Raspberry Pi 5 上设置 Raspberry Pi AI Kit

本指南将帮助您在 Raspberry Pi 5 上安装 Raspberry Pi AI Kit。这将使您能够使用 Hailo AI 神经网络加速器运行 rpicam-apps 摄像头演示。 如果您在开始安装人工智能套件之前需要帮助&#xff0c;本指南提供了安装过程的分步图片。 安装人工智能套件&#xff1a;https://www.…

【初出江湖】SOA 与微服务:哪个最适合您的业务?

目录标题 面向服务的体系结构 (SOA)SOA 角色那么它们是如何通信和协同工作的呢&#xff1f; SOA 的优势 微服务架构微服务的优势 SOA 和微服务之间的区别SOA 与微服务&#xff1a;常见问题采用 SOA 和微服务面临哪些挑战&#xff1f;SOA 和微服务是否可以共存&#xff1f;每种体…

wpf prism 《1》、区域 、模块化

安装prism.DryIoc 修改app.xaml <prism:PrismApplication x:Class"WpfApp3.App"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local"clr-namespace:W…

vue2的使用

准备容器引包&#xff08;官网&#xff09; — 开发版本/生产版本创建Vue实例 new Vue()指定配置项&#xff0c;渲染数据 el:指定挂载点data提供数据 可以把线上的cdn的vue的地址下载到本地进行依赖。 Vue2下载地址 https://v2.vuejs.org/v2/guide/installation.html vue.js没…

Linux虚拟机搭建K8S环境

文章目录 一、环境准备二、系统初始化三、部署master四、添加node节点五、部署网络六、部署dashboard七、登录dashboard面板 一、环境准备 首先在vmware上新建4台相同配置的虚拟机&#xff0c;除了IP和主机名外&#xff0c;其余配置相同。由于是搭建K8S初始环境&#xff0c;没…

开学寄快递,行李轻松寄,出行无压力

“春风得意马蹄疾&#xff0c;一日看尽长安花。”新的学期&#xff0c;新的征程&#xff0c;新生们在准备迎接开学时&#xff0c;不想拖着重重的行李开学的&#xff0c;那么寄快递这件事可得提上日程啦! 一、如何选择快递 如何选择一家价格实惠的快递公司成为了大家关注的焦点…

Linux bash脚本 批量创建文件

目录 一. 需求二. 前置知识一. 无进度条版本1.1 知识点1.2 代码1.3 效果 二. 有进度条版本2.1 代码2.2 效果 一. 需求 在当前目录下生成指定年份的文件&#xff0c;要求从生成1月到12月&#xff0c;每个月份的文件。 若用户不指定年份&#xff0c;则默认生成当前年的文件提示…

【C++】手动实现String类的封装(分文件编译)

实现了String类的大部分封装&#xff0c;采用分文件编译 //mystring.h #ifndef MYSTRING_H #define MYSTRING_H#include <iostream> #include <cstring> using namespace std;class myString { private:char *str; //定义一个字符串int size; //记录字符串…

[知识分享]华为铁三角工作法

在通信技术领域&#xff0c;尤其是无线通信和物联网领域&#xff0c;“华为铁三角”是华为公司内部的一种销售、交付和服务一体化的运作模式。这种模式强调的是以客户为中心&#xff0c;通过市场、销售、交付和服务三个关键环节的紧密协作&#xff0c;快速响应客户需求&#xf…

tensorrt plugin

自定义plugin 流程 首先明确要开发的算子&#xff0c;最好是 CUDA 实现&#xff1b;继承 IPluginV2DynamicExt / IPluginV2IOExt类实现一个Plugin 类&#xff0c;在这里调用前面实现的算子&#xff1b;继承 IPluginCreator 类实现一个 PluginCreator 类&#xff0c;用于创建插…

JeecgBoot积木报表AviatorScript表达式注入漏洞复现

文章目录 漏洞信息漏洞复现环境搭建poc复现DNSLog验证 漏洞信息 影响组件&#xff1a;JimuReport积木报表 影响版本&#xff1a;v1.6.0 &#xff1c; JimuReport ≤ 1.7.8 漏洞名称&#xff1a;AviatorScript表达式注入漏洞 漏洞链接&#xff1a;积木报表软件存在AviatorSc…

redis分布式是如何实现的(面试版)

需要结合项目中的业务进行回答&#xff0c;通常情况下&#xff0c;分布式锁使用的场景&#xff1a;集群情况下的定时任务、抢单、幂等性场景。 下面先来看一个抢卷场景&#xff1a; 以下情况会出现超卖情况&#xff1a; 因为线程会交替执行&#xff0c;所以线程查询优惠价的数…

在大语言模型中,生成文本的退出机制,受max_generate_tokens限制,并不是所有的问答都完整的跑完整个transformer模型

目录 在大语言模型中,生成文本的退出机制,受max_generate_tokens限制,并不是所有的问答都完整的跑完整个transformer模型 1. max_generate_tokens的作用 2. 退出机制与Transformer模型 3. 实际应用中的影响 4. 结论 在大语言模型中,生成文本的退出机制,受max_genera…

php法律事务综合管理系统Java律师事务所业务流程管理平台python法律服务与案件管理系统(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…

【解决方案】项目重构之如何使用 MySQL 替换原来的 MongoDB

前言 在笔者 Java 后端开发的项目经历中&#xff0c;MySQL 和 MongoDB 都有使用过作为后端的数据库来对业务数据进行持久化&#xff0c;两者没有孰优孰劣之分&#xff0c;都可以在合适的场景下发挥出它们的优势。 今天要分享的是一个项目重构过程中如何将数据库选型由原来的 Mo…