一、轮询模式多通道采集
💦CubeMX配置如下,注意
注意:转换要填写第一个序列,否则转换的数据不准确
while (1)
{
adc_temp1=Get_Adc_Average(ADC_CHANNEL_0,20,1);
voltage_temp1=(float)adc_temp1*(3.3/4096);
adc_temp2=Get_Adc_Average(ADC_CHANNEL_1,20,1);//rank不管那个通道,都要填序列1
voltage_temp2=(float)adc_temp2*(3.3/4096);
printf("V:%f,%f\n",voltage_temp1,voltage_temp2);
HAL_Delay(1);
}
}
uint16_t Get_Adc(uint32_t ch,uint8_t rank)
{
ADC_ChannelConfTypeDef ADC1_ChanConf;
ADC1_ChanConf.Channel=ch; //通道
ADC1_ChanConf.Rank=rank; //第1个序列,序列1
ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间
ADC1_ChanConf.Offset=0;
HAL_ADC_ConfigChannel(&hadc1,&ADC1_ChanConf); //通道配置
HAL_ADC_Start(&hadc1); //开启ADC
HAL_ADC_PollForConversion(&hadc1,10); //轮询转换
return (uint16_t)HAL_ADC_GetValue(&hadc1); //返回最近一次ADC1规则组的转换结果
}
//获取指定通道的转换值,取times次,然后平均
//times:获取次数
//返回值:通道ch的times次转换结果平均值
uint16_t Get_Adc_Average(uint32_t ch,uint8_t times,uint8_t rank)
{
uint32_t temp_val=0;
uint8_t t;
for(t=0;t<times;t++)
{
temp_val+=Get_Adc(ch,rank);
//HAL_Delay(5);
}
return temp_val/times;
}
测试发现,扫描,连续,间接模式,开启和关闭对转换结果没有影响。
二、DMA多通道采集
1.CubeMX软件配置
💦将扫描模式打开,多通道,必须开启扫描模式
💦将连续转换打开,DMA使能。
2.代码示例_F407
代码如下(示例):
uint16_t adc_dma_temp[2]={0};
uint8_t adc_dma_cnt=0;
uint32_t adc_dma_sum1=0,adc_dma_sum2=0;
float voltage_temp1=0,voltage_temp2=0;
uint8_t adc_dma_state=0;
uint16_t data1,data2;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc==&hadc1)
{
adc_dma_sum1+=adc_dma_temp[0];
adc_dma_sum2+=adc_dma_temp[1];
adc_dma_cnt++;
if(adc_dma_cnt>=20)
{
data1=(uint16_t)(adc_dma_sum1/adc_dma_cnt);
data2=(uint16_t)(adc_dma_sum2/adc_dma_cnt);
voltage_temp1=(float)data1*(3.3/4096);
voltage_temp2=(float)data2*(3.3/4096);
printf("V:%f,%f\n",voltage_temp1,voltage_temp2);
adc_dma_cnt=0;
adc_dma_sum1=0;
adc_dma_sum2=0;
}
}
}
💦因为是连续转换模式,所以在函数初始化时,开启一次转换即可。
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
extern uint16_t adc_dma_temp[2];
extern uint16_t data1,data2;
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adc_dma_temp, 2);//开启转换
while (1)
{
for(uint8_t i=20;i>=1;i--)
{
data_buff[i]=data_buff[i-1];
}
data_buff[0]=data1;
HAL_Delay(1000);
}
}
💦结果如下:通道1,采集正弦信号,通道2采集3.3V电压,通道2误差较大,原因未知。
三补充
💦如果不使用连续转换模式,就需要在while循环中开启转换,转换效率不如连续转换高。
💦DMA的circular模式理解:当转换完成后自动搬运。