STM32G474采用“多个单通道ADC转换”读取3个ADC引脚的电压

STM32G474采用"多个单通道ADC转换"读取3个ADC引脚的电压:PC0、PA1和PA2。本测试将ADC1_IN6映射到PC0引脚,ADC12_IN2映射到PA1引脚,ADC1_IN3映射到PA2引脚。

1、ADC输入

ADC输入电压范围:Vref-- ≤ VIN ≤ Vref+

ADC支持"单端输入":

在"单端输入模式"下,"通道i"的模拟电压等于VINPi和VREF-之间的差值。

ADC支持"差动输入":

在"差动输入模式"下,"通道i"的模拟电压等于VINPi和VINNi之间的差值。

1)、当VINPi等于VREF-时,VINNi等于VREF+,最大负输入差分电压(VREF-)对应于0x000 ADC输出;

2)、当VINPi等于VREF+时,VINNi等于VREF-,最大正输入差分电压(VREF+)对应于0xFFF ADC输出;

3)、当VINPi和VINNi连接在一起时,零输入差分电压对应于0x800 ADC输出;

2、测试程序

ADC_HandleTypeDef hadc1;

__IO uint16_t ADC1_RESULT3;

void ADC1_Init(void);
void Read_ADC_Value_Use_SoftwareTriger(void);

void ADC1_Init(void)

{

GPIO_InitTypeDef GPIO_InitStruct = {0};

/* Peripheral clock enable */

__HAL_RCC_ADC12_CLK_ENABLE(); //使能"ADC1和ADC2时钟"

__HAL_RCC_GPIOC_CLK_ENABLE(); //使能"PC口时钟"

GPIO_InitStruct.Pin = GPIO_PIN_0; //选择编号为0的引脚

GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; //模拟模式

GPIO_InitStruct.Pull = GPIO_NOPULL; //引脚上拉和下拉都没有被激活

HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
//根据GPIO_InitStruct结构变量指定的参数初始化GPIOC的外设寄存器
//将ADC1_IN6映射到PC0引脚

__HAL_RCC_GPIOA_CLK_ENABLE(); //使能"PA口时钟"

GPIO_InitStruct.Pin=GPIO_PIN_1|GPIO_PIN_2; //选择编号为1和2的引脚

GPIO_InitStruct.Mode=GPIO_MODE_ANALOG; //模拟模式

GPIO_InitStruct.Pull=GPIO_NOPULL; //引脚上拉和下拉都没有被激活

HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);
//根据GPIO_InitStruct结构变量指定的参数初始化GPIOA的外设寄存器
//将ADC12_IN2映射到PA1引脚,将ADC1_IN3映射到PA2引脚

/***********************************************/

hadc1.Instance = ADC1; //选择ADC1

hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
//分频系数:4分频,ADCCLK=PCLK2/4=170/4=42.5MHZ
//设置ADCx_CCR寄存器bit17:16(CKMODE1:0]),CKMODE1:0=11,adc_hclk/4

hadc1.Init.Resolution = ADC_RESOLUTION_12B;
//分辨率:12位模式
//设置ADC_CFGR寄存器bit4:3(RES1:0),令RES1:0=00b,AD转换结果为12位

hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
//对齐方式:右对齐
//设置ADC_CFGR寄存器bit15(ALIGN位),令ALIGN=0,AD转换结果为"右对齐"

hadc1.Init.GainCompensation = 0;
//ADC增益设置为0
//设置ADC_CFGR2寄存器bit16(GCOMP),令GCOMP=0,常规ADC工作模式

hadc1.Init.NbrOfConversion = 1;
//"正则通道序列长度"为1,只有有1个AD转换
//设置ADC_SQR1寄存器的bit3:0(L3:0),令L3:0=1-1,表示"正则通道序列长度"为1,有1个AD转换

hadc1.Init.NbrOfDiscConversion=0;//不连续采样通道数为0

hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
//因为hadc1.Init.NbrOfConversion = 1,所以要使用"单通道转换"
//如果是单通道转换使用ADC_SCAN_DISABLE
//如果是多通道转换使用ADC_SCAN_ENABLE。

hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
//ADC触发源选择"软件触发AD转换"
//设置HRTIM->ADC1R寄存器bit5(ADC1EEV1位),ADC1EEV1=0,使用"内部软件"触发一次ADC转换

hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
//上升沿触发
//设置ADC->CFGR寄存器bit11:10(EXTEN1:0),EXTEN1:0=01b,硬件触发检测为上升沿

hadc1.Init.ContinuousConvMode = DISABLE;
//因为要采用"软件触发AD转换",所以要用"单次转换"
//使用ENABLE配置为使能自动连续转换;
//使用DISABLE配置为单次转换,转换一次后停止,需要手动控制才重新启动转换
//设置ADC_CFGR寄存器bit13(CONT位),令CONT=1,ADC采用"连续转换模式"

hadc1.Init.SamplingMode=ADC_SAMPLING_MODE_NORMAL;
//设置ADC_CFGR2寄存器bit27(SMPTRIG),令SMPTRIG=0,禁用"ADC轮询采样模式"
//ADC转换采样相位持续时间

hadc1.Init.DiscontinuousConvMode = DISABLE;
//设置ADC_CFGR寄存器bit16(DISCEN位),令DISCEN=0,对于常规通道,禁止"不连续采样模式"

hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
//ADC_EOC_SINGLE_CONV和 ADC_EOC_SEQ_CONV,指定转换结束时是否产生EOS中断或事件标志
//配置ADC_IER寄存器bit2(EOCIE位),EOCIE=1,使能ADC转换完成产生中断

hadc1.Init.LowPowerAutoWait = DISABLE;
//配置是否使用低功耗自动延迟等待模式:关闭低功耗模式
//配置ADC_CR寄存器bit29(DEEPPWD位),令DEEPPWD=0,ADC not in Deep-power down
//可选参数为 ENABLE 和DISABLE,当使能时,仅当一组内所有之前的数据已处理完毕时
//才开始新的转换,适用于低频应用。该模式仅用于 ADC 的轮询模式,不可用于 DMA 以及中断

hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
//数据溢出覆盖;当过载发生时,使用ADC_DR的新值覆盖
//设置ADC_CFGR寄存器bit12(OVRMOD),令OVRMOD=1,当检测到溢出时,将用最后一个转换结果覆盖ADC_DR寄存器

hadc1.Init.OversamplingMode = DISABLE;
//设置ADC_CFGR2寄存器bit27(SMPTRIG),令SMPTRIG=1,启用过采样功能
//这里需要设置为DISABLE,否则数据会发生错误,不清楚HAL库这么做,有什么用

hadc1.Init.DMAContinuousRequests = DISABLE;
//不开启DMA请求连续模式或者单独模式
//设置ADC_CFGR寄存器bit0(DMAEN),令DMAEN=0,不使能DMA

HAL_ADC_Init(&hadc1);

}

void Read_ADC_Value_Use_SoftwareTriger(void)

{

float f;

ADC_ChannelConfTypeDef sConfig = {0};

LED1_Toggle();

sConfig.Channel = ADC_CHANNEL_6;//ADC通道6,前面已将ADC1_IN6映射到PC0引脚

sConfig.Rank = ADC_REGULAR_RANK_1;
//设置ADC_SQR1寄存器bit10:6(SQ14:0),SQ14:0=6,即AD通道6的序号为1
//AD转换顺序排列:配置通道3位于"第1个序列"

sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
//采样时间
//设置ADC_SMPR1寄存器bit8:6(SMP22:0),SMP22:0=000b,2.5 ADC clock cycles

sConfig.SingleDiff = ADC_SINGLE_ENDED;

//配置ADC通道输入为"单端模式",非"差动输入模式"

sConfig.OffsetNumber = ADC_OFFSET_NONE;//无偏移数量

sConfig.Offset = 0;//偏移量=0

HAL_ADC_ConfigChannel(&hadc1, &sConfig);//配置AD通道6的序号为1

HAL_ADC_Start(&hadc1);//启动一次AD转换

HAL_ADC_PollForConversion(&hadc1,10);
//等待"常规组"转换完成
//Wait for regular group conversion to be completed

ADC1_RESULT0=HAL_ADC_GetValue(&hadc1);
//获取ADC"常规组"转换结果
//Get ADC regular group conversion result.
// HAL_ADC_Stop(&hadc1);
//停止常规组的ADC转换,禁用ADC外设。
//Stop ADC conversion of regular group,disable ADC peripheral.

sConfig.Channel = ADC_CHANNEL_2;//ADC通道6,前面已将ADC12_IN2映射到PA1引脚

sConfig.Rank = ADC_REGULAR_RANK_1;
//设置ADC_SQR1寄存器bit10:6(SQ14:0),SQ14:0=2,即AD通道2的序号为2
//AD转换顺序排列:配置通道3位于"第1个序列"

sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
//采样时间
//设置ADC_SMPR1寄存器bit8:6(SMP22:0),SMP22:0=000b,2.5 ADC clock cycles

sConfig.SingleDiff = ADC_SINGLE_ENDED;

//配置ADC通道输入为"单端模式",非"差动输入模式"

sConfig.OffsetNumber = ADC_OFFSET_NONE;//无偏移数量

sConfig.Offset = 0;//偏移量=0

HAL_ADC_ConfigChannel(&hadc1, &sConfig);//配置AD通道2的序号为2

HAL_ADC_Start(&hadc1);//启动一次AD转换

HAL_ADC_PollForConversion(&hadc1,10);
//等待"常规组"转换完成
//Wait for regular group conversion to be completed

ADC1_RESULT1=HAL_ADC_GetValue(&hadc1);
//获取ADC"常规组"转换结果
//Get ADC regular group conversion result.

sConfig.Channel = ADC_CHANNEL_3;//ADC通道3,前面已将ADC1_IN3映射到PA2引脚

sConfig.Rank = ADC_REGULAR_RANK_1;
//设置ADC_SQR1寄存器bit10:6(SQ14:0),SQ14:0=3,即AD通道3的序号为3
//AD转换顺序排列:配置通道3位于"第1个序列"

sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
//采样时间
//设置ADC_SMPR1寄存器bit8:6(SMP22:0),SMP22:0=000b,2.5 ADC clock cycles

sConfig.SingleDiff = ADC_SINGLE_ENDED;

//配置ADC通道输入为"单端模式",非"差动输入模式"

sConfig.OffsetNumber = ADC_OFFSET_NONE;//无偏移数量

sConfig.Offset = 0;//偏移量=0

HAL_ADC_ConfigChannel(&hadc1, &sConfig);//配置AD通道3的序号为3

HAL_ADC_Start(&hadc1);//启动一次AD转换

HAL_ADC_PollForConversion(&hadc1,10);
//等待"常规组"转换完成
//Wait for regular group conversion to be completed

ADC1_RESULT2=HAL_ADC_GetValue(&hadc1);
//获取ADC"常规组"转换结果
//Get ADC regular group conversion result.

printf("ADC1_RESULT0=0x%X\r\n",ADC1_RESULT0);

printf("ADC1_RESULT1=0x%X\r\n",ADC1_RESULT1);

printf("ADC1_RESULT2=0x%X\r\n",ADC1_RESULT2);

f=ADC1_RESULT0;f=f/4096;f=f*3300;

printf("PC0=%0.1fmV\r\n",f);

f=ADC1_RESULT1;f=f/4096;f=f*3300;

printf("PA1=%0.1fmV\r\n",f);

f=ADC1_RESULT2;f=f/4096;f=f*3300;

printf("PA2=%0.1fmV\r\n",f);

}

3、测试结果

相关推荐
全球通史2 小时前
Keil 配置 MSPM0G3507 开发环境避坑:SysConfig、msp.h 和 driverlib.a 报错完整解决记录
stm32·单片机·嵌入式硬件
secondyoung3 小时前
Cortex-R52学习:MPU内存保护机制
arm开发·单片机·学习·arm·mpu
iCxhust5 小时前
C# 命令行指令 查看二进制文件
开发语言·单片机·嵌入式硬件·c#·proteus·微机原理·8088单板机
huangdong_5 小时前
电商图片下载工具完整对比:从技术原理到实测数据
经验分享
某林2128 小时前
ROS2 机器人底盘调试避坑指南:从 `/odom` 丢失到彻底跑通的硬核排障实录
stm32·机器人·人机交互
芯岭技术郦8 小时前
集成 2.4G 射频收发器、MCU 及丰富外设的XL2417D透传模组
单片机·嵌入式硬件
luj_17689 小时前
R语言生态优势与学习曲线分析
c语言·开发语言·网络·经验分享·算法
进击的小头9 小时前
第7篇:MOS 管最全入门:原理、关键参数、选型、驱动与典型应用
经验分享·科技·嵌入式硬件·学习
zlinear数据采集卡9 小时前
定时器电路深度解析:从经典555到STM32定时器,从ZLinear采集卡的工程化设计实战
stm32·单片机·嵌入式硬件·fpga开发·自动化
y.Ghost9 小时前
FreeRTOS-基础知识
嵌入式硬件