1、ADC简介
ADC:Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。简单地说就是将模拟电压值,转换成对应的肉眼可读数值(典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。)
12位ADC是一种逐次逼近型模拟数字转换器。STTM32F407有3个ADC控制器,多达18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中(12位存储在16位寄存器中,有两种对齐方式----左对齐和右对齐)。
12位对应4096即存储最大值是4096,转换电压数据如下;
18个通道对应16个可测量引脚电压,两个内部信号源(内部温度传感器,内部参考电压)
2、ADC转换模式(重要)
1 单次转换模式:ADC只执行一次转换;
2 连续转换模式:转换结束之后马上开始新的转换;
3 扫描模式:ADC扫描被规则通道和注入通道选中的所有通道,在每个组的每个通道上执行单次转换。在每个转换结束时,这一组的下一个通道被自动转换。如果设置了CONT位(开启了连续 转换模式),转换不会在选择组的最后一个通道上停止,而是再次从选择组的第一个通道继续转换。
4 间断模式:触发一次,转换一个通道,在触发,在转换。在所选转换通道循环,由触发信号启动新一轮的转换,直到转换完成为止。
扫描模式简单的说是一次对所有所选中的通道进行转换,比如开了ch0,ch1,ch4,ch5。 ch0转换完以后就会自动转换通道1,4,5直到转换完这个过程不能被打断。如果开启了连续转换模式,则会在转换完ch5之后开始新一轮的转换。
这就引入了间断模式,可以说是对扫描模式的一种补充。它可以把0,1,4,5这四个通道进行分组。可以分成0,1一组,4,5一组。也可以每个通道单独配置为一组。这样每一组转换之前都需要先触发一
ADC单通道:
只进行一次ADC转换:配置为“单次转换模式”,扫描模式关闭。ADC通道转换一次后,就停止转换。等待再次使能后才会重新转换
进行连续ADC转换:配置为“连续转换模式”,扫描模式关闭。ADC通道转换一次后,接着进行下一次转换,不断连续。
ADC多通道:
只进行一次ADC转换:配置为“单次转换模式”,扫描模式使能。ADC的多个通道,按照配置的顺序依次转换一次后,就停止转换。等待再次使能后才会重新转换
进行连续ADC转换:配置为“连续转换模式”,扫描模式使能。ADC的多个通道,按照配置的顺序依次转换一次后,接着进行下一次转换,不断连续。
也就是:多通道必须使能扫描模式
3、中断
中断触发条件有三个,规则通道转换结束,注入通道转换结束,或者模拟看门狗状态位被设置时都能产生中断,
ADC完成一次转换 可以产生完成信号EOC,或者进入中断
4、HAL单通道配置
4.1、单通道单次
HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout); //等待转换结束,只适用于轮询,注意配置转换时间
HAL_ADC_Start(ADC_HandleTypeDef* hadc);//轮询模式,需放在循环中不断开启
HAL_ADC_GetValue(ADC_HandleTypeDef *hadc) //从寄存器中的得到模拟数字
4.2、单通道连续
按理说将下图中的Disabled改成Enable即可
但是测试后并未实现连续的功能,后续再查找原因
5、HAl多通道配置(都要开启扫描模式)
ADC查询模式小总结:在关闭间断模式的情况下,多通道采集尽量不使用ADC查询模式(即在主函数while循环中)进行,不然采样值容易出错,如果要用一定要开启间断采样模式。
5.1、多通道单次
参数配置:
ADC非DMA多通道采集
while (1)
{
for(i=0;i<4;i++)
{
HAL_ADC_Start(&hadc1);//启动ADC转换,必须放在for循环中,否则只能采集第一个通道的ADC值;
HAL_ADC_PollForConversion(&hadc1,100); //用于轮询转换,是一个阻塞函数,等待转换完成,参数100ms是阻塞时间
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC)) {
//判断转换完成标志位是否设置,为1的时候产生中断。
ADC_value=HAL_ADC_GetValue(&hadc1); //开始读ADC的值
}
}
}
5.2、多通道连续
开启Continuous conversion Mode
6、HAL配置单通道ADC+DMA
在每次完成ADC转换后,会产生完成标志或者进入中断
产生中断后回进入公共的中断服务函数,完成中断处理,中断服务函数最终会调用ADC转换完成回调函数,所以采集完成后在回调函数中处理。
在回调函数中,获取数据,可以在回调函数里将数据进行赋值,处理数据可以在主函数中处理,也可以在回调中处理。
中断中处理(需要开启相关的中断):
uint16_t adc_dma_temp=0;
uint8_t adc_dma_cnt=0;
uint32_t adc_dma_sum=0;
float voltage_temp=0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc==&hadc1)
{
adc_dma_sum+=adc_dma_temp;
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adc_dma_temp, 1);//获取数据后,开启下次转换
adc_dma_cnt++;
if(adc_dma_cnt>=20)
{
adc_dma_temp=(uint16_t)(adc_dma_sum/adc_dma_cnt);
voltage_temp=(float)adc_dma_temp*(3.3/4096);
printf("V:%f\n",voltage_temp);
adc_dma_cnt=0;
adc_dma_sum=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;
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adc_dma_temp, 1);//开启一次,让其进入中断
while (1)
{
HAL_Delay(5);
}
}
主函数中处理:
int main(void)
{
/* USER CODE BEGIN 1 */
uint16_t Adc_Dma_Data = 0;
float Voltage;
uint8_t adc_state = 0;
uint16_t T_Buf[100];
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_FSMC_Init();
lcd_init();
MX_USART1_UART_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)&Adc_Dma_Data,1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// HAL_ADC_Start_DMA(&hadc1,(uint32_t *)&Adc_Dma_Data,1);
Voltage = Adc_Dma_Data*(3.3/4096);
HAL_Delay(100);
sprintf((char*)T_Buf,"AdcData:%d",Adc_Dma_Data);
lcd_show_string(10,50,160,16,16,(char*)T_Buf,100);
sprintf((char*)T_Buf,"Voltage:%f",Voltage);
lcd_show_string(10,100,160,16,16,(char*)T_Buf,100);
HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);
HAL_Delay(100);
}
/* USER CODE END 3 */
}
HAL中需要配置:
可使得DMA连续转运数据,实现实时的变化
7、HAL配置多通道ADC+DMA
ADC的DMA模式小总结:DMA模式最简单,并且采样过程基本不会影响CPU,一般使用ADC的DMA模式进行采样。
参考这个文章的多通道配置
【CubeIDE】STM32 HAL库史上最详细教程(二):单/多通道ADC读取电压_pollforconversion-CSDN博客细看文章:【CubeIDE】STM32 HAL库史上最详细教程(二):单/多通道ADC读取电压_pollforconversion-CSDN博客
前文知识点参考文章:【STM32】HAL库 STM32CubeMX教程九---ADC_cubemx adc-CSDN博客