相关代码编写
配置好后点击生成代码,在生成代码的adc.c文件中的初始化函数MX_ADC1_Init中添加如下代码:
HAL_ADCEx_Calibration_Start(&hadc1); /* 校准ADC */
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC_Value,ADC_DMA_BUF_SIZE);
在stm32f1xx_it.c文件的DMA中断服务函数DMA1_Channel1_IRQHandler中添加如下代码 :
if(__HAL_DMA_GET_FLAG(&hdma_adc1,DMA_FLAG_TC1))//传输完成
{
g_adc_dma_sta = 1;//标志位置1
__HAL_DMA_CLEAR_FLAG(&hdma_adc1,DMA_FLAG_TC1);//清除传输完成标志位
}
ADC的采集代码如下所示:
/* Includes ------------------------------------------------------------------*/
#include "adc_driver.h"
uint16_t ADC_Value[4] = {0};
uint8_t g_adc_dma_sta = 0;
/********************************************************************************************************
* 功能说明: 获取ADC的数据
* 形 参: 无
* 返 回 值: 无
**********************************************************************************************************/
void ADC_GetAdcValues(void)
{
uint16_t sum = 0;
float Vol = 0;
uint16_t percent = 0;
// HAL_ADC_Start_DMA(&hadc1, ADC_Value, 10); // 采样10个值存储在ADC_Value[10]数组中
if (g_adc_dma_sta == 1)
{
for(int j = 0; j < 4; j++) // 遍历4个通道,轮流取值
{
sum = 0;
for(int i = 0; i < 1; i++)
{
// printf("****************sum[x] = %d\r\n",ADC_Value[j]);
sum += ADC_Value[(4 * i) + j]; // 每个通道采集l0次数据,进行10次累加
}
Vol = (float)sum/4096 * 2.5;
percent = (float)sum/4096 * 100;
// sum = sum / 10; // 取平均值
// printf("sum[%d] = %d\r\n",j,sum);
// printf("Vol[%d] = %.2f\r\n",j,Vol);
if(j == 0)
{
Can_data.Txbuf[2] = percent;
printf("*****大制动区= %d %%\r\n",percent);
}
if(j == 1)
{
Can_data.Txbuf[0] = percent;
printf("制动区= %d %%\r\n",percent);
}
}
// printf("sum[x] = %d\r\n",sum);
g_adc_dma_sta = 0; // 清除DMA采集完成标志位
// HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC_Value, 4); // 开启下一次ADC和DMA采集
// HAL_ADC_Start(&hadc1);//
}
}
问题总结
使能连续转换模式 hadc1.Init.ContinuousConvMode = ENABLE;,程序才会一直进 DMA中断函数DMA1_Channel1_IRQHandler
ADC校准可以使ADC采集值和 Vref参考值(基准电压)接近。但是f4系列不支持。
HAL_ADCEx_Calibration_Start(&hadc1); /* 校准ADC */