STM32CubeMX系列|ADC模数转换

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/(212) = 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: %d\r\n",AD_Value);
  Vol_Value = AD_Value*(3.3/4096);	//AD值乘以分辨率即为电压值
  printf("ADC1_IN1 VOL value: %.2fV\r\n",Vol_Value);
  
  HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
  HAL_Delay(1000);
}

4. 下载验证

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

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Chuangke_Andy/article/details/108768563