STM32H743 cubemx配置 LL库 ADC3 调试笔记
硬件信息,PH3(CH14) PH4(CH15) PH5(CH16) 设计为ADC接口, +MCU内部温度传感器和参考电压,总计5个通道。
单片机运行时钟为400MHz,ADC时钟设计为2分频 32MHz。
采用BDMA循环读取ADC数据。
在调试过程中,发现只有温度传感器是正常,其他的采样不正常,经过一步一步的查询和调试,找到了问题所在,特写下本文,作为记录,方便后面查阅。
本文 分3个 步骤,来记录ADC3的调试过程
一、 单通道 ,软件触发,非连续采样
- cubemx配置,

- 额外的ADC初始化

经过这样配置后,发现可以采集到CH16的 ADC数据。
附录上例程,软件触发,单通道
二、多通道,软件触发,非连续采样 - cubemx配置 ,
引入了CH14 CH15 CH16, 3个adc通道,所以配置自动转为扫描模式,但是依旧是非连续采样。

- 额外的ADC初始化
uint16_t ADC_CnvValue1[21];
void myADC_Start_DMA(void)
{ LL_ADC_SetBoostMode(ADC3, LL_ADC_BOOST_MODE_50MHZ);LL_ADC_StartCalibration(ADC3, LL_ADC_CALIB_OFFSET_LINEARITY, LL_ADC_SINGLE_ENDED); while(LL_ADC_IsCalibrationOnGoing(ADC3) != 0UL){};//LL_ADC_SetChannelPreselection(ADC3, LL_ADC_CHANNEL_14|LL_ADC_CHANNEL_15|LL_ADC_CHANNEL_16 );LL_ADC_SetChannelPreselection(ADC3, LL_ADC_CHANNEL_16 ); LL_ADC_SetChannelPreselection(ADC3, LL_ADC_CHANNEL_15 ); LL_ADC_SetChannelPreselection(ADC3, LL_ADC_CHANNEL_14 ); LL_ADC_Enable(ADC3);while(LL_ADC_IsActiveFlag_ADRDY(ADC3) != SET);
}void ADC3_ReadPH3(void) {LL_ADC_ClearFlag_EOC(ADC3); // 清除转换结束标志LL_ADC_ClearFlag_EOS(ADC3); // 清除序列结束标志LL_ADC_ClearFlag_OVR(ADC3); // 清除溢出标志(最关键,不清除会阻塞转换) LL_ADC_REG_StartConversion(ADC3);// 等待每个通道转换完成并读取结果for(int i = 0; i < 3; i++){while(LL_ADC_IsActiveFlag_EOC(ADC3) == 0); // 等待转换结束标志 ADC_CnvValue1[i] = LL_ADC_REG_ReadConversionData16(ADC3);// 读取转换结果LL_ADC_ClearFlag_EOC(ADC3);// 清除EOC标志}while(LL_ADC_IsActiveFlag_EOS(ADC3) == 0);//下面是错误代码
//while(LL_ADC_IsActiveFlag_EOS(ADC3) == 0);
//ADC_CnvValue1[idx++] = LL_ADC_REG_ReadConversionData16(ADC3);
// ADC_CnvValue1[idx++] = LL_ADC_REG_ReadConversionData16(ADC3);
// ADC_CnvValue1[idx++] = LL_ADC_REG_ReadConversionData16(ADC3);
// if(idx >= 21)
// idx = 0;
}
工程连接,软件触发,多通道读取
- 问题
在这个过程中,遇到了问题,咨询了AI豆包,说多通道转化完之后,会缓存,所以豆包给的代码是上面我注释的那个连续读的方式,导致我一直卡在这个地方,获取不到正确的数据。
后面自己改成检测EOC标志位,然后再读取的方式,就可以完整的获取到3个通道的正确数据了。
附录上下载例程
三、多通道,连续采样,BDMA中断循环采集数据
-
cubemx配置,配置扫描模式,连续采样,DMA循环模式,5个通道


-
额外的ADC初始化代码
void myADC_Start_DMA(void)
{ LL_BDMA_SetDataLength(BDMA, LL_BDMA_CHANNEL_0, (ADC_CHANNEL_MAX*ADCVAL_LEN));LL_BDMA_SetPeriphAddress(BDMA, LL_BDMA_CHANNEL_0, LL_ADC_DMA_GetRegAddr(ADC3, LL_ADC_DMA_REG_REGULAR_DATA));LL_BDMA_SetMemoryAddress(BDMA, LL_BDMA_CHANNEL_0,(uint32_t )&ADC_CnvValue[0][0]);LL_BDMA_EnableChannel(BDMA, LL_BDMA_CHANNEL_0); //高于25M,必须设置这个LL_ADC_BOOST_MODE_50MHZLL_ADC_SetBoostMode(ADC3, LL_ADC_BOOST_MODE_50MHZ);/* 启动校准 */LL_ADC_StartCalibration(ADC3, LL_ADC_CALIB_OFFSET_LINEARITY, LL_ADC_SINGLE_ENDED); /* 等待校准完成 */while(LL_ADC_IsCalibrationOnGoing(ADC3) != 0UL){};/* 通道预选设置,这个很关键 */
// LL_ADC_SetChannelPreselection(ADC3, LL_ADC_CHANNEL_14|LL_ADC_CHANNEL_15|LL_ADC_CHANNEL_16|LL_ADC_CHANNEL_TEMPSENSOR | LL_ADC_CHANNEL_VREFINT);LL_ADC_SetChannelPreselection(ADC3, LL_ADC_CHANNEL_TEMPSENSOR ); LL_ADC_SetChannelPreselection(ADC3, LL_ADC_CHANNEL_VREFINT ); LL_ADC_SetChannelPreselection(ADC3, LL_ADC_CHANNEL_16 ); LL_ADC_SetChannelPreselection(ADC3, LL_ADC_CHANNEL_15 ); LL_ADC_SetChannelPreselection(ADC3, LL_ADC_CHANNEL_14 ); //设置传输模式//LL_ADC_REG_SetDataTransferMode(ADC3, LL_ADC_REG_DMA_TRANSFER_UNLIMITED);//使能DMA传输完成中断,在DMA中断中进行数据处理LL_BDMA_EnableIT_TC(BDMA,LL_BDMA_CHANNEL_0); LL_BDMA_EnableChannel(BDMA,LL_BDMA_CHANNEL_0); LL_ADC_Enable(ADC3);while(LL_ADC_IsActiveFlag_ADRDY(ADC3) != SET); LL_ADC_REG_StartConversion(ADC3);
}
通过这样配置,就可以完整的获取到ADC的5个通道的数据
工程下载示例,BDMA -ADC3
- 问题
在这个过程中,遇到的问题是,
LL_ADC_SetChannelPreselection(ADC3, LL_ADC_CHANNEL_14|LL_ADC_CHANNEL_15|LL_ADC_CHANNEL_16|LL_ADC_CHANNEL_TEMPSENSOR | LL_ADC_CHANNEL_VREFINT);
我这样去设置,发现只有温度传感器的数据是正常的,其他的都不太正常。然后比对了好久的寄存器内容,发现PCSEL位不正确, 再去查询 LL_ADC_SetChannelPreselection 的源代码
__STATIC_INLINE void LL_ADC_SetChannelPreselection(ADC_TypeDef *ADCx, uint32_t Channel)
{
#if defined(ADC_VER_V5_V90)if (ADCx != ADC3){/* ADC channels preselection */ADCx->PCSEL_RES0 |= (1UL << (__LL_ADC_CHANNEL_TO_DECIMAL_NB(Channel) & 0x1FUL));}
#else/* ADC channels preselection */ADCx->PCSEL |= (1UL << (__LL_ADC_CHANNEL_TO_DECIMAL_NB(Channel) & 0x1FUL));
#endif /* ADC_VER_V5_V90 */
}
才发现,这里,不能通过或语句的方式去配置所有的通道,必须是1个通道设置一次,这里确实非常关键,因为在软件读取的情况下,我都没有发现这个地方,后面这边想着偷懒一下,减少几条语句,所以使用了或的方式,导致了该现象的出现。
还有一些关于BDMA和ADC3的配置,我之前写在这个文档中
