四、GD32 MCU 常见外设介绍 (6) ADC 模块介绍

6.1.ADC 基础知识

12 位逐次逼近式模数转换器模块(ADC),可以采样来自于外部输入通道、内部输入通道的模拟信号,采样转换后,转换结果可以按照最低有效位对齐或最高有效位对齐的方式保存在相应的数据寄存器中。

6.2.GD32 ADC 外设原理

GD32 ADC 主要特性

◼ 高性能:

– ADC采样分辨率: 12位、 10位、 8位、或者6位分辨率;

– 前置校准功能;

– 可编程采样时间;

– 数据存储模式:最高有效位对齐和最低有效位对齐;

– 支持规则数据转换的DMA请求。

◼ 模拟输入通道:

– 16个外部模拟输入通道;

– 1个内部温度传感器输入通道(VSENSE);

– 1个内部参考电压输入通道(VREFINT)。

◼ 转换开始的发起:

– 软件触发;

– 硬件触发。

◼ 转换模式:

– 转换单个通道,或者扫描一序列的通道;

– 单次运行模式,每次触发转换一次选择的输入通道;

– 连续运行模式,连续转换所选择的输入通道;

– 间断运行模式;

– 同步模式(适用于具有两个或多个ADC的设备)。

◼ 转换结果阈值监测器功能: 模拟看门狗。

◼ 中断的产生:

– 常规序列转换结束;

– 模拟看门狗事件。

◼ 过采样:

– 16位的数据寄存器;

– 可调整的过采样率,从2x到256x;

– 高达8位的可编程数据移位。

◼ ADC供电要求:

– 2.4V到3.6V,一般供电电压为3.3V。

◼ ADC输入范围: VREF- ≤VIN ≤VREF+。

– VREF- : ADC 负参考电压, VREF- = VSSA

– VREF+ : ADC 正参考电压, 2.6 V ≤ VREF+ ≤ VDDA

ADC 结构框图介绍

6.3.硬件连接说明

ADC的检测需要将输入阻抗和采样周期保持一定的关系,下表列出了以GD32E103为例子 

6.4.软件配置说明

查询法

查询法采用的是转换单个通道,或者扫描一序列的通道,通过不断切换通道的方式去读取对应通道的ADC数值。我们介绍使用库函数来设置 ADC0 的通道来进行 AD 转换的步骤,下面讲解其详细设置步骤:

开启 GPIO口时钟和 ADC0 时钟,设置GPIO口为模拟输入。

rcu_periph_clock_enable(RCU_GPIOA);/* enable GPIOB clock */rcu_periph_clock_enable(RCU_GPIOB);/* enable ADC0 clock */
rcu_periph_clock_enable(RCU_ADC0);
/* config ADC clock */
rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV4);
/* enable alternate function clock */
rcu_periph_clock_enable(RCU_AF); //使能 GPIO 口复用

这里需要说明一下, ADC 的通道与引脚的对应关系在数据手册可以查到

(1)配置 ADC 输入时钟分频,模式为独立模式,转换长度以及触发方式等

/* reset ADC */
adc_deinit(ADC0);
/* ADC mode config */
adc_mode_config(ADC_MODE_FREE); //独立模式
/* ADC continous function enable */
adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE)
/* ADC data alignment config */
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT); //ADC 数据右对齐
adc_special_function_config(ADC0,ADC_CONTINUOUS_MODE,DISABLE);
/* ADC channel length config */
adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 1);//设置 ADC 转换的通道数量
/* ADC trigger config */
adc_external_trigger_source_config(ADC0,ADC_REGULAR_CHANNEL,ADC0_1_EXTTRIG_REGULAR_NONE);
//通过软件触发 ADC 转换
adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);

(2)开启 AD 转换器

在设置完了以上信息后,我们就开启 AD 转换器了

/* enable ADC interface */
adc_enable(ADC0);
delay_1ms(1);//延迟 等待稳定
/* ADC calibration and reset calibration */
adc_calibration_enable(ADC0);//使能 ADC 校准

(3)读取 ADC 值 在上面的步骤完成后, ADC 就算准备好了。所谓的查询法就是不断地进行通道切换

unsigned short adc0_transfer(unsigned char adc_channel)
{
uint16_t ADC_temp;/* ADC regular channel config */adc_regular_channel_config(ADC0, 0, adc_channel, ADC_SAMPLETIME_55POINT5);
adc_software_trigger_enable(ADC0,ADC_REGULAR_CHANNEL);while(!adc_flag_get(ADC0, ADC_FLAG_EOC));//等待转换完成/* clear the end of conversion flag */adc_flag_clear(ADC0, ADC_FLAG_EOC);ADC_temp=adc_regular_data_read(ADC0);return ADC_temp;
}

这里还需要说明一下ADC的参考电压,是以Vref作为参考电压。

常规通道转换 DMA 搬运

通过ADC转换,在ADC 转换完成后 触发DMA 进行数据搬运。

DMA 请求,可以通过设置 ADC_CTL1 寄存器的 DMA 位来使能,它用于规则组多个通道的转换结果。 ADC 在规则组一个通道转换结束后产生一个 DMA 请求, DMA 接受到请求后可以将转换的数据从 ADC_RDATA 寄存器传输到用户指定的目的地址。

在和查询法一节的差别,主要在于ADC 的配置方面和DMA的配置

(1)ADC 的配置

/* ADC channel length config */adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 4);//常规通道长度配置/* ADC regular channel config */adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_4, ADC_SAMPLETIME_55POINT5);adc_regular_channel_config(ADC0, 1, ADC_CHANNEL_5, ADC_SAMPLETIME_55POINT5);adc_regular_channel_config(ADC0, 2, ADC_CHANNEL_6, ADC_SAMPLETIME_55POINT5);adc_regular_channel_config(ADC0, 3, ADC_CHANNEL_7, ADC_SAMPLETIME_55POINT5);/* ADC trigger config */
adc_external_trigger_source_config(ADC0,ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_NONE);adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);
/* ADC DMA function enable */adc_dma_mode_enable(ADC0);//使能 DMA 模式/* enable ADC interface */adc_enable(ADC0);delay_1ms(1);/* ADC calibration and reset calibration */
adc_calibration_enable(ADC0);

 (2)DMA的配置

 /* ADC_DMA_channel configuration */
dma_parameter_struct dma_data_parameter;/* ADC DMA_channel configuration */dma_deinit(DMA0, DMA_CH0);/* initialize DMA single data mode */dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(ADC0)); //外设地址dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;dma_data_parameter.memory_addr = (uint32_t)(&adc_value); //搬运目标地址dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT; dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;dma_data_parameter.number = 4;dma_data_parameter.priority = DMA_PRIORITY_HIGH;dma_init(DMA0, DMA_CH0, &dma_data_parameter);/* enable DMA circulation mode */dma_circulation_enable(DMA0, DMA_CH0);/* enable DMA channel */
dma_channel_enable(DMA0, DMA_CH0);

(3)触发ADC 转换

adc_software_trigger_enable(ADC0,ADC_REGULAR_CHANNEL);

 注入通道-中断

在和查询法一节的差别,主要在于ADC 的配置方面和注入通道会产生中断

(1)ADC 的配置

 /* reset ADC */adc_deinit(ADC0);/* ADC mode config */adc_mode_config(ADC_MODE_FREE);/* ADC continous function enable */adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);/* ADC data alignment config */adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);/* ADC channel length config *//注入通道配置adc_channel_length_config(ADC0, ADC_INSERTED_CHANNEL, 4);//注入通道长度配置/* ADC inserted channel config */adc_inserted_channel_config(ADC0, 0, ADC_CHANNEL_0, ADC_SAMPLETIME_55POINT5);adc_inserted_channel_config(ADC0, 1, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5);adc_inserted_channel_config(ADC0, 2, ADC_CHANNEL_2, ADC_SAMPLETIME_55POINT5);adc_inserted_channel_config(ADC0, 3, ADC_CHANNEL_3, ADC_SAMPLETIME_55POINT5);/* ADC trigger config */ //通过 EXTI 15 进行触发adc_external_trigger_source_config(ADC0,ADC_INSERTED_CHANNEL,ADC0_1_EXTTRIG_INSERTED_EXTI_15); /* ADC external trigger enable */adc_external_trigger_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE);
/* clear the ADC flag */adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC);adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC);/* enable ADC interrupt */
adc_interrupt_enable(ADC0, ADC_INT_EOIC);//使能注入通道的中断
/* enable ADC */
adc_enable(ADC0);
delay_1ms(1);
/* ADC calibration and reset calibration */
adc_calibration_enable(ADC0);

(2)ADC 注入通道转换完成服务函数

void ADC0_1_IRQHandler(void)
{/* clear the ADC flag */adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC);//清除注入通道转换完成标志位/* read ADC inserted group data register */inserted_data[0] = adc_inserted_data_read(ADC0, ADC_INSERTED_CHANNEL_0);inserted_data[1] = adc_inserted_data_read(ADC0, ADC_INSERTED_CHANNEL_1);inserted_data[2] = adc_inserted_data_read(ADC0, ADC_INSERTED_CHANNEL_2);inserted_data[3] = adc_inserted_data_read(ADC0, ADC_INSERTED_CHANNEL_3);
}

6.5.ADC 使用注意事项

  1. ADC通道的采集引脚未配置为模拟输入,GD32要求通道IO口必须配置为模拟输入;

  2. ADC时钟过高,ADC采样时钟高于ADC最高采样时钟获取到的数据不具有参考意义,需要手动分频到合适的ADC 要求的频率;

  3. ADC采样值偏小或不稳定,应该适当的降低ADC时钟,加大采样周期的值;

  4. ADC的查询法在获取ADC数值的时候,不允许重入,即不允许在同一时间调用ADC的数据读取函数;

  5. ADC在使能之后需要进行短暂的延时,时间周期约为2毫秒左右,以保证ADC能正常启动。

本章内容每日持续更新,如有兴趣,请关注收藏

更多GD32 MCU相关咨询:https://www.gd32bbs.com/ 

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

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

相关文章

【过题记录】 7.21

Mad MAD Sum 算法&#xff1a;思维&#xff0c;前缀最大值 模拟一下他的运行过程就会发现&#xff0c;两次之后整个数组就固定了&#xff0c;之后每次都是每个数往后移动一位&#xff0c;可以模拟两次之后计算每个数的存活轮数&#xff0c;计算贡献。 #include<bits/stdc.h…

PD协议芯片ECP5701兼容PD 2.0和PD 3.0(5V,9V,12V,15V,20V),支持 PD 输入多种类型无线充方案

文章目录 前言 一、TYPE-C口无线充与传统充电器的对比 1. TYPE-C口无线充的特点&#xff08;无需线材&#xff0c;更方便&#xff1b;接口定位性强&#xff0c;分明&#xff1b;兼容多个设备&#xff1b;充电速度更快&#xff1b;充电效率更高&#xff09; 2. 传统充电器的特点…

为什么 FPGA 的效率低于 ASIC?

FPGA是“可重构逻辑”器件。先制造的芯片&#xff0c;再次设计时“重新配置”。 ASIC 不需要“重新配置”。你先设计&#xff0c;把它交给代工厂&#xff0c;然后制造芯片。 现在让我们看看这些芯片的结构是什么样的&#xff0c;以及它们的不同之处。 ● 逻辑单元&#xff1a;F…

神经网络理论(机器学习)

motivation 如果逻辑回归的特征有很多&#xff0c;会造出现一些列问题&#xff0c;比如&#xff1a; 线性假设的限制&#xff1a; 逻辑回归是基于线性假设的分类模型&#xff0c;即认为特征与输出之间的关系是线性的。如果特征非常多或者特征与输出之间的关系是非线性的&#…

【Linux】线程——线程池、线程池的实现、线程安全的线程池、单例模式的概念、饿汉和懒汉模式、互斥锁、条件变量、信号量、自旋锁、读写锁

文章目录 Linux线程7. 线程池7.1 线程池介绍7.2 线程池的实现7.3 线程安全的线程池7.3.1 单例模式的概念7.3.2 饿汉和懒汉模式 8. 常见锁使用汇总8.1 互斥锁&#xff08;Mutex&#xff09;8.2 条件变量&#xff08;Condition Variable&#xff09;8.3 信号量&#xff08;Semaph…

探索 GPT-4o mini:成本效益与创新的双重驱动

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

79页PDF免费下载 | 全域数字化转型评估模型研究报告

一、前言&#xff1a; 随着数字技术的飞速发展&#xff0c;零售行业正站在转型的十字路口。如何在变革中找到方向&#xff0c;如何通过数字化转型提升企业竞争力&#xff0c;已成为每个零售企业必须面对的课题。腾讯智慧零售与伏羲智库深度合作&#xff0c;推出《2024年全域数…

05-用户画像+mysql-hive数据导入

将用户数据导入数仓 新建 create_hive_table.sh文件 在终端执行以下文件 sh create_hive_table.sh sqoop create-hive-table \ --connect jdbc:mysql://up01:3306/tags_dat \ tags_dat库名 --username root \ root 用户名 --password 123456 \ 123456 密码 --ta…

前端练习<HtmlCSS>——悬浮抽卡片(附完整代码及实现效果)

这个小练习来源于b站up小K师兄&#xff0c;大家可以通过下面的链接学习哦~up讲的非常详细。 写一个好玩的悬浮抽卡片效果&#xff5e; 先看一下效果&#xff1a; 1.鼠标没有放置到card上 2.鼠标放到card上&#xff0c;所有card呈角度散开 3.单击选中某一张卡片&#xff0c;…

vue2 使用代码编辑器插件 vue-codemirror

vue 使用代码编辑器插件 vue-codemirror 之前用过一次&#xff0c;当时用的一知半解的&#xff0c;所以也没有成文&#xff0c;前几天又因为项目有需求&#xff0c;所以说有用了一次&#xff0c;当然&#xff0c;依旧是一知半解&#xff0c;但是还是稍微写一下子吧&#xff01;…

vue2使用univerjs

1、univerjs Univer 提供了一个全面的企业级文档与数据协同的解决方案&#xff0c;支持电子表格、文本文档和演示幻灯片三大核心文档类型。通过灵活的 API 和插件机制&#xff0c;开发者可以在 Univer 的基础上进行个性化功能的定制和扩展&#xff0c;以适应不同用户在不同场景…

提升网站性能:ThinkPHP6中如何实现Mysql分页查询

随着互联网的快速发展&#xff0c;web应用程序的开发也越来越复杂。而分页查询是web应用程序中常见的功能之一。thinkphp6是一个web框架&#xff0c;可以帮助开发人员快速开发应用程序。在本文中&#xff0c;我们将讨论如何在thinkphp6中使用mysql进行分页查询。 首先&#xf…

【python】OpenCV—Shape Detection

文章目录 1、需求描述2、代码实现3、涉及到的库函数cv2.arcLengthcv2.approxPolyDP 4、案例5、参考 1、需求描述 给出图像&#xff0c;找出其轮廓&#xff0c;近似确认其为几变形图像 输入 输出 2、代码实现 # 导入必要的包 import cv2 import argparse import imutils imp…

C++STL初阶(7):list的运用与初步了解

在了解了vector之后&#xff0c;我们只需要简单学习List与vector不一样的接口即可 1.list的基本接口 1.1 iterator list中&#xff0c;与vector最大的区别就是迭代器由随机迭代器变成双向迭代器 string和vector中的迭代器都是随机迭代器&#xff0c;支持-等&#xff0c;而LIS…

centos系统mysql集群复制双主双从

文章目录 MySQL 双主双从集群一、 准备环境二、 配置主服务器1. 配置 MySQL 主服务器 1 (192.168.1.1)2. 配置 MySQL 主服务器 2 (192.168.1.2) 三、配置从服务器1. 配置 MySQL 从服务器 1 (192.168.1.3)2. 配置 MySQL 从服务器 2 (192.168.1.4)3. 在主服务器 1 上配置复制到主…

【接口测试】params传参与body传参区别

文章目录 一.params传参二.body传参三.两者区别说明 一.params传参 params传参一般用于get请求 params传参时,参数会附于URL后面以问号形式展示。 示例&#xff1a; http://ip地址:端口号/login?usernamexm&pwd111二.body传参 body传参一般用于post请求 body传参时需…

JavaScript(12)——内置对象

JavaScript内部提供的对象&#xff0c;包含各种属性和方法给开发者调用。 Math Math对象是JavaScript提供的一个“数学”对象 包含的方法有&#xff1a; random:生成0-1之间的随机数 ceil&#xff1a;向上取整 floor&#xff1a;向下取整 max&#xff1a;找最大数 min&#…

前置-Linux相关知识速记

linux Linux命令大全 [!IMPORTANT] chown-chmod-ls-chgrp-cdpwd-mkdir-rmdir-cp-rm-mv-cat-tac-nl-more-less-head-tail 应用领域 通常服务器使用 LAMP&#xff08;Linux Apache MySQL PHP&#xff09;或 LNMP&#xff08;Linux Nginx MySQL PHP&#xff09;组合。 目前…

STM32智能工业监控系统教程

目录 引言环境准备智能工业监控系统基础代码实现&#xff1a;实现智能工业监控系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;工业监控与优化问题解决方案与优化收尾与总结 1. 引言 智能工业监控系统通…

Chapter18 基于物理的渲染——Shader入门精要学习

Chapter18 基于物理的渲染 一、PBS理论和数学基础1.光是什么微表面模型 2.渲染方程3.精确光源4.双向反射分布函数 BRDF5.漫反射项&#xff08;Lambert 模型&#xff09;Lambertian BRDF为&#xff1a;Disney BRDF中漫反射项 6.高光反射项微面元理论BRDF的高光反射项①菲涅尔反射…