STM32CubeMX系列 | ADC模数转换

2023-03-21  

ADC模数转换

1. ADC简介

ADC(analog to digital converter)即模数转换器,它可以将模拟量信号转换为数字信号,按照转换原理主要分为逐次逼近型、双积分型、电压频率转换型三种。STM32F1的ADC是12位逐次逼近型的模数转换器,它有18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位存储寄存器中。模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阈值。ADC的时钟不要超过14M,否则将导致结果准确度下降。ADC结构框图以及ADC引脚说明如下图示:

  • 电压输入引脚和输入通道引脚见上表;另外主ADC1中还有2个内部通道:通道16连接到芯片内部的温度传感器,通道17连接到了内部参考电压 VREFINT ;ADC2/ADC3的通道16/17都连接到了内部的 VSS

  • ADC的转换分为两个通道组:规则通道组(16路)和注入通道组(4路),规则通道相当于正常运行的程序,注入通道相当于中断

  • 选择好输入通道和转换顺序后需要使能ADC,可以直接开启ADC转换或者选择外部事件触发转换

  • ADC最大工作频率为14M,一般设置分配因子为6,即ADC的输入时钟ADC_CLK = 12M

  • ADC要完成对输入电压的采样需要若干个ADC_CLK周期,采样周期最小是1.5个(即如果要达到最快的采样,应设置采样周期为1.5个周期,即1.5乘以1/ADC_CLK)

  • ADC的总转换时间 Tconv = 采样时间 + 12.5个周期;按以上设置的话, Tconv = (1.5+12.5)个周期 = 14 * (1/12M) = 1.17us,即最短转换时间为1.17us

  • ADC转换后的数据根据不同的转换组,放在不同的数据寄存器(16位)中;由于ADC是12位转换精度,而数据寄存器是16位,因此存放数据的时候有左对齐和右对齐之分

  • 规则组含有16个通道但是对应存放数据的寄存器只有一个,如果使用多通道转换则应当在通道转换完成后就把数据取走,或者开启DMA模式把数据传输到内存里,否则就会造成数据的覆盖

  • 使能相应中断标志位,ADC能3种产生相应中断:规则转换与注入转换结束、模拟看门狗事件、DMA请求

2. 硬件设计

本实验通过ADC1通道1采样外部电压值,将采样的AD值和转换后的电压值通过USART1串口打印出来,同时D1指示灯闪烁,提示系统正常运行

  • D1指示灯

  • ADC1_INT1

  • USART1串口

  • 电位器

3. 软件设计

3.1 STM32CubeMX设置

  • RCC设置外接HSE,时钟设置为72M,ADC预分频因子设置为6,ADC_CLK为12MHz

  • PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平

  • USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位

  • 激活ADC1通道1,设置右对齐,关闭扫描、连续及间断模式,使能regular conversion,设置软件触发、设置采样时间1.5个周期

  • 输入工程名,选择工程路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码

3.2 MDK-ARM编程

  • 在adc.c文件中可以看到ADC初始化函数

void MX_ADC1_Init(void){

  ADC_ChannelConfTypeDef sConfig = {0};

  hadc1.Instance = ADC1;

  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;

  hadc1.Init.ContinuousConvMode = DISABLE;

  hadc1.Init.DiscontinuousConvMode = DISABLE;

  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;

  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

  hadc1.Init.NbrOfConversion = 1;

  if (HAL_ADC_Init(&hadc1) != HAL_OK){

    Error_Handler();

  }

  /** Configure Regular Channel*/

  sConfig.Channel = ADC_CHANNEL_1;

  sConfig.Rank = ADC_REGULAR_RANK_1;

  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){

    Error_Handler();

  }

}


void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle){

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  if(adcHandle->Instance==ADC1){

    /* ADC1 clock enable */

    __HAL_RCC_ADC1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_1;

    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  }

}

在主函数while循环中添加如下测试程序,ADC1是12位转换精度,因此电压分辨率为:3.3/  = 3.3/4096

while (1){

  HAL_ADC_Start(&hadc1);    //启动ADC转换

  HAL_ADC_PollForConversion(&hadc1,10); //等待转换完成,10ms表示超时时间

  AD_Value = HAL_ADC_GetValue(&hadc1);  //读取ADC转换数据(12位数据)

  printf("ADC1_IN1 ADC value: %drn",AD_Value);

  Vol_Value = AD_Value*(3.3/4096);  //AD值乘以分辨率即为电压值

  printf("ADC1_IN1 VOL value: %.2fVrn",Vol_Value);


  HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);

  HAL_Delay(1000);

}


4. 下载验证

编译无误后下载到开发板,可以看到系统运行时D1指示灯不断闪烁,调节电位器时,获取的AD转换值和电压值将变化,并通过串口打印出来


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。