【STM32】ADC模数转换器
1 ADC简介
ADC(Analog-Digital Converter)模拟-数字转换器
ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁
STM32是数字电路,只有高低电平,没有几V电压的概念,想读取电压值,就需要借助ADC模数转换器了。DAC则是相反的功能。
12位逐次逼近型ADC,1us转换时间
分辨率:一般用多少位来表示,0 ~ 2 ^ 12 - 1(量化结果0~4095)
转换时间:也是转换频率,从转换开始到产生结果需要花1us时间,即转换频率是1MHz
输入电压范围:0~3.3V,转换结果范围:0~4095
线性对应
18个输入通道,可测量16个外部和2个内部信号源
16个GPIO口、内部温度传感器(测量CPU的温度)和内部参考电压(1.2V的基准电压)
规则组和注入组两个转换单元
模拟看门狗自动监测输入电压范围
STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道
1.1 逐次逼近型ADC
ADC0809的内部结构图,独立的8位逐次逼近型ADC芯片。
左边是8路输入通道,通过通道选择开关,选中一路,输入到比较器前进行转换;下面是地址锁存和译码(想选中哪个通道,就把通道号放在这三个引脚上,再给一个锁存信号,上面对应的通路开关就可以自动拨好了,相当于38译码器)
比较器有两个输入端,一个是待测电压,另一个是DAC(数模转换器)的电压输出端;如果DAC输出的电压比较大,就调小DAC数据;如果DAC输出的电压比较小,就增大DAC数据;直到DAC输出的电压和外部通道输入的电压近似相等,这样DAC输入的数据就是外部电压的编码数据了,这就是DAC的实现原理。一般使用二分法调节。
1.2 ADC框图
具体的
有温度传感器、内部参考电压,总共18个输入通道,接到模拟多路开关,其输出接到模数转换器,即逐次比较,转换结果放在数据寄存器里。
普通的的流程是:多路开关选中某一个通道,开始转换,等待转换完成,取出结果。
这里比较高级,可以同时选中多个,而且在转换的时候,还分成了两个组,规则通道组和注入通道组,其中规则组可以一次性最多选择16个通道,注入组一次最多选择4个通道。规则组的数据寄存器只能存储一个结果,如果不想之前的结果被覆盖,那在转换完成之后,要尽快把结果拿走(使用DMA转运数据);注入组可以存4个结果,不用担心数据覆盖。
左下角是触发转换部分,对于STM32的ADC,触发ADC开始转换的信号有两种:一种是软件触发,程序中调用一条代码;另一种是硬件触发,就是这些触发源。上面是注入组触发源,下面是规则组触发源。这些触发源主要来自定时器,有定时器的各个通道,还有TRGO定时器主模式的输出。定时器可以通向ADC、DAC这些外设,用于触发转换。因为ADC经常需要过一个固定的时间段转换一次,正常的思路是:用定时器,每隔1ms申请一次中断,在中断里手动开始一次转换;但是频繁进中断对程序是有影响的,所以对这种需要频繁进中断,并且在中断里只完成简单的工作的情况,一般都会有硬件的支持。还可以选择外部中断引脚来触发转换。
VREF+、VREF-是ADC的参考电压,决定了ADC的输入电压范围,VDDA、VSSA是ADC的供电引脚,一般情况下VREF+接VDDA,VREF-接VSSA。
右边这里是ADCCLK是ADC的时钟,是用于驱动内部逐次比较的时钟,这个时钟来自ADC的预分频器,而ADC预分频器来自RCC的。
模拟看门狗里面可以存储阈值高限和阈值底限,如果指定了模拟看门狗,并且指定了看门的通道,越限之后,它就会乱叫,在上面申请一个模拟看门狗中断,最后通向NVIC。
对于规则组和注入组,转换完成之后,也会有一个EOC转换完成的信号,EOC是规则组的完成信号,JEOC是注入组完成的信号,这两个信号会在状态寄存器里置一个标志位,读取这个标志位就可以知道是不是转换完成了;同时这两个标志位也可以去到NVIC,申请中断,如果开启了NVIC对应的通道,它们就会触发中断。
1.3 ADC基本结构
左边是输入通道,16个GPIO口外加两个内部通道,然后进入AD转换器。AD转换器里有两个组,一个是规则组,一个是注入组,规则组最多选择16个通道,注入组最多选择4个通道,然后转换的结果存在AD数据寄存器里,其中规则组只有一个数据寄存器,而注入组有4个数据寄存器。下面有触发控制,触发控制可以选择软件触发和硬件触发,硬件触发主要是来自定时器,当然也可以选择外部中断的引脚;右边是来自RCC的ADC时钟CLOCK,ADC逐次比较的功能就是这个时钟推动的。然后上面可以布置一个模拟看门狗用于检测转换结果的范围,如果超出设定的阈值,就通过中断输出控制,向NVIC申请中断。另外规则组和注入组完成之后会有个EOC信号,它会置一个标志位,当然也可以通向NVIC。右下角有个开关控制,在库函数中就是ADC_Cmd,用于给ADC上电的。
1.4 输入通道
通道 | ADC1 | ADC2 | ADC3 |
通道0 | PA0 | PA0 | PA0 |
通道1 | PA1 | PA1 | PA1 |
通道2 | PA2 | PA2 | PA2 |
通道3 | PA3 | PA3 | PA3 |
通道4 | PA4 | PA4 | PF6 |
通道5 | PA5 | PA5 | PF7 |
通道6 | PA6 | PA6 | PF8 |
通道7 | PA7 | PA7 | PF9 |
通道8 | PB0 | PB0 | PF10 |
通道9 | PB1 | PB1 | |
通道10 | PC0 | PC0 | PC0 |
通道11 | PC1 | PC1 | PC1 |
通道12 | PC2 | PC2 | PC2 |
通道13 | PC3 | PC3 | PC3 |
通道14 | PC4 | PC4 | |
通道15 | PC5 | PC5 | |
通道16 | 温度传感器 | ||
通道17 | 内部参考电压 |
ADC通道和引脚复用的关系。
ADC12_IN0的意思是ADC1和ADC2的IN0都是在PA0上的。以此类推。双ADC模式。
1.5 规则组的转换模式
在ADC初始化中会有两个参数,一个是选择单次转换还是连续转换;另一个是扫描模式还是非扫描
1.5.1 单次转换,非扫描模式
这个列表就是规则组里面的菜单,有16个空位。可以在这里写入要转换的通道,比如通道2,在非扫描的模式下,这个菜单就只有第一个序列1的位置有效。这时菜单同时选中一组的方式就退化成简单地选中一个的方式了,在这里可以在序列1的位置指定想转换的通道,比如通道2,然后触发转换,ADC就会对通道2进行模数转换,过一小段时间后,转换完成,转换结果放在数据寄存器里,同时给EOC标志位置1,整个转换过程就结束了。判断EOC标志位来确定转换是否完成。如果想再启动一次转换,那就需要再触发一次,转换结束,置EOC标志位,读结果。如果想换一个通道转换,那就在转换之前把第一个位置的通道2改成其他通道,再启动转换就可以了。这就是单次转换、非扫描的转换模式。
1.5.2 连续转换,非扫描模式
首先还是非扫描模式。所以菜单列表就只用第一个,然后与上一个单次转换不同的是它在一次转换结束后不会停止,而是立刻开始下一轮的转换,然后一直持续下去。只触发一次就可以转换了。
好处是:开始转换之后不需要等待一段时间,因为一直在转换,所以也不需要手动开始转换,也不用判断是否结束,想要读AD值的时候,直接从寄存器取就是了。
1.5.3 单次转换,扫描模式
单次转换,每触发一次,转换结束后,就会停下来。扫描模式会用到菜单列表,选择通道,可以任意指定,可以重复,初始化结构体中有个参数指定通道数目。这里为了防止数据被覆盖,就需要用DMA及时将数据挪走,7个通道转换完成之后,产生EOC信号,转换结束。再触发下一次,开始新的转换。
1.5.4 连续转换,扫描模式
在上一个模式的基础上变了,就是一次转换完成后,立刻开始下一次转换。
还有间断模式,每隔几个转换,暂停一次需要再次触发才能继续。
1.6 触发控制
这个表是规则组的触发源,有来自定时器的信号,也有来自外部引脚/片上外设的信号,具体需要AFIO重映射。还有软件触发。这些触发信号通过右边寄存器的位来完成。
1.7 数据对齐
ADC是12位的,但是数据寄存器是16位的,因此存在一个数据对齐的问题
数据右对齐(一般是这个)
数据左对齐
有点像大端模式,小端模式
1.8 转换时间
AD转换的步骤:采样,保持,量化,编码
STM32 ADC的总转换时间为:TCONV = 采样时间 + 12.5个ADC周期(12位)
例如:当ADCCLK=14MHz,采样时间为1.5个ADC周期
TCONV = 1.5 + 12.5 = 14个ADC周期 = 1μs
1.9 校准
ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差
建议在每次上电后执行一次校准
启动校准前, ADC必须处于关电状态超过至少两个ADC时钟周期
1.10 硬件电路
第一个是电位器产生一个可调的电压,这里电位器的两个固定端,一个接3.3,一个接GND,这样中间的滑动端就可以输出一个0~3.3的可调电压输出了。这里可以接ADC的输入通道,比如PA0口;滑动端往上滑时,电压增大,往下滑时,电压减小。阻值不宜太小。
第二个是传感器输出电压的电路,一般是光敏电阻、热敏电阻、红外接收管、麦克风等。串联分压,当传感器阻值变小时,下拉作用变强,输出端电压就下降;反之,输出端电压增大。
第三个是电压转换电路,比如想测0~5V的VIN电压,但是ADC只能接收0~3.3V的电压,分压。
手册
2 AD单通道
2.1 接线图
2.2 模块封装
按这个初始化
相关库函数
// 在rcc.h中
// 配置ADCCLK分频器,2/4/6/8分频
void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);void ADC_DeInit(ADC_TypeDef* ADCx); // 恢复缺省设置
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct); // 初始化
void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct); // 结构体初始化
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState); // 给ADC上电的// 中断输出控制,用于某个中断,能不能通往NVIC
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);// 复位校准/获取复位状态/开始校准/获取开始校准状态
void ADC_ResetCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
void ADC_StartCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);// ADC软件开始转换控制,软件触发
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);// 配置间断模式
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number); // 每隔几个通道间断一次
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); // 是否启用间断模式// ADC规则组通道配置
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);// ADC外部触发转换控制
void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);// ADC获取转换值
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);// ADC获取双模式转换值
uint32_t ADC_GetDualModeConversionValue(void);// 获取标志位状态/清除标志位状态/获取中断状态/清除中断挂起位
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);// 带Injected是注入组的函数
版本1:单次转换非扫描
AD.c
#include "stm32f10x.h" // Device header// AD初始化函数
void AD_Init(void)
{// 1开启RCC时钟,ADC、GPIORCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 72M / 6 = 12M// 2配置GPIO模拟输入模式GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_Init(GPIOA, &GPIO_InitStructure);// 3配置多路开关,选择规则组的输入通道,指定通道/规则组序列器的次序/通道采样时间ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);// 4配置ADC转换器ADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 右对齐ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 外部触发选择,不使用外部触发ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 工作模式(独立/双ADC)ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 单次/连续转换ADC_InitStructure.ADC_NbrOfChannel = 1; // 通道数目ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 扫描/非扫描转换// 单次转换非扫描模式// 单次转换/连续转换 扫描/非扫描ADC_Init(ADC1, &ADC_InitStructure);// 5开关控制ADC_Cmd(ADC1, ENABLE);// 6校准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); // 软件触发转换while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); // 等待转换完成return ADC_GetConversionValue(ADC1); // 返回转换值
}
版本2:连续转换非扫描
#include "stm32f10x.h" // Device header// AD初始化函数
void AD_Init(void)
{// 1开启RCC时钟,ADC、GPIORCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 72M / 6 = 12M// 2配置GPIO模拟输入模式GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_Init(GPIOA, &GPIO_InitStructure);// 3配置多路开关,选择规则组的输入通道,指定通道/规则组序列器的次序/通道采样时间ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);// 4配置ADC转换器ADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 右对齐ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 外部触发选择,不使用外部触发ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 工作模式(独立/双ADC)
// ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 单次/连续转换ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 单次/连续转换ADC_InitStructure.ADC_NbrOfChannel = 1; // 通道数目ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 扫描/非扫描转换// 单次转换非扫描模式// 单次转换/连续转换 扫描/非扫描ADC_Init(ADC1, &ADC_InitStructure);// 5开关控制ADC_Cmd(ADC1, ENABLE);// 6校准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)
{
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 软件触发转换
// while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); // 等待转换完成return ADC_GetConversionValue(ADC1); // 返回转换值
}
2.3 主函数
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"uint16_t ADValue;
float voltage;int main()
{OLED_Init(); // 初始化OLEDAD_Init();OLED_ShowString(1, 1, "ADValue:");OLED_ShowString(2, 1, "Voltage:0.00v"); // 将转换结果换算成电压值while (1){ADValue = AD_GetValue();voltage = (float)ADValue / 4095 * 3.3; // 实际电压值OLED_ShowNum(1, 9, ADValue, 4);OLED_ShowNum(2, 9, voltage, 1); // 显示整数部分OLED_ShowNum(2, 11, (uint16_t)(voltage * 100) % 100, 2); // 显示小数Delay_ms(100);}
}
3 AD多通道
3.1 接线图
使用了4个通道
3.2 模块封装
单次转换非扫描
#include "stm32f10x.h" // Device header// AD初始化函数
void AD_Init(void)
{// 1开启RCC时钟,ADC、GPIORCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 72M / 6 = 12M// 2配置GPIO模拟输入模式GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_Init(GPIOA, &GPIO_InitStructure);// 3配置多路开关,选择规则组的输入通道,指定通道/规则组序列器的次序/通道采样时间ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);// 4配置ADC转换器ADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 右对齐ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 外部触发选择,不使用外部触发ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 工作模式(独立/双ADC)ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续转换ADC_InitStructure.ADC_NbrOfChannel = 1; // 通道数目ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 非扫描转换// 单次转换非扫描模式// 单次转换/连续转换 扫描/非扫描ADC_Init(ADC1, &ADC_InitStructure);// 5开关控制ADC_Cmd(ADC1, ENABLE);// 6校准ADC_ResetCalibration(ADC1); // 复位校准while(ADC_GetResetCalibrationStatus(ADC1) == SET); // 等待复位校准完成ADC_StartCalibration(ADC1); // 开始校准while(ADC_GetCalibrationStatus(ADC1) == SET); // 等待校准完成
}// 获取转换结果
uint16_t AD_GetValue(uint8_t ADC_Channel)
{// 3配置多路开关,选择规则组的输入通道,指定通道/规则组序列器的次序/通道采样时间// 填充通道ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5);ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 软件触发转换while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); // 等待转换完成return ADC_GetConversionValue(ADC1); // 返回转换值
}
3.3 主函数
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"uint16_t AD0, AD1, AD2, AD3;int main()
{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);}
}
相关文章:

【STM32】ADC模数转换器
1 ADC简介 ADC(Analog-Digital Converter)模拟-数字转换器 ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁 STM32是数字电路,只有高低电平,没有几V电压的概念ÿ…...

Git篇---第九篇
系列文章目录 文章目录 系列文章目录前言一、使用过git merge和git rebase吗?它们之间有什么区别?二、使用过git cherry-pick,有什么作用?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看…...

Paper Reading: (ACRST) 基于自适应类再平衡自训练的半监督目标检测
目录 简介工作重点方法CropBankFBRAFFRTwo-stage Pseudo-label Filtering 实验与SOTA比较消融实验 简介 题目:《Semi-Supervised Object Detection with Adaptive Class-Rebalancing Self-Training》,AAAI’22, 基于自适应类再平衡自训练的半…...

2023年贺岁电影:一眼多,二眼好多
如果从11月末开始统计,今年贺岁档共有72部贺岁片,平均一天就有2部电影上映,看完总计需要花费7400分钟。 这个数量几乎快赶上2021年到2022年贺岁片的总和。 今年电影市场快速回暖以来,多部爆款作品接力上映,持续刺激市…...

软件测试面试中基础与功能的问题
一、 你们的测试流程是怎么样的? 答:1.项目开始阶段, BA (需求分析师) 从用户方收集需求并将需求转化为规格说明书,接 下来在 项目组领导 会组织需求评审。 2.需求评审通过后,BA 会组织 项目…...

map|二分查找|离线查询|LeetCode:2736最大和查询
本文涉及的基础知识点 二分查找算法合集 题目 给你两个长度为 n 、下标从 0 开始的整数数组 nums1 和 nums2 ,另给你一个下标从 1 开始的二维数组 queries ,其中 queries[i] [xi, yi] 。 对于第 i 个查询,在所有满足 nums1[j] > xi 且…...

你知道Java中的BigInteger类和BigDecimal类吗?
BigInteger和BigDecimal: 我们在学习JavaSE基础的时候学习过int和double,前者是整形,后者是双精度浮点数,但它们是有最大值的,也就是说,他两并不支持无限大的数字。 其范围如下所示: 因此对于…...

33.搜索旋转排序数组
题目来源: leetcode题目,网址:33. 搜索旋转排序数组 - 力扣(LeetCode) 解题思路: 在二分查找时,分情况讨论即可。通过与第一个元素和最后一个元素的比较来获得 mid 处于第一个序列中还是第…...

【unity】【WebRTC】从0开始创建一个Unity远程媒体流app-设置输入设备
【项目源码】 包括本篇需要的脚本都打包在项目源码中,可以通过下面链接下载: https://download.csdn.net/download/weixin_41697242/88623091 【背景】 目前我们能投射到远端浏览器(或者任何其它Peer)的媒体流只有默认的MainCamera画面,其实我们还可以通过配置输入来传…...

Redis持久化AOF详解
基础面试题 什么是AOF AOF(Append-Only File)用于将Redis服务器收到的写操作追加到日志文件,通过该机制可以保证服务器重启后依然可以依靠日志文件恢复数据。 它的工作过程大抵分为以下几步: 收到客户端的写入命令(例如SET、DE…...

基于ssm网络安全宣传网站设计论文
摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本网络安全宣传网站就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息…...

机器人行业数据闭环实践:从对象存储到 JuiceFS
JuiceFS 社区聚集了来自各行各业的前沿科技用户。本次分享的案例来源于刻行,一家商用服务机器人领域科技企业。 商用服务机器人指的是我们日常生活中常见的清洁机器人、送餐机器人、仓库机器人等。刻行采用 JuiceFS 来弥补对象存储性能不足等问题。 值得一提的是&am…...

墒情监测FDS-400 土壤温湿电导率盐分传感器
墒情监测FDS-400 土壤温湿电导率盐分传感器产品概述 土壤温度部分是由精密铂电阻和高精度变送器两部分组成。变送器部分由电源模块、温度传感模块、变送模块、温度补偿模块及数据处理模块等组成,解决铂电阻因自身特点导入的测量误差,变送器内有零漂电路…...

QT -CloudViewer工具
QT -CloudViewer工具 一、演示效果二、关键程序三、程序下载 一、演示效果 二、关键程序 void CloudViewer::doOpen(const QStringList& filePathList) {// Open point cloud file one by onefor (int i 0; i ! filePathList.size(); i) {timeStart(); // time startmycl…...

GoLong的学习之路,进阶,微服务之使用,RPC包(包括源码分析)
今天这篇是接上上篇RPC原理之后这篇是讲如何使用go本身自带的标准库RPC。这篇篇幅会比较短。重点在于上一章对的补充。 文章目录 RPC包的概念使用RPC包服务器代码分析如何实现的?总结Server还提供了两个注册服务的方法 客户端代码分析如何实现的?如何异步…...

uniapp x 相比于其他的开发系统框架怎么样?
首先我们要知道niapp这是一种基于Vue.js开发的跨平台应用框架,可以将同一套代码同时运行在多个平台上,包括iOS、Android、H5等。相比其他开发系统框架,他有什么优点呢?让我们共同探讨一下吧! 图片来源:unia…...

2024最新独立站建站教程!WordPress 搭建独立站的方法和步骤
不知道大家是否听说过 WordPress ?最近有个国外博主分享,她60岁的奶奶居然用WordPress建了个关于她宠物日常的小博客,看来 WordPress 在国外真的是很普及。其实,国外很多商家还利用 WordPress 搭建自己的电商网站,那说…...

深入React Flow Renderer(二):构建拖动操作栏
在上一篇博客中,我们介绍了如何启动React Flow Renderer并创建一个基本的工作流界面。本文将进一步深入,着重讨论如何构建一个可拖动的操作栏,它是用户与工作流交互的入口之一。 引言 操作栏是工作流界面的一部分,通常位于界面的…...

Java项目学生管理系统六后端补充
班级管理 1 班级列表:后端 编写JavaBean【已有】编写Mapper【已有】编写Service编写controller 编写Service 接口 package com.czxy.service;import com.czxy.domain.Classes;import java.util.List;/*** author 桐叔* email liangtongitcast.cn* description*/ p…...

PDF控件Spire.PDF for .NET【转换】演示:将 PDF 转换为线性化
PDF 线性化,也称为“快速 Web 查看”,是一种优化 PDF 文件的方法。通常,只有当用户的网络浏览器从服务器下载了所有页面后,用户才能在线查看多页 PDF 文件。然而,如果 PDF 文件是线性化的,即使完整下载尚未…...

猫头虎博主深度探索:Amazon Q——2023 re:Invent大会的AI革新之星
猫头虎博主深度探索:Amazon Q——2023 re:Invent大会的AI革新之星 授权说明:本篇文章授权活动官方亚马逊云科技文章转发、改写权,包括不限于在 亚马逊云科技开发者社区, 知乎,自媒体平台,第三方开发者媒体等亚马逊云科…...

Spring框架-GOF代理模式之JDK动态代理
我们可以分成三步来完成jdk动态代理的实现 第一步:创建目标对象 第二步:创建代理对象 第三步:调用代理对象的代理方法 public class Client {public static void main(String[] args) {//创建目标对象final OrderService target new OrderS…...

基于JAVAEE技术校园车辆管理系统论文
摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本校园车辆管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息…...

基于FFmpeg,实现播放器功能
一、客户端选择音视频文件 MainActivity package com.anniljing.ffmpegnative;import android.Manifest; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Ur…...

利用tf-idf对特征进行提取
TF-IDF是一种文本特征提取的方法,用于评估一个词在一组文档中的重要性。 一、代码 from sklearn.feature_extraction.text import TfidfVectorizer import numpy as npdef print_tfidf_words(documents):"""打印TF-IDF矩阵中每个文档中非零值对应…...

遇到运维故障,有没有排查和解决故障的正确流程?
稳定是偶然,异常才是常态,用来标注IT运维工作再适合不过。 因为对于IT运维来说,工作最常遇到的就是不稳定性带来的各种故障,经常围绕发现故障、响应故障、定位故障、恢复故障这四大步。 故障处理是最心跳的事情,没有…...

javaWebssh汽车销售管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计
一、源码特点 java ssh汽车销售管理系统是一套完善的web设计系统(系统采用ssh框架进行设计开发),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用 B/S模式开发。开发环境为TOMCAT7.…...

基于pandoraNext使用chatgpt4
1.登陆GitHub 获取pandoraNext项目GitHub - pandora-next/deploy: Pandora Cloud Pandora Server Shared Chat BackendAPI Proxy Chat2API Signup Free PandoraNext. New GPTs(Gizmo) UI, All in one! 在release中选择相应版本操作系统的安装包进行下载 2.获取license_…...

12.视图
目录 1.视图的含义与作用 2.视图的创建与查看 1.创建视图的语法形式 2、查看视图: 1.使用DESCRIBE语句查看视图基本信息 2.使用SHOW TABLE STATUS语查看视图基本信息查看视图的信息 3.使用SHOW CREATE VIEW语查看视图详细信息 4.在views表中查看视图详细信息…...

Leetcode69 x的平方根
x的平方根 题解1 袖珍计算器算法题解2 二分查找题解3 牛顿迭代 给你一个非负整数 x ,计算并返回 x 的 算术平方根 。 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。 注意:不允许使用任何内置指数函数和算符&…...