当前位置: 首页 > news >正文

【GD32F303红枫派使用手册】第十二节 ADC-双轴按键摇杆多通道循环采样实验

12.1 实验内容

本实验是通过ADC规则组多通道循环采样方式实现双轴按键摇杆传感器x和y轴电压值的读取,通过本实验主要学习以下内容:

  • 双轴按键摇杆传感器工作原理
  • DMA原理
  • 规则组多通道循环采样

12.2 实验原理

12.2.1 双轴按键摇杆传感器工作原理

摇杆一般在航模中的无人机、电玩、遥控车、云台等设备上应用广泛,很多带有屏幕的设备也经常使用摇杆作为菜单选择的输入控制。

双轴按键摇杆主要由两个电位器和一个按键开关组成,两个电位器随着摇杆扭转角度分别输出X、Y轴上对应的电压值,在Z轴方向上按下摇杆可触发轻触按键,在配套机械结构的作用下,无外力扭动的摇杆初始状态下,两个电位器都处在量程的中间位置。

12.2.2 DMA原理

本实验中ADC通道有两个,分别为摇杆传感器x轴和y轴电压,所以我们用规则组多通道采样实现双轴的电压读取,从上一章内容中可以知道,ADC规则组实现多通道转换时,必须要用到DMA。下面我们介绍下DMA原理。

DMA(直接存储器访问控制器)是一个非常好用的外设,它提供了一种硬件的方式在外设和存储器之间或者存储器和存储器之间传输数据,而无需 CPU 的介入,从而使 CPU 可以专注在处理其他系统功能上。GD32F303有两个DMA,其中DMA0有7个通道,DMA1有5个通道。DMA的特性如下:

  • 传输数据长度可编程配置,最大到 65536;
  • 12 个通道,并且每个通道都可配置(DMA0 有 7 个通道, DMA1 有 5 个通道);
  • AHB 和 APB 外设,片上闪存和 SRAM 都可以作为访问的源端和目的端;
  • 每个通道连接固定的硬件 DMA 请求;
  • 支持软件优先级(低、中、高、极高)和硬件优先级(通道号越低,优先级越高);
  • 存储器和外设的数据传输宽度可配置:字节,半字,字;
  • 存储器和外设的数据传输支持固定寻址和增量式寻址;
  • 支持循环传输模式;
  • 支持外设到存储器,存储器到外设,存储器到存储器的数据传输;
  • 每个通道有 3 种类型的事件标志和独立的中断;
  • 支持中断的使能和清除。  

DMA实现很简单,只要配置好以下几要素即可。

  1. 源地址和目标地址:DMA进行数据搬运过程为从源地址读取到数据,再搬运到目标地址。本实验中,需要把ADC转换结果搬运到自定义的buffer中,所以源地址就要设置为ADCx_RDATA寄存器地址,目标地址为buffer地址。
  1. 源和目标的地址增量方式:地址增量方式有固定模式和增量模式两种,固定模式是指进行一次DMA搬运后,下次搬运的源地址或目标地址保持不变;增量模式指进行一次DMA搬运后,下次搬运的源地址或目标地址会加1。本实验中,源地址始终都应该为ADCx_RDATA地址,所以源地址增量方式需要设置为固定模式,而目标地址为自定义buffer,我们需要用buffer[0]存储x轴数据,buffer[1]存储y轴数据,所以目标地址增量方式需要设置为增量模式。
  1. DMA传输方向:DMA传输方向有三种,分别为外设地址->存储器地址、存储器地址->外设地址以及存储器->存储器。本实验中源地址是外设地址,目标地址为自定义buffer地址即存储器地址,故传输方向需设置为外设地址->存储器地址。
  1. 源和目标数据位宽:源和目标数据位宽表示每次搬运的数据长度,可以设置为8bit、16bit和32bit。本实验中ADC的数据只占用ADCx_RDATA寄存器的低半字即16bit,所以源和目标位宽选择16bit即可。
  1. DMA传输个数和循环模式:传输个数表示一轮DMA传输可以搬运的次数。循环模式表示当一轮DMA传输结束后,是否直接进行下一轮搬运,当开启循环模式后,当上一轮DMA传输结束后,源地址和目标地址会恢复到最开始的状态。本实验中,需要转换2个通道ADC,故DMA传输个数设置为2,循环模式开启。
  1. DMA通道优先级:DMA的每个通道都有一个软件优先级,当DMA控制器在同一时间接收到多个外设请求时,仲裁器将根据外设请求的优先级来决定响应哪一个外设请求。优先级包括软件优先级和硬件优先级,优先级规则如下:
    软件优先级:分为4级,低,中,高和极高。可以通过寄存器DMA_CHxCTL的PRIO位域来配置。
    硬件优先级:当通道具有相同的软件优先级时,编号低的通道优先级高。例:通道0和通道2配置为相同的软件优先级时,通道0的优先级高于通道2。

上面描述了DMA配置的一些要素,那么DMA是如何被触发的呢,我们来看下DMA请求映射表:

DMA0各通道请求表:

DMA1各通道请求表:

本实验中是ADC配合DMA来使用,如果使用DMA去搬运ADC0的数据,从上表查询得知需要使用DMA0的通道0,如果是搬运ADC2的数据,则要用到DMA1的通道4。如现在设置DMA1的通道4去搬运ADC2的数据,当ADC2每转换一个通道,ADC2_RDATA会更新一次数据,此时ADC2会自动向DMA1的通道4发出一次搬运请求,DMA收到请求后会进行一次数据搬运。DMA的请求和应答方式见下图:

12.3 硬件设计

本实验的原理图如下:

从原理图中可以看出,摇杆的x、y轴分别接到了PF7和PF8,从Datasheet中可以查到PF7对应ADC2_CH5,PF8对应ADC2_CH6。

12.4 代码解析

本实验用到两个ADC2通道,使用ADC2规则组搭配DMA1通道4进行数据转换和搬运,ADC2规则组和DMA1通道4都开启循环模式,一旦开始ADC2规则组转换,会持续对摇杆x、y轴电压进行转换和数据搬运。

12.4.1 DMA和ADC初始化

在driver_adc.c中定义driver_adc_regular_ch_dma_config函数,该函数实现DMA和ADC的初始化。

C
void driver_adc_regular_ch_dma_config(typdef_adc_ch_general *ADC, typdef_adc_ch_parameter *ADC_CH,void *buffer)
{        dma_parameter_struct dma_data_parameter;/*DMA时钟开启*/rcu_periph_clock_enable(ADC->dma_parameter.rcu_dma);        /*DMA通道参数复位*/dma_deinit(ADC->dma_parameter.dma_periph, ADC->dma_parameter.dma_channel);        /*DMA源地址、目标地址、增量方式、传输位宽、传输方向、传输个数、优先级设置*/dma_data_parameter.periph_addr  = (uint32_t)(&ADC_RDATA(ADC->adc_port));dma_data_parameter.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;dma_data_parameter.memory_addr  = (uint32_t)(buffer);dma_data_parameter.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;if(ADC->adc_mode == ADC_DAUL_REGULAL_PARALLEL){dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_32BIT; }else{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       = ADC->dma_parameter.dma_number;dma_data_parameter.priority     = ADC->dma_parameter.dma_priority;dma_init(ADC->dma_parameter.dma_periph, ADC->dma_parameter.dma_channel, &dma_data_parameter);/*DMA循环模式设置*/if(ADC->dma_parameter.dma_circulation_mode == ENABLE){dma_circulation_enable(ADC->dma_parameter.dma_periph, ADC->dma_parameter.dma_channel);}else{dma_circulation_disable(ADC->dma_parameter.dma_periph, ADC->dma_parameter.dma_channel);}/*使能DMA*/dma_channel_enable(ADC->dma_parameter.dma_periph, ADC->dma_parameter.dma_channel);/*ADC初始化*/driver_adc_config(ADC,ADC_CH);
}

在driver_adc.h中声明了ADC DMA的结构体:

C
typedef struct __typdef_adc_dma_parameter
{rcu_periph_enum rcu_dma;//DMA时钟uint32_t dma_periph;//DMA号dma_channel_enum dma_channel;//DMA通道号uint32_t dma_number;//DMA传输个数uint32_t dma_priority;//DMA通道优先级EventStatus dma_circulation_mode;//循环模式
}typdef_adc_dma_parameter;

这段代码比较简单,请读者按照前面介绍的DMA原理进行解析。

12.4.2 摇杆ADC设置所需要的参数及IO口结构体定义

在bsp_adc.c中,对摇杆ADC设置所需要的参数及IO扩结构体数组进行了定义:

C
typdef_adc_ch_general  Rocker_ADC= {.rcu_adc = RCU_ADC2,//ADC2的时钟.adc_psc = RCU_CKADC_CKAPB2_DIV6,//ADC2设置为APB2 6分频.adc_port = ADC2,//ADC口为ADC2.adc_mode = ADC_MODE_FREE,//ADC模式为独立模式.adc_channel_group = ADC_REGULAR_CHANNEL,//使用规则组.adc_scan_function = ENABLE,//开启扫描模式.adc_continuous_function = ENABLE,//开启循环模式.ch_count = 2,//转换长度为2.dma_parameter = {.rcu_dma = RCU_DMA1,//DMA1的时钟.dma_periph = DMA1,//使用DMA1.dma_channel = DMA_CH4,//使用通道4.dma_number = 2,//DMA传输长度为2.dma_priority = DMA_PRIORITY_HIGH,//DMA通道优先级.dma_circulation_mode = ENABLE//DMA循环模式打开},.trigger_source = ADC0_1_2_EXTTRIG_REGULAR_NONE,//ADC触发源选择为软件触发.DMA_mode = ENABLE//使用DMA
};typdef_adc_ch_parameter Rocker_ch[2] = 
{{.rcu_port = RCU_GPIOF,//GPIOF时钟.port = GPIOF,//GPIO port.pin = GPIO_PIN_7,//PF7.gpio_speed = GPIO_OSPEED_10MHZ,//PF7速度设置为10MHz.adc_channel = ADC_CHANNEL_5,//PF7是ADC2的通道5.sample_time = ADC_SAMPLETIME_55POINT5//设置采样周期为55.5},{.rcu_port = RCU_GPIOF,//GPIOF时钟.port = GPIOF,//GPIO port.pin = GPIO_PIN_8,//PF8.gpio_speed = GPIO_OSPEED_10MHZ,//PF8速度设置为10MHz.adc_channel = ADC_CHANNEL_6,//PF8是ADC2的通道6.sample_time = ADC_SAMPLETIME_55POINT5//设置采样周期为55.5}
};//ADC通道参数配置,包括IO口,和对应通道以及采样周期

12.4.3 摇杆 ADC初始化和触发ADC转换的具体实现函数

在bsp_adc.c中定义了摇杆 DMA和ADC初始化和触发ADC转换的函数:

C
uint16_t Rocker_data[2] ;
void bsp_Rocker_ADC_config()
{driver_adc_regular_ch_dma_config(&Rocker_ADC,Rocker_ch,(uint16_t*)Rocker_data);driver_adc_software_trigger_enable(&Rocker_ADC);        
}

12.4.4 main函数实现

C
int main(void)
{delay_init();//延时函数初始化bsp_uart_init(&BOARD_UART);//BOARD_UART串口初始化bsp_Rocker_ADC_config();//摇杆ADC配置while (1){delay_ms(100);//延时100msprintf(" the Rocker x and y axis data is %d,%d \r\n", Rocker_data[0],Rocker_data[1]);//打印摇杆数据}
}

本例程main函数首先进行了延时函数初始化,为了演示实验结果,这里初始化了BOARD_UART串口,关于串口的使用,请读者参考串口章节,然后是摇杆ADC配置。在主循环中,每100ms打印一次摇杆x、y轴的ADC转换数据。

12.5 实验结果

使用USB-TypeC线,连接电脑和板上USB to UART口后,配置好串口调试助手,即可看到摇杆打印数据了,摇动摇杆可以看到x、y轴ADC转换数据的变化。

 

由聚沃科技原创,来源于【红枫派开发板】第十二讲 ADC-双轴按键摇杆多通道循环采样实验 - 苏州聚沃电子科技有限公司 (gd32bbs.com) GD32MCU技术交流群:859440462  

  

相关文章:

【GD32F303红枫派使用手册】第十二节 ADC-双轴按键摇杆多通道循环采样实验

12.1 实验内容 本实验是通过ADC规则组多通道循环采样方式实现双轴按键摇杆传感器x和y轴电压值的读取,通过本实验主要学习以下内容: 双轴按键摇杆传感器工作原理 DMA原理 规则组多通道循环采样 12.2 实验原理 12.2.1 双轴按键摇杆传感器工作原理 摇…...

Rust-03-数据类型

在 Rust 中,每一个值都属于某一个 数据类型,这告诉 Rust 它被指定为何种数据,以便明确数据处理方式。Rust 是 静态类型语言,也就是说在编译时就必须知道所有变量的类型。根据值及其使用方式,编译器通常可以推断出我们想…...

代理IP使用api接

代理IP使用API接口,通常是指通过API接口获取代理IP地址,并将其应用于爬虫、数据采集、反爬虫等场景中,以提高数据采集效率和保护数据采集安全。 一般来说,代理IP提供商会提供API接口文档和SDK供开发者使用。你需要先注册并登录代…...

C++中的适配器模式

目录 适配器模式(Adapter Pattern) 实际应用 图形渲染库适配器 日志系统适配器 支付系统适配器 总结 适配器模式(Adapter Pattern) 适配器模式是一种结构型设计模式,它使得原本由于接口不兼容而不能一起工作的类…...

MySQL入门学习-聚合和分组.最大值(MAX()函数)

MAX() 函数用于返回表达式的最大值。它通常与聚合和分组一起使用,以计算分组中的最大值。 以下是一些常见的聚合和分组函数: 1. MAX():返回表达式的最大值。 2. MIN():返回表达式的最小值。 3. AVG():返回表达式的…...

LLM大语言模型(十六):最新开源 GLM4-9B 本地部署,带不动,根本带不动

目录 前言 本机环境 GLM4代码库下载 模型文件下载:文件很大 修改为从本地模型文件启动 启动模型cli对话demo 慢,巨慢,一个字一个字的蹦 GPU资源使用情况 GLM3资源使用情况对比 前言 GLM-4-9B 是智谱 AI 推出的最新一代预训练模型 …...

【JVM】JVM 的内存区域

Java虚拟机(JVM)在执行Java程序时,将其运行时数据划分到若干不同的内存区域。这些内存区域的管理对Java应用程序的性能和稳定性有着重要影响。JVM的内存区域主要包括以下几部分: 方法区(Method Area)&#…...

intel新CPU性能提升68%!却在内存上违反祖训

前几天的台北电脑展「Computex」,各家都拿出了看家本领。 老朋友 AMD 在会展上发布了最新的锐龙 9000 系列和自己家移动处理器 HX AI 系列,IPC 和能效都取得了不错的进步。 当然隔壁蓝厂 intel 也没闲着,当即就掏出了下一代的低功耗移动端处…...

stm32MP135裸机编程:修改官方GPIO例程在DDR中点亮第一颗LED灯

0 参考资料 轻松使用STM32MP13x - 如MCU般在cortex A核上裸跑应用程序.pdf 正点原子stm32mp135开发板&原理图 STM32Cube_FW_MP13_V1.1.0 STM32CubeIDE v1.151 需要修改那些地方 1.1 修改LED引脚 本例使用开发板的PI3引脚链接的LED作为我们点亮的第一颗LED灯,…...

探索乡村振兴新模式:发挥科技创新在乡村振兴中的引领作用,构建智慧农业体系,助力美丽乡村建设

随着科技的不断进步,乡村振兴工作正迎来前所未有的发展机遇。科技创新作为推动社会发展的重要力量,在乡村振兴中发挥着越来越重要的引领作用。本文旨在探讨如何发挥科技创新在乡村振兴中的引领作用,通过构建智慧农业体系,助力美丽…...

机器学习笔记:focal loss

1 介绍 Focal Loss 是一种在类别不平衡的情况下改善模型性能的损失函数最初在 2017 年的论文《Focal Loss for Dense Object Detection》中提出这种损失函数主要用于解决在有挑战性的对象检测任务中,易分类的负样本占据主导地位的问题,从而导致模型难以…...

Python编程:解锁超能力,开挂人生!

在当今数字化时代,编程技能变得日益重要,而Python作为一门功能强大且易于学习的编程语言,已经成为许多人的首选。掌握Python,确实可以让你在技术领域如鱼得水,仿佛拥有了超能力一般。 Python的简易语法和丰富的库资源…...

TSINGSEE青犀视频:城市道路积水智能监管,智慧城市的守护者

随着城市化进程的加快,城市道路网络日益复杂,尤其在夏季,由于暴雨频发,道路积水问题成为影响城市交通和市民生活的重要因素之一。传统的道路积水监测方式往往依赖于人工巡逻和简单的监控设备,这些方法存在效率低下、响…...

几款免费又好用的项目管理工具(甘特图)

选择甘特图工具时,我们不仅要考虑工具的基本功能,还要考虑其易用性、团队协作能力、定制性以及与其他软件的集成能力。以下是几款好用的甘特图工具及它们的优点和不足,帮助你来选择适合自己的工具: 1、进度猫 特点: 任…...

落地台灯什么牌子的比较好?五款适合学生使用的大路灯分享

以往只知道养孩子难,但到底有多难,心里确实没有个切实的预期,但随着我家孩子越长越大,我才知道原来想要把孩子的身心健康照顾好到底是有多难!吃、穿、住、行无一不要精心挑选,就是为了能给他营造一个更好的…...

(免费领源码)基于 node.js#vue#mysql的网上游戏商城35112-计算机毕业设计项目选题推荐

摘 要 本论文主要论述了如何使用node.js语言开发一个基于vue的网上游戏商城,本系统将严格按照软件开发流程进行各个阶段的工作,本系统采用的数据库是Mysql,使用node.js的koa技术技术构建的一个管理系统,实现了本系统的全部功能。在…...

[2024-06]-[大模型]-[Ollama] 0-相关命令

常用的ollama命令[持续更新中] ollama更新: curl https://ollama.ai/install.sh |sh带着flash attention启动: OLLAMA_FLASH_ATTENTION1 ollama serve停止ollama服务: sudo systemctl stop ollama note:目前遇到sudo systemctl …...

Image组件无法设置长按事件

最近对image 设置长按事件,通过api发现有个长按事件 LongPressGesture,但是使用了长按没反应,于是看文档,文档描述如下: 当组件默认支持可拖拽时,如Text、TextInput、TextArea、HyperLink、Image和RichEd…...

计算机网络 —— 数据链路层(VLAN)

计算机网络 —— 数据链路层(VLAN) 什么是VLAN为什么要有VLANVLAN如何实现IEEE 802.1Q 我们今天来看VLAN: 什么是VLAN VLAN(Virtual Local Area Network,虚拟局域网)是一种网络技术,它将一个物…...

Redis基本操作介绍

1. 安装与启动 安装:Redis支持多种操作系统,包括Linux、Windows等。从Redis官网下载相应的安装包,并按照系统要求进行安装。启动: Linux系统:在终端中,进入Redis的安装目录,运行redis-server命…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: ​onCreate()​​ ​调用时机​:Activity 首次创建时调用。​…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...