STM32--ADC
一、简介
*ADC(Analog-Digital Converter)模拟-数字转换器
*ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁
*12位逐次逼近型ADC,1us转换时间
*输入电压范围:0~3.3V,转换结果范围:0~4095(12位转换分辨率)
*18个输入通道,可测量16个外部和2个内部信号源(在任意多个通道上以任意顺序进行的一系列转换构成成组转换(规则通道)。例如,可以如下顺序完成转换:通道3、通道8、通道2、通道0、通道2、通道2、通道15)
*规则组和注入组两个转换单元(规则通道:我们平时用的一般通道,按顺序进行转换),(注入通道:可以理解为插入。它是一种在规则通道转换的时候强行插入要转换的一种。注入通道只有在规则通道存在的时候才会出现)
*模拟看门狗自动监测输入电压范围
*转换时间:最短的转化时间--Tconv = 采样时间 + 12.5个周期
PCLK2 = 72M,ADC_CLK = 72/6 = 12M
Tconv = 1.5+12.4 = 14周期 = 14/12us = 1.17us
*AD转换的步骤:采样,保持,量化,编码
*STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道(F4有三个ADC)


1、电压输入范围
*输入电压: VREF- <= VIN <= VREF+
*决定输入电压的引脚:VREF-,VREF+,VDDA,VSSA
*VSSA和VREF- 接地,VREF+ 和VDDA 接3.3V
*得到ADC的电压输入范围为: 0-3.3V

电压怎么测?
电压输入范围:ADC可以测量-10V ~ +10V
根据基尔霍夫定理:(Vin - Vout)/R2 + (3v3-Vout)/R1=Vout/R3
Vout=(Vint + 10)/6

二、ADC的基本结构

ps:STM32f103c8t6有ADC1和ADC2,有两个转换单元(规则组、注入组),规则组有16个通道,注入组有4个通道。
规则通道有数据覆盖的问题(用DMA来解决 只能用于ADC1,只有一个数据寄存器),注入通道没有数据覆盖的问题(四个通道有四个存放寄存器)
三、转换模式
1、单次转换,非扫描模式

2、连续转换,非扫描模式
3、单次转换,扫描模式
4、连续转换,扫描模式
四、转换顺序
规则通道:
注入通道:
1、ADC单通道DMA读取
#include "adc.h"
uint16_t ADC_conversionValue;//单ADC模式时,数据寄存器只用到低16位(用来存放 ADC发过来的数据)
static void ACDx_GPIO_Config(void)
{GPIO_InitTypeDef ADC_GPIO_StructInit;ADCx_PIN_RCC_Clock_Cmd(ADCx_PIN_Periph,ENABLE);ADC_GPIO_StructInit.GPIO_Mode = GPIO_Mode_AIN; //必须是模拟输入ADC_GPIO_StructInit.GPIO_Pin = ADCx_PIN;GPIO_Init(ADCx_PIN_PORT, &ADC_GPIO_StructInit);
}static void Config_ADC_Init(void)
{ADC_InitTypeDef ADC_StructInit;DMA_InitTypeDef DMA_StructInit;/*--------------------------DMA-----------------------------------------*/RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //打开时钟DMA_DeInit(DMA1_Channel1); //将DMA寄存器复位成刚上电的样子DMA_StructInit.DMA_MemoryBaseAddr = (uint32_t)&ADC_conversionValue; //存储器地址DMA_StructInit.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC_x->DR)); //外设地址 DMA_StructInit.DMA_DIR = DMA_DIR_PeripheralSRC; //传输方向DMA_StructInit.DMA_BufferSize = 1; //传输数目DMA_StructInit.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据宽度,数据寄存器只用到低16位DMA_StructInit.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //存储器数据宽度,数据寄存器只用到低16位DMA_StructInit.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址是否递增DMA_StructInit.DMA_MemoryInc = DMA_MemoryInc_Disable; //存储器地址是否递增DMA_StructInit.DMA_Mode = DMA_Mode_Circular; //模式选择(现在时循环模式)DMA_StructInit.DMA_Priority = DMA_Priority_High; //通道优先级DMA_StructInit.DMA_M2M = DMA_M2M_Disable; //存储器到存储器模式DMA_Init( DMA1_Channel1, &DMA_StructInit);DMA_Cmd(DMA1_Channel1, ENABLE);/*---------------------ADC------------------------------------*/ADCx_RCC_Clock_Cmd(ADCx_Periph, ENABLE);ADC_StructInit.ADC_Mode = ADC_Mode_Independent; //设置独立模式(因为只有一个ADC通道)ADC_StructInit.ADC_ScanConvMode = DISABLE; //配置是否扫描(用在多通道)ADC_StructInit.ADC_ContinuousConvMode = ENABLE; //配置是否要连续转换ADC_StructInit.ADC_DataAlign = ADC_DataAlign_Right; //配置数据的对齐模式ADC_StructInit.ADC_NbrOfChannel = 1; //配置要转换通道的数目ADC_StructInit.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//配置触发模式(这里是软件触发,外部触发是有定时器或者GPIO才会使用)ADC_Init(ADC_x, &ADC_StructInit);RCC_ADCCLKConfig(RCC_PCLK2_Div8); //时钟配置72/8=9MADC_RegularChannelConfig(ADC_x, ADCx_Channel, 1, ADC_SampleTime_55Cycles5); //规则通道的配置,第三个参数是配置第几次转换,第四个参数是配置采样周期ADC_Cmd(ADC_x, ENABLE); //使能ADC中断ADC_StartCalibration(ADC_x); //开始校准ADCwhile(ADC_GetCalibrationStatus(ADC_x)); //等待校准完成ADC_SoftwareStartConvCmd(ADC_x, ENABLE); //软件触发使能(开始工作)//使能DMA ADCADC_DMACmd(ADC_x, ENABLE);}void ADCx_Init(void)
{ACDx_GPIO_Config();Config_ADC_Init();
}extern uint16_t ADC_conversionValue;
int main()
{float conversionValue = 0;initSysTick();usart_init();ADCx_Init();while(1){conversionValue = (float)ADC_conversionValue/4096*3.3;printf("hex %04x\r\n",ADC_conversionValue);printf("conversionValue %f\r\n",conversionValue);ms_delay(2000);}}
2、ADC单通道中断读取
#ifndef ADC_H
#define ADC_H
#include "stm32f10x.h"
static void ACDx_GPIO_Config(void);
static void Config_ADC_Init(void);
static void ADCx_NVIC_Config(void);
void ADCx_Init(void);//ADC引脚配置的宏
#define ADCx_PIN GPIO_Pin_1
#define ADCx_PIN_PORT GPIOA
#define ADCx_PIN_Periph RCC_APB2Periph_GPIOA
#define ADCx_PIN_RCC_Clock_Cmd RCC_APB2PeriphClockCmd//ADC配置的宏
#define ADCx_Periph RCC_APB2Periph_ADC2
#define ADCx_RCC_Clock_Cmd RCC_APB2PeriphClockCmd
#define ADC_x ADC2
#define ADCx_Channel ADC_Channel_1#define ADCx_IRQHandler ADC1_2_IRQHandler
#endif#include "adc.h"static void ACDx_GPIO_Config(void)
{GPIO_InitTypeDef ADC_GPIO_StructInit;ADCx_PIN_RCC_Clock_Cmd(ADCx_PIN_Periph,ENABLE);ADC_GPIO_StructInit.GPIO_Mode = GPIO_Mode_AIN; //必须是模拟输入ADC_GPIO_StructInit.GPIO_Pin = ADCx_PIN;GPIO_Init(ADCx_PIN_PORT, &ADC_GPIO_StructInit);
}static void Config_ADC_Init(void)
{ADC_InitTypeDef ADC_StructInit;ADCx_RCC_Clock_Cmd(ADCx_Periph, ENABLE);ADC_StructInit.ADC_Mode = ADC_Mode_Independent; //设置独立模式(因为只有一个ADC通道)ADC_StructInit.ADC_ScanConvMode = DISABLE; //配置是否扫描(用在多通道)ADC_StructInit.ADC_ContinuousConvMode = ENABLE; //配置是否要连续转换ADC_StructInit.ADC_DataAlign = ADC_DataAlign_Right; //配置数据的对齐模式ADC_StructInit.ADC_NbrOfChannel = 1; //配置要转换通道的数目ADC_StructInit.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//配置触发模式(这里是软件触发,外部触发是有定时器或者输入引脚触发才会使用)ADC_Init(ADC_x, &ADC_StructInit);RCC_ADCCLKConfig(RCC_PCLK2_Div8); //时钟配置72/8=9MADC_RegularChannelConfig(ADC_x, ADCx_Channel, 1, ADC_SampleTime_55Cycles5); //规则通道的配置,第三个参数是配置第几个转换换通道,第四个参数是配置采样周期,第二个参数是第几个通道(例:A0是通道1)ADC_ITConfig(ADC_x, ADC_IT_EOC, ENABLE); //配置成规则通道中断ADC_Cmd(ADC_x, ENABLE); //使能ADC中断ADC_StartCalibration(ADC_x); //开始校准ADCwhile(ADC_GetCalibrationStatus(ADC_x)); //等待校准完成ADC_SoftwareStartConvCmd(ADC_x, ENABLE); //软件触发使能(开始工作)}static void ADCx_NVIC_Config(void)
{NVIC_InitTypeDef ADCx_NVIC_StructInit;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);ADCx_NVIC_StructInit.NVIC_IRQChannel = ADC1_2_IRQn;ADCx_NVIC_StructInit.NVIC_IRQChannelCmd = ENABLE;ADCx_NVIC_StructInit.NVIC_IRQChannelPreemptionPriority = 1;ADCx_NVIC_StructInit.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&ADCx_NVIC_StructInit);
}void ADCx_Init(void)
{ACDx_GPIO_Config();Config_ADC_Init();ADCx_NVIC_Config();
}extern uint32_t ADC_Conversion_value;
int main()
{float ADC_Value = 0;initSysTick();usart_init();ADCx_Init();while(1){ADC_Value = (float)ADC_Conversion_value/4096*3.3;printf("adc_float=%fv\r\n",ADC_Value);printf("adc_Hex=%04x\r\n",ADC_Conversion_value);ms_delay(2000);}}void ADCx_IRQHandler(void)
{if(ADC_GetITStatus(ADC_x, ADC_IT_EOC) == SET){ADC_Conversion_value = ADC_GetConversionValue(ADC_x);//读取转换的数值}ADC_ClearITPendingBit(ADC_x, ADC_IT_EOC);
} 3、ADC多通道DMA读取
#ifndef ADC_H
#define ADC_H
#include "stm32f10x.h"
static void ACDx_GPIO_Config(void);
static void Config_ADC_Init(void);
void ADCx_Init(void);//ADC引脚配置的宏
#define ADCx_PIN GPIO_Pin_1
#define ADCx_PIN_PORT GPIOA
#define ADCx_PIN_Periph RCC_APB2Periph_GPIOA
#define ADCx_PIN_RCC_Clock_Cmd RCC_APB2PeriphClockCmd//ADC配置的宏
#define ADCx_Periph RCC_APB2Periph_ADC1
#define ADCx_RCC_Clock_Cmd RCC_APB2PeriphClockCmd
#define ADC_x ADC1
#define ADCx_Channel ADC_Channel_1#define len 3#endif#include "adc.h"
uint16_t ADC_conversionValue[len];//单ADC模式时,数据寄存器只用到低16位(用来存放 ADC发过来的数据)
static void ACDx_GPIO_Config(void)
{GPIO_InitTypeDef ADC_GPIO_StructInit;ADCx_PIN_RCC_Clock_Cmd(ADCx_PIN_Periph,ENABLE);ADC_GPIO_StructInit.GPIO_Mode = GPIO_Mode_AIN; //必须是模拟输入ADC_GPIO_StructInit.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_Init(ADCx_PIN_PORT, &ADC_GPIO_StructInit);
}static void Config_ADC_Init(void)
{ADC_InitTypeDef ADC_StructInit;DMA_InitTypeDef DMA_StructInit;/*--------------------------DMA-----------------------------------------*/RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //打开时钟DMA_DeInit(DMA1_Channel1); //将DMA寄存器复位成刚上电的样子DMA_StructInit.DMA_MemoryBaseAddr = (uint32_t)ADC_conversionValue; //存储器地址DMA_StructInit.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC_x->DR)); //外设地址 DMA_StructInit.DMA_DIR = DMA_DIR_PeripheralSRC; //传输方向DMA_StructInit.DMA_BufferSize = len; //传输数目(缓冲区大小,应该等于数据目的地的大小)// 外设数据大小为半字,即两个字节DMA_StructInit.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据宽度,数据寄存器只用到低16位// 内存数据大小也为半字,跟外设数据大小相同DMA_StructInit.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //存储器数据宽度,数据寄存器只用到低16位DMA_StructInit.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址是否递增DMA_StructInit.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器地址是否递增DMA_StructInit.DMA_Mode = DMA_Mode_Circular; //模式选择(现在时循环模式)DMA_StructInit.DMA_Priority = DMA_Priority_High; //通道优先级DMA_StructInit.DMA_M2M = DMA_M2M_Disable; //存储器到存储器模式DMA_Init( DMA1_Channel1, &DMA_StructInit);DMA_Cmd(DMA1_Channel1, ENABLE);/*---------------------ADC------------------------------------*/ADCx_RCC_Clock_Cmd(ADCx_Periph, ENABLE);ADC_StructInit.ADC_Mode = ADC_Mode_Independent; //设置独立模式(因为只有一个ADC)ADC_StructInit.ADC_ScanConvMode = ENABLE; //配置是否扫描(用在多通道)ADC_StructInit.ADC_ContinuousConvMode = ENABLE; //配置是否要连续转换ADC_StructInit.ADC_DataAlign = ADC_DataAlign_Right; //配置数据的对齐模式ADC_StructInit.ADC_NbrOfChannel = len; //配置要转换通道的数目ADC_StructInit.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//配置触发模式(这里是软件触发,外部触发是有定时器或者输入引脚触发才会使用)ADC_Init(ADC_x, &ADC_StructInit);RCC_ADCCLKConfig(RCC_PCLK2_Div8); //时钟配置72/8=9MADC_RegularChannelConfig(ADC_x, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5); //规则通道的配置,第三个参数是配置第几次转换,第四个参数是配置采样周期ADC_RegularChannelConfig(ADC_x, ADC_Channel_2, 2, ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC_x, ADC_Channel_3, 3, ADC_SampleTime_55Cycles5);ADC_Cmd(ADC_x, ENABLE); //使能ADC中断// 初始化ADC 校准寄存器 ADC_ResetCalibration(ADC_x);// 等待校准寄存器初始化完成while(ADC_GetResetCalibrationStatus(ADC_x));ADC_StartCalibration(ADC_x); //开始校准ADCwhile(ADC_GetCalibrationStatus(ADC_x)); //等待校准完成ADC_SoftwareStartConvCmd(ADC_x, ENABLE); //软件触发使能(开始工作)//使能DMA ADC请求ADC_DMACmd(ADC_x, ENABLE);}void ADCx_Init(void)
{ACDx_GPIO_Config();Config_ADC_Init();
}// 局部变量,用于保存转换计算后的电压值
float ADC_ConvertedValueLocal[len];
int main()
{float conversionValue = 0;initSysTick();usart_init();ADCx_Init();printf("\r\n ----这是一个ADC多通道采集实验----\r\n");while(1){ADC_ConvertedValueLocal[0] =(float) ADC_conversionValue[0]/4096*3.3;ADC_ConvertedValueLocal[1] =(float) ADC_conversionValue[1]/4096*3.3;ADC_ConvertedValueLocal[2] =(float) ADC_conversionValue[2]/4096*3.3;printf("\r\n CH0 value = %f V \r\n",ADC_ConvertedValueLocal[0]);printf("\r\n CH1 value = %f V \r\n",ADC_ConvertedValueLocal[1]);printf("\r\n CH2 value = %f V \r\n",ADC_ConvertedValueLocal[2]);ms_delay(2000);}} 4、双ADC_DMA读取_同步规则
#ifndef ADC_H
#define ADC_H
#include "stm32f10x.h"
static void ACDx_GPIO_Config(void);
static void Config_ADC_Init(void);
void ADCx_Init(void);//ADC引脚配置的宏
#define ADCx_PIN GPIO_Pin_1
#define ADCx_PIN_PORT GPIOA
#define ADCx_PIN_Periph RCC_APB2Periph_GPIOA
#define ADCx_PIN_RCC_Clock_Cmd RCC_APB2PeriphClockCmd//ADC配置的宏
#define ADCx_Periph RCC_APB2Periph_ADC1
#define ADCx_RCC_Clock_Cmd RCC_APB2PeriphClockCmd
#define ADC_x ADC1
#define ADCx_Channel ADC_Channel_1#define len 1#endif#include "adc.h"
uint32_t ADC_conversionValue[len];//单ADC模式时,数据寄存器只用到低16位(用来存放 ADC发过来的数据)
static void ACDx_GPIO_Config(void)
{GPIO_InitTypeDef ADC_GPIO_StructInit;ADCx_PIN_RCC_Clock_Cmd(ADCx_PIN_Periph,ENABLE);ADC_GPIO_StructInit.GPIO_Mode = GPIO_Mode_AIN; //必须是模拟输入ADC_GPIO_StructInit.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 ;GPIO_Init(ADCx_PIN_PORT, &ADC_GPIO_StructInit);
}static void Config_ADC_Init(void)
{ADC_InitTypeDef ADC_StructInit;DMA_InitTypeDef DMA_StructInit;/*--------------------------DMA-----------------------------------------*/RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //打开时钟DMA_DeInit(DMA1_Channel1); //将DMA寄存器复位成刚上电的样子DMA_StructInit.DMA_MemoryBaseAddr = (uint32_t)ADC_conversionValue; //存储器地址DMA_StructInit.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC_x->DR)); //外设地址 DMA_StructInit.DMA_DIR = DMA_DIR_PeripheralSRC; //传输方向DMA_StructInit.DMA_BufferSize = len; //传输数目(缓冲区大小,应该等于数据目的地的大小)// 外设数据大小为半字,即两个字节DMA_StructInit.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; //外设数据宽度(32位)// 内存数据大小也为半字,跟外设数据大小相同DMA_StructInit.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; //存储器数据宽度(32位)DMA_StructInit.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址是否递增DMA_StructInit.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器地址是否递增DMA_StructInit.DMA_Mode = DMA_Mode_Circular; //模式选择(现在时循环模式)DMA_StructInit.DMA_Priority = DMA_Priority_High; //通道优先级DMA_StructInit.DMA_M2M = DMA_M2M_Disable; //存储器到存储器模式DMA_Init( DMA1_Channel1, &DMA_StructInit);DMA_Cmd(DMA1_Channel1, ENABLE);/*---------------------ADC1------------------------------------*/ADCx_RCC_Clock_Cmd(ADCx_Periph, ENABLE);ADC_StructInit.ADC_Mode = ADC_Mode_RegSimult; //设置成规则同步模式(因为有两个ADC)ADC_StructInit.ADC_ScanConvMode = ENABLE; //配置是否扫描(用在多通道)ADC_StructInit.ADC_ContinuousConvMode = ENABLE; //配置是否要连续转换ADC_StructInit.ADC_DataAlign = ADC_DataAlign_Right; //配置数据的对齐模式ADC_StructInit.ADC_NbrOfChannel = len; //配置要转换通道的数目ADC_StructInit.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//配置触发模式(这里是软件触发,外部触发是有定时器或者输入引脚触发才会使用)ADC_Init(ADC_x, &ADC_StructInit);RCC_ADCCLKConfig(RCC_PCLK2_Div8); //时钟配置72/8=9MADC_Cmd(ADC_x, ENABLE); //使能ADC中断ADC_RegularChannelConfig(ADC_x, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);//设置通道1(PA1)//使能DMA ADC请求ADC_DMACmd(ADC_x, ENABLE);/*--------------------ADC2-------------------------------------*/ADCx_RCC_Clock_Cmd(RCC_APB2Periph_ADC2, ENABLE);ADC_StructInit.ADC_Mode = ADC_Mode_RegSimult; //设置成规则同步模式(因为有两个ADC)ADC_StructInit.ADC_ScanConvMode = ENABLE; //配置是否扫描(用在多通道)ADC_StructInit.ADC_ContinuousConvMode = ENABLE; //配置是否要连续转换ADC_StructInit.ADC_DataAlign = ADC_DataAlign_Right; //配置数据的对齐模式ADC_StructInit.ADC_NbrOfChannel = len; //配置要转换通道的数目ADC_StructInit.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//配置触发模式(这里是软件触发,外部触发是有定时器或者GPIO才会使用)
// RCC_ADCCLKConfig(RCC_PCLK2_Div8); //时钟配置72/8=9MADC_Init(ADC2, &ADC_StructInit);ADC_Cmd(ADC2, ENABLE); //使能ADC中断ADC_RegularChannelConfig(ADC2, ADC_Channel_2, 1, ADC_SampleTime_55Cycles5);//设置通道2(PA2)/* 使能ADCx_2的外部触发转换 */ADC_ExternalTrigConvCmd(ADC2, ENABLE);// 初始化ADC1 校准寄存器 ADC_ResetCalibration(ADC_x);// 等待校准寄存器初始化完成while(ADC_GetResetCalibrationStatus(ADC_x));ADC_StartCalibration(ADC_x); //开始校准ADCwhile(ADC_GetCalibrationStatus(ADC_x)); //等待校准完成// 初始化ADC2 校准寄存器 ADC_ResetCalibration(ADC2);// 等待校准寄存器初始化完成while(ADC_GetResetCalibrationStatus(ADC2));ADC_StartCalibration(ADC2); //开始校准ADCwhile(ADC_GetCalibrationStatus(ADC2)); //等待校准完成ADC_SoftwareStartConvCmd(ADC_x, ENABLE); //软件触发使能(开始工作)}void ADCx_Init(void)
{ACDx_GPIO_Config();Config_ADC_Init();
}extern uint32_t ADC_conversionValue[len];//单ADC模式时,数据寄存器只用到低16位(用来存放 ADC发过来的数据)
// 局部变量,用于保存转换计算后的电压值
float ADC_ConvertedValueLocal[len*2];
int main()
{uint16_t temp0=0 ,temp1=0;initSysTick();usart_init();ADCx_Init();printf("\r\n ----这是一个双ADC规则同步采集实验----\r\n");while(1){// 取出ADC1数据寄存器的高16位,这个是ADC2的转换数据temp0 = (ADC_conversionValue[0]&0XFFFF0000) >> 16;//取高16位(ADC2的数据)// 取出ADC1数据寄存器的低16位,这个是ADC1的转换数据temp1 = (ADC_conversionValue[0]&0XFFFF); //取低16位(ADC1的数据)ADC_ConvertedValueLocal[0] =(float) temp0/4096*3.3;ADC_ConvertedValueLocal[1] =(float) temp1/4096*3.3;printf("\r\n ADC1 value = %f V \r\n",ADC_ConvertedValueLocal[1]);printf("\r\n ADC2 value = %f V \r\n",ADC_ConvertedValueLocal[0]);ms_delay(2000);}}
PS:
*多路ADC模式的时候 ,要配置外部触发转换,单路ADC只需要配置软件触发转换


*多路ADC模式的时候,ADC1,ADC2一起使用,例如设置规则同步的时候,通道的数目要一致,ADC1有两个通道,ADC2也需要有两个通道
*
五、触发源
*ADC 的触发转换有两种方法:分别是通过软件或外部事件(也就是硬件)触发转换。
*软件触发转换的方法。方法是:通过写 ADC_CR2 寄存器的 ADON 这个位来控制,写 1 就开始转换,写 0 就停止转换,这个控制 ADC 转换的方式非常简单。
*外部事件触发转换的方法,有定时器和输入引脚触发等等

六、校准
*ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差
*建议在每次上电后执行一次校准
*启动校准前, ADC必须处于关电状态超过至少两个ADC时钟周期

七、DMA请求
*因为规则通道转换的值储存在一个仅有的数据寄存器中,所以当转换多个规则通道时需要使用 DMA,这可以避免丢失已经存储在ADC_DR寄存器中的数据。
*只有在规则通道的转换结束时才产生DMA请求,并将转换的数据从ADC_DR寄存器传输到用户 指定的目的地址。
*只有ADC1和ADC3拥有DMA功能。由ADC2转化的数据可以通过双ADC模式,利用ADC1的DMA功能传输。(ADC2转换的数据要用DMA传输的时候,就可以用双ADC模式)。
八、中断
*ADC1和ADC2的中断映射在同一个中断向量上,而ADC3的中断有自己的中断向量。
九、数据对齐
相关文章:
STM32--ADC
一、简介 *ADC(Analog-Digital Converter)模拟-数字转换器 *ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁 *12位逐次逼近型ADC,1us转换时间 *输入电压范围:0~3.3V&…...
【TB作品】msp430f149单片机,读取ds18b20温度,显示到数码管,串口发送温度到电脑
功能 msp430f149单片机 读取ds18b20温度,显示到数码管,串口发送温度到电脑 部分程序 /************************************************* * 程序功能:用DS18B20测量室温并在数码管上显示。 * --------------------------------------…...
vue组合式和选项式
Vue中的组合式(Composition API)和选项式(Options API)是两种不同的编写组件逻辑的方法。 组合式API(Composition API): 使用函数来定义组件逻辑,可以更灵活地重用和组合逻辑。使用setup函数作为组件的入口点,在这里可以访问pro…...
使用OpenCV创建全景图像
使用OpenCV创建全景图像 前言图像拼接策略创建全景图像相关链接前言 在本节中,我们将学习组合多个图像来创建全景图像。使用相机拍摄全景照片时,通常会拍摄多张照片,通过算法将这些图像中共同存在的元素(从左到右)映射到一张单独的图像中。为了执行图像的拼接,将利用 cv2 …...
Nios II 实现流水灯实验
Nios II 实现流水灯实验 一.硬件设计1.新建Quartus项目2. 设计Nios ii 二.软件设计 前言 实验目标: 学习 Quartus 、Platform Designer、Nios-II SBT 的基本操作;初步了解 SOPC 的开发流程,基本掌握 Nios-II 软核的定制方法;掌握 …...
Spring boot 随笔 1 DatasourceInitializer
0. 为啥感觉升级了 win11 之后,电脑像是刚买回来的,很快 这篇加餐完全是一个意外:时隔两年半,再看 Springboot-quartz-starter 集成实现的时候,不知道为啥我的h2 在应用启动的时候,不能自动创建quartz相关…...
vue3_组件间通信方式
目录 一、父子通信 1.父传子( defineProps) 2.父传子(useAttrs) 3.子传父(ref,defineExpose ) 4.子传父(defineEmits) 5.子传父(v-model) …...
mysql的锁(全局锁)
文章目录 mysql按照锁的粒度分类全局锁概念:全局锁使用场景:全局锁备份案例: mysql按照锁的粒度分类 全局锁 概念: 全局锁就是对整个数据库实例加锁。MySQL 提供了一个加全局读锁的方法,命令是: Flush tables with…...
Spring Boot 整合开源 Tess4J库 实现OCR图片文字识别
😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~ 🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志 🎐 个人CSND主页——Mi…...
使用 Docker 和 Docker Compose 部署 Vue
使用 Docker 和 Docker Compose 部署 Vue 项目有两种方式:直接使用 Docker 和使用 Docker Compose。 创建 Dockerfile 在Vue.js项目根目录下创建一个 Dockerfile 的文件 # 使用最新的官方 Node.js 镜像作为基础镜像,并命名为 builder 阶段 FROM node:…...
力扣linkedlist
反转链表、 public class reverseList { // 1->2->3->o 、 o<-1<-2<-3public ListNode reverseList(ListNode head){//反转链表ListNode prevnull;ListNode currhead;while(curr!null){ListNode nextcurr.next;curr.nextprev;prevcurr;currnext;}retu…...
springboot 启动原理、启动过程、启动机制的介绍
Spring Boot 是一种基于 Java 的框架,用于创建独立的、生产级别的 Spring 应用程序。它的主要目标是简化 Spring 应用的初始搭建和开发过程,同时提供一系列大型项目常见的非功能性特征(如嵌入式服务器、安全性、度量、健康检查和外部化配置)。以下是 Spring Boot 的一些核心…...
大模型ChatGLM的部署与微调
前言:最近大模型太火了,导师让我看看能不能用到自己的实验中,就想着先微调一个chatGLM试试水,微调的过程并不难,难的的硬件条件跟不上,我试了一下lora微调,也算跑通了吧,虽然最后评估…...
全球七家半导体工厂建设受阻:英特尔、三星、台积电等面临延期挑战
过去两年间,半导体行业经历了市场衰退、复苏慢于预期以及资金紧缩等问题,英特尔、台积电和三星等主要企业虽然继续推进扩张计划,但不断调整和放缓工厂建设的步伐与时间表,以更好地服务于长期发展目标。据统计,全球范围…...
JavaScript错误;调试;“=”,“==”,“===”的区别
try...catch语句 try..catch语句是JavaScript中用来处理异常的一种方式。它允许我们在代码块中尝试执行可能会引发错误的代码,并在发生错误时捕获并处理异常。 下面是try..catch语句的基本语法: try {// 可能会引发错误的代码 } catch (error) {// 处理…...
thinkphp6的请求
由于笔者是刚入门thinkphp,所以学习时对照thinkphp的官网,各位读者也可以对照官网学习。还麻烦各位笔者一键三连,谢谢。 1.请求对象 当前的请求对象由think\Request类负责,该类不需要单独实例化调用,通常使用依赖注入…...
ant design vue 表格错位,表头错位
ant design vue 表格错位,表头错位 在官网中,我们可以看到下面图片的描述: 好的,我们按照官网来一波,前面都设置了固定宽度,娃哈哈就不设置了.会出现下面效果 为啥会多了一个竖线(因为按照官网来一波x:1300,这个1300太小的原因) 3.那我们把1300改成1600,1700试试,结果也不是…...
【小白向】微信小程序解密反编译教程
# 前言 最近笔者有做到微信小程序的渗透测试,其中有一个环节就是对微信小程序的反编译进行源码分析,所谓微信小程序反编译,就是将访问的小程序进行反向编译拿到部分源码,然后对源码进行安全审计,分析出其中可能存在的…...
Flutter基础 -- Dart 语言 -- 类抽象接口继承函数库
目录 1. 类 class 1.1 定义、使用类 1.2 构造函数 1.3 初始化列表 1.4 命名构造函数 1.5 重定向构造函数 1.6 callable 2. 类 get set 2.1 定义、使用 get set 2.2 简化 get set 2.3 业务场景 3. 静态 static 3.1 static 定义 3.2 函数内部访问 3.3 静态方法 3…...
【TB作品】msp430单片机,播放蜂鸣器音乐,天空之城
功能 msp430单片机,连接一个无源蜂鸣器,播放蜂鸣器音乐,天空之城。 适用于所有msp430单片机。 硬件 无源蜂鸣器,接单片机P1.5,使用vcc3.3v供电。 如果根据简谱修改音乐? //第一步 //首先修改music0 的变量&…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...
什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...
