由于该MCU和开发板主要针对电机,所以ADC的数据采集也是针对电机的数据进行采集,针对BLDC电机驱动,需要我们实时采集各项电流,电压,并对电流的过流,电压的欠压,过压进行判断,同时还需要电源电压,电机调速电位器等模拟量进行采集。
1.电机通用评估板的ADC采样电路如下:
1.1.电机三相IV,IU,IW电压采集电路,通过电阻分压,并使用稳压管进行I/O过压保护。
1.2.电机三相电流和总电流采集电路,通过APM32M3514自带的运算放大器进行放大,该示例中选用外部放大电阻。并通过一个运算放大器提供1.65V的参考电压。
1.3.输入电压和电阻可调旋钮的采集电路,
2.APM32M3514 MCU使用的ADC硬件电路使用通道介绍
2.1.电机三相电压采集ADC引脚,使用通道ADC_IN13,ADC_IN14,ADC_IN15,分别采集V,U,W三相。
1.2.PA0是采集参考电压,目前未使用,PA4,PB0和PB10分别采集IV相电流,IU相电流和ISUM总电流,
2.3.PA6用于采集输入电压,PA7用于采集可变电阻调节旋钮阻值变化
3.代码展示和讲解
3.1.ADC的IO及通道初始化
void Drv_Adc_Init(void)
{
ADC_Config_T ADC_InitStructure;
//ADC DMA Initial
DMA_Config_T DMA_InitStructure;
DMA_InitStructure.peripheralAddress = (uint32_t)&(ADC->DATA);//ADC地址
DMA_InitStructure.memoryAddress = (uint32_t)&ADC_ConvertedValue[0]; //内存地址
DMA_InitStructure.direction = DMA_DIR_PERIPHERAL; //方向(从外设到内存)
DMA_InitStructure.bufferSize = TOTAL_CHANNEL;//TOTAL_CHANNEL; //传输内容的大小---传输次数
DMA_InitStructure.peripheralInc = DMA_PERIPHERAL_INC_DISABLE; //外设地址固定
DMA_InitStructure.memoryInc = DMA_MEMORY_INC_ENABLE;//DMA_MEMORY_INC_ENABLE; //内存地址固定
DMA_InitStructure.peripheralDataSize = DMA_PERIPHERAL_DATASIZE_HALFWORD ; //外设数据单位
DMA_InitStructure.memoryDataSize = DMA_MEMORY_DATASIZE_HALFWORD ; //内存数据单位
DMA_InitStructure.circular = DMA_CIRCULAR_ENABLE ; //DMA模式:循环传输
DMA_InitStructure.priority = DMA_PRIORITY_LEVEL_VERYHIGH ; //优先级:高
DMA_InitStructure.memoryTomemory = DMA_M2M_DISABLE; //禁止内存到内存的传输
ADC_Reset();
DMA_Config(DMA_CHANNEL_1, &DMA_InitStructure); //配置DMA的1通道
DMA_Enable(DMA_CHANNEL_1);
ADC_ClockMode(ADC_CLOCK_MODE_ASYNCLK);//48M/4=12mADC_CLOCK_MODE_SYNCLKDIV4
/* Enable ADC clock */
// RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC);
ADC_ConfigStructInit(&ADC_InitStructure);
ADC_InitStructure.convMode = ADC_CONVERSION_SINGLE;
ADC_InitStructure.scanDir = ADC_SCAN_DIR_UPWARD;
ADC_InitStructure.extTrigConv1 = ADC_EXT_TRIG_CONV_TRG1; // timer1 CC4
ADC_InitStructure.extTrigEdge1 = ADC_EXT_TRIG_EDGE_RISING;
ADC_InitStructure.dataAlign = ADC_DATA_ALIGN_RIGHT;
ADC_InitStructure.resolution = ADC_RESOLUTION_12B;
ADC_Config(&ADC_InitStructure);
ADC_ConfigChannel(ADC_CHANNEL_2 | ADC_CHANNEL_8 | ADC_CHANNEL_6 | ADC_CHANNEL_7| ADC_CHANNEL_12| ADC_CHANNEL_13| ADC_CHANNEL_14| ADC_CHANNEL_15 ,ADC_SAMPLE_TIME_1_5);
ADC->CFG1_B.OVRMAG = 1;
ADC_EnableInterrupt(ADC_INT_CS);
//=========================ADC中断使用=================================================
NVIC_EnableIRQ(ADC_COMP_IRQn);//
NVIC_SetPriority(ADC_COMP_IRQn,0);
ADC_DMARequestMode(ADC_DMA_MODE_CIRCULAR);
ADC_EnableDMA();
ADC_Enable();
ADC_StartConversion();//必需要启动一下
/* Config ADC Channel GPIO */
GPIO_Config_T GPIO_InitStructure;
GPIO_InitStructure.pin = GPIO_Pin_ADC_VDC;//pin
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;//GPIO speed
GPIO_InitStructure.mode = GPIO_MODE_AN;//GPIO configured as analog input
GPIO_InitStructure.pupd = GPIO_PUPD_NO;//no pull-up and pull-down
GPIO_Config(GPIO_ADC_VDC, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_Handle;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_Handle, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_IU;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_IU, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_IV;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_IV, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_IBUS;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_IBUS, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_UV;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_UV, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_VV;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_VV, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_WV;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_WV, &GPIO_InitStructure);
}
3.2.启动ADC转换
/* Wait until ADC is ready 等待ADC准备好*/
while (!ADC_ReadStatusFlag(ADC_FLAG_ADRDY));
ADC_StartConversion();//开启ADC转换
__enable_irq(); //Enable all interrupts
3.3.ADC中断
当产生中断时,读取ADC的转换结果,并将之保存,注意转换结果是按通道顺序排列。
uint16_t chnlvcur[50] = {0};
uint16_t chnlucur[50] = {0};
uint16_t chnlibus[50] = {0};
uint16_t chnluvol[50] = {0};
uint16_t chnlvvol[50] = {0};
uint16_t chnlwvol[50] = {0};
uint16_t chnlsvol[50] = {0};
uint16_t chnlinvol[50] = {0};
uint16_t i = 0;
void ADC_COMP_IRQHandler(void)
{
chnlvcur = (int16_t)ADC_GetValue(CURR_CHANNEL_V);
chnlucur = (int16_t)ADC_GetValue(CURR_CHANNEL_U);
chnlibus = (int16_t)ADC_GetValue(IBUS_CHANNEL);
chnlsvol = (int16_t)ADC_GetValue(Handle_CHANNEL);
chnlinvol = (int16_t)ADC_GetValue(VDC_CHANNEL);
chnluvol = (int16_t)ADC_GetValue(VOL_CHANNEL_U);
chnlvvol = (int16_t)ADC_GetValue(VOL_CHANNEL_V);
chnlwvol = (int16_t)ADC_GetValue(VOL_CHANNEL_W);
i++;
if(i>= 50)
{
i = 0;
}
}
}
4.代码运行结果查看
6.测试情况及数据
以下表电机工作时和不工作时,ADC采集的电压值作为比较,发现电机不工作时,这时电流波动较小,电压采集结果稳定,误差小。而在电机工作时,发现偶尔会出现电压值偏差很大,并且是正偏或负偏很大的值都偶尔出现,通过该测试可以发现,我们ADC在面对电流变化复杂的情况,不仅软件需要做滤波,硬件也需要处理好电源的突然变化。针对该评估板对动态输入电压对ADC的影响,可以每十组数据,去掉最大值和最小值,进行均值滤波,就可以将这种现象带来的误差减小到最小。
序号 |
输入电压(电机工作) |
输入电压(电机不工作) |
0 |
1360 |
1358 |
1 |
1352 |
1359 |
2 |
1362 |
1361 |
3 |
1361 |
1358 |
4 |
1361 |
1358 |
5 |
1361 |
1358 |
6 |
1355 |
1358 |
7 |
1359 |
1358 |
8 |
1360 |
1358 |
9 |
1361 |
1358 |
10 |
1361 |
1359 |
11 |
1360 |
1358 |
12 |
1525 |
1359 |
13 |
1348 |
1358 |
14 |
1367 |
1359 |
15 |
1358 |
1358 |
16 |
1371 |
1359 |
17 |
1752 |
1358 |
18 |
1328 |
1358 |
19 |
1361 |
1359 |
20 |
1360 |
1359 |
21 |
1361 |
1359 |
22 |
1361 |
1358 |
23 |
1359 |
1358 |
24 |
1399 |
1359 |
25 |
1361 |
1358 |
26 |
1361 |
1358 |
27 |
1361 |
1358 |
28 |
1360 |
1359 |
29 |
1360 |
1359 |
30 |
1361 |
1358 |
31 |
1361 |
1358 |
32 |
1361 |
1358 |
33 |
1361 |
1358 |
34 |
1120 |
1359 |
35 |
1359 |
1358 |
36 |
1356 |
1358 |
37 |
1363 |
1358 |
38 |
1347 |
1358 |
39 |
1247 |
1358 |
40 |
1715 |
1359 |
41 |
1198 |
1359 |
42 |
1361 |
1359 |
43 |
1361 |
1358 |
44 |
1361 |
1358 |
45 |
1361 |
1359 |
46 |
1357 |
1358 |
47 |
1362 |
1358 |
48 |
1361 |
1358 |
49 |
1361 |
1359 |
7.综合评价
通过这次测试,可以看出该芯片的ADC精度高,采样时间和采集值都表现不错。