18.ADC模数转换

news2024/10/5 17:20:53

1.STM32ADC简介:

ADC(Analog to Digital Converter)即模数转换器,它可以将模拟信号转换成数字信号。按照其转换原理主要分为逐次逼近型、双积分型、电压频率转换型三种。

STM32 ADC主要特性:        

  • 12位分辨率;
  • 转换结束、注入转换结束和发生模拟看门狗事件时产生中断;
  • 单次和连续转换模式;
  • 从通道0到通道n的自动扫描模式;
  • 自校准;

1)STM32一般都有3个ADC,这些ADC可以独立的使用,可以使用双重或三重的模式,这种模式是为了提高ADC采样率;

2)STM32的ADC一般是12位的逐次逼近型的模拟转换器,多达18个复用通道可以测量16个外部的模拟通道和2个内部的信号源;

3)这些AD转换可以是单次连续扫描或间断模式执行,ADC结果可以左对齐或右对齐存放在16位的一个数据存储器中;

4)ADC还具有模拟看门狗的特性,运行应用程序来检测输入电压是否超出用户定义的阀值上限和下限,如果超过则触发模拟看门狗中断;

2.STM 32介绍:

  • 带内嵌数据一致性的数据对齐;
  • 采样间隔可以按通道分别编程;
  • 规则转换和注入转换均有外部触发选项;
  • 间断模式;
  • 双重模式(带2个或以上ADC的器件);
  • ADC转换时间;
  • ADC供电要求:2.4V到3.6V;
  • ADC输入范围:VREF-≤VIN≥VREF+;
  • 规则通道转换期间有DMA请求产生;
STM ADC结构框图:

 

① 第一部分:电压输入引脚:

在设计电路中,将VEF+连接到基准电压源中,基准电压源实现的方法有很多种如TL431,将基准电压设置为固定的2.5V,实现高精度测量;

② 第二部分:输入通道(18个=16外+2内):

ADC2和ADC3不具有内部通道,ADC具有2个内部通道(内部温度传感器+内部参考电压VREF);

③ 第三部分:通道转换顺序(注入通道(最多4路)+规则通道(最多16路)):

  • 如果在规则通道进行转换的时候,有注入通道插入进来,就要先执行注入通道转换等注入通道转换完成之后,再回到规则通道往下继续转换;
  • 每组包含一个转换序列,序列可以按任意序列在任意的通道上进行完成,通过这个转换序列可以将要转换的通道进行排序;
  • 规则通道组序列寄存器有3个(SQR3、SQR2、SQR1),SQR3(控制1到6的转换),SQR2(控制7到12的转换),SQR1(控制13到16的转换);
  • 注入通道组序列寄存器只有1个,最多支持4个通道(JSQR(00->1次转换,01->2次转换,10->3次转换,11->4次转换));
  • 如果在转换期间修改了SQR或JSQR寄存器中的值,将复位当前转换,并向ADC发送一次新的启动脉冲以转换新选择的通道;

④ 第四部分:触发源:

触发极性(4个):禁止触发检测、上升沿触发检测、下降沿触发检测、上升沿和下降沿触发检测;

⑤ 第五部分:ADC时钟(APB2最大支持14M):

  • 72/6=12M;
  • 采样的周期,可以通过ADC的采样时间寄存器来设置,ADC采样时间寄存器(SMPRE(10~17通道)+SMPR2(0~9通道));
  • 每个通道可以分别用不同的采样时间,每个通道采样时间可以独立设置,采样周期最小是1.5个TCLK;
  • Tcon(总的转换时间)=采样时间+12.5周期;

⑥ 第六部分:数据寄存器:

  • ADC是12位,数据寄存器都是16位,因此存在左对齐和右对齐;
  • 规则通道中(只有1个寄存器,容易出现数据覆盖),当转换完成之后,就立刻将数据取走,可以开启DMA将数据自动的搬到其他地方去;

⑦ 第七部分:中断:

只有在ADC1和ADC3中,才可以产生DMA请求;        

3.ADC配置步骤:

ADC相关库函数在stm32f10x_adc.c和stm32f10x_adc.h文件中;
  1. 使能端口时钟和ADC时钟,设置引脚模式为模拟输入:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
  2. 设置ADC的分频因子:RCC_ADCCLKConfig(RCC_PCLK2_Div6);
  3. 初始化ADC参数,包括ADC工作模式、规则序列等:void ADC_Init();
  4. 使能ADC并校准:void ADC_Cmd()、ADC_ResetCalibration(ADC1) 复位校准、ADC_StartCalibrationStatus(ADC1) 开启校准;
  5. 读取ADC转换值:void ADC_RegularChannelConfig()、                                                     void ADC_SoftwareStartConvCmd()、ADC_GetConversionValue()、ADC_GetFlagStatus()

4.ADC模数转换实验:

功能实现:通过ADC1通道1采样外部电压值,将采样的AD值和转换后的电压值通过串口打印出来,同时LED0指示灯闪烁,提示系统正常运行。

(1)原理图:

(2)主函数:

#include "delay.h"
#include "led.h"
#include "usart1.h"
#include "adc.h"



int main(){
    
    u8 i=0;    
    u16 val=0;
    float vol=0.0f;
   
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);      //设置分组
    delay_init();                                        //延时初始化
    LED_Init();  
    usart1_Init(9600);                                   //串口通信初始化
    ADCx_Init();                                         //ADC1初始化
   
    while(1)
       {
          i++;
          if(i%20==0)
          {
             LED0=!LED0;
          }

           delay_ms(10);
          
          if(i%100==0)        //1s
          {
             val=Get_ADC_Value(ADC_Channel_1,20);     //获取转换并且滤波后的值;通道1,20次
             printf("检测的AD值=%d\r\n",val);
             
             //AD值 0~4095,电压采集范围:0~3.3V
             vol=(float)val*(3.3/4095);
             printf("检测的电压值=%2.f V\r\n",vol);
             printf("\r\n");
    
          }
       
      }       
}

(3)头文件:

#ifndef __ADC_H
#define __ADC_H

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;

void ADCx_Init(void);                     //ADC1初始化
u16  Get_ADC_Value(u8 ch,u8 times);       //读取ADC转换值 


#endif

(4)ADC模数转换功能函数:

#include "stm32f10x.h"
#include "delay.h"
#include "adc.h"


/*
   功能:ADC1初始化->ADC1(PA1)
   变量:无
   返回值:无
*/
void ADCx_Init(void)
{
   GPIO_InitTypeDef GPIO_InitStruct;
   ADC_InitTypeDef ADC_InitStruct;
   
   
   //1.使能端口时钟和ADC时钟,设置引脚模式
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
   
   GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;                          //模拟输入模式
   GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;                              //PA1
   GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;       
   GPIO_Init(GPIOA,&GPIO_InitStruct);
   
   //2.设置ADC的分频因子
   RCC_ADCCLKConfig(RCC_PCLK2_Div6);                                 //ADC最大不超过16M,(72/6=12)<16
   
   //3.初始化ADC参数,包括工作模式、规则序列等
   ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;                    //不连续转换
   ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;                 //对齐方式->右对齐
   ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;    //不使用外部触发,使用软件触发
   ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;                     //ADC工作模式设置为独立模式
   ADC_InitStruct.ADC_NbrOfChannel=1;                                //通道数
   ADC_InitStruct.ADC_ScanConvMode=DISABLE;                          //不扫描
   ADC_Init(ADC1,&ADC_InitStruct);
   
   //4.使能ADC校准
   ADC_Cmd(ADC1,ENABLE);                                             //使能ADC1
   ADC_ResetCalibration(ADC1);                                       //复位校准
   while(ADC_GetResetCalibrationStatus(ADC1));                       //复位校准完成标志,完成后退出循环
   ADC_StartCalibration(ADC1);                                       //开启校准
   while(ADC_GetCalibrationStatus(ADC1));                            //开启复位校准完成标志,完成后退出循环
   
   //5.开启软件触发方式
   ADC_SoftwareStartConvCmd(ADC1,ENABLE);
     
}



/*
   功能:读取ADC转换的值
   变量:ch:选择通道  times:读取的次数
   返回值:返回平均值(进行滤波后的值)

*/
u16  Get_ADC_Value(u8 ch,u8 times)
{
   u8 i=0;
   u32 temp_val=0;               //存储获取到的ADC转换值
   
   //ADC规则通道配置
   ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5);       //选择ADC、通道、通道数量、采样周期
   
   //读取数据
   for(i=0;i<times;i++)
   {
      ADC_SoftwareStartConvCmd(ADC1,ENABLE);             //开启ADC转换,因为使用的是单次转换,所以每次转换都需要开启
      while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));      //ADC_FLAG_EOC:规则组转换完成
      temp_val+=ADC_GetConversionValue(ADC1);            //获取转换的值
      delay_ms(10);
   }
   
   return temp_val/times;        //返回进过滤波后的数据
   
}


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue基础 -- 生命周期 数据共享

1 组件的生命周期 1.1 生命周期 & 生命周期函数 生命周期&#xff08;Life Cycle&#xff09;是指一个组件从创建 -> 运行 -> 销毁的整个阶段&#xff0c;强调的是一个时间段。 生命周期函数&#xff1a;是由 vue 框架提供的内置函数&#xff0c;会伴随着组件的生命…

UNI-APP_vmin横屏适配问题

vmax和vmin vmax 相对于视口的宽度或高度中较大的那个。其中最大的那个被均分为100单位的vmax vmin 相对于视口的宽度或高度中较小的那个。其中最小的那个被均分为100单位的vmin当竖屏布局时750rpx是竖屏布局屏幕的宽度 vmin不管横竖屏的情况下&#xff0c;100vmin都是手机屏幕…

Web漏洞-敏感信息泄露-Git操作

实验目的 熟悉常见git常见操作&#xff0c;如上传、回归、修改仓库等操作。 实验环境 git操作服务器&#xff0c;1台 web安全操作机&#xff0c;1台&#xff08;可选&#xff09; 实验内容 1.安装Git&#xff1a;sudo apt-get install git 2.安装Apache&#xff0c;为了模…

机器学习技术(二)——Python科学运算模块(Numpy、Pandas)

机器学习技术&#xff08;二&#xff09;——Python科学运算模块&#xff08;Numpy、Pandas&#xff09; 文章目录 机器学习技术&#xff08;二&#xff09;——Python科学运算模块&#xff08;Numpy、Pandas&#xff09;一、Numpy1、介绍、安装与导入2、Numpy常用操作 二、Pan…

Java面向对象程序开发——多线程开发

文章目录 前言多线程多线程的实现①、继承Thread类Thread常用方法Thread的构造器优缺点 ②、实现Runnable接口优缺点 ③、实现Callable接口Runnable接口和继承Thread类的区别 线程同步机制volatile同步锁 同步方法lock锁 线程池 前言 线程(thread)是一个程序内部的一条执行路径…

shared_ptr产生内存泄漏的场景

使用 shared_ptr 可以帮助管理动态分配的内存&#xff0c;它使用引用计数的方式来跟踪共享对象的引用数量&#xff0c;当引用计数为零时&#xff0c;会自动释放内存。然而&#xff0c;shared_ptr 也存在一些潜在的内存泄漏的场景&#xff0c;下面是一些常见的情况&#xff1a; …

LVS和keepa lived群集

keepa lived 简述 一.keepalived 服务重要功能 1管理LS负载均衡器软件 keepalived可以通过读取自身的配置文件&#xff0c;实现通过更底层的接口直接管理Lvs配置以及服务的启动 停止功能 这会使 LVS应用跟更加简便 2 支持故障自动切换 (failover) ①两台知己同时安装好kee…

网络字节序和套接字

4.1主机字节序列和网络字节序列 主机字节序列分为&#xff1a;大端字节序和小端字节序 大端&#xff1a;高位字节存储在内存的低地址处&#xff0c;低位字节存储在内存的高地址处。 小端&#xff1a;高位字节存储在内存的高地址处&#xff0c;低位字节存储在内存的低地址处。…

【算法基础】数据结构

链表 单链表 826. 单链表 - AcWing题库 #include<bits/stdc.h> using namespace std; const int N 100010; int m; int e[N],ne[N];//记录数据和下一结点坐标 int head,idx;//当前指向的结点 void init() {head-1;idx0; } void addtohead(int x) {e[idx]x;ne[idx]hea…

前端框架Vue

Vue 介绍 官方网站&#xff1a;https://cn.vuejs.org/ Vue.js是一种用于构建用户界面的开源JavaScript框架。它是一种轻量级的框架&#xff0c;易于学习和使用。它基于标准HTML&#xff0c;CSS和JavaScript构建&#xff0c;并提供了一套生声明式的&#xff0c;组件时的编程模…

【深入浅出 Spring Security(十三)】使用 JWT 进行前后端分离认证(附源码)

使用 JWT 进行前后端分离认证 一、JWT 的简单介绍二、使用 JWT 进行安全认证后端结合SpringSecurity实现前端Vue3结合Pinia、Axios实现测试结果 一、JWT 的简单介绍 JWT 全称 Java web Token&#xff0c;在此所讲述的是 JWT 用于身份认证&#xff0c;用服务器端生成的JWT去替代…

spring--Ioc控制反转/DI依赖注入

IOC控制反转-解耦 1.概念&#xff1a;在使用对象的时候&#xff0c;由主动的new转换为外部提供对象&#xff0c;将对象创建的控制权交给外部&#xff0c;即控制反转 2.spring提供了一个容器&#xff0c;称为IOC容器&#xff0c;用来从当ioc中的外部 3.被管理或者被创建的对象在…

ChatGPT实战:如何规划自己的职业生涯?

ChatGPT的出现&#xff0c;不仅改变了人们对人工智能技术的认识&#xff0c;也对经济社会发展产生了深远的影响。那么&#xff0c;在ChatGPT时代&#xff0c;人们应该如何规划自己的职业呢&#xff1f; 职业规划是一个有意义且重要的过程&#xff0c;它可以帮助你在职业生涯中…

什么是BI可视化?企业管理决策为什么要用BI系统?

在当今的商业环境中&#xff0c;数据已经成为企业决策制定的重要基础。然而&#xff0c;面对海量的数据&#xff0c;如何有效地分析和利用这些数据&#xff0c;成为了企业管理者面临的一大挑战。BI(Business Intelligence)系统应运而生&#xff0c;它可以帮助企业管理者从复杂的…

基于Java企业人事管理系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

如何用好强大的 TDengine 集群 ? 先了解 RAFT 在 3.0 中的应用

大家都知道&#xff1a;由于单机数据库在数据规模、并发访问量等方面存在瓶颈&#xff0c;无法满足大规模应用的需求。因此才有了把数据切割分片&#xff0c;分布存储分布处理在多个节点上的数据库&#xff0c;也就是分布式数据库的由来。 而为了实现数据库的高可用&#xff0…

新装Ubuntu虚拟机环境--基本配置流程

新装Ubuntu虚拟机环境--基本配置流程 安装vmware tools修改源 安装vmware tools 点击菜单栏–>虚拟机–>安装VMwaretools桌面上有个图标&#xff0c;点进去 打开这个压缩包–>Extract到桌面&#xff08;or别的文件夹都可以&#xff0c;如果提示空间不足就换其它文件夹…

手把手写一个LED驱动(1)

目录 1.开启驱动开发之路 1.1、驱动开发的准备工作 1.2、驱动开发的步骤 1.3、实践 2.最简单的模块源码分析 2.1、常用的模块操作命令 2.2、模块的安装 2.3、模块的版本信息vermagic 2.4、模块卸载 2.5、模块中常用宏(MODULE_xxx这种宏的作用是用来添加模块描述信息) …

2023年仪器仪表行业研究报告

第一章 行业概况 仪器仪表行业是指专门从事研究、设计、制造、销售和服务于科学研究、生产和生活中所需的各种仪器、仪表和自动化设备的行业。这些仪器和仪表可以用于测量、指示、记录、调节和控制物理、化学和生物过程中的各种参数。这个行业涵盖了广泛的设备和系统&#xff…

今日分享:Midjourney巧妙地用参考图/垫图来绘画图

大家都知道AI绘画工具每次生成的效果都是随机的&#xff0c;但是现在很多AI绘图工具都提供了利用参考图/垫图的方式出图&#xff0c;这样就可以让让AI画作生成自己想要的布局、场景、色彩等等。 国内的AI绘图工具一般都好操作&#xff0c;国外主流的Midjourney也可以添加参考图…