一、ADC几种模式
1、扫描模式: 使用STM32CUBEMX配置了多通道后,这一项默认开启且无法设置成关闭。这个模式就是自动扫描你开启的所有通道进行转换,直至转换完。例如你开启了CH0、CH1、CH2、CH3这四个通道,启动转换后ADC会自动将这4个通道全部转换完,但是这种连续性是可以被打断的,所以就引出了间断模式。
2、连续模式: 在CUBE中选中ENABLE就是连续模式,DISABLE就是单次模式。开启连续模式后,ADC的转换不由其他控制。例如将ADC设置为了定时器的TGRO触发采样,如果开启连续模式,ADC将忽略定时器的触发采样。(连续转换模式开启后其实就是满频率的采样)。
3、间断模式: 可以将多个通道进行分组采集,例如你开启了CH0~3这4个通道,假如你设置了间断次数为4,就相当于将4个通道分成了4组,每组1个通道,那么要想采集完这4个通道就需要手动触发4次ADC采集;如果设置了间断次数为2,那么采集完4个通道就需要手动触发2次ADC采集。
二、配置ADC单通道采集
while (1)
{
HAL_ADC_Start(&hadc1); //启动ADC转换
HAL_ADC_PollForConversion(&hadc1, 50); //等待转换完成,50为最大等待时间,单位为ms
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))//判断ADC转换是否完成
{
ADC_Value = HAL_ADC_GetValue(&hadc1); //获取AD值
printf("ADC1 Reading : %d \r\n",ADC_Value);
printf("PA5 True Voltage value : %.4f \r\n",ADC_Value*3.3f/4096);
}
HAL_Delay(1000);
}
三、轮询模式的多通道采集(同单通道)
uint32_t ADC_Get_Average(uint32_t Channel,uint8_t times)
{
ADC_ChannelConfTypeDef sConfig; //通道初始化
uint32_t value_sum=0;
uint8_t i;
sConfig.Channel = Channel;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; //采用周期239.5周期
sConfig.Rank = 1;
HAL_ADC_ConfigChannel(&hadc1,&sConfig);
for(i=0;i<times;i++)
{
HAL_ADC_Start(&hadc1); //启动转换
HAL_ADC_PollForConversion(&hadc1,30); //等待转化结束
value_sum += HAL_ADC_GetValue(&hadc1); //求和
HAL_ADC_Stop(&hadc1); //停止转换
}
return value_sum/times; //返回平均值
}
while (1)
{
SEGGER_RTT_printf(0,"ADC_CHANNEL_10 AD:%d\r\n",ADC_Get_Average(ADC_CHANNEL_10,30));
SEGGER_RTT_printf(0,"ADC_CHANNEL_11 AD:%d\r\n",ADC_Get_Average(ADC_CHANNEL_11,30));
SEGGER_RTT_printf(0,"ADC_CHANNEL_12 AD:%d\r\n",ADC_Get_Average(ADC_CHANNEL_12,30));
SEGGER_RTT_printf(0,"ADC_CHANNEL_13 AD:%d\r\n\r\n",ADC_Get_Average(ADC_CHANNEL_13,30));
HAL_Delay(200);
/* USER CODE BEGIN 3 */
}
四、DMA实现多通道采集
4.1 STM32Cubemx配置
(1)Data Alignment--->Right alignment 此项选择右对齐,保持不变。
(2)Scan Conversion Mode--->Enable 此项选择扫描模式使能,代表对15路ADC输入分别扫描,如果不使能,其将会只读取一个输入的值。
(3)Continuous Conversion Mode --->Enable 此项选择连续扫描模式,表示将连续不断的对ADC的值进行转换。如果此项不使能,将会只采集一次就会停止,直到下一次使能才继续进行一次ADC转换。
(4)Discontinuous Conversion Mode--->Disable 此项和第三项是重复的。
(5)Number of Conversion---->15 此处有多少路输入就选择多少,而且只有在此处选择数字之后下面才会出来15个不同的通道。而且此处应该是在进入ADC1中第一个需要操作的步骤,否则(2)(3)是灰色的,无法选择使能。
(6)在出现的15个Rank中,分别配置每一路,例如Rank1配置为Channel 0,采样时间55.5Cycles; Rank2配置为Channel 1,采样时间同样为55.5Cycles。此处的注意事项是,如果你不对每一路进行检查配置,可能出现好多Rank同时采集一个Channel,从而导致AD的采集数据的错误。
4.2 采集一次
uint16_t ADC_Value[5];
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC_Value,sizeof(ADC_Value) / sizeof(ADC_Value[0]));
while (1)
{
/* USER CODE END WHILE */
SEGGER_RTT_printf(0,"%d %d %d %d %d\r\n",ADC_Value[0],ADC_Value[1],ADC_Value[2],ADC_Value[3],ADC_Value[4]);
HAL_Delay(1000);
/* USER CODE BEGIN 3 */
}
4.3 多次采集求平均值
#define FILTER_NUM 30
#define ADC_CHANNELS 5
uint16_t ADC_ConvertedValue[FILTER_NUM][ADC_CHANNELS];
uint16_t getADC_CH(uint8_t channel)
{
uint16_t tbuf[FILTER_NUM];
uint32_t tdat = 0;
// 判断传入参数是否合法
if (channel >= ADC_CHANNELS)
{
return 0;
}
for (int i = 0; i < FILTER_NUM; i++)
{
tbuf[i] = ADC_ConvertedValue[i][channel];
}
for (int i = 0; i < FILTER_NUM; i++)
{
tdat += tbuf[i];
}
tdat = tdat/FILTER_NUM;
if (tdat < 5)
{
tdat = 0;
}
return tdat;
}
int main()
{
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&ADC_ConvertedValue, FILTER_NUM * ADC_CHANNELS);
while (1)
{
for (int i = 0; i < ADC_CHANNELS; i++)
{
SEGGER_RTT_printf(0,"getADC_CH[%d] = %d\r\n", i, getADC_CH(i));
}
HAL_Delay(1000);
}
}