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

【GD32】DMA实战指南:串口数据高效收发与循环模式应用详解

1. DMA技术基础与GD32实现原理第一次接触DMA这个概念时我也被它绕晕过。简单来说DMADirect Memory Access就像是你请了个私人助理专门负责帮你跑腿搬数据。想象一下你正在写代码突然需要把一大段数据从内存搬到串口发送出去。如果没有DMACPU就得亲自当搬运工一个个字节地搬效率低不说CPU还干不了别的活。GD32的DMA控制器设计得非常灵活我实测下来发现它有三大特点特别实用多通道并行GD32F103系列有2个DMA控制器每个控制器7个通道相当于可以同时处理14个数据传输任务宽数据支持支持8位、16位、32位数据传输这个在混合数据类型的项目中特别有用智能仲裁当多个外设同时请求DMA时会根据优先级自动调度不会出现数据冲突这里有个实际项目中的坑要提醒大家GD32的DMA通道和外设是固定映射的比如USART0的发送必须用DMA0的CH3。我第一次用的时候没注意这个配置了半天就是不工作后来查参考手册才发现这个问题。2. 串口DMA发送实战详解2.1 基础发送配置先来看最基础的DMA串口发送实现。下面这个例程是我在智能家居项目中实际用到的代码已经稳定运行了2年多void USART_DMA_Send_Config(void) { dma_parameter_struct dma_init_struct; // 使能DMA时钟 rcu_periph_clock_enable(RCU_DMA0); // 初始化DMA参数 dma_struct_para_init(dma_init_struct); dma_init_struct.direction DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_addr (uint32_t)send_buffer; // 发送缓冲区地址 dma_init_struct.memory_inc DMA_MEMORY_INCREASE_ENABLE; // 内存地址自增 dma_init_struct.memory_width DMA_MEMORY_WIDTH_8BIT; dma_init_struct.number 256; // 最大发送256字节 dma_init_struct.periph_addr (uint32_t)USART_DATA(USART0); // 串口数据寄存器地址 dma_init_struct.periph_inc DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.priority DMA_PRIORITY_ULTRA_HIGH; dma_init(DMA0, DMA_CH3, dma_init_struct); // 使能DMA通道 dma_channel_enable(DMA0, DMA_CH3); }这段代码有几个关键点需要注意内存地址自增一定要开启否则永远只会发送第一个字节外设地址必须固定为串口数据寄存器地址优先级设置要根据实际需求来实时性要求高的设成ULTRA_HIGH2.2 大数据量发送优化当需要发送超过256字节的数据时就需要用到DMA传输完成中断了。我在工业传感器项目中是这样处理的// 在初始化时添加中断配置 nvic_irq_enable(DMA0_Channel3_IRQn, 0, 0); dma_interrupt_enable(DMA0, DMA_CH3, DMA_INT_FTF); // 中断服务函数 void DMA0_Channel3_IRQHandler(void) { if(dma_interrupt_flag_get(DMA0, DMA_CH3, DMA_INT_FLAG_FTF)){ dma_interrupt_flag_clear(DMA0, DMA_CH3, DMA_INT_FLAG_FTF); // 处理下一批数据 if(send_remaining 0){ uint16_t chunk_size send_remaining 256 ? 256 : send_remaining; dma_transfer_number_config(DMA0, DMA_CH3, chunk_size); dma_memory_address_config(DMA0, DMA_CH3, (uint32_t)(send_buffer total_sent)); dma_channel_enable(DMA0, DMA_CH3); total_sent chunk_size; send_remaining - chunk_size; } } }这种分块发送的方式特别适合传输大文件或图像数据。实测在115200波特率下传输10KB数据CPU占用率不到1%。3. 串口DMA接收的高效方案3.1 循环缓冲接收模式DMA接收最大的优势就是可以实现零等待数据接收。下面分享我在物联网网关中使用的方案#define RX_BUFFER_SIZE 512 uint8_t rx_buffer[RX_BUFFER_SIZE]; volatile uint16_t rx_index 0; void USART_DMA_Receive_Config(void) { dma_parameter_struct dma_init_struct; // DMA接收配置 dma_struct_para_init(dma_init_struct); dma_init_struct.direction DMA_PERIPHERAL_TO_MEMORY; dma_init_struct.memory_addr (uint32_t)rx_buffer; dma_init_struct.memory_inc DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width DMA_MEMORY_WIDTH_8BIT; dma_init_struct.number RX_BUFFER_SIZE; dma_init_struct.periph_addr (uint32_t)USART_DATA(USART0); dma_init_struct.periph_inc DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.priority DMA_PRIORITY_HIGH; dma_init(DMA0, DMA_CH4, dma_init_struct); // 关键开启循环模式 dma_circulation_enable(DMA0, DMA_CH4); dma_channel_enable(DMA0, DMA_CH4); } // 获取接收数据长度 uint16_t USART_Get_Received_Length(void) { uint16_t remaining dma_transfer_number_get(DMA0, DMA_CH4); return RX_BUFFER_SIZE - remaining; }这个方案的精妙之处在于循环模式下DMA会自动从头开始写不会溢出通过计算剩余传输数可以知道接收了多少数据完全不需要CPU干预数据来了自动存到缓冲区3.2 接收数据解析技巧有了DMA接收缓冲区后数据解析就变得非常简单。我常用的方法是双指针法void Process_Received_Data(void) { static uint16_t last_index 0; uint16_t current_index USART_Get_Received_Length(); while(last_index ! current_index){ uint8_t data rx_buffer[last_index]; // 这里处理每个字节数据 if(data \n){ // 收到完整一帧 Process_Frame(last_index); } last_index; if(last_index RX_BUFFER_SIZE){ last_index 0; } } }这种方法在解析Modbus等协议时特别高效实测在1Mbps波特率下也能稳定处理。4. 循环模式的高级应用4.1 双缓冲技术实现在音频处理等实时性要求高的场景我推荐使用双缓冲技术。这是我在智能音箱项目中的实现#define BUF_SIZE 256 uint8_t buffer1[BUF_SIZE], buffer2[BUF_SIZE]; void DMA_Double_Buffer_Config(void) { dma_parameter_struct dma_init_struct; dma_struct_para_init(dma_init_struct); dma_init_struct.direction DMA_PERIPHERAL_TO_MEMORY; dma_init_struct.memory0_addr (uint32_t)buffer1; dma_init_struct.memory1_addr (uint32_t)buffer2; dma_init_struct.memory_inc DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width DMA_MEMORY_WIDTH_8BIT; dma_init_struct.number BUF_SIZE; dma_init_struct.periph_addr (uint32_t)USART_DATA(USART0); dma_init_struct.periph_inc DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.priority DMA_PRIORITY_ULTRA_HIGH; dma_init(DMA0, DMA_CH4, dma_init_struct); // 关键配置使能双缓冲和循环模式 dma_memory_switch_enable(DMA0, DMA_CH4); dma_circulation_enable(DMA0, DMA_CH4); dma_channel_enable(DMA0, DMA_CH4); // 配置中断 nvic_irq_enable(DMA0_Channel4_IRQn, 0, 0); dma_interrupt_enable(DMA0, DMA_CH4, DMA_INT_HTF | DMA_INT_FTF); } void DMA0_Channel4_IRQHandler(void) { if(dma_interrupt_flag_get(DMA0, DMA_CH4, DMA_INT_FLAG_HTF)){ dma_interrupt_flag_clear(DMA0, DMA_CH4, DMA_INT_FLAG_HTF); // 处理buffer1数据 Process_Buffer(buffer1, BUF_SIZE); } else if(dma_interrupt_flag_get(DMA0, DMA_CH4, DMA_INT_FLAG_FTF)){ dma_interrupt_flag_clear(DMA0, DMA_CH4, DMA_INT_FLAG_FTF); // 处理buffer2数据 Process_Buffer(buffer2, BUF_SIZE); } }这种实现有三大优势半传输中断和传输完成中断分别对应两个缓冲区数据处理和接收完全并行没有等待时间适合需要实时处理的音频、视频等数据流4.2 内存到内存的高效传输除了外设数据传输DMA的内存到内存传输也非常有用。我在图像处理项目中这样使用void DMA_MemCopy(uint32_t *src, uint32_t *dst, uint32_t size) { dma_parameter_struct dma_init_struct; dma_struct_para_init(dma_init_struct); dma_init_struct.direction DMA_MEMORY_TO_MEMORY; dma_init_struct.memory_addr (uint32_t)dst; dma_init_struct.memory_inc DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width DMA_MEMORY_WIDTH_32BIT; dma_init_struct.number size/4; dma_init_struct.periph_addr (uint32_t)src; dma_init_struct.periph_inc DMA_PERIPH_INCREASE_ENABLE; dma_init_struct.periph_width DMA_PERIPHERAL_WIDTH_32BIT; dma_init_struct.priority DMA_PRIORITY_HIGH; dma_init(DMA0, DMA_CH6, dma_init_struct); dma_channel_enable(DMA0, DMA_CH6); while(dma_flag_get(DMA0, DMA_CH6, DMA_FLAG_FTF) RESET); }实测这个内存拷贝函数比标准memcpy快3倍以上特别是在处理大块图像数据时效果更明显。有几点需要注意数据宽度最好设为32位以获得最大带宽传输数量要按数据宽度换算32位就是size/4内存和外设地址自增都要开启

相关文章:

【GD32】DMA实战指南:串口数据高效收发与循环模式应用详解

1. DMA技术基础与GD32实现原理 第一次接触DMA这个概念时,我也被它绕晕过。简单来说,DMA(Direct Memory Access)就像是你请了个私人助理,专门负责帮你跑腿搬数据。想象一下,你正在写代码,突然需…...

MediaPipe Pose实战应用:人体骨骼关键点检测,从图片到可视化全流程

MediaPipe Pose实战应用:人体骨骼关键点检测,从图片到可视化全流程 1. 项目背景与技术优势 想象一下这样的场景:健身房里的智能镜实时纠正你的瑜伽姿势,康复中心通过摄像头分析患者的步态异常,动画工作室无需动作捕捉…...

FreeRTOS临界区避坑指南:taskENTER_CRITICAL()用不对,你的系统可能随时崩溃

FreeRTOS临界区避坑指南:taskENTER_CRITICAL()用不对,你的系统可能随时崩溃 调试嵌入式系统时最令人抓狂的瞬间,往往是那些看似毫无规律的随机崩溃——比如某个传感器数据偶尔错位、系统突然卡死、或是中断服务程序莫名丢失事件。上周我就遇到…...

[特殊字符] OpenClaw v2.6.4 一键部署指南:5分钟让AI接管你的电脑(保姆级教程)

&#x1f525; 重点提示&#xff1a;本文提供的安装包已内置28万Tokens额度&#xff0c;<span style"color:#ff6b6b"> &#x1f4be; 最新版下载&#xff1a;&#x1f449; 点击获取 OpenClaw v2.6.4 一键安装包 &#x1f4cb; 环境要求 项目要求操作系统Wind…...

Lovable开发平台,生成安卓和iOS都能运行的原生App方案(用Kotlin或者Switf编写)

Lovable 核心生成的是 Web 应用&#xff08;React Supabase&#xff09;&#xff0c;它本身不直接编写纯原生的 Kotlin 或 Swift 代码。 不过&#xff0c;它通过 Capacitor 这个桥接框架实现了"一套代码&#xff0c;两端运行"的折中方案&#xff1a; &#x1f6e0;️…...

终极指南:5分钟掌握ComfyUI-BiRefNet-ZHO,轻松实现专业级图像视频抠图

终极指南&#xff1a;5分钟掌握ComfyUI-BiRefNet-ZHO&#xff0c;轻松实现专业级图像视频抠图 【免费下载链接】ComfyUI-BiRefNet-ZHO Better version for BiRefNet in ComfyUI | Both img & video 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-BiRefNet-ZHO …...

面向星上实时处理的银河飞腾多核DSP与FPGA异构计算平台构建

1. 银河飞腾DSP与FPGA异构计算平台概述 在卫星载荷这种特殊应用场景下&#xff0c;传统的通用处理器往往难以满足实时性、可靠性和低功耗的多重要求。我参与过多个航天项目&#xff0c;深刻体会到国产化异构计算平台的重要性。银河飞腾多核DSP搭配FPGA的方案&#xff0c;正好能…...

B站视频下载神器:三步搞定高清视频与音频永久收藏

B站视频下载神器&#xff1a;三步搞定高清视频与音频永久收藏 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader &#x1f633; 项目地址: https://gitcode.com/gh_mirrors/bi/Bi…...

告别SD卡!用闲置的香橙派Zero给树莓派4B做网络启动服务器(保姆级配置)

用香橙派Zero打造树莓派4B网络启动服务器&#xff1a;极简硬件的高阶玩法 手里闲置的香橙派Zero开发板除了吃灰还能做什么&#xff1f;今天我们来解锁一个硬核玩法——将它改造成树莓派4B的网络启动服务器。这种配置不仅能让你彻底告别SD卡&#xff0c;还能实现多台树莓派的集中…...

2025届最火的AI写作助手实测分析

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 一种借助自然语言处理技术的智能工具&#xff0c;是 AI 写作软件&#xff0c;它能够帮用户迅…...

如何智能配置系统防休眠:Move Mouse实战指南与高效方案

如何智能配置系统防休眠&#xff1a;Move Mouse实战指南与高效方案 【免费下载链接】movemouse Move Mouse is a simple piece of software that is designed to simulate user activity. 项目地址: https://gitcode.com/gh_mirrors/mo/movemouse 你是否曾在远程会议中短…...

别再对着HDF5文件发愁了!用Matlab读取gprMax的out文件,这份保姆级教程帮你搞定

从零掌握gprMax仿真数据&#xff1a;Matlab解析HDF5格式的完整实战指南 地质雷达仿真数据处理的第一个拦路虎&#xff0c;往往是那个神秘的.out文件。作为gprMax软件的输出结果&#xff0c;它采用HDF5格式存储&#xff0c;这种结构化的数据容器虽然高效&#xff0c;却让不少初学…...

别再被XML命名空间坑了!手把手教你用JAXB解析带命名空间的XML(附完整代码)

深度解析JAXB处理XML命名空间的五种实战方案 金融报文、Web服务响应、企业级数据交换——在这些需要处理标准化XML格式的场景中&#xff0c;命名空间就像一把双刃剑。它本是为了解决元素命名冲突而设计&#xff0c;却常常成为Java开发者使用JAXB解析时的"拦路虎"。当…...

从‘记账本’到‘智能合约’:手把手教你用Remix IDE部署第一个私有链Demo

从‘记账本’到‘智能合约’&#xff1a;手把手教你用Remix IDE部署第一个私有链Demo 区块链技术正在重塑数字世界的信任机制&#xff0c;而智能合约作为其核心应用之一&#xff0c;已经渗透到金融、供应链、版权管理等众多领域。对于开发者而言&#xff0c;理解区块链原理固然…...

新手入门不迷路:我花一周整理的神经网络工作原理通俗笔记,看完就能懂

引言 不知道有没有和我当初一样的朋友&#xff0c;刚接触深度学习的时候&#xff0c;信心满满翻开《深度学习》花书&#xff0c;刚看了两章神经元&#xff0c;满页的偏导、矩阵乘法直接给我干懵了。合上书脑子里就一个想法&#xff1a;神经网络这玩意儿是不是给天才准备的&…...

别再死磕‘Solving environment: failed’了!手把手教你配置Conda的.condarc文件(附清华/中科大源完整配置)

深度解析Conda环境配置&#xff1a;从原理到实践的.condarc文件终极指南 当你在终端看到"Solving environment: failed"这个刺眼的红色报错时&#xff0c;是否感到一阵无力&#xff1f;作为Python开发者&#xff0c;我们或多或少都经历过这种挫败感——明明按照教程…...

告别手动转换!用MyBatis TypeHandler优雅处理MySQL 8.0的JSON字段(附完整Spring Boot配置)

告别手动转换&#xff01;用MyBatis TypeHandler优雅处理MySQL 8.0的JSON字段&#xff08;附完整Spring Boot配置&#xff09; 在Spring Boot项目中处理MySQL的JSON字段时&#xff0c;开发者常常陷入手动序列化/反序列化的繁琐操作中。本文将带你彻底摆脱这种低效模式&#xf…...

从零搭建你的第一个“家庭网络实验室”:ENSP + 虚拟PC + 云设备实战指南

从零搭建你的第一个“家庭网络实验室”&#xff1a;ENSP 虚拟PC 云设备实战指南 在卧室里复现企业级网络拓扑&#xff1f;用一台笔记本电脑模拟智能家居的完整数据流转&#xff1f;这不是科幻场景&#xff0c;而是每位网络技术爱好者都能实现的低成本学习方案。本文将手把手带…...

别再手动输单号了!用Python的reportlab库5分钟搞定Code128条形码批量生成

用Python的reportlab库5分钟实现Code128条形码批量生成 每次月底盘点时&#xff0c;行政部的李姐总要加班到深夜——她需要手动将3000多个资产编号逐个输入到标签打印系统。直到上个月&#xff0c;隔壁IT部门的小张用20行Python代码帮她解决了这个问题。现在&#xff0c;只需运…...

从MATLAB到FPGA:手把手教你用Verilog在Vivado里实现SVPWM(附死区时间配置)

从MATLAB到FPGA&#xff1a;SVPWM算法在Vivado中的Verilog实现全解析 在电机控制领域&#xff0c;空间矢量脉宽调制&#xff08;SVPWM&#xff09;技术因其电压利用率高、谐波含量低等优势&#xff0c;已成为变频驱动系统的核心算法。对于已经掌握MATLAB仿真的工程师而言&#…...

3步搞定顽固窗口:WindowResizer 窗口强制调整工具完全指南

3步搞定顽固窗口&#xff1a;WindowResizer 窗口强制调整工具完全指南 【免费下载链接】WindowResizer 一个可以强制调整应用程序窗口大小的工具 项目地址: https://gitcode.com/gh_mirrors/wi/WindowResizer 你是否遇到过那些无法正常拖拽大小的应用程序窗口&#xff1…...

VisualCppRedist AIO终极指南:一键解决Windows运行库缺失问题

VisualCppRedist AIO终极指南&#xff1a;一键解决Windows运行库缺失问题 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist VisualCppRedist AIO是一个革命性的Win…...

告别啸叫与发热!手把手教你搞定DC-DC电源PCB布局(附Buck电路实战避坑清单)

告别啸叫与发热&#xff01;手把手教你搞定DC-DC电源PCB布局&#xff08;附Buck电路实战避坑清单&#xff09; 在硬件工程师的日常工作中&#xff0c;DC-DC电源模块的设计总是让人又爱又恨。高效的电源转换性能背后&#xff0c;往往隐藏着各种"暗坑"——莫名其妙的啸…...

别再手动翻页了!Jupyter Notebook 一键生成目录的保姆级教程(含豆瓣源加速)

解放生产力&#xff1a;Jupyter Notebook智能目录生成全攻略 在数据分析的日常工作中&#xff0c;我们常常需要处理包含数十个代码块和Markdown章节的复杂笔记本。想象一下这样的场景&#xff1a;当你需要回顾三个月前做的市场分析报告时&#xff0c;面对一个滚动条细如发丝的.…...

惊艳展示!CYBER-VISION零号协议实时分割效果:盲道、行人、车辆精准识别

惊艳展示&#xff01;CYBER-VISION零号协议实时分割效果&#xff1a;盲道、行人、车辆精准识别 1. 视觉革命&#xff1a;当AI遇见助盲科技 在熙攘的城市街道上&#xff0c;视障人士的每一次出行都是一场充满未知的挑战。传统的盲杖只能探测到脚边的障碍&#xff0c;而CYBER-V…...

免费QQ空间备份神器:一键导出所有说说记录,永久保存青春记忆

免费QQ空间备份神器&#xff1a;一键导出所有说说记录&#xff0c;永久保存青春记忆 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 还记得那些年你在QQ空间留下的青春印记吗&#xff1…...

告别MATLAB环境:保姆级教程教你用App Designer打包独立EXE(含Runtime配置避坑)

MATLAB App Designer应用打包实战&#xff1a;从开发到分发的全流程指南 在工程计算和科研领域&#xff0c;MATLAB一直是不可或缺的工具。随着App Designer的推出&#xff0c;开发交互式GUI应用变得前所未有的简单。但当你完成了一个优秀的应用后&#xff0c;如何让没有MATLAB环…...

WechatRealFriends技术指南:微信好友关系检测原理与系统化操作流程

WechatRealFriends技术指南&#xff1a;微信好友关系检测原理与系统化操作流程 【免费下载链接】WechatRealFriends 微信好友关系一键检测&#xff0c;基于微信ipad协议&#xff0c;看看有没有朋友偷偷删掉或者拉黑你 项目地址: https://gitcode.com/gh_mirrors/we/WechatRea…...

从周期到成长:中国巨石如何成为AI材料基础设施核心?

4月15日晚间&#xff0c;中国巨石披露2026年一季度业绩预告&#xff0c;预计归母净利润11.69亿元至13.15亿元&#xff0c;同比增长60%至80%&#xff1b;扣非净利润同样增长60%至80%。如果仅从数字看&#xff0c;这是一个典型的高增长季度&#xff0c;但更重要的问题是&#xff…...

PyQt5-tools安装总失败?可能是你的Python版本和系统环境在‘打架’(附兼容性自查清单)

PyQt5-tools安装失败深度排查&#xff1a;环境兼容性全景解决方案 当你在终端看到那个刺眼的红色报错——"Could not find a version that satisfies the requirement pyqt5-tools"时&#xff0c;可能已经尝试了更换镜像源、添加信任主机参数等常规操作。但问题依旧存…...