这篇笔记以及学习参考了大佬的文章STM32CubeMX | HAL库的ADC多通道数据采集(轮训、DMA、DMA+TIM)、读取内部传感器温度_tim+adc+dma采集-CSDN博客

 江科大笔记—ADC模式转换_adc左对齐和右对齐区别-CSDN博客

一、基本原理

  1、ADC采样关键参数

  •        ADC的分辨率:

是指它能够将输入信号分成多少个离散的量化级别(份数)。通常用比特数来表示,例如stm32f103c8t6就是12位ADC,则分辨率为2^12=4096个量化级,(也可以一定程度上理解成精度)

  •         ADC采样时间

:完成一次采样的时间,这里以ADC时钟周期为单位

例:我使用的这款芯片ADC的时钟频率最高不能超过14Mhz,当我们的系统时钟频率为72Mhz时,ADC通道则必须使用6分频或者8分频,来保证ADC的时钟频率最高不能超过14Mhz

计算采样时间

                                        TCONV = 采样时间(由用户配置)+ 12.5个周期

  • 采样间隔时间

如果ADC的采样触发选用事件触发时,为保证采样准确性,间隔时间要大于采样时间

例如:选用定时器触发时,定时器的计数时间要大于采样时间。

  • 采样时间计算

计算得采样时间=(1/12M)*(55.5+12.5)=6.5us

  2、cubemax参数配置解读

  • Data alignment:                        数据对齐模式:分为左对齐和右对齐Right alignment

STM32中的ADC是12位(0-4095)的,但是数据寄存器拥有16位,故存在数据对齐的问题。
数据右对齐,即作为转换结果的12位数据向右靠,高位补0。
数据左对齐,即作为转换结果的12位数据向左靠,低位补0。

 一般通常使用数据右对齐,这样在读取16位寄存器,直接就是转换结果。
如果选择左对齐,直接读取,得到的数据会比实际的数据大,因为数据左对齐就是把数据左移4次,二进制特点:就是数据左移一次,就等效于把数据乘以2。这里左移4次,相当于乘以16,所以直接读取,得到的数据会比实际的数据大16倍。

左对齐用处:当对分辨率的要求不高时(对电压仅作大概的判断即可)可以采用左对齐,将数据寄存器的高8位取出,就相当于舍弃了转换结果的4位的精度,12位的ADC退化位为8位的ADC。

  •  Scan Conversion Mode:                  扫描模式(勾选了多通道后会默认打开)
  • Continuous Conversion Mode:      连续转换模式
  • DisContinuousConversion Mode:  间断转换模式

这三个参数需要放一起进行理解

  • 单次转换 非扫描模式        单次转换 扫描模式
  • 连续转换 非扫描模式        连续转换 扫描模式
  • 单次转换:

每触发一次,转换结束就会停下来,下次转换就得再触发才能开始。

  • 连续转换:

一次转换完成后不会停止,而是立刻开始下一轮的转换,并持续下去。

  • 非扫描模式:

只对存放在序列1的通道起作用。

  • 扫描模式:

可以根据配置的顺序依次采集多个ADC通道

小结:转换作用的是完整的采集之间是否的连续关系,扫描则是一次完整采集中的通道是否连续关系

  • 间断模式:

在扫描模式的情况下,还可以使用间断模式。它的作用是在扫描的过程中,每隔几次转换就暂停,需要再次触发才能继续。

  • 注入通道和看门狗

这个项目暂不涉及,先做了解即可

根据数据手册,可将注入通道理解为ADC里的中断,当注入通道触发时,暂停正在转换的规则通道,优先处理注入通道转换,完成后回到规则通道暂停的位置继续执行。

看门狗可以理解为事件中断,当转换的值低于或者高于配置的值时,就会触发中断。

 二、硬件连接

根据原理图连接硬件,要注意的是5V接VCC,因为stm32f103c8t6 的ADC采集范围只有0-3.3V,如果为5V的话,就会导致推杆有死区,在3.3-5V范围时数据皆为4095不改变。导致无法判定位置,所以接VCC就好,这样就不会有死区。

实物照片

三、cubemax项目配置

这里我选择DMA的方式接收数据,配置ADC分频为6分频,这时ADC时钟频率为12M

选ADC1的IN0和IN1以及一个内部温度通道

  • 勾选ADC1 通道

勾选ADC1的IN0和IN1以及一个内部温度通道

这里我们只用到了ADC1,所以ADC通用设置默认为独立(Independent)模式

  • 数据对齐

数据对齐为右对齐

  • 连续模式

连续模式关闭,在程序中手动循环开启达到循环的效果,还有一个因素是开启连续模式后会一直进行采集,而且DMA数据地址是递增的,假如存放地址的数组不够大的话就会导致数据溢出,程序 卡蹦,而且这样的话采集到的数据也难以辨认对应的哪条通道;

  • 间断模式

间断模式也关闭,执行几次转换后关闭,暂时不需要,我们配置的三个通道转换完成后自动停止,和这个功能重复,不需要再配置;

  • 触发源选择

触发源选择为软件触发,在程序中使用相应函数开启即可;

  • 将规则通道数配置

将规则通道数改为3条,然后根据需求配置三个通道顺序,采样时间均设置为55.5个周期

DMA配置,添加ADC1通道,配置为循环模式,字宽为半字

ok,配置完成生成工程。

四、代码

 main.c

#define   ADC_CHANNELS 3               // ADC通道数量
uint16_t  adc_buffer[ADC_CHANNELS];    // 数组存储三个通道的数据
float     voltage[ADC_CHANNELS];       // 转换后的电压值
char buff[20];                         //用来给OLED显示
float temp;                          //温度
//声明类型转换函数
void Float_To_Str(float num, char *buffer);

int main()
{

/*
省略cubemax生成的初始化代码
*/

//校正(初始化)ADC通道,让数据更精确
HAL_ADCEx_Calibration_Start(&hadc1);

while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
/*
手动开启ADC、DMA转换,转换完成会自动停止,
放循环里就实现了连续转换的效果
*/
  HAL_ADC_Start_DMA(&hadc1,(uint32_t*)adc_buffer,ADC_CHANNELS);
/*
我这里因为是使用OLED进行显示带有小数的数据
所以封装了一个将float类型转换为字符的函数

*/
  Float_To_Str(adc_buffer[0],buff);
  OLED_ShowString(1,1,buff);
//通过OLED显示数据,要使用的话记得配置OLED模块
  HAL_UART_Transmit(&huart2,buff,sizeof(buff),1000);
//通过串口阻塞模式将数据发送出去,要使用的话记得配置和使能串口

  Float_To_Str(adc_buffer[1],buff);
  HAL_UART_Transmit(&huart2,buff,sizeof(buff),1000);
  OLED_ShowString(2,1,buff);

  Float_To_Str(adc_buffer[2],buff);
  HAL_UART_Transmit(&huart2,buff,sizeof(buff),1000);
  OLED_ShowString(3,1,buff);
 
 //根据内部电压对应温度关系计算温度
  voltage[2]=(adc_buffer[2]*3.3)/4095;
  temp = (1430-voltage[2]*1000)/4.3+25;
  
  Float_To_Str(temp,buff);
  HAL_UART_Transmit(&huart2,buff,sizeof(buff),1000);
  OLED_ShowString(4,1,buff);
  }
  /* USER CODE END 3 */
}

void Float_To_Str(float num, char *buffer) 

void Float_To_Str(float num, char *buffer)
 {
    int integer = (int)num;
    int decimal = (int)((num - integer) * 100 + 0.5); // +0.5实现四舍五入

    if(decimal >= 100)
     { // 处理进位(如3.999→4.00)
        decimal -= 100;
        integer++;
    }

    // 格式化为字符串(如"123.45"),要包含头文件#include "stdio.h"
    sprintf(buffer, "%d.%02d   ", integer, decimal);
}

 五、实际效果演示

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐