STM32-ADC模数转换器

目录

一、ADC简介

二、逐次逼近型ADC内部结构

三、STM32内部ADC转换结构

四、ADC基本结构

五、输入通道

六、转换模式

6.1单次转换,非扫描模式

6.2连续转换,非扫描模式

6.3单次转换,扫描模式

6.4连续转换,扫描模式

七、触发控制

​编辑

八、数据对齐

九、转换时间

十、硬件电路

十一、开发步骤

十二、ADC库函数

十三、实验

13.1 AD单通道

13.2 AD多通道


一、ADC简介

>ADC(Analog-Digital Converter)模拟-数字转换器
>ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁
>12位逐次逼近型ADC(表示范围:0-2^12-1(4095)),1us转换时间(频率:1MHz)      
>输入电压范围:0~3.3V,转换结果范围:0~4095
>18个输入通道,可测量16个外部和2个内部信号源
>规则组和注入组两个转换单元
>模拟看门狗自动监测输入电压范围

>STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道

二、逐次逼近型ADC内部结构

三、STM32内部ADC转换结构

ADCCLK来源于APB2

四、ADC基本结构

五、输入通道

六、转换模式

6.1单次转换,非扫描模式

6.2连续转换,非扫描模式

6.3单次转换,扫描模式

6.4连续转换,扫描模式

七、触发控制

八、数据对齐

(一般采用右对齐,读出来的数据直接就是结果)

九、转换时间

①AD转换的步骤:采样,保持,量化,编码

②STM32 ADC的总转换时间为:
    TCONV = 采样时间 + 12.5个ADC周期(12位)

例如:当ADCCLK=14MHz,采样时间为1.5个ADC周期
    TCONV = 1.5 + 12.5 = 14个ADC周期 = 1μs

十、硬件电路

十一、开发步骤

①开启RCC时钟,包括ADC和GPIO,ADCCLK的分频器也要配置

②配置GPIO,模拟输入模式

③配置多路开关,将通道接入规则组列表中

④结构体配置ADC转换器(单次/多次、扫描/非扫描、通道数、触发源、数据对齐方式)

(可选)⑤模拟看门狗,配置阈值和监测通道,开启中断ITConfig,NVIC

⑤开关控制,调用ADC_Cmd函数,开启ADC,校准

十二、ADC库函数

/*rcc.h*/

void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);

作用:配置ADCCLK分频器

/*adc.h*/

void ADC_DeInit(ADC_TypeDef* ADCx);//恢复缺省配置
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);//Init初始化
void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct);//StructInit结构体初始化

void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);//使能ADC

void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);//开启DMA输出信号

void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);//中断输出控制

============================控制校准的函数=============================
void ADC_ResetCalibration(ADC_TypeDef* ADCx);//复位校准
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);//获取复位校准状态
void ADC_StartCalibration(ADC_TypeDef* ADCx);//开始校准
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);//获取开始校准状态

=====================================================================

void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);

//ADC_软件开始转换控制,用于软件触发的函数(重要)
FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);

//ADC获取软件开始转换状态(一般不用)

============================间断模式==================================
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);

//每隔几个通道间断一次
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);

//是不是启用间断模式

=====================================================================
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);

//ADC规则组通道配置

参数:

①ADCx

②ADC_Channel,通道

③Rank,序列几的位置

④ADC_SampleTime,指定通道的采样时间

=====================================================================
void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);

//ADC_外部触发转换控制,是否允许外部触发转换

=====================================================================
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);

//ADC获取转换值(重要)

=====================================================================
uint32_t ADC_GetDualModeConversionValue(void);

//ADC_获取双模式转换值
============================模拟看门狗=================================

void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);

//是否启动模拟看门狗
void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold);

//配置高低阈值
void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);

//配置看门的通道

===============================内部两通道==============================

void ADC_TempSensorVrefintCmd(FunctionalState NewState);

//ADC_温度传感器、内部参考电压控制

=============================标志位===================================

FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);

//获取标志位状态
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);

//清除标志位
ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);

//获取中断状态
void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);

//清除中断挂起位状态

十三、实验

13.1 AD单通道

实验现象:用电位器产生一个0~3.3V连续变化的模拟电压信号,接到PA0,ADC读取数据显示到屏幕上

参考代码:

AD.c

#include "stm32f10x.h"                  // Device header//*本例程使用连续非扫描模式,软件触发一次即可*//
void AD_Init(void)
{/*一、开启RCC时钟(ADC,GPIO)*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//ADCCLK分频RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72MHz/6=12MHz/*二、配置GPIO,模拟输入*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);/*三、配置多路开关,左边通道接入右边规则组列表(选择规则组的注入通道)*/ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);/*四、配置ADC转换器*/ADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//工作模式(独立/双ADC)ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据对齐(左/右)ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//触发源,此处使用软件触发ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//连续转换/单次转换ADC_InitStructure.ADC_ScanConvMode = DISABLE;//扫描/非扫描ADC_InitStructure.ADC_NbrOfChannel = 1;ADC_Init(ADC1,&ADC_InitStructure);//扫描模式下用到几个通道/*五、开关控制,开启ADC*/ADC_Cmd(ADC1,ENABLE);   //校准ADC_ResetCalibration(ADC1);//复位校准while(ADC_GetResetCalibrationStatus(ADC1) == SET);//等待复位校准完成ADC_StartCalibration(ADC1);//启动校准while(ADC_GetCalibrationStatus(ADC1) == SET);//等待校准是否完成ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}uint16_t AD_GetValue(void)
{return ADC_GetConversionValue(ADC1);
}

AD.h

#ifndef __AD_H
#define __AD_Hvoid AD_Init(void);
uint16_t AD_GetValue(void);#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"uint16_t ADValue;//AD值
float Voltage;//电压值int main(void)
{OLED_Init();AD_Init();OLED_ShowString(1,1,"ADValue:");OLED_ShowString(2,1,"Voltage:0.00V");while (1){ADValue = AD_GetValue();Voltage = (float)ADValue/4095*3.3;OLED_ShowNum(1,9,ADValue,4);OLED_ShowNum(2,9,Voltage,1);//整数OLED_ShowNum(2,11,(uint16_t)(Voltage*100)%100,2);//小数部分Delay_ms(100);}
}

*OLED代码参考本专栏文章STM32-OLED

13.2 AD多通道

实验设置:将电位器、光敏电阻、热敏电阻、反射红外模块的AO(模拟电压输出端)分别接到PA0/PA1/PA2/PA3

参考代码:

AD.c

#include "stm32f10x.h"                  // Device header//*本例程使用单次非扫描模式*//
void AD_Init(void)
{/*一、开启RCC时钟(ADC,GPIO)*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//ADCCLK分频RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72MHz/6=12MHz/*二、配置GPIO,模拟输入*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);/*四、配置ADC转换器*/ADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;ADC_InitStructure.ADC_ScanConvMode = DISABLE;ADC_InitStructure.ADC_NbrOfChannel = 1;ADC_Init(ADC1,&ADC_InitStructure);/*五、开关控制,开启ADC*/ADC_Cmd(ADC1,ENABLE);   //校准ADC_ResetCalibration(ADC1);//复位校准while(ADC_GetResetCalibrationStatus(ADC1) == SET);//等待复位校准完成ADC_StartCalibration(ADC1);//启动校准while(ADC_GetCalibrationStatus(ADC1) == SET);}uint16_t AD_GetValue(uint8_t ADC_Channel)
{/*三、配置多路开关,左边通道接入右边规则组列表(选择规则组的注入通道)*/ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5);ADC_SoftwareStartConvCmd(ADC1,ENABLE);while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//通过标志位来查看是否转换完成return ADC_GetConversionValue(ADC1);
}

AD.h

#ifndef __AD_H
#define __AD_Hvoid AD_Init(void);
uint16_t AD_GetValue(uint8_t ADC_Channel);#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"uint16_t AD0,AD1,AD2,AD3;int main(void)
{OLED_Init();AD_Init();OLED_ShowString(1,1,"AD0:");OLED_ShowString(2,1,"AD1:");OLED_ShowString(3,1,"AD2:");OLED_ShowString(4,1,"AD3:");while (1){AD0 = AD_GetValue(ADC_Channel_0);AD1 = AD_GetValue(ADC_Channel_1);AD2 = AD_GetValue(ADC_Channel_2);AD3 = AD_GetValue(ADC_Channel_3);OLED_ShowNum(1,5,AD0,5);OLED_ShowNum(2,5,AD1,5);OLED_ShowNum(3,5,AD2,5);OLED_ShowNum(4,5,AD3 ,5);Delay_ms(100);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT打包exe文件,在其它电脑里双击exe就可以直接运行

想要不依赖QT环境,在其它电脑里直接双击exe文件就可以运行当前程序。具体打包过程如下: 使用QT编译出release版本的exe release版本运行无误后,需要找到当前构建生成的exe所在文件夹 可以看到具体目录在这里 我在该目录下的bin文件夹里找到…

高速视频采集卡设计方案:620-基于PCIe的高速视频采集卡

一、产品概述 基于PCIe的高速视频采集卡,通过PCIe3.0X8传输到存储计算服务器,实现信号的分析、存储。 北京太速科技 产品固化FPGA逻辑,适配视频连续采集,缓存容量2GB,开源的PCIe QT客户端软件&#xff0c…

在mt4上怎么查看CHFJPY品种的合约细则?

在MetaTrader 4 (MT4) 上查看CHFJPY品种的合约细则的方法如下: FXCM福汇官方个人注册登录流程 1.打开MT4软件并登录到您的交易账户。 2.在MT4界面的"市场观察"窗格中,找到并右键单击"CHFJPY"货币对。如果您无法找到"市场观察…

Transformer Decoder的输入

大部分引用参考了既安的https://www.zhihu.com/question/337886108/answer/893002189这篇文章,个人认为写的很清晰,此外补充了一些自己的笔记。 弄清楚Decoder的输入输出,关键在于图示三个箭头的位置: 以翻译为例: 输…

MyBatis ORM映射

MyBatis只能自动维护库表”列名“与”属性名“相同时的对应关系&#xff0c;二者不同时无法自动ORM 因此需要使用到ORM映射。 共有两种解决办法&#xff1a;1.列的别名 2.结果映射 1.列的别名 在SQL中使用 as 为查询字段添加列别名&#xff0c;以匹配属性名 public List<…

Kafka--Kafka日志索引详解以及生产常见问题分析与总结

一、Kafka的Log日志梳理 ​ 这一部分数据主要包含当前Broker节点的消息数据(在Kafka中称为Log日志)。这是一部分无状态的数据&#xff0c;也就是说每个Kafka的Broker节点都是以相同的逻辑运行。这种无状态的服务设计让Kafka集群能够比较容易的进行水平扩展。比如你需要用一个新…

VSCode报错插件Error lens

1.点击左侧扩展图标→搜索“error lens”→点击“安装” 2.安装成功页面如下&#xff1a; 3.代码测试一下&#xff1a;书写代码的过程中会出现红色提醒或红色报错 4.另外推荐小伙伴们安装中文插件&#xff0c;学习过程中会比较实用方便&#xff0c;需要安装中文插件的小伙伴请点…

详解数据科学自动化与机器学习自动化

过去十年里&#xff0c;人工智能&#xff08;AI&#xff09;构建自动化发展迅速并取得了多项成就。在关于AI未来的讨论中&#xff0c;您可能会经常听到人们交替使用数据科学自动化与机器学习自动化这两个术语。事实上&#xff0c;这些术语有着不同的定义&#xff1a;如今的自动…

安卓手机语音备忘录在哪里?

我们在日常生活和工作中&#xff0c;使用手机记事的时候&#xff0c;不仅需要在备忘录或便签软件中记录文字、图片&#xff0c;有时候我们也需要记录语音或音频文件。那么安卓手机语音备忘录在哪里呢&#xff1f;其实绝大多数的安卓手机中都是没有专门的语音备忘录的&#xff0…

pyCharm 创建一个FastApi web项目,实现接口调用

FastApi和Django区别 我这边演示项目使用的fastApi作为web框架&#xff0c;当然主流一般都是使用Django做web框架&#xff0c;但是Django是一个重量级web框架他有很多组件&#xff0c;如授权&#xff0c;分流等全套web功能。我这边呢只需要有个接口可以被别人调用&#xff0c;…

多维时序 | MATLAB实现KOA-CNN-BiGRU-Multihead-Attention多头注意力机制多变量时间序列预测

多维时序 | MATLAB实现KOA-CNN-BiGRU-Multihead-Attention多头注意力机制多变量时间序列预测 目录 多维时序 | MATLAB实现KOA-CNN-BiGRU-Multihead-Attention多头注意力机制多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLAB实现KOA-CNN-B…

伦敦金交易内地与香港有何区别

伦敦金交易是国际银行间市场层面的现货黄黄金交易&#xff0c;亚洲市场的交易中心在中国香港&#xff0c;现在不管是香港本地还是内地的投资者&#xff0c;都可以在网上开户&#xff0c;通过香港的平台参与伦敦金交易&#xff0c;所得到的服务是同等的、公平的、与国际市场接轨…

UE4 UE5 一直面向屏幕

一直面相屏幕&#xff0c;方法很简单 新建一个蓝图&#xff0c;如下添加组件&#xff1a; 蓝图如下&#xff1a; Rotation Actor &#xff1a;需要跟随镜头旋转的物体 Update&#xff1a;一个timeline&#xff08;替代event tick 只是为了循环&#xff09; Timeline&#xff…

MySQL是如何保证数据不丢失的?

文章目录 前言Buffer Pool 和 DML 的关系DML操作流程加载数据页更新记录 数据持久化方案合适的时机刷盘双写机制日志先行机制日志刷盘机制Redo Log 恢复数据 总结 前言 上篇文章《InnoDB在SQL查询中的关键功能和优化策略》对InnoDB的查询操作和优化事项进行了说明。但是&#…

【git学习笔记 01】打标签

文章目录 一、声明二、对标签的基本认知什么是标签&#xff1f;为什么要打标签&#xff1f;如何生成类似github中readme的图标 三、标签相关命令四、示例操作 一、声明 本帖持续更新中如有纰漏&#xff0c;望批评指正&#xff01;参考视频链接&#xff0c;非常感谢原作者&…

tcp vegas 为什么好

我吹捧 bbr 时曾论证过它在和 buffer 拧巴的时候表现如何优秀&#xff0c;但这一次说 vegas 时&#xff0c;我说的是从拥塞控制这个问题本身看来&#xff0c;vegas 为什么好&#xff0c;并且正确。 接着昨天 tcp vegas 鉴赏 继续扯。 假设一群共享带宽的流量中有流量退出或有…

AWS RDS慢日志文件另存到ES并且每天发送邮件统计慢日志

1.背景&#xff1a;需要对aws rds慢日志文件归档到es&#xff0c;让开发能够随时查看。 2.需求&#xff1a;并且每天把最新的慢日志&#xff0c;过滤最慢的5条sql 发送给各个产品线的开发负责人。 3.准备&#xff1a; aws ak/sk &#xff0c;如果rds 在不同区域需要认证不同的…

UE5 C++(六)— 枚举UENUM、结构体USTRUCT和补充属性说明符

文章目录 枚举&#xff08;ENUM&#xff09;第一种方式第二种方式 结构体&#xff08;USTRUCT&#xff09;补充属性说明符&#xff08;ExposeOnSoawn&#xff09;结构体创建数据表格 枚举&#xff08;ENUM&#xff09; 第一种方式 定义枚举 UENUM(BlueprintType) namespace …

Java如何开发PC客户端(Windows,Mac,Linux)

项目编译工具&#xff1a;Gradle开发工具&#xff1a; Idea开发语言&#xff1a; 建议java17以上ui组件&#xff1a;openjfx (org.openjfx.javafxplugin)打包工具: jpackage (org.beryx.jlink)如果打包出现错误&#xff0c;可以安装wix(3.1以上) dotnetfx(3.5以上) 试试看 一…

Swagger2接口测试文档

目录 一、Swagger简介 1.1 Swagger是什么&#xff1f; 1.2 为什么要用Swagger 1.3 Swagger注解 二、Spring集成Swagger 三、测试环境配置 一、Swagger简介 1.1 Swagger是什么&#xff1f; Swagger 是一个开源的 API 设计和文档工具&#xff0c;它可以帮助开发人员更快、…