打印
[其他ST产品]

STM32CUBEMX + ADC

[复制链接]
1357|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
STM32CUBEMX + ADC(单通道,双通道DMA)STM32CUBEMX + ADC(单通道,双通道DMA)
案例应用 :使用ADC采集电压(单通道、单通道+DMA、双通道+DMA),并利用串口打印采集转换后的电压值
1.工具
IAR
STM32CUBEMX
开发板STM32F411VET6
预备知识参见:【STM32】HAL库 STM32CubeMX教程九—ADC
2.工程配置
2.1 单通道
2.1.1系统时钟RCC、SYS配置





12411656195becf225.png (118 KB )

12411656195becf225.png

使用特权

评论回复
沙发
gaonaiweng|  楼主 | 2023-11-25 14:44 | 只看该作者
2.1.2 ADC配置,这里强调2点,

使用ADC1——>IN4(通道4),本案例使用F4开发版,在12bit分辨率下,最小转换时间为15周期(最小转换时间 > 采样时间,具体可以百度),本案例转换时间为 15/16M = 0.937us

(F4)最小转换时间:

​ 12bit——>15周期

​ 10bit——>13周期

​ 8bit——>11周期

​ 6bit——> 9周期

使用特权

评论回复
板凳
gaonaiweng|  楼主 | 2023-11-25 14:45 | 只看该作者
注入模式,可以这样理解:把注入模式看作为中断,若果有注入,注入优先(相较于规则),完成之后在继续规则模式

2.1.3 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目

使用特权

评论回复
地板
gaonaiweng|  楼主 | 2023-11-25 14:45 | 只看该作者
main.c
#include "main.h"
#include "adc.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
void SystemClock_Config(void);

uint32_t ADC_Value;

int main(void)
{
  HAL_Init();
  SystemClock_Config();

  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_USART2_UART_Init();

  printf("start\r\n");
  while (1)
  {
     HAL_ADC_Start(&hadc1);     //启动ADC转换
     HAL_ADC_PollForConversion(&hadc1, 50);   //等待转换完成,50为最大等待时间,单位为ms

     if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
    {
      ADC_Value = HAL_ADC_GetValue(&hadc1);   //获取AD值

      printf("ADC1 Reading : %d \r\n",ADC_Value);//采样的值
      printf("PA4 True Voltage value : %.4f \r\n",ADC_Value*3.3f/4096);
          //转化后的电压值
      }
          HAL_Delay(1000);
  }
}

使用特权

评论回复
5
gaonaiweng|  楼主 | 2023-11-25 14:45 | 只看该作者
2.2 单通道+DMA
2.2.1 STM32CUBEMX配置与单通道大致一样,需要修改的见下图(开启DMA请求,并在DMA配置中添加ADC1)

使用特权

评论回复
6
gaonaiweng|  楼主 | 2023-11-25 14:45 | 只看该作者
注意:DMA配置里要选择 Mode选择Circular,Data Width选择 Word,(如果是HalfWord,则会将采集到的数值进行合并,范围超出2^12 = 4096)

使用特权

评论回复
7
gaonaiweng|  楼主 | 2023-11-25 14:46 | 只看该作者
2.2.2 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目

main.c
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"

void SystemClock_Config(void);

uint32_t ADC_Value[100];
uint8_t i;
float ad1 = 0;

int main(void)
{
  HAL_Init();
  SystemClock_Config();

  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_USART2_UART_Init();
  //开启ADC_DMA采集
  HAL_ADC_Start_DMA(&hadc1, ADC_Value, 100);//DMA自动把对应的通道值放入ADC_Value数组内
  
  while (1)
  {
    //数据处理 与 DMA存值 不同步 ,在这里判断下转换是否完成,完成则进行数据处理
     if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
     {         
                  for(i = 0; i < 100; i++)//数据处理 与 DMA存值 不同步  
                  {
                        ad1 += ADC_Value[i];      
                  }  
                       ad1 /=  100.0;
                       printf("PA4 Reading Vol Value: %.4f \r\n", ad1*3.3f/4096);
                       HAL_Delay(500);
       
     }
   
  }
  /* USER CODE END 3 */
}

使用特权

评论回复
8
gaonaiweng|  楼主 | 2023-11-25 15:04 | 只看该作者
DMA:搬运数据思想
将一块内存的数据搬到另外一块内存,(注意内存可位于系统内部,也可位于外部设备,其实就是一块地址,形象的可理解为buf[], 某个寄存器等。)
在搬运的时候,1次搬运的数据大小必须是2的n次方(n= 0,1…),只要设置好相应外设的dma映射通道号(这一部分是由hardware designer设计的),以及其他相应配置,并使能DMA功能, 它就自动开始搬运了,(内存到内存这种方式是相对较快的)。

使用特权

评论回复
9
gaonaiweng|  楼主 | 2023-11-25 15:04 | 只看该作者
2.3 多通道+DMA
2.3.1 STM32CUBEMX配置与单通道+DMA大致一样,需要修改的见下图(2个通道IN4、IN6, 开启连续扫描模式;并注意Rank下选择不同的通道,不配置默认通道 相同,我刚开始没有配置,结果2个引脚采集的值一样,浪费了半天时间找原因…)

使用特权

评论回复
10
gaonaiweng|  楼主 | 2023-11-25 15:05 | 只看该作者

使用特权

评论回复
11
gaonaiweng|  楼主 | 2023-11-25 15:05 | 只看该作者
2.3.2 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目

main.c
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"

uint32_t ADC_1 = 0, ADC_2 = 0;
uint32_t ADC_Value[100];
uint8_t i;

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_USART2_UART_Init();

  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 100);//100数据量
  printf("ADC Sampling start\r\n");

  while (1)
  {
     
      HAL_Delay(500);//这里不加延时,采集输出值第一次为0
      for(i=0; i<100;)
     {
      ADC_1 = ADC_Value[i++];   
      ADC_2 = ADC_Value[i++];
     }
      printf("double channel ADC test\r\n");
      printf("ADC_1 = %1.4f\r\n", ADC_1*3.3f/4096);
      printf("ADC_2 = %1.4f\r\n", ADC_2*3.3f/4096);

  }
  


}

使用特权

评论回复
12
gaonaiweng|  楼主 | 2023-11-25 15:06 | 只看该作者
函数HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);//第三个参数我还是不明白,但是支持数据量,库函数这样解释:

很多人说是数据量,不是长度,我很纳闷(数据量分2种情况:

1.单通道 1次将采集的length个数据存放到存储区,然后执行下一次采集存放,
2.多通道 1次将采集的length个数据存放到存储区,然后执行下一次采集存放,length应为
通道数的倍数 保证每个通道的数据量持平

使用特权

评论回复
13
Bblythe| | 2024-7-21 08:23 | 只看该作者

这样可以获得更光滑的表面。

使用特权

评论回复
14
童雨竹| | 2024-7-21 10:18 | 只看该作者

给电源加上额定电压,记录输出电流和电压值

使用特权

评论回复
15
Wordsworth| | 2024-7-21 11:21 | 只看该作者

这些半孔就是我们所说的邮票孔焊盘

使用特权

评论回复
16
Clyde011| | 2024-7-21 12:24 | 只看该作者

变压器副边同时对负载供电。

使用特权

评论回复
17
公羊子丹| | 2024-7-21 13:17 | 只看该作者

对称性结构,脉冲变压器原边是两个对称线圈,两只开关管接成对称关系,轮流通断,工作过程类似于线性放大电路中的乙类推挽功率放大器

使用特权

评论回复
18
万图| | 2024-7-21 14:20 | 只看该作者

当需要将单个模块板安装在另一个PCB的顶部

使用特权

评论回复
19
Uriah| | 2024-7-21 15:23 | 只看该作者

板与板(或空板)之间用邮票孔连接

使用特权

评论回复
20
帛灿灿| | 2024-7-21 17:19 | 只看该作者

这时候共模电流会被衰减

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

69

主题

697

帖子

3

粉丝