欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STM32CubeMX系列|ADC模数转换

程序员文章站 2022-04-01 23:12:20
...

ADC模数转换

1. ADC简介

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

STM32CubeMX系列|ADC模数转换
STM32CubeMX系列|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串口
  • 电位器

STM32CubeMX系列|ADC模数转换

3. 软件设计

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

STM32CubeMX系列|ADC模数转换

  • PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平
  • USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位
  • **ADC1通道1,设置右对齐,关闭扫描、连续及间断模式,使能regular conversion,设置软件触发、设置采样时间1.5个周期

STM32CubeMX系列|ADC模数转换

  • 输入工程名,选择工程路径(不要有中文),选择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转换值和电压值将变化,并通过串口打印出来

STM32CubeMX系列|ADC模数转换