【国产mcu填坑篇】华大单片机(小华半导体)一、SPI的DMA应用(发送主机)HC32L136

  • 最近需要用华大的hc32l136的硬件SPI+DMA传输,瞎写很久没调好,看参考手册,瞎碰一天搞通了。。。

    • 先说下我之前犯的错误,也是最宝贵的经验,供参考
      • 没多看参考手册直接写(即使有点烂仍然提供了最高的参考价值。。。),重点看SPIDMAC章节
      • 错误使用了软件触发传输,测到的现象是前两个字节可以正确发送,后面的无论是发送数量和数据都对不上了,误以为软件触发可用,自己的配置有问题,实际测试软件触发和规格书讲的一样,是不可用的或者说是不可靠的
    • 再说下正确的使用方式,文末会粘上测试代码
      • 关键点就一个,触发方式不要选DmaSWTrig软件触发(至于最后实例能用的这个,从软件的角度看还是软件触发,但官方的角度似乎不认为这是软件触发,或许是软件触发SPI硬件再触发DMA所以叫硬件触发?不管也罢,,,)
  • 特别注意:DMA可能存在硬件bug,在发送的最后一个字节DMA发送完成标记位(硬件置位)有50%概率提前置位,如果CS拉高太快(优化等级太高并且直接操作寄存器来操作CS)会概率导致最后一个字节异常,可以在拉高CS前加一个很小的延时解决,我单独测试DMA时没有异常,随便打开一个定时器中断(频率越高越容易)就可以碰到了,错误时序如下:
    在这里插入图片描述

  • 语文课兴许没及格,下面是参考手册的一些相关描述,没看明白:

  1. 先讲SPI支持软硬件访问
    在这里插入图片描述
    2.再讲只支持硬件块传输模式,且SPI和系统时钟不同频时不支持硬件触发(官方对软件/硬件触发的解释不是很到位,至少和我理解的不太一样)
    在这里插入图片描述
  2. 但是spi时钟和系统时钟必然是不同频的,那硬件触发到底能不能用呢?
    在这里插入图片描述
  3. 再看,所谓的软件/硬件DMA传输模式就是软件/硬件请求方式不同,似乎哪个也不支持了。。。软硬件触发和软硬件传输似乎没有关系?
    在这里插入图片描述
  • 最后,还是实践出真知。。。
  • 测试程序参考,每200ms用SPI+DMA发送24个字节:
#define SPI_HANDLE M0P_SPI1
#define DMA_HANDLE DmaCh1uint8_t data_tx_test[24] =
{0x11,0x22,0x23,0x44,0x55,0x66,0x77,0x88,0x11,0x22,0x23,0x44,0x55,0x66,0x77,0x88,0x11,0x22,0x23,0x44,0x55,0x66,0x77,0x88,
};//主要是CS/CLK/MOSI三个脚,不相干引脚忽略即可
static void App_GpioInit(void)		
{stc_gpio_cfg_t           stcPortCfg;DDL_ZERO_STRUCT(stcPortCfg);							//结构体初始化清零Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); //GPIO 外设时钟使能stcPortCfg.enDrv = GpioDrvH;stcPortCfg.enDir  = GpioDirOut;Gpio_Init(LCD_BK_PORT, LCD_BK_PIN, &stcPortCfg);  Gpio_Init(LCD_CS_PORT, LCD_CS_PIN, &stcPortCfg);  Gpio_SetAfMode(LCD_CS_PORT, LCD_CS_PIN,GpioAf1); 				//CSGpio_Init(LCD_RESET_PORT, LCD_RESET_PIN, &stcPortCfg);  Gpio_Init(LCD_WR_PORT, LCD_WR_PIN, &stcPortCfg);  Gpio_Init(LCD_SCK_PORT, LCD_SCK_PIN, &stcPortCfg);  Gpio_SetAfMode(LCD_SCK_PORT, LCD_SCK_PIN,GpioAf1);  			//CLKGpio_Init(LCD_SDA_PORT, LCD_SDA_PIN, &stcPortCfg);  Gpio_SetAfMode(LCD_SDA_PORT, LCD_SDA_PIN,GpioAf1);  			//MOSI	
}static void App_SPIInit(void)
{stc_spi_cfg_t  SpiInitStruct;Sysctrl_SetPeripheralGate(SysctrlPeripheralSpi1,TRUE);//SPI0模块配置:主机SpiInitStruct.enSpiMode = SpiMskMaster;   		//配置位主机模式SpiInitStruct.enPclkDiv = SpiClkMskDiv2;  		//波特率:fsys/2SpiInitStruct.enCPOL    = SpiMskcpolhigh;  		//极性SpiInitStruct.enCPHA 	= SpiMskCphasecond; 	//第二电平采样Spi_Init(SPI_HANDLE, &SpiInitStruct);Spi_FuncEnable(SPI_HANDLE,SpiMskDmaTxEn);		//这里只使用了发送功能
}static void App_DmaCfg(void)
{ stc_dma_cfg_t stcDmaCfg;Sysctrl_SetPeripheralGate(SysctrlPeripheralDma,TRUE); 			//打开DMA时钟DDL_ZERO_STRUCT(stcDmaCfg);stcDmaCfg.enMode =  DmaMskBlock;                           		//选择块传输stcDmaCfg.u16BlockSize = 1;                             		//块传输个数stcDmaCfg.u16TransferCnt = 24;                    				//块传输次数,一次传输数据大小为 块传输个数*BUFFER_SIZEstcDmaCfg.enTransferWidth = DmaMsk8Bit;                   		//传输数据的宽度,此处选择字(8Bit)宽度stcDmaCfg.enSrcAddrMode = DmaMskSrcAddrInc;                		//源地址自增stcDmaCfg.enDstAddrMode = DmaMskDstAddrFix;                		//目的地址固定stcDmaCfg.enDestAddrReloadCtl = DmaMskDstAddrReloadEnable;		//使能重新加载传输目的地址stcDmaCfg.enSrcAddrReloadCtl = DmaMskSrcAddrReloadEnable;		//使能重新加载传输源地址stcDmaCfg.enSrcBcTcReloadCtl = DmaMskBcTcReloadEnable;			//使能重新加载BC/TC值stcDmaCfg.u32SrcAddress = (uint32_t)&data_tx_test[0]; 			//指定传输源地址stcDmaCfg.u32DstAddress = (uint32_t)&(M0P_SPI1->DATA);    		//指定传输目的地址stcDmaCfg.enRequestNum = DmaSPI1TXTrig;                        	//设置为硬件触发stcDmaCfg.enTransferMode = DmaMskOneTransfer;              		//dma只传输一次,DMAC传输完成时清除CONFA:ENS位stcDmaCfg.enPriority = DmaMskPriorityFix;                  		//各通道固定优先级,CH0优先级 > CH1优先级Dma_InitChannel(DMA_HANDLE,&stcDmaCfg);                        	//初始化dma通道0Dma_Enable();//Dma_EnableChannel(DMA_HANDLE);								//开启通道即开启一次发送
}void dma_test(void)
{en_dma_stat_t ste;while(1){ delay1ms(200);M0P_SPI1->SSN = FALSE;Dma_EnableChannel(DMA_HANDLE);								//启动传输,所以这种方式到底算软件还是硬件??ste = Dma_GetStat(DMA_HANDLE);while(ste != DmaTransferComplete){ste = Dma_GetStat(DMA_HANDLE);}delay10us(1);												//!!!这个延时是必要的,防止数据多时上面的等待不能有效判断最后一个字节M0P_SPI1->SSN = TRUE;}
}void demo(void)
{App_GpioInit();App_DmaCfg();App_SPIInit();dma_test();
}
  • 实测SPI主机发送ok:
    在这里插入图片描述

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

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

相关文章

iis配置asp网站

1.安装IIS的ASP win7和win10都是一样的 下安装IIS时ASP一般被默认不选中的状态,因此需要打开IIS检查功能视图栏中是否存在ASP选项,若没有则需要从控制面板->程序和 功能->打开或关闭Windows功能->Internet信息服务->万维网服务->应用程序…

数环通更新动态|新增连接器抖店自建、叮当OKR、千易ERP、货拉拉

更新快速预览 新增连接器4个 抖店自建 叮当OKR 千易ERP 货拉拉 应用更新2个 百度统计(2) 旺店通(1) 应用连接器 新增连接器 1.抖店自建 抖店是抖音官方打造的电商商家实现一站式经营平台,为商家提供全链路服务&#xf…

Selenium定位元素的方法css和xpath的区别

selenium是一种自动化测试工具,它可以通过不同的定位方式来识别网页上的元素,如id、name、class、tag、link text、partial link text、css和xpath。 css和xpath是两种常用的定位方式,它们都可以通过元素的属性或者层级关系来定位元素&#…

MacOS环境下Kali Linux安装及使用指导

Kali Linux是一个开源的、基于Debian的Linux发行版,面向各种信息安全任务,如渗透测试、安全研究、计算机取证和逆向工程,是最先进的渗透测试发行版,它的前身是BackTrack。 1. 我们为什么要用Kali Linux 由于Kali Linux具有以下特…

【脑筋急转弯系列】乒乓球称重问题

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

SpringBoot+Vue实现一个系统登录功能

1. 创建一个Spring Boot项目&#xff0c;添加Web和Security依赖。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId> </dependency>2. 创建一个User实体类&#xff0c;用…

vue render函数的使用场景

render函数使用和详解_render函数如何使用-CSDN博客 上面链接写的很详细&#xff0c;有不懂的地方可以留言互相交流哈&#xff01;~~~~~~

蓝桥杯简介

蓝桥杯全国软件和信息技术专业人才大赛是由工业和信息化部人才交流中心举办的全国性IT学科赛事。这个比赛在全国范围内有着广泛的影响力&#xff0c;参赛人数已经累计超过40万人&#xff0c;涵盖了全国1200余所高校。在高校教育教学改革和创新人才培养方面&#xff0c;蓝桥杯大…

FDTD2018a安装问题记录

FDTD2018a安装问题记录 目录问题解决方案 目录 问题 解决方案 电脑名字如果是中文改成英文

编程笔记 html5cssjs 036 CSS概述

编程笔记 html5&css&js 036 CSS概述 一、什么是 CSS?二、样式非常重要三、CSS 语法四、CSS 注释五、示例 CSS (Cascading Style Sheets&#xff0c;层叠样式表&#xff09;&#xff0c;是一种用来为结构化文档&#xff08;如 HTML 文档或 XML 应用&#xff09;添加样式…

全局唯一ID实现方案——雪花算法

全局唯一ID实现方案——雪花算法 雪花算法原理 Snowflake&#xff0c;雪花算法是由Twitter开源的分布式ID生成算法&#xff0c;以划分命名空间的方式将 64-bit位分割成多个部分&#xff0c;每个部分代表不同的含义。而 Java中64bit的整数是Long类型&#xff0c;所以在 Java 中…

数据加密过程和数据加密的方法有哪些?

在信息日益发达的今天&#xff0c;数据安全已成为越来越受到关注的问题。数据加密技术作为保护信息安全的重要手段&#xff0c;对于维护个人隐私、企业机密以及国家安全具有重要意义。希望通过本文的学习&#xff0c;您能够对数据加密有一个全面的认识&#xff0c;并在实际应用…

基于Java的校车管理系统

源码跳转链接: 基于java的校车管理系统 基于Java的校车管理系统 摘要一、绪论1.1设计目的与意义1.2需求分析1.3用户、管理员用例图 二、系统总体设计2.1系统模块设计2.2数据库分析与设计2.2.1数据库概念结构设计2.2.2表结构设计2.2.3数据库连接池原理 2.3系统后台设计与分析2.…

DAY9--learning english

一、积累 1.compilation 2.mow lawn 3.vendor 4.transparent 5. perpetual 6. extinct 7. thirst 8.defy 9.resentment 10.ample 11.restore 12. firm 13. coincidence 14. spoil 15. astonish 16. blade 17.pierce 18. indigenous 19.perspective 20.vibrant 二、练习 1.spe…

关于枚举问题

一、abc算法 #include "cstdio" int main(){int a,b,c;//定义名字为a,b,c的三个整型变量for(a0;a<9;a){ // a的初始值是0&#xff0c;当a满足a<9的时候&#xff0c;可以执行循环体 //自增的意思for(b0;b<9;b){for(c0;c<9;c){//abcbcc532//abc--&g…

Wpf 使用 Prism 实战开发Day11

仓储&#xff08;Repository&#xff09;/工作单元&#xff08;Unit Of Work&#xff09;模式 仓储&#xff08;rep&#xff09;:仓储接口定义了对实体类访问数据库及操作的方法。它统一管理数据访问的逻辑&#xff0c;并与业务逻辑层进行解耦。 简单的理解就是对访问数据库的一…

【设计模式之美】重构(三)之解耦方法论:如何通过封装、抽象、模块化、中间层等解耦代码?

文章目录 一. “解耦”概述二. 如何给代码“解耦”&#xff1f;1. 封装与抽象2. 中间层2.1. 引入中间层能**简化模块或类之间的依赖关系**。2.2. 引入中间层可以起到过渡的作用&#xff0c;能够让开发和重构同步进行&#xff0c;不互相干扰。 3. 模块化4. 其他设计思想和原则4.…

SpringBoot+Vue2+Echarts实现图表的统计

SpringBootVue2Echarts实现图表的统计 一、需求 该功能是为了实现在对学生分班的人数统计下&#xff0c;所作出的相应调整。Echarts图表在实际项目中也有使用。 二、具体实现 1、数据库设计 班级表&#xff1a;classes 字段名类型长度小数点是否允许为空是否为主键说明ci…

opencv通过轮廓点生成闭合图像

前言 有时候需要将某一些点生成闭合的二值图像。记录一下。 // 轮廓点个数 int nrCurvePoints curContour.nr; // 轮廓点 DIM2DL* curvePoints curContour.pts;std::vector<cv::Point> points; // 轮廓点集合 for (int cntPoint 0; cntPoint < nrCurvePoints; cn…

[晓丽紫]每日论文分享(有中文摘要,源码或项目地址)--大模型,扩散模型...

专属领域论文订阅 关注{晓理紫|小李子}&#xff0c;每日更新论文&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持 分类: 大语言模型LLM视觉模型VLM扩散模型视觉导航具身智能&#xff0c;机器人强化学习开放词汇&#xff0c;检测分割 [晓丽紫]每日论…