【STM32】ADC|多通道ADC采集

本次实现的是ADC实现数字信号与模拟信号的转化,数字信号时不连续的,模拟信号是连续的。

1.ADC转化的原理

模拟-数字转换技术使用的是逐次逼近法,使用二分比较的方法来确定电压值
在这里插入图片描述
当单片机对应的参考电压为3.3v时,0~ 3.3v(模拟信号)对应0~4095(数字信号),假如我们知道一个数字信号的值为x,那么他对应的模拟信号
x/4095=y/3.3
y就是x对应的模拟信号
假如要确定0.8v对应的数字信号的值
在这里插入图片描述
他会将0.8v电压保存在电容中,然后先和3.3v的一半对应的1.65v(2048)做比较,如果小于1.65v的话,12位最高位就是0,因为1000 0000 0000 对应的就是2048

在这里插入图片描述
接着就是和1.65的一半比较,0.825v(1024)>0.8v,所以12位中倒数第二高位就是0,因为0.825(1024)对应二进制就是0100 0000 0000
在这里插入图片描述
接着0.8v和0.825的一半比较->0.4125v(512),0.8v>0.4125v,所以第三位为1,因为512对应的二进制为0010 00000000
在这里插入图片描述
按这个方法依次确定0.8v对应的12位的二进制数,然后这个二进制对应的十进制就是0.8v对应的数字信号的值
所以对应的过程是1.启动ADC 2.采样&转换 3.获取&计算,针对STM32F103C8T6芯片有10个外部通道,和两个内部通道(内部温度传感器,内部参考电压)进行ADC的转化,ADC1和ADC2,两个转化结构,每个转化结构都有一个注入组和一个规则组,我们现在只讲讲规则组,我们要对一个通道的电压值进行采集的时候,我们需要将这个通道注册进这个通道中,当启动ADC,然后采样转化的电压值就会放在规则通道数据寄存器(12位二进制值)中,等待获取

2.实操

在这里插入图片描述
单片机有一个电位器,通过旋转电位器,使得PA5的输出电压发送变化,我们将其输出到串口上去
在这里插入图片描述
对应的PA5刚好是ADC1的通道5

  char message[50]="";
  float v=0.0;
  int value=0;
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  { 
	  HAL_ADC_Start(&hadc1);//开启ADC1
	  HAL_ADC_PollForConversion(&hadc1,HAL_MAX_DELAY);//等待转换
	  value=HAL_ADC_GetValue(&hadc1);//从寄存器中获取电压值
	  v=(value/4095.0)*3.3;//转模拟信号
	  sprintf(message,"v:%.2f,value:%d",v,value);
	  HAL_UART_Transmit(&huart2,message,strlen(message),HAL_MAX_DELAY);
	  HAL_Delay(500);
   /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

在这里插入图片描述
但是发现一个问题,就是电位器扭到头
在这里插入图片描述
最大为3.25v,达不到3.3v,这是因为手册里面说
在这里插入图片描述

  char message[50]="";
  float v=0.0;
  int value=0;
  HAL_ADCEx_Calibration_Start(&hadc1);//校准
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  HAL_ADC_Start(&hadc1);//开启ADC1
	  HAL_ADC_PollForConversion(&hadc1,HAL_MAX_DELAY);//等待转换
	  value=HAL_ADC_GetValue(&hadc1);//从寄存器中获取电压值
	  v=(value/4095.0)*3.3;//转模拟信号
	  sprintf(message,"v:%.2f,value:%d",v,value);
	  HAL_UART_Transmit(&huart2,(uint8_t*)message,strlen(message),HAL_MAX_DELAY);
	  HAL_Delay(500);




    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

在这里插入图片描述
其实还有一种是循环转换,只需要开启一次ADC即可
在这里插入图片描述

  char message[50]="";
  float v=0.0;
  int value=0;
  HAL_ADCEx_Calibration_Start(&hadc1);//校准
  HAL_ADC_Start(&hadc1);//开启ADC1
  HAL_ADC_PollForConversion(&hadc1,HAL_MAX_DELAY);//等待转换
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	
	  value=HAL_ADC_GetValue(&hadc1);//从寄存器中获取电压值
	  v=(value/4095.0)*3.3;//转模拟信号
	  sprintf(message,"v:%.2f,value:%d",v,value);
	  HAL_UART_Transmit(&huart2,(uint8_t*)message,strlen(message),HAL_MAX_DELAY);
	  HAL_Delay(500);




    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

3.ADC多路采集

在前面说过,如果要获取对应通道的电压值,就需要将这个通道注册进规则组中,然后数据准备就绪, HAL_ADC_PollForConversion函数不断的检测ADC状态寄存器中转换结束标志位(EOC)是否为1,如果是,转换完成,将转换的值放入规则通道数据寄存器中,然后调用HAL_ADC_GetValue读取规则通道数据寄存器,然后对应的ADC状态寄存器中的转换结束标志位置0.
在多采集中需要将多个通道打开实现转换,会按照规则组注册顺序,依次将对应通道的电压值放入规则通道数据寄存器,然后写到内存中。
我们可以使用DMA来对规则通道数据寄存器的值搬运到内存,当搬运完成,就会触发DMA完成中断,进行处理转换后的值
本次实现热敏电阻,电位器,单片机内部温度,内部参考电压的ADC转换,并通过串口将其发送
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
PA4,PA5 ADC在ADC1的通道4,通道5上,以及内部温度通道,内部参考电压通道
在这里插入图片描述
注意将四个通道的多久采集值调到四个通道转换最大值,确保数据都已经被转换
在这里插入图片描述

uint16_t data[4];
char message[50]="";
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{

  if(hadc==&hadc1)
  {
	  sprintf(message,"%d %d %d %d",data[0],data[1],data[2],data[3]);
      HAL_UART_Transmit(&huart2, (uint8_t*)message,sizeof(message),HAL_MAX_DELAY);

  }

}
int main(void)
{

  HAL_Init();



 

  HAL_ADCEx_Calibration_Start(&hadc1);//校准

  while (1)
  {

	  HAL_ADC_Start_DMA(&hadc1,(uint32_t*)data,4);//开启ADC,DMA完成搬运调用DMA完成中断中断,在中断中发送转换值到串口
	  HAL_Delay(500);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

在这里插入图片描述
依次是电位器,热敏电阻,内部温度,内部参考电压未转化为模拟电压
除此之外我们可以使用循环转换,和DMA的循环搬运就可以实现开启一次ADC就可以一直将转换后的四个值发送到串口,因为会一直转换,不用知道什么时候转换完成,我们将发送到串口放到while中
在这里插入图片描述

uint16_t data[4];
char message[50]="";

int main(void)
{

  HAL_Init();



 

  HAL_ADCEx_Calibration_Start(&hadc1);//校准
 HAL_ADC_Start_DMA(&hadc1,(uint32_t*)data,4);//开启ADC,DMA完成搬运调用DMA完成中断中断,在中断中发送转换值到串口
  while (1)
  {

	  
	  sprintf(message,"%d %d %d %d",data[0],data[1],data[2],data[3]);
      HAL_UART_Transmit(&huart2, (uint8_t*)message,sizeof(message),HAL_MAX_DELAY);
	  HAL_Delay(500);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/967825.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从零到一:基于Rook构建云原生Ceph存储的全面指南(上)

文章目录 一.Rook简介二.Rook与Ceph架构2.1 Rook结构体系2.2 Rook包含组件1)Rook Operator2)Rook Discover3)Rook Agent 2.3 Rook与kubernetes结合的架构图如下2.4 ceph特点2.5 ceph架构2.6 ceph组件 三.Rook部署Ceph集群3.1 部署条件3.3 获取…

如何在本地部署deepseek?

1、打开ollama官网,点download(下载需要翻墙 https://ollama.com/ 2、双击下载好的OllamaSetup.exe,一直点下一步即可。 3、winR 输入cmd,打开命令提示符,输入ollama。有以下提示即安装完成。 4、可以根据 nvidia-…

团结引擎 OpenHarmony 平台全面支持 UAAL,实现引擎能力嵌入原生应用

团结引擎1.4版本已于近日正式发布!在这一版本中,OpenHarmony 平台迎来了一个具有里程碑意义的更新:全面支持 Used as a Library(UAAL)。UAAL 这一技术方案,具有将引擎嵌入原生应用的独特能力,其…

【DeepSeek】在本地计算机上部署DeepSeek-R1大模型实战(完整版)

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈人工智能与大模型应用 ⌋ ⌋ ⌋ 人工智能(AI)通过算法模拟人类智能,利用机器学习、深度学习等技术驱动医疗、金融等领域的智能化。大模型是千亿参数的深度神经网络(如ChatGPT&…

【Elasticsearch】Elasticsearch检索方式全解析:从基础到实战(二)

接着上一篇文章;我们继续来研究es的复杂检索 文章目录 (1) bool用来做复合查询(2)Filter【结果过滤】(3)term(4)Aggregation(执行聚合) (1) bool用来做复合查询 复合语…

如何使用DiskGenius做备份并且恢复?

如何使用DiskGenius做备份并且恢复? 前言 前言 此操作适用于将1台旧电脑的数据迁移到新电脑上 一、进入PE使用DG分区进行备份镜像 二、分区备份 1选择要操作的硬盘——2选择操作分区——3备份分区 1选择文件路径(保存pmf文件的位置选择存到U盘中&…

ZZNUOJ(C/C++)基础练习1091——1100(详解版)⭐

目录 1091 : 童年生活二三事(多实例测试) C C 1092 : 素数表(函数专题) C C 1093 : 验证哥德巴赫猜想(函数专题) C C 1094 : 统计元音(函数专题) C C 1095 : 时间间隔(多…

【Spring AI】基于SpringAI+Vue3+ElementPlus的QA系统实现一

整理不易,请不要吝啬你的赞和收藏。 1. 前言 这是 SpringAI 系列的第二篇文章,这篇文章将介绍如何基于 RAG 技术,使用 SpringAI Vue3 ElementPlus 实现一个 Q&A 系统。本文使用 deepseek 的 DeepSeek-V3 作为聊天模型,使用…

【Vue】在Vue3中使用Echarts的示例 两种方法

文章目录 方法一template渲染部分js部分方法一实现效果 方法二template部分js or ts部分方法二实现效果 贴个地址~ Apache ECharts官网地址 Apache ECharts示例地址 官网有的时候示例显示不出来,属于正常现象,多进几次就行 开始使用前,记得先…

1.【线性代数】——方程组的几何解释

1.方程组的几何解释 概述举例举例一1. matrix2.row picture3.column picture 概述 三种表示方法 matrixrow picturecolumn picture 举例 举例一 { 2 x − y 0 − x 2 y 3 \begin{cases} 2x - y 0 \\ -x 2y 3 \end{cases} {2x−y0−x2y3​ 1. matrix [ 2 − 1 − 1 2…

KITE提示词框架:引导大语言模型的高效新工具

大语言模型的应用日益广泛。然而,如何确保这些模型生成的内容在AI原生应用中符合预期,仍是一个需要不断探索的问题。以下内容来自于《AI 原生应用开发:提示工程原理与实战》一书(京东图书:https://item.jd.com/1013604…

【论文阅读】Revisiting the Assumption of Latent Separability for Backdoor Defenses

https://github.com/Unispac/Circumventing-Backdoor-Defenses 摘要和介绍 在各种后门毒化攻击中,来自目标类别的毒化样本和干净样本通常在潜在空间中形成两个分离的簇。 这种潜在的分离性非常普遍,甚至在防御研究中成为了一种默认假设,我…

基于Springmvc+MyBatis+Spring+Bootstrap+EasyUI+Mysql的个人博客系统

基于SpringmvcMyBatisSpringBootstrapEasyUIMysql的个人博客系统 1.项目介绍 使用Maven3Spring4SpringmvcMybatis3架构;数据库使用Mysql,数据库连接池使用阿里巴巴的Druid;使用Bootstrap3 UI框架实现博客的分页显示,博客分类&am…

香港中文大学 Adobe 推出 MotionCanvas:开启用户掌控的电影级图像视频创意之旅。

简介: 亮点直击 将电影镜头设计引入图像到视频的合成过程中。 推出了MotionCanvas,这是一种简化的视频合成系统,用于电影镜头设计,提供整体运动控制,以场景感知的方式联合操控相机和对象的运动。 设计了专门的运动条…

数据结构 单链表的模拟实现

一、链表的定义 线性表的链式存储就是链表。 它是将元素存储在物理上任意的存储单元中,由于⽆法像顺序表⼀样通过下标保证数据元素之间的逻辑关系,链式存储除了要保存数据元素外,还需额外维护数据元素之间的逻辑关系,这两部分信息…

Avalonia-wpf介绍

文章目录 工程简述窗体样式暗色模式亚克力模糊效果ExperimentalAcrylicBorder” 和 “ExperimentalAcrylicMaterial” 的介绍ExperimentalAcrylicBorderExperimentalAcrylicMaterial按钮排版按钮图标按钮命令响应式命令添加一个新对话框对话框窗口样式对话框的输入与输出显示对…

Node.js开发属于自己的npm包(发布到npm官网)

在 Node.js 中开发并发布自己的 npm 包是一个非常好的练习,可以帮助我们更好地理解模块化编程和包管理工具,本篇文章主要阐述如何使用nodejs开发一个属于自己的npm包,并且将其发布在npm官网。在开始之前确保已经安装了 Node.js 和 npm。可以在…

操作系统常见调度算法的详细介绍

目录 1. 先进先出算法(FIFO) 2. 前后台调度算法 3. 最短处理机运行期优先调度算法(短进程优先算法) 4. 最高响应比优先调度算法(HRRN) 5. 优先级调度算法 6. 时间片轮转调度算法 7. 多级反馈队列轮转…

ADB详细教程

目录 一、ADB简介 二、配置 配置环境变量 验证是否安装成功 三、简单使用 基本命令 设备连接管理 USB连接 WIFI连接(需要USB线) 开启手机USB调试模式 开启USB调试 四、其他 更换ADB默认启动端口 一、ADB简介 ADB(Android Debug…