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"的模拟电压等于VINP[i]和VREF-之间的差值。

ADC支持"差动输入":

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

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

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

3)、当VINP[i]和VINN[i]连接在一起时,零输入差分电压对应于0x800 ADC输出;

2、测试程序

ADC_HandleTypeDef hadc1;

__IO uint16_t ADC1_RESULT[3];

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(CKMODE[1:0]]),CKMODE[1:0]=11,adc_hclk/4

hadc1.Init.Resolution = ADC_RESOLUTION_12B;
//分辨率:12位模式
//设置ADC_CFGR寄存器bit4:3(RES[1:0]),令RES[1: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(L[3:0]),令L[3: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(EXTEN[1:0]),EXTEN[1: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(SQ1[4:0]),SQ1[4:0]=6,即AD通道6的序号为1
//AD转换顺序排列:配置通道3位于"第1个序列"

sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
//采样时间
//设置ADC_SMPR1寄存器bit8:6(SMP2[2:0]),SMP2[2: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_RESULT[0]=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(SQ1[4:0]),SQ1[4:0]=2,即AD通道2的序号为2
//AD转换顺序排列:配置通道3位于"第1个序列"

sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
//采样时间
//设置ADC_SMPR1寄存器bit8:6(SMP2[2:0]),SMP2[2: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_RESULT[1]=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(SQ1[4:0]),SQ1[4:0]=3,即AD通道3的序号为3
//AD转换顺序排列:配置通道3位于"第1个序列"

sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
//采样时间
//设置ADC_SMPR1寄存器bit8:6(SMP2[2:0]),SMP2[2: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_RESULT[2]=HAL_ADC_GetValue(&hadc1);
//获取ADC"常规组"转换结果
//Get ADC regular group conversion result.

printf("ADC1_RESULT[0]=0x%X\r\n",ADC1_RESULT[0]);

printf("ADC1_RESULT[1]=0x%X\r\n",ADC1_RESULT[1]);

printf("ADC1_RESULT[2]=0x%X\r\n",ADC1_RESULT[2]);

f=ADC1_RESULT[0];f=f/4096;f=f*3300;

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

f=ADC1_RESULT[1];f=f/4096;f=f*3300;

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

f=ADC1_RESULT[2];f=f/4096;f=f*3300;

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

}

3、测试结果

相关推荐
情意绵绵67433 分钟前
车用CAN接口芯片:汽车神经系统的沉默构建者
单片机·嵌入式硬件·汽车·硬件架构·硬件工程
2401_859049081 小时前
MSPM0--Timer(一口一口喂版)
arm开发·单片机·mcu·算法
Dovis(誓平步青云)1 小时前
基于面向对象设计的C++日期推算引擎:精准高效的时间运算实现与运算重载工程化实践
开发语言·c++·经验分享·笔记
xu_wenming2 小时前
华为Watch的ECG功能技术分析
人工智能·嵌入式硬件·算法
跨境卫士X3 小时前
全球宠物经济新周期下的亚马逊跨境采购策略革新——宠物用品赛道成本优化三维路径
经验分享
欢乐熊嵌入式编程3 小时前
智能手表集成测试报告(Integration Test Report)
嵌入式硬件·物联网·目标跟踪·集成测试·智能手表
我不是帅戈3 小时前
STM32单片机内存分配详细讲解
stm32·单片机·嵌入式·内存管理·.map文件
汇能感知4 小时前
光谱相机的图像预处理技术
经验分享·笔记·科技
Yesheldon11 小时前
Cadence 高速系统设计流程及工具使用三
嵌入式硬件·fpga开发·硬件架构·硬件工程·智能硬件
inputA12 小时前
【LwIP源码学习6】UDP部分源码分析
c语言·stm32·单片机·嵌入式硬件·网络协议·学习·udp