GD32 SPI 查询方式和DMA方式在全双模式下效率区别

最近在使用SPI的时候,遇到了一些数据传输效率问题,在此记录自己学习过程。SPI的基础知识这里就不在讲述了,直接分析SPI查询方式和DMA方式的效率问题。这里使用的芯片是GD32F303CC。

SPI以查询方式进行全双工通信

1.查询手册,SPI0挂载在APB2总线下,最高频率120MHZ。

2.接下来对SPI0进行配置

以下只是简化的配置内容,可以看出SPI0的CLK速率是3.75MHZ,还有一个注意的点MISO配置的是输入模式,而不是输出。

// SPI0 主机模式 使用软件SPI片选信号
/* SPI0 GPIO config:NSS/PA3, SCK/PA5, MISO/PA6, MOSI/PA7 */
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5 | GPIO_PIN_7);
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_6); // MOSI 浮空输入
/* PA3 as NSS */
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);

/* SPI0 parameter config */
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_init_struct.device_mode = SPI_MASTER;
spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT;
spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
spi_init_struct.nss = SPI_NSS_SOFT;     //软件片选
spi_init_struct.prescale = SPI_PSC_32;  //120M/32 = 3.75M
spi_init_struct.endian = SPI_ENDIAN_MSB;
spi_init(SPI0, &spi_init_struct);

3.使用API函数进行数据的发送和接收,最后通过逻辑分析仪抓取时序图

发现SPI传输数据的过程中,SCK的时钟频率为3.703M符合我们设置的CLK频率,但是我们发现两个SPI的字节之间有一段SCK是空闲的,从逻辑分析仪上看时间高达1.95us,比SPI传输一个自字节的时间还长,在极大的影响了SPI的传输速率。其实这个空闲时间正是MCU在搬运SPI的数据。

到底是不是这么回事呢,我们提升SPI的SCK速率,来继续观察。

 这里我们把SPI的CLK速率提升到15Mhz,发现空闲状态的时间已经是传输数据的时间的好几倍了,且空闲状态的时间为1.87us(逻辑分析仪采样率不足导致),与1.95us接近。如果传输大量数据的话,使用查询的方式效率还是太低。

SPI以DMA进行全双工通信

1.查询SPI0的DMA相关信息 

DMA 功能在传输过程中将应用程序从数据读写过程中释放出来, 从而提高了系统效率。根据查询手册我们知道,SPI0的RX和TX分别挂载在DMA0的通道1和通道2下面。

2.接下来对SPI0进行配置

其他SPI的配置都和前面一致,只是新增了SPI DMA相关的配置。这里简短的贴上一部分代码:

void spi_dma_config(void)
{
    dma_parameter_struct dma_init_struct;

    /* SPI0 transmit dma config:DMA0-DMA_CH2  */
    dma_deinit(DMA0, DMA_CH2);
    dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI0);
    dma_init_struct.memory_addr = (uint32_t)spi0_send_array;
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dma_init_struct.priority = DMA_PRIORITY_LOW;
    dma_init_struct.number = arraysize;
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init(DMA0, DMA_CH2, &dma_init_struct);
    /* configure DMA mode */
    dma_circulation_disable(DMA0, DMA_CH2);
    dma_memory_to_memory_disable(DMA0, DMA_CH2);

    /* SPI0 receive dma config:DMA0-DMA_CH1  */
    dma_deinit(DMA0, DMA_CH1);
    dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI0);
    dma_init_struct.memory_addr = (uint32_t)spi0_receive_array;
    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.priority = DMA_PRIORITY_HIGH;
    dma_init(DMA0, DMA_CH1, &dma_init_struct);
    /* configure DMA mode */
    dma_circulation_disable(DMA0, DMA_CH1);
    dma_memory_to_memory_disable(DMA0, DMA_CH1);

    /* SPI1 transmit dma config:DMA0,DMA_CH4  */
    dma_deinit(DMA0, DMA_CH4);
    dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI1);
    dma_init_struct.memory_addr = (uint32_t)spi1_send_array;
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
    dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
    dma_init(DMA0, DMA_CH4, &dma_init_struct);
    /* configure DMA mode */
    dma_circulation_disable(DMA0, DMA_CH4);
    dma_memory_to_memory_disable(DMA0, DMA_CH4);

    /* SPI1 receive dma config:DMA0,DMA_CH3  */
    dma_deinit(DMA0, DMA_CH3);
    dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI1);
    dma_init_struct.memory_addr = (uint32_t)spi1_receive_array;
    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA0, DMA_CH3, &dma_init_struct);
    /* configure DMA mode */
    dma_circulation_disable(DMA0, DMA_CH3);
    dma_memory_to_memory_disable(DMA0, DMA_CH3);
}
3.使用API函数进行数据的发送和接收,最后通过逻辑分析仪抓取时序图

从逻辑分析仪上可以看出,SPI使用DMA发送不会再出现两个字节之间CLK空余时间,极大的提升了SPI的传输速率。

防伪记录:文章原创于yl浪迹天涯。

总结

对于一般数据几个字节的传输,还是建议使用查询式(阻塞式)SPI,因为传输更加容易,DMA方式适合于高频次大容量数据传输的场景。比如在使用SPI 读取W25Q128芯片ID或者一般的操作指令的时候,就没有必要使用DMA方式了,但是在一次读取几个页的数据的时候,建议还是使用DMA方式。

附带源码

参考源码来源于GD32官网的GD32F30x_Firmware_Library_Vx.x.x库里面的Examples,具体代码直接去GD32官网下载即可。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring Cloud Alibaba-全链路灰度设计

文章目录 灰度发布概念灰度发布架构Spring Cloud Alibaba技术架构下的灰度发布实现基础设计HttpHeader设计 Spring Cloud Gateway改造Spring Cloud Gateway实现灰度发布过滤器 后端服务自定义Spring MVC请求拦截器OpenFeign改造自定义Loadbalancer 测试微服务注册元信息修改自定…

在windows11环境下安装CUDA11.6+Anaconda3+pyToach1.13搭建炼丹炉

0.电脑环境 系统:win11 显卡:NVIDIA GTX1650 还有一个pyCharm,其他也用不到了,需要的文章中会进行说明 1.安装CUDA11.6 目前2023.03出来的pyToach2.0是用不到了,因为最低版本支持CUDA11.7。我的显卡是1650&#xff0c…

阿里巴巴高管换血,吴永明接替张勇

文章目录 经济学人 💰 第 26 周🩸 阿里巴巴高管换血,吴永明接替张勇🌄 孙正义再出山🐿️ 英特尔加码德国!投资330亿美元建两座芯片工厂!🌊 亚马逊被指控强加 Prime 服务✈️ 印度航空…

Jmeter多接口测试之参数传递

目录 前言: 接口示例 正则表达式提取器 正则表达式提取实例 Json提取器 Json提取器实例 前言: 在进行多接口测试时,有些情况下需要将前一个接口返回数据作为后一个接口的参数,以模拟实际场景。JMeter作为一款常用的性能测试…

【EXCEL】如何查找特殊字符 问号‘?’星号 ‘*’

目录 0.环境 1.适用场景 1)直接搜索问号的结果: 2)修改【查找内容】后,搜索结果变为精准定位: 2.具体做法 0.环境 windows wps(或excel,这里试了,此问题wps和excel表格是通用…

中间件解析漏洞

服务器解析漏洞算是历史比较悠久了,但如今依然广泛存在。在此记录汇总一些常见服务器(WEB server)的解析漏洞,比如IIS6.0、IIS7.5、apache、nginx等 2|0 二、IIS5.x-6.x解析漏洞(针对asa/asp/cer) 2|11、打…

区块链中怎么惩罚虚假信息的矿工,工作量证明POW,共识算法

目录 区块链中怎么惩罚虚假信息的矿工 工作量证明POW 什么是工作量证明? 现在出现了另一个问题:如果其他人偷看了小明的答案并且抢答了怎么办? 为什么区块可以安全广播? 共识算法 小结 区块链中怎么惩罚虚假信息的矿工 1…

三分钟学习一个python小知识4-----------我的对python中numpy的理解, 我列举了关于numpy常用的10个例子来深入理解numpy

这里写目录标题 1、NumPy是什么2、NumPy的常见应用---必须掌握2.1.创建一个数组2.2.数组的属性2.3.取数组中的元素2.4.数组的运算2.5.数组的转置2.6. 数组的索引和切片2.7. 数组的重塑2.8. 数组的广播2.9. 数组的聚合操作2.10. 数组的排序 总结 1、NumPy是什么 NumPy是专门用于…

Spring MVC简介附入门案例

目录 一、SpringMVC简介 1.1 MVC模型 1.2 SpringMVC 二、SpringMVC入门案例 2.1 创建项目 2.2 引入依赖和tomcat插件 2.3 修改web.xml文件 2.4 新建springmvc.xml文件 2.5 编写控制器 2.6 配置运行方式 2.7 运行测试 三、SpringMVC执行流程 3.1 SpringMVC的组件…

Kangas:计算机视觉中的pandas

Kangas:计算机视觉中的pandas 介绍Kangas的优点 使用Kangas读取CSV文件读取图像文件Kangas DataGrid训练模型 介绍 在计算机视觉领域,Kangas是一种在图像数据处理和分析方面越来越受欢迎的工具之一。就像Pandas改变了数据分析人员处理表格数据的方式一样…

macOS FreeBSD 如何刷新 DNS 缓存

macOS FreeBSD 如何刷新 DNS 缓存 全文:如何刷新 DNS 缓存 (macOS, Linux, Windows) Unix Linux Windows 如何刷新 DNS 缓存 (macOS, FreeBSD, RHEL, CentOS, Debian, Ubuntu, Windows) 请访问原文链接:https://sysin.org/blog/how-to-flush-dns-cach…

AI绘画:切换黑色风格,安装更棒的主题!

从Stable Diffusion 出现的第一天起,我就开始关注这个项目,后来也出过几期教程。 一直以来都是只追求功能实现,不管界面的问题。现在我突然想要换一个帅气的主题了…就是这么突然! 默认的白色主题太….普通…既没有设计感啊&…

智能井盖传感器:以科技破解城市顽疾

在城市的道路网络中,井盖扮演着重要的角色,用于覆盖下方的管道和设施,然而,由于井盖的老化、损坏或被盗,常常会导致安全问题的发生,如路面塌陷、行人受伤等。井盖的状态监测和维护一直是城市管理者面临的挑…

社区分享|JumpServer开源堡垒机一直都是我的第一选择

编者注:本文由JumpServer开源堡垒机社区用户James Wei供稿。 “我最开始接触到的堡垒机就是JumpServer,最了解的也是JumpServer,已经完全习惯了JumpServer的使用习惯,这也是我一直选择JumpServer的一个重要原因。” ——JumpSer…

跟着AIGC学Linux:简介(一)

文章目录 1.Linux内核的历史2.基本概念3.发行版4.Linux应用领域5.Linux VS Windows横向对比表格: 1.Linux内核的历史 Linux内核最初由一位名叫Linus Torvalds的芬兰计算机科学家于1991年创建。当时,Torvalds是一名赫尔辛基大学的学生,他在寻…

Microsoft365有用吗?2023最新版office有哪些新功能?

office自97版到现在已有20多年,一直是作为行业标准,格式和兼容性好,比较正式,适合商务使用。包含多个组件,除了常用的word、excel、ppt外,还有收发邮件的outlook、管理数据库的access、排版桌面的publisher…

【Windows】虚拟串口工具VSPD7.2安装

【Windows】虚拟串口工具VSPD7.2安装 1、背景2、VSPD7.2安装3、创建虚拟串口 1、背景 ​Virtual Serial Ports Driver​是由著名的软件公司Eltima制作的一款非常好用的​虚拟串口工具​,简称:VSPD。 VSPD其功能如同 Windows机器上COM 串行端口的仿真器…

永磁同步直线电机学习笔记——什么是直线电机?

永磁同步直线电机(Permanent Magnet Linear Synchronous Motor,简称PMLSM)是一种电动机,它通过将永磁体和线圈组合在一起,将电能转化为机械运动。与传统的旋转电机不同,PMLSM是一种直线运动电机&#xff0c…

【Java高级语法】(十七)Stream流式编程:释放流式编程的效率与优雅,狂肝万字只为全面讲透Stream流!~

Java高级语法详解之Stream流 1️⃣ 概念及特征2️⃣ 优势和缺点3️⃣ 使用3.1 语法3.2 常用API详解3.3 案例 4️⃣ 应用场景5️⃣ 使用技巧6️⃣ 并行流 ParallelStream🌾 总结 1️⃣ 概念及特征 Java的Stream流是在Java 8中引入的一种用于处理集合数据的功能强大且…

【小沐学Web】Node.js搭建HTTPS 服务器

文章目录 1、简介1.1 HTTPS协议1.2 Node.js中的HTTPS 2、生成自签名证书2.1 key文件2.2 csr文件2.3 crt文件 4、代码测试4.1 Node.js简介4.2 Node.js的http模块4.3 Node.js的Express模块4.4 Node.js的https模块4.5 Node.js的httpsexpress模块 结语 1、简介 1.1 HTTPS协议 HTTP…