STM32--ADC模数转换器

news2024/11/11 4:49:20

学习江科大自化协stm32教程记录的笔记

ADC模数转换器

ADC(Analog-Digital Converter)模拟-数字转换器

ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁

DAC是数字-模拟转换器,但是PWM比DAC简单好用,一般使用DAC驱动电机,目前DAC主要应用于波形生成领域

12位逐次逼近型ADC,1us转换时间

分辨率:0 ~ 212 -1,即0 ~ 4095 ,位数越高量化结果越精细,分辨率越高

输入电压范围:0 ~ 3.3V,转换结果范围:0 ~ 4095

18个输入通道,可测量16个外部和2个内部信号源

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

规则组和注入组两个转换单元

一次启动一个组,可以连续转换多个数据

模拟看门狗自动监测输入电压范围

检测指定通道,当数值超出阈值时,自动申请中断,无需手动在主函数中进行判断

一、逐次逼近型ADC

image-20221211123629747

二、ADC框图

2.1完整框图

image-20221211131053264

2.2 分析

image-20221211134242951



image-20221211143348853

2.3 输入通道对应引脚

通道ADC1ADC2ADC3
通道0PA0PA0PA0
通道1PA1PA1PA1
通道2PA2PA2PA2
通道3PA3PA3PA3
通道4PA4PA4PF6
通道5PA5PA5PF7
通道6PA6PA6PF8
通道7PA7PA7PF9
通道8PB0PB0PF10
通道9PB1PB1
通道10PC0PC0PC0
通道11PC1PC1PC1
通道12PC2PC2PC2
通道13PC3PC3PC3
通道14PC4PC4
通道15PC5PC5
通道16温度传感器
通道17内部参考电压

三、转换模式

1、单次转换,非扫描模式

2、连续转换,非扫描模式

3、单次转换,扫描模式

4、连续转换,扫描模式

image-20221211144033797

image-20221211144356149

四、触发控制

image-20221211144655873

五、数据对齐

右对齐

image-20221211144528294

左对齐

image-20221211144533308

一般使用右对齐,读出数据直接就是转换结果

左对齐可以降低精度,只读高八位,舍去后四位

六、转换时间

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

其中采样、保持放一起,量化、编码放一起

STM32 ADC的总转换时间为:TCONV = 采样时间 + 12.5个ADC周期

例如:当ADCCLK=14MHz,采样时间为1.5个ADC周期

TCONV = 1.5 + 12.5 = 14个ADC周期 = 1μs

七、校准

ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差

建议在每次上电后执行一次校准

启动校准前, ADC必须处于关电状态超过至少两个ADC时钟周期

实例:AD单通道和AD多通道

AD单通道

功能实现:用电位计产生0~3.3V的连续变化的模拟电压,在LCD显示转换后的数据和处理后得到的电压值

AD.c

#include "stm32f10x.h"                  // Device header

void AD_Init(void){
	//开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	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_InitTypeDefstructure;
	ADC_InitTypeDefstructure.ADC_DataAlign = ADC_DataAlign_Right;//对齐方式
	ADC_InitTypeDefstructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//触发源选择
	ADC_InitTypeDefstructure.ADC_Mode = ADC_Mode_Independent;//配置ADC工作模式
	ADC_InitTypeDefstructure.ADC_ContinuousConvMode = DISABLE;//连续转换
	ADC_InitTypeDefstructure.ADC_ScanConvMode = DISABLE;//扫描转换
	ADC_InitTypeDefstructure.ADC_NbrOfChannel = 1;//通道数目
	
	ADC_Init(ADC1,&ADC_InitTypeDefstructure);
	
	//开启ADC
	ADC_Cmd(ADC1,ENABLE);
	//校准ADC
	ADC_ResetCalibration(ADC1);//复位校准
	while(ADC_GetResetCalibrationStatus(ADC1) == SET);//等待校准完成
	ADC_StartCalibration(ADC1);//复位校准
	while(ADC_GetCalibrationStatus(ADC1) == SET);
	
}

uint16_t AD_GetValue(void){
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发转换
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//获取标志位状态
	return ADC_GetConversionValue(ADC1);//获取转换值
}

AD.h

#ifndef __AD_H__
#define __AD_H__

void AD_Init(void);
uint16_t AD_GetValue(void);
#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "OLED.h" 
#include "AD.h" 

uint16_t value;
float V;
int main(){
	OLED_Init();
	AD_Init();
	
	OLED_ShowString(1,1,"ADValue:");
	OLED_ShowString(2,1,"V:0.00V");
	while(1){
		value = AD_GetValue();
		V = (float)value /4095 * 3.3;
		OLED_ShowNum(1,9,value,4);
		OLED_ShowNum(2,3,V,1);
		OLED_ShowNum(2,5,(uint16_t)(V*100)%100,2);
		
	}
}

OLED.c

#include "stm32f10x.h"                  // Device header

void LCD_Init(void){

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    	
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2);
}

void LED1_on(void){
	GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}
void LED1_off(void){
	GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
void LED1_Turn(void){
	if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1) == 0){
		GPIO_SetBits(GPIOA, GPIO_Pin_1);
	}
	else{
		GPIO_ResetBits(GPIOA, GPIO_Pin_1);
	}
}
void LED2_on(void){
	GPIO_ResetBits(GPIOA, GPIO_Pin_2);
}
void LED2_off(void){
	GPIO_SetBits(GPIOA, GPIO_Pin_2);
}
void LED2_Turn(void){
	if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_2) == 0){
		GPIO_SetBits(GPIOA, GPIO_Pin_2);
	}
	else{
		GPIO_ResetBits(GPIOA, GPIO_Pin_2);
	}
}

OLED.h

#ifndef __LCD_H__
#define __LCD_H__

void LCD_Init(void);
void LED1_on(void);
void LED1_off(void);
void LED2_on(void);
void LED2_off(void);
void LED1_Turn(void);
void LED2_Turn(void);
#endif

AD多通道

功能实现:同时测光敏、热敏、反射红外、电位计的转换值,并显示

AD.c

#include "stm32f10x.h"                  // Device header

void AD_Init(void){
	//开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	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_InitTypeDefstructure;
	ADC_InitTypeDefstructure.ADC_DataAlign = ADC_DataAlign_Right;//对齐方式
	ADC_InitTypeDefstructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//触发源选择
	ADC_InitTypeDefstructure.ADC_Mode = ADC_Mode_Independent;//配置ADC工作模式
	ADC_InitTypeDefstructure.ADC_ContinuousConvMode = DISABLE;//连续转换
	ADC_InitTypeDefstructure.ADC_ScanConvMode = DISABLE;//扫描转换
	ADC_InitTypeDefstructure.ADC_NbrOfChannel = 1;//通道数目
	
	ADC_Init(ADC1,&ADC_InitTypeDefstructure);
	
	//开启ADC
	ADC_Cmd(ADC1,ENABLE);
	//校准ADC
	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_H__

void AD_Init(void);
uint16_t AD_GetValue(uint8_t ADC_Channel);
#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "OLED.h" 
#include "AD.h" 

uint16_t AD0,AD1,AD2,AD3;
float V;
int main(){
	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,4);
		OLED_ShowNum(2,5,AD1,4);
		OLED_ShowNum(3,5,AD2,4);
		OLED_ShowNum(4,5,AD3,4);
		
	}
}

OLED.c

#include "stm32f10x.h"                  // Device header

void LCD_Init(void){

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    	
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2);
}

void LED1_on(void){
	GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}
void LED1_off(void){
	GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
void LED1_Turn(void){
	if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1) == 0){
		GPIO_SetBits(GPIOA, GPIO_Pin_1);
	}
	else{
		GPIO_ResetBits(GPIOA, GPIO_Pin_1);
	}
}
void LED2_on(void){
	GPIO_ResetBits(GPIOA, GPIO_Pin_2);
}
void LED2_off(void){
	GPIO_SetBits(GPIOA, GPIO_Pin_2);
}
void LED2_Turn(void){
	if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_2) == 0){
		GPIO_SetBits(GPIOA, GPIO_Pin_2);
	}
	else{
		GPIO_ResetBits(GPIOA, GPIO_Pin_2);
	}
}

OLED.h

#ifndef __LCD_H__
#define __LCD_H__

void LCD_Init(void);
void LED1_on(void);
void LED1_off(void);
void LED2_on(void);
void LED2_off(void);
void LED1_Turn(void);
void LED2_Turn(void);
#endif

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

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

相关文章

AI 助你轻松剪视频 # AutoCut

如果你还在犯愁每次剪视频都要反复听才能下手,不妨试试AutoCut , AI 大神李沐开源的一个剪辑神器,使用 Python 开发,它可以通过字幕来剪切视频。AutoCut 对你的视频自动生成字幕。然后你选择需要保留的句子,AutoCut 将对你视频中对…

C语言:变量的深入理解

文章目录一.什么是变量C语言中为什么要有类型?C语言中的类型为什么有这么多种呢?定义变量的本质为什么需要定义变量定义变量的本质定义变量时的规则二.深刻理解signed/unsigned定义的变量1.运算时的符号位2.数据的存储情况3.unsigned定义时的小细节三.大…

Android 13 VTS HIDL interface 解析

Android 13 VTS Introduction Android 13已经发布,VTS testcase发生很多变化,在此博客中对其每个测试项目进行流程介绍。 这里先对VTS 做一个介绍: VTS是vendor test suite简称,意为供应商测试套件。目的是确保Vendor层实现的兼容…

Spring Boot自动装配原理

Spring Boot自动装配原理1.Spring Boot 入口2.SpringBootApplicationSpringBootConfigurationComponentScanEnableAutoConfiguration判断自动装配开关是否打开获取EnableAutoConfiguration注解中的 exclude 和 excludeName获取需要自动装配的所有配置类最后3.总结1.Spring Boot…

Github访问量过百万!阿里内部至尊级分布式事务手册,实至名归

分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式…

[附源码]JAVA毕业设计养生药膳推荐系统(系统+LW)

[附源码]JAVA毕业设计养生药膳推荐系统(系统LW) 项目运行 环境项配置: Jdk1.8 Tomcat8.5 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术…

[LeetCode周赛复盘] 第 323 场周赛20221211

[LeetCode周赛复盘] 第 323 场周赛20221211 一、本周周赛总结二、 [Easy] 6257. 删除每行中的最大值1. 题目描述2. 思路分析3. 代码实现三、[Medium] 6258. 数组中最长的方波1. 题目描述2. 思路分析3. 代码实现四、[Medium] 6259. 设计内存分配器1. 题目描述2. 思路分析3. 代码…

web前端期末大作业【足球网页】学生网页设计作业源码

🎉精彩专栏推荐 💭文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业: 【📚毕设项目精品实战案例 (10…

基于C++实现(控制台)单位职工管理系统(数据结构)【100010017】

1需求分析 1.1 问题描述 对单位的职工进行管理, 包括插入、 删除、 查找、 排序等功能。 1.2 问题要求 职工对象数不必很多, 便于一次读入内存, 所有操作不经过内外存交换。 (1) 由键盘输 入职工对象,…

1564_AURIX_TC275_电压监控寄存器整理

全部学习汇总: GreyZhang/g_TC275: happy hacking for TC275! (github.com) 1. 如果HSM保护开启了,那么访问修改其他的bit就会导致一个总线错误。 2. SMU中可以配置电压监控的相关alarm是否配置 生效。 这个寄存器是几个欠压阈值的配置,在这…

在Ubuntu中为ROG笔记本安装驱动asusctl

我是在Kubuntu22.04上安装的,系统自带“省电”、“平衡”、“性能”三个电源选项,显卡模式切换是拿nvidia驱动切换的,所以目前装的这个驱动我只用到了灯光调节功能。 文章目录介绍安装安装asusctl卸载显卡模式切换驱动supergfxctl使用方法启用…

LwIP——无操作系统启动流程

目录 启动流程 虚拟网卡控制块 发送流程 接收流程 总结 启动流程 通过阅读正点原子的无操作系统移植工程的源码,可以总结出LwIP的无操作系统的启动流程。 前面一些都是基于其他的外设的初始化,我们只关心这里lwip_comm_init(),这个函数的…

eve-ng ubuntu 20.04 设置iptables

eve-ng ubuntu 20.04 设置iptables一、设置方法1、建立iptables规则开机加载脚本2、建立iptables规则关机/重启保存脚本3、添加可执行权限4、保存当前iptables规则到配置文件二、命令解释一、设置方法 1、建立iptables规则开机加载脚本 sudo vi /etc/network/if-pre-up.d/ipt…

(十一)Vue之条件渲染

文章目录v-if与v-else-if、v-else一起使用v-show关于 <template>标签Vue学习目录 上一篇&#xff1a;&#xff08;十&#xff09;Vue之绑定样式 v-if v-if&#xff0c;默认为true&#xff0c;如果为false&#xff0c;底层实现是直接把这个节点删除 适用于&#xff1a;…

MLE,MAP,经验风险最小化,结构风险最小化,邻域风险最小化

文章目录Maximun likelihood extimationMaximum A Posterior EstimationVicinal Risk Minimization, VRMMaximun likelihood extimation 最大似然估计:样本->参数,完全相信观测到的数据,最优可能产生这些看到的数据的模型就是最理想的模型. 频率学派认为,参数是一个常数,不…

fpga实操训练(基础)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 之前我们虽然说过怎么编写verilog代码&#xff0c;怎么用iverilog软件和gtkwave软件进行仿真验证&#xff0c;但是一直没有说明如何在真实的板子上…

web前端期末大作业——基于HTML+CSS+JavaScript仿蘑菇街时尚服装购物商城

常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他等网页设计题目, A…

28个你应该知道的JavaScript技巧

今天我将分享一些Javascript中的常用技巧&#xff0c;以帮助您解决问题。设置过程中的常见问题更快更容易。 01、Javascript 反向字符串 下面是代码&#xff1a; /*niemvuilaptrinh.com*/const stringReverse str > str.split("").reverse().join("")…

搜索引擎项目测试报告

目录单元测试构建索引模块文档信息对象Document的构建的单元测试**针对每一篇文档进行分析、处理、分词**针对文档内容提取关键字的测试&#xff08;正则表达式&#xff09;测试去掉script测试去掉标签完整测试Document类中的parseContent方法关于ansj分词器的测试关于构建倒排…

CleanMyMac4.12.2最新免费的macOS电脑清理工具

相信不少的小伙伴都在用苹果电脑&#xff0c;不论是 iMac&#xff0c;还是 MacBook&#xff0c;用着用着电脑就变慢了。这通病与苹果电脑的性能无关&#xff0c;主要是硬盘空间不足的问题&#xff01;当然你可以在购买电脑的时候就把硬盘升级&#xff0c;但主要的问题是 – 没有…