GD32F103VE使用DMA传输读取内部温度和参考电压值

GD32F103VE使用DMA传输读取内部温度和参考电压值。出厂CPU芯片不同,温度误差不同,不要纠结了。

GD32F103的ADC为12位AD转换器,ADC转换结果保存在16位数据寄存器中;

模拟输入通道:
16个外部模拟输入通道;
1个内部温度传感器通道(Vsense)
1个内部参考电压输入通道(VrefInt)

触发转换:
软件触发;
硬件触发;

转换模式:
单通道转换或多通道扫描转换;
单次模式,选择指定的模拟输入通道后,触发一次,则转换一次;
连续模式,选择指定的模拟输入通道后,连续进行AD转换;用于DMA
同步模式,当同时使用ADC0,ADC1和ADC2时,这3个设备就可以同时进行AD转换;
间断模式;

ADC的VDDA电源引脚需要接入3.3V;
ADC输入模拟量的范围:Vref- 至Vref+之间;

ADC_RSQ0~ADC_RSQ2寄存器规定了"规则组通道"的选择;
ADC_RSQ0的RL[3:0]用来指定"规则通道组"转换序列的长度,即"规则通道组"选择;
连续进行AD转换的通道总数为(RL[3:0]+1),在DMA传输中要知道有多少个通道参与AD转换

ADC_ISQ寄存器规定了"注入组通道"的选择;
ADC_ISQ0的IL[3:0]用来指定"整个注入通道组"转换序列的长度,即"规则通道组"选择
连续进行AD转换的通道总数为(IL[3:0]+1),在DMA传输中要知道有多少个通道参与AD转换

注意:ADC同时使用"规则组通道"和"注入组通道",则"注入组通道"的采样周期不能1.5和7.5个采样周期;

GD32F103的ADC0映射到DMA0的通道0
GD32F103的ADC2映射到DMA1的通道4
GD32F103的ADC1没有DMA功能
注意:在多通道AD转换中,DMA使用循环工作模式比较好;

ADC0_CH16为温度传感器通道,Internal temperature sensor output voltage;
ADC0_CH17为内部参考电压通道,Internal voltage reference output voltage;
Vref-引脚必须连接至VSSA引脚,Vref+连接到VDDA,但在64脚以下的CPU(含64脚),其Vref+和Vref-已经在内部连接至VDDA和VSSA;
注意:ST和GD的手册里都写着不同芯片最大偏差45度

#include "ADC.h"
#include "delay.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()/*
GD32F103的ADC为12位AD转换器,ADC转换结果保存在16位数据寄存器中;模拟输入通道:
16个外部模拟输入通道;
1个内部温度传感器通道(Vsense)
1个内部参考电压输入通道(VrefInt)触发转换:
软件触发;
硬件触发;转换模式:
单通道转换或多通道扫描转换;
单次模式,选择指定的模拟输入通道后,触发一次,则转换一次;
连续模式,选择指定的模拟输入通道后,连续进行AD转换;用于DMA
同步模式,当同时使用ADC0,ADC1和ADC2时,这3个设备就可以同时进行AD转换;
间断模式;ADC的VDDA电源引脚需要接入3.3V;
ADC输入模拟量的范围:Vref- 至Vref+之间;ADC_RSQ0~ADC_RSQ2寄存器规定了"规则组通道"的选择;
ADC_RSQ0的RL[3:0]用来指定"规则通道组"转换序列的长度,即"规则通道组"选择;
连续进行AD转换的通道总数为(RL[3:0]+1),在DMA传输中要知道有多少个通道参与AD转换ADC_ISQ寄存器规定了"注入组通道"的选择;
ADC_ISQ0的IL[3:0]用来指定"整个注入通道组"转换序列的长度,即"规则通道组"选择
连续进行AD转换的通道总数为(IL[3:0]+1),在DMA传输中要知道有多少个通道参与AD转换注意:ADC同时使用"规则组通道"和"注入组通道",则"注入组通道"的采样周期不能1.5和7.5个采样周期;GD32F103的ADC0映射到DMA0的通道0
GD32F103的ADC2映射到DMA1的通道4
GD32F103的ADC1没有DMA功能
注意:在多通道AD转换中,DMA使用循环工作模式比较好;ADC0_CH16为温度传感器通道,Internal temperature sensor output voltage;
ADC0_CH17为内部参考电压通道,Internal voltage reference output voltage;
Vref-引脚必须连接至VSSA引脚,Vref+连接到VDDA,但在64脚以下的CPU(含64脚),其Vref+和Vref-已经在内部连接至VDDA和VSSA;
注意:ST和GD的手册里都写着不同芯片最大偏差45度
*/#define ADC0_CH_Number   2
#define ADC0_cnt         20
#define ADC0_Buffer_Size 40
uint16_t ADC0_Buffer[ADC0_cnt][ADC0_CH_Number];void DMA0_DMA_CH0_config(void);
void ADC0_Init(void);
void ADC0_To_DMA0_Init(void);
void Read_TemperatureValue(void);void DMA0_DMA_CH0_config(void)
{dma_parameter_struct dma_init_ADC0;dma_deinit(DMA0,DMA_CH0);dma_init_ADC0.direction = DMA_PERIPHERAL_TO_MEMORY;//DMA传送方向:从外设到内存dma_init_ADC0.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));//源数据块首地址为:ADC0寄存器dma_init_ADC0.periph_inc = DMA_PERIPH_INCREASE_DISABLE;  //源数据块地址不递增dma_init_ADC0.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; //源数据块的数据宽度为16位dma_init_ADC0.memory_addr = (uint32_t)(&ADC0_Buffer);//目的数据首地址为:ADC0_Buffer[]dma_init_ADC0.memory_inc = DMA_MEMORY_INCREASE_ENABLE;//目的数据块地址递增dma_init_ADC0.memory_width = DMA_MEMORY_WIDTH_16BIT;//目的数据块的数据宽度为16位dma_init_ADC0.number = (uint32_t)ADC0_Buffer_Size;//目的数据块的数据长度dma_init_ADC0.priority = DMA_PRIORITY_ULTRA_HIGH;      //超高的优先级dma_init(DMA0,DMA_CH0,&dma_init_ADC0);//使用dma_init_struct数据结构初始化DMA0通道0配置"DMA0通道5工作模式"开始///dma_circulation_enable(DMA0,DMA_CH0);//使能"DMA0通道0循环工作模式"//DMA0触发后,会按照指定的序号,循环触发读取ADC的值//在多通道AD转换中,DMA使用循环工作模式比较好
//	dma_circulation_disable(DMA0, DMA_CH0);//不使能"DMA0通道0循环工作模式"dma_memory_to_memory_disable(DMA0, DMA_CH0); //不使能"DMA0通道0内存到内存传输模式"
配置"DMA0通道5工作模式"结束///
///配置串口DMA接收开结束dma_channel_enable(DMA0,DMA_CH0);//使能指定的DMA0通道0	
}void ADC0_Init(void)
{adc_deinit(ADC0);//reset ADC0adc_tempsensor_vrefint_enable();//channel 16 and 17 enable of ADC0 //使能温度传感器通道和内部参考电压通道adc_mode_config(ADC_MODE_FREE);//只使用一个ADC,属于独立模式adc_special_function_config(ADC0,ADC_SCAN_MODE,ENABLE);//在多通道AD转换,要使用"扫描模式"adc_special_function_config(ADC0,ADC_CONTINUOUS_MODE,ENABLE);//设置AD转换为"连续模式"adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);//使用软件触发AD转换,ADC trigger configadc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);//ADC data alignment configadc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL,2);//连续进行AD转换的通道总数为2,在DMA传输中要知道有多少个通道参与AD转换/* ADC regular channel config */adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_16, ADC_SAMPLETIME_71POINT5);//将ADC0中ADC_CHANNEL_16通道放在第0位置优先进行AD转换,采样时间为71.5个时钟周期//配置读取内部温度adc_regular_channel_config(ADC0, 1, ADC_CHANNEL_17, ADC_SAMPLETIME_71POINT5);//将ADC0中ADC_CHANNEL_17通道放在第1位置优先进行AD转换,采样时间为71.5个时钟周期//配置读取内部参考电压adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);//使用软件触发AD转换adc_external_trigger_config(ADC0,ADC_REGULAR_CHANNEL,ENABLE);//使能ADC规则通道组外部触发,enable ADC regular channel group external triggeradc_enable(ADC0);//使能ADC0delay_ms(10);     //等待10msadc_calibration_enable(ADC0);//等待ADC0校准完成adc_dma_mode_enable(ADC0);//使能ADC转DMA功能,ADC DMA function enableadc_software_trigger_enable(ADC0,ADC_REGULAR_CHANNEL);//触发ADC0设备执行1次AD转换//由于前面配置"ADC0为连续转换模式",所以启动转换后,就可以连续执行AD转换了
}void ADC0_To_DMA0_Init(void)
{rcu_periph_clock_enable(RCU_ADC0);//使能ADC0时钟rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8);//配置ADC时钟8分频//由于ADC最大时钟频率为14MHz,经过8分频后,变为1.75MHz//	rcu_periph_clock_enable(RCU_GPIOA);//使能GPIOA端口时钟
//	rcu_periph_clock_enable(RCU_GPIOB);
//	rcu_periph_clock_enable(RCU_GPIOC);//使能GPIOC端口时钟
//	rcu_periph_clock_enable(RCU_GPIOD);
//	rcu_periph_clock_enable(RCU_GPIOE);
//	rcu_periph_clock_enable(RCU_GPIOF);
//	rcu_periph_clock_enable(RCU_GPIOG);//	rcu_periph_clock_enable(RCU_AF);rcu_periph_clock_enable(RCU_DMA0);
//	rcu_periph_clock_enable(RCU_DMA1);
//	rcu_periph_clock_enable(RCU_I2C1);
//	rcu_periph_clock_enable(RCU_ADC0);
//	rcu_periph_clock_enable(RCU_ADC2);
//	rcu_periph_clock_enable(RCU_ADC1);//使能ADC1时钟
//  rcu_periph_clock_enable(RCU_TIMER1);//	gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE);//使用SW下载,不使用JTAG下载,管脚用作其它功能//  gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6);//配置PA4,PA5和PA6引脚为模拟输入口//PA4复用到ADC01_IN4引脚,即ADC0/ADC1的第4通道//PA5复用到ADC01_IN5引脚,即ADC0/ADC1的第5通道//PA6复用到ADC01_IN6引脚,即ADC0/ADC1的第6通道
//	gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ,GPIO_PIN_4);
//	//配置PA4引脚为模拟输入口,复用到ADC01_IN4引脚,即ADC0/ADC1的第4通道
//	gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ,GPIO_PIN_5);
//	//配置PA5引脚为模拟输入口,复用到ADC01_IN5引脚,即ADC0/ADC1的第5通道
//	gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ,GPIO_PIN_6);
//	//配置PA6引脚为模拟输入口,复用到ADC01_IN6引脚,即ADC0/ADC1的第6通道//  gpio_init(GPIOC,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_3 | GPIO_PIN_4);//配置PC3和PC4引脚为模拟输入口//PC3复用到ADC012_IN13引脚,即ADC0/ADC1/ADC2的第13通道//PC4复用到ADC01_IN14,即ADC0/ADC1的第14通道
//	gpio_init(GPIOC, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ,GPIO_PIN_3);
//	//配置PC3引脚为模拟输入口,复用到ADC012_IN13引脚,即ADC0/ADC1/ADC2的第13通道
//	gpio_init(GPIOC, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ,GPIO_PIN_4);
//	//配置PC4引脚为模拟输入口,复用到ADC01_IN14,即ADC0/ADC1的第14通道DMA0_DMA_CH0_config();ADC0_Init();
}/*
温度(°C) = {(V25 - VSENSE) / Avg_Slope} + 25
V25 = VSENSE在25°C时的数值,这里取1.43V
Avg_Slope = 温度与VSENSE曲线的平均斜率,4.3mV/°C
即:(1.43 - voltage) / 0.0043 + 25;
ST和GD的手册里都写着不同芯片最大偏差45度,
*/
void Read_TemperatureValue(void)
{uint8_t i;uint32_t sum1,sum2;uint16_t *p;float f;sum1=0;sum2=0;p=&ADC0_Buffer[0][0];for(i=0;i<ADC0_cnt;i++){sum1=*p+sum1;p++;//内部温度数据累加sum2=*p+sum2;p++;//内部电压数据累加}sum1=sum1/ADC0_cnt;//计算平均值sum2=sum2/ADC0_cnt;//计算平均值printf("\r\nADC0_16: %d ", sum1);f = sum1;f = f	* 3.300;f = f / 4096;  //转换成电压值单位为Vprintf("\r\nADC0_16_Voltage: %0.3fV", f);f = V25 -f;f =f / AvgSlope;f= f+25; //计算温度值printf("\r\nTmoerature: %0.1f\r\n", f);printf("\r\nADC0_17: %d ", sum2);f = sum2;f = f	* 3.300;f = f / 4096;  //转换成电压值单位为Vprintf("\r\nInternalVoltage: %0.3fV\r\n", f);
}
#ifndef __ADC_H
#define __ADC_H#include "gd32f10x.h" //使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t#define V25       1.430   //V
#define AvgSlope  0.0043  //V/°Cextern void ADC0_To_DMA0_Init(void);
extern void Read_TemperatureValue(void);
#endif

main.c如下:
 

#include "gd32f10x.h" //使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t
#include "delay.h"#include "UART3.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "ADC.h"uint16_t volValue = 0;const char CPU_Reset_REG[]="\r\nCPU reset!\r\n";
int main(void)
{//NVIC_PRIGROUP_PRE4_SUB0:抢占优先级为4bit(取值为0~15),子优先级为0bit(没有响应优先级)//NVIC_PRIGROUP_PRE3_SUB1:抢占优先级为3bit(取值为0~7),子优先级为1bit(取值为0~1)//NVIC_PRIGROUP_PRE2_SUB2:抢占优先级为2bit(取值为0~3),子优先级为2bit(取值为0~3)//NVIC_PRIGROUP_PRE1_SUB3:抢占优先级为1bit(取值为0~1),子优先级为3bit(取值为0~7)//NVIC_PRIGROUP_PRE0_SUB4:抢占优先级为0bit(没有抢占优先级),子优先级为3bit(取值为0~15)nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);//设置系统中断优先级"抢占优先级为4bit,子优先级为0bit"delay_init();INTX_ENABLE();//开启所有中断UART3_Init(115200);//初始化UART3printf("%s",CPU_Reset_REG);//调试串口输出"\r\nCPU reset!\r\n"ADC0_To_DMA0_Init();while(1){delay_ms(500);Read_TemperatureValue();}
}

 

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

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

相关文章

【electron】electron安装过慢和打包报错:Unable to load file:

文章目录 一、安装过慢问题:二、打包报错&#xff1a;Unable to load file: 一、安装过慢问题: 一直处于安装过程 【解决】 #修改npm的配置文件 npm config edit#添加配置 electron_mirrorhttps://cdn.npm.taobao.org/dist/electron/二、打包报错&#xff1a;Unable to load…

camera hal|如何学习一个新平台

全网最具价值的Android Camera开发学习系列资料~ 作者:8年Android Camera开发,从Camera app一直做到Hal和驱动~ 欢迎订阅,相信能扩展你的知识面,提升个人能力~ 我自己目前从事的是android camera hal 的工作,工作上接触到的芯片平台要么是高通的,要么是mtk的。 其实…

c语言作业

作业1&#xff1a; 关于实参和形参 形参是实参的一份临时拷贝。 形参是在函数调用的时候才实例化&#xff0c;才开辟内存空间。 函数调用如果采用传值调用&#xff0c;改变形象不影响实参。 改变形参不是影响实参。 作业2&#xff1a; 函数调用exec&#xff08;&#xf…

C++QT教程3——手册4.11.1自带教程(笔记)——创建一个基于Qt Widget的应用程序

文章目录 创建一个基于Qt Widget的应用程序创建Text Finder项目素材文件 填补缺失的部分设计用户界面完成头文件完成源文件创建资源文件 编译和运行程序 参考文章 创建一个基于Qt Widget的应用程序 本教程介绍如何使用Qt Creator创建一个小型Qt应用程序&#xff0c;名为Text F…

电脑IP地址错误无法上网怎么办?

电脑出现IP地址错误后就将无法连接网络&#xff0c;从而无法正常访问互联网。那么当电脑出现IP地址错误时该怎么办呢&#xff1f; 确认是否禁用本地连接 你需要先确定是否禁用了本地网络连接&#xff0c;如果发现禁用&#xff0c;则将其启用即可。 启用方法&#xff1a;点击桌…

Spring 使用注解开发、代理模式、AOP

使用注解开发 在Spring4之后&#xff0c;要使用注解开发&#xff0c;必须要保证AOP的包导入了 项目搭建&#xff1a; 在配置文件中导入约束&#xff0c;增加注解支持 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.spri…

uniapp把城市换成26个字母和城市排序

后端返回的数据 我们要得效果 <template><view><view v-for"(value,key) in cities" :key"key"><view style"color: red;"> {{ key }} </view><view style"border: 1rpx solid black;"><tex…

PostgreSql 备份恢复

一、概述 数据库备份一般可分为物理备份和逻辑备份&#xff0c;其中物理备份又可分为物理冷备和物理热备&#xff0c;下面就各种备份方式进行详细说明&#xff08;一般情况下&#xff0c;生产环境采取的定时物理热备逻辑备份的方式&#xff0c;均是以下述方式为基础进一步研发编…

Linux 基础

巩固基础&#xff0c;砥砺前行 。 只有不断重复&#xff0c;才能做到超越自己。 能坚持把简单的事情做到极致&#xff0c;也是不容易的。 linux的目录结构 linux的文件系统采用树状的目录结构&#xff0c;在此结构的最上层是根目录“/”&#xff0c; 然后在此目录下再创建其他…

【算法——双指针】LeetCode 1089 复写零

千万不要被这道题标注着“简单”迷惑了&#xff0c;实际上需要注意的细节很多。 题目描述&#xff1a; 解题思路&#xff1a; 正序遍历&#xff0c;确定结果数组的最后一个元素所在的位置&#xff1b;知道最后一个元素的位置后倒序进行填充。 先找到最后一个需要复写的数 先…

javaee dom4j读取xml文件

引入jar包 dom4j-1.6.1.jar 创建xml文件 <?xml version"1.0" encoding"UTF-8"?> <books><book id"1"><title ID"t1">背影</title><price>88</price><author>三毛</author>…

Excel表格制作,快速提升效率好方法!

“作为一个刚开始工作的职场新人&#xff0c;每天要做各种不同的表格&#xff0c;真的让我很崩溃&#xff0c;感觉我对这些表格制作一点都不了解&#xff0c;Excel表格制作有什么比较好的方法吗&#xff1f;” Excel作为一款广泛应用于各个领域的管理和分析工作&#xff0c;给我…

【STM32】FreeRTOS消息队列和信号量学习

一、消息队列&#xff08;queue&#xff09; 队列是一种用于实现任务与任务之间&#xff0c;任务与中断之间消息交流的机制。 注意&#xff1a;1.数据的操作是FIFO模式。 2.队列需要明确数据的大小和队列的长度。 3.写和读都会出现堵塞。 实验&#xff1a;创建一个消息队列…

qt5.15.2 使用mysql8.1

报错&#xff1a; QMYSQL driver not loaded 报错&#xff1a;无 QMYSQL 使用 QStringList drivers QSqlDatabase::drivers(); //获取现在可用的数据库驱动 foreach(QString driver, drivers) qDebug() << driver; “QSQLITE” “QMARIADB” “QMYSQL” “QMYSQL3” “…

Linux常用命令——dmidecode命令

在线Linux命令查询工具 dmidecode 在Linux系统下获取有关硬件方面的信息 补充说明 dmidecode命令可以让你在Linux系统下获取有关硬件方面的信息。dmidecode的作用是将DMI数据库中的信息解码&#xff0c;以可读的文本方式显示。由于DMI信息可以人为修改&#xff0c;因此里面…

网络编程的使用

文章目录 基础代码URL类进行传输编码解码 协议TCPUDPhttp PORT端口协议的实现TCPUDP 模拟服务器 基础代码 最后一个是&#xff1a;只要再timeout时间内连接上就是true URL类 导了一个common-iojar包&#xff0c;那个IOUtils就是那个里面的工具类 进行传输编码解码 协议 TC…

【Spring Cloud +Vue+UniApp】智慧建筑工地平台源码

智慧工地源码 、智慧工地云平台源码、 智慧建筑源码支持私有化部署&#xff0c;提供SaaS硬件设备运维全套服务。 前言&#xff1a;互联网建筑工地&#xff0c;是将互联网的理念和技术引入建筑工地&#xff0c;从施工现场源头抓起&#xff0c;最大程度的收集人员、安全、环境、材…

微信小程序调用map数据 并在wxml中对数组进行截取的操作

wxs文件的位置如图 实现数组截取 只保留五张图片 <wxs module"filter" src"./slicefunc.wxs"></wxs> <view class"wrap"><view class"search-box" bindtap"toSearch"><view class"v1"…

【几个python虚拟环境会遇到的问题】

几个python虚拟环境会遇到的问题 twine is not recognized as an internal or external command,operable program or batch file.setup命令不报错但不起作用pipreqs is not recognized as an internal or external command,operable program or batch file. ‘twine’ is not …

快递管理系统springboot 寄件物流仓库java jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 快递管理系统springboot 系统有1权限&#xff1a;管…