双ADC同步采集可以节省一半时间
CUBEMX配置ADC
void Read_adc( void )
{
//dma方式*****************************************
uint16_t ad1[20],ad2[20];
AdcDMA_flag = 0;
HAL_ADCEx_MultiModeStart_DMA(&hadc1, ADC_Value, 18);//启动多通道,双ADC同步采集DMA模式,ADC1在低16位,ADC2在高16位
while(AdcDMA_flag == 0) //因为要配合DAC进行采集,这里用用单次阻塞式采集,
{
delay_us(1);
}
/*******************************************
双ADC同步DMA采样,各采样18次,去除最高和最低
保留16次采样,右移2位得到14Bit采样值
********************************************/
for (i=0 ; i< 18; i++) { //分离提取ADC中各通道值 ,取18个
ad1[i] = ADC_Value[i];
ad2[i] = ADC_Value[i]>>16;
// printf("No.%d= %d, %d\r\n",i,ad1[i],ad2[i]);
}
uint32_t total_ad1 = 0, ad1_max = 0, ad1_min = 4095;
uint32_t total_ad2 = 0, ad2_max = 0, ad2_min = 4095;
for ( i = 0; i < 18; i++) //累加18次,去除最大和最小值,相当于累加16次
{
if (ad1_max < ad1[i]) ad1_max = ad1[i];
if (ad2_max < ad2[i]) ad2_max = ad2[i];
if (ad1[i] < ad1_min) ad1_min = ad1[i];
if (ad2[i] < ad2_min) ad2_min = ad2[i];
total_ad1 += ad1[i];
total_ad2 += ad2[i];
// printf("total_1=%d,total_2=%d\r\n",total_1,total_2);
}
total_ad1 = (total_ad1 - ad1_min - ad1_max) ;
total_ad2 = (total_ad2 - ad2_min - ad2_max) ;
// printf("max= %d min= %d\r\n",ad1_max,ad1_min);
// printf("total_16= %d, total_2=%d\r\n",total_1,total_2);
//计算过采样14b的值
// AdcDMA_flag = 0;
V_ADC14b= (total_ad1)>>2;
I_ADC14b= (total_ad2)>>2;
}
ADC初始化后要先校准
HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED); //校准ADC1
HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED); //校准ADC2
在While(1)中读取ADC
uint32_t time = HAL_GetTick(); //同步时间
while (1)
{
if(HAL_GetTick()-time >=1000)
{
time = HAL_GetTick(); //同步时间
Read_adc();
printf("V_ADC=%d,I_ADC=%d\r\n",V_ADC14b,I_ADC14b);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
电压/电流差分采样电路
开始是使用STM32F303内部运放进行差分采样,结果发现读数跳动较大,无输入时也有底数,且OPAMP之间有串扰,改用外置运放后读数相对稳定,无输入时读数为0,实测ADC读数跳动在3~4个字,注意这里使用了14位过采样,不使用过采样的话读数会更稳定。
完整程序下载:
https://download.csdn.net/download/u013348132/12034532