【STM32】STM32CUBEMX + ADC(单通道,双通道DMA)

2023-11-04

STM32CUBEMX + ADC(单通道,双通道DMA)

案例应用 :使用ADC采集电压(单通道、单通道+DMA、双通道+DMA),并利用串口打印采集转换后的电压值

1.工具

2.工程配置

2.1 单通道

2.1.1系统时钟RCC、SYS配置
在这里插入图片描述
2.1.2 ADC配置,这里强调2点,

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

    (F4)最小转换时间:

    ​ 12bit——>15周期

    ​ 10bit——>13周期

    ​ 8bit——>11周期

    ​ 6bit——> 9周期
    在这里插入图片描述

  • 注入模式,可以这样理解:把注入模式看作为中断,若果有注入,注入优先(相较于规则),完成之后在继续规则模式
    在这里插入图片描述
    2.1.3 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目

​ 重定义printf函数具体见:【STM32】STM32CUBEMX+UART串口调试,循环接受发送数据

  • 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);
      }
    }
    
    

    2.2 单通道+DMA

    2.2.1 STM32CUBEMX配置与单通道大致一样,需要修改的见下图(开启DMA请求,并在DMA配置中添加ADC1
    在这里插入图片描述

    ——>注意:DMA配置里要选择 Mode选择Circular,Data Width选择 Word,(如果是HalfWord,则会将采集到的数值进行合并,范围超出2^12 = 4096)
    在这里插入图片描述

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 */
}

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

2.3 多通道+DMA

2.3.1 STM32CUBEMX配置与单通道+DMA大致一样,需要修改的见下图(2个通道IN4、IN6, 开启连续扫描模式;并注意Rank下选择不同的通道,不配置默认通道 相同,我刚开始没有配置,结果2个引脚采集的值一样,浪费了半天时间找原因…)
在这里插入图片描述
在这里插入图片描述

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);
    
      }
      
    
    
    }
    

函数HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);//第三个参数我还是不明白,但是支持数据量,库函数这样解释:
在这里插入图片描述
很多人说是数据量,不是长度,我很纳闷(数据量分2种情况:

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

如有不同见解可留言

ADC单通道采集:STM32CUBEMX+ADC采集,STM32F411VET6, IAR

ADC单通道+DMA采集:STM32CUBEMX+ADC单通道+DMA采集,STM32F411VET6, IAR

ADC多通道+DMA采集:STM32CUBEMX+ADC双通道+DMA采集,STM32F411VET6, IAR

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【STM32】STM32CUBEMX + ADC(单通道,双通道DMA) 的相关文章

  • 具有可绑定属性的自定义视图未在 Xamarin.Forms SAP 上正确绑定

    我有一个复选框 应该触发按钮的 IsEnabled 事件 但不知何故 应该执行的命令永远不会正确绑定并因此执行 这是 CheckBox xaml cs 控件 中的可绑定属性 public static readonly BindablePr
  • SharpZipLib - 将文件夹/目录添加到 zip 存档

    通过示例 我很好地掌握了如何提取 zip 文件 几乎在每个示例中 识别 ZipEntry 是否为目录的方法如下 string directoryName Path GetDirectoryName theEntry Name string
  • 在Application_AquireRequestState事件中用POST数据重写Url

    我有一个在其中注册路线的代码Application AcquireRequestState应用程序的事件 注册路由后 我会在 Http 运行时缓存中设置一个标志 这样我就不会再次执行路由注册代码 在此事件中注册路线有特定原因Applicat
  • 从 future 中检索值时的 SIGABRT

    我在使用 C 11 future 时遇到问题 当我打电话时wait or get 关于返回的未来std async 程序接收从mutex标头 可能是什么问题呢 如何修复它 我在 Linux 上使用 g 4 6 将以下代码粘贴到 ideone
  • 导出类时编译器错误

    我正在使用 Visual Studio 2013 但遇到了一个奇怪的问题 当我导出一个类时 它会抛出 尝试引用已删除的函数 错误 但是 当该类未导出时 它的行为会正确 让我举个例子 class Foo note the export cla
  • Paradox 表 - Oledb 异常:外部表不是预期的格式

    我正在使用 Oledb 从 Paradox 表中读取一些数据 我遇到的问题是 当我将代码复制到控制台应用程序时 代码可以工作 但在 WinForms 中却不行 两者都以 x86 进行调试 我实际上只是复制代码 在 WinForms 应用程序
  • 指向字节数组的指针

    由于 Misra C 的要求 我的一位同事想要使用指针声明 但我遇到了一些问题 Misra 安全关键指南 不会让我们纯粹的程序员使用指针 但会让我们对数组字节进行操作 他打算获取一个指向字节数组的指针 因此我们不会在堆栈上传递实际的数组 T
  • 无法加载文件或程序集“EntityFramework,版本=6.0.0.0”

    我究竟做错了什么 我该如何解决这个问题 我有一个包含多个项目的解决方案 它是一个 MVC NET 4 5 Web 应用程序 在调试模式下启动后调用其中一个项目时 出现此错误 导致此错误的项目具有以下参考 两个都是版本6 0 0 0 应用程序
  • 格式化货币

    在下面的示例中 逗号是小数点分隔符 我有这个 125456 89 我想要这个 125 456 89 其他示例 23456789 89 gt 23 456 789 89 Thanks 看看这个例子 double value 12345 678
  • 如何用 C 语言练习 Unix 编程?

    经过五年的专业 Java 以及较小程度上的 Python 编程并慢慢感觉到我的计算机科学教育逐渐消失 我决定要拓宽我的视野 对世界的一般用处 并做一些 对我来说 感觉更重要的事情就像我真的对机器有影响一样 我选择学习 C 和 Unix 编程
  • 系统错误 124 - SHFileOperation 的 ERROR_INVALID_LEVEL

    我在使用时遇到问题SHFileOperation SHFileOperation SHFILEOPSTRUCT https stackoverflow com questions 9191415 shfileoperation shfile
  • 从事务范围调用 WCF 服务方法

    我有这样的代码 using TransactionScope scope TransactionScopeFactory CreateTransactionScope some methodes calls for which scope
  • .NET JIT 编译的代码缓存在哪里?

    NET 程序首先被编译为 MSIL 代码 当它被执行时 JIT编译器会将其编译为本机机器代码 我想知道 这些JIT编译的机器代码存储在哪里 它只存储在进程的地址空间中吗 但由于程序的第二次启动比第一次快得多 我认为即使在执行完成后 该本机代
  • 相当于 C# 中 Java 的“ByteBuffer.putType()”

    我正在尝试通过从 Java 移植代码来格式化 C 中的字节数组 在 Java 中 使用方法 buf putInt value buf putShort buf putDouble 等等 但我不知道如何将其移植到 C 我尝试过 MemoryS
  • 从 C 线程调用 Python 代码

    我对从 C 或 C 线程调用 Python 代码时如何确保线程安全感到非常困惑 The Python 文档 http docs python org c api init html non python created threads似乎是
  • 如何访问窗口?

    我正在尝试使用其句柄访问特定窗口 即System IntPtr value Getting the process of Visual Studio program var process Process GetProcessesByNam
  • “int i=1,2,3”和“int i=(1,2,3)”之间的区别 - 使用逗号运算符的变量声明[重复]

    这个问题在这里已经有答案了 int i 1 2 3 int i 1 2 3 int i i 1 2 3 这些说法有什么区别 我无法找出任何具体原因 Statement 1 Result Compile error 运算符的优先级高于 运算符
  • #pragma pack(16) 和 #pragma pack(8) 的效果总是相同吗?

    我正在尝试使用来对齐数据成员 pragma pack n http msdn microsoft com en us library 2e70t5y1 28v vs 100 29 aspx 以下面为例 include
  • 如何获取 QIcon 的文件/资源​​路径

    假设我做了这样的事情 QIcon myIcon resources icon ico 我稍后如何确定该图标的路径 例如 QString path myIcon getPath 问题是 没有getPath 会员 我找不到类似的东西 但肯定有办
  • 从有符号字符转换为无符号字符然后再转换回来?

    我正在使用 JNI 并有一个 jbyte 类型的数组 其中 jbyte 表示为有符号字符 即范围从 128 到 127 jbyte 表示图像像素 对于图像处理 我们通常希望像素分量的范围为0到255 因此 我想将jbyte值转换为0到255

随机推荐