news 2026/5/1 8:01:08

HC32F460 DMA的链式传输(SPI从机+DMA发送/接收)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HC32F460 DMA的链式传输(SPI从机+DMA发送/接收)

1、SPI从机+DMA接收

SPI从机的接收机制与串口接收类似(参考前面文章),在使用DMA进行数据接收时,其配置方式也较为相似,因此不再重复说明DMA的具体配置过程。

由于SPI外设本身不提供接收超时中断机制,因此无法依赖超时信号来判断一次接收操作是否完成。为了解决这一问题,本DEMO中采用了片选信号(CS)的上升沿中断作为接收完成的判断依据。

具体实现逻辑如下:

  • SPI片选信号(CS)被配置为上升沿触发的外部中断源;
  • 当主机完成数据发送、释放片选信号后,CS引脚由低变高,触发上升沿中断;
  • 在该中断服务程序中,先判断当前已接收的数据长度,然后对DMA通道进行重置或重新使能,以便准备下一次接收操作;

这种方式有效地利用了SPI通信的物理特性,即片选信号为低时通信正在进行,为高时通信结束,从而实现了对接收完成事件的判断。

片选信号中断配置以及中断复位函数代码如下:

//片选中断配置,上升沿中断,用于指示通信结束 void SPI3_CS_Intterupt_Init(void) { stc_extint_init_t stcExtIntInit; stc_irq_signin_config_t stcIrqSignConfig; stc_gpio_init_t stcGpioInit; /* GPIO config */ (void)GPIO_StructInit(&stcGpioInit); stcGpioInit.u16ExtInt = PIN_EXTINT_ON; (void)GPIO_Init(SPI3_SS0_PORT, SPI3_SS0_PIN, &stcGpioInit); /* ExtInt config */ (void)EXTINT_StructInit(&stcExtIntInit); stcExtIntInit.u32Filter = EXTINT_FILTER_ON; stcExtIntInit.u32FilterClock = EXTINT_FCLK_DIV8; stcExtIntInit.u32Edge = EXTINT_TRIG_RISING; (void)EXTINT_Init(SPI3_SS0_EXTINT_CH, &stcExtIntInit); /* IRQ sign-in */ stcIrqSignConfig.enIntSrc = SPI3_SS0_INTSRC; stcIrqSignConfig.enIRQn = SPI3_CS_IRQn; stcIrqSignConfig.pfnCallback = &BSP_SPI_Slave_IRQHandler; (void)INTC_IrqSignIn(&stcIrqSignConfig); /* NVIC config */ NVIC_ClearPendingIRQ(stcIrqSignConfig.enIRQn); NVIC_SetPriority(stcIrqSignConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT); NVIC_EnableIRQ(stcIrqSignConfig.enIRQn); } //从机片选中断处理 void BSP_SPI_Slave_IRQHandler(void) { if (SET == EXTINT_GetExtIntStatus(SPI3_SS0_EXTINT_CH)) { SPI3_Recv_Lenth = SPI3_RX_BUF_SIZE - DMA_GetTransCount(SPI3_RX_DMA_UNIT, SPI3_RX_DMA_CH); //获取接收长度 SPI3_Receive_Evt = 1; //置位接收完成事件标志 DMA_SetDestAddr(SPI3_RX_DMA_UNIT, SPI3_RX_DMA_CH, (uint32_t)&SPI3_RxBuf[0]); //设置下次开始接收的地址 DMA_SetTransCount(SPI3_RX_DMA_UNIT, SPI3_RX_DMA_CH, SPI3_RX_BUF_SIZE); //设置下次DMA传输长度 EXTINT_ClearExtIntStatus(SPI3_SS0_EXTINT_CH); //清除中断标志 } }

2、SPI从机+DMA发送

在SPI从机的设计中,数据的发送过程是由主机完全控制的。从机无法预知主机何时开始读取数据,也无法确定主机需要接收多少数据。因此,从机必须始终保持数据就绪状态,并确保DMA发送通道随时准备响应主机的读取请求。

SPI从机内部通常包含两个关键寄存器:发送数据寄存器(DR) 和 移位寄存器(Shift Register)。当这两个寄存器均为空时,写入发送数据寄存器的数据会立即被转移到移位寄存器中,从而触发发送寄存器空”事件,进而可能再次通过DMA向发送数据寄存器写入新数据。这种行为虽然不会导致数据覆盖,但在通信尚未开始前,从机并不知道主机希望读取哪些数据。因此,提前填充到这两个寄存器中的数据可能是不合适的,甚至会导致错误的数据被发送出去。

为了解决这个问题,通常需要主机与从机之间进行一定的协议协商:

  • 主机先发送命令帧,通知从机需要执行的操作或读取的数据类型。
  • 从机接收到命令后,解析并准备相应的数据,并在内部完成数据缓冲。
  • 为了确保数据正确性,从机需清空发送数据寄存器和移位寄存器中的旧数据,但由于SPI外设没有专门用于清除移位寄存器的配置项,因此通常的做法是先关闭SPI外设再重新启用,以清空内部状态。
  • 最后,主机发起正式的数据读取操作,此时从机已准备好正确的数据,可以确保数据传输的准确性。

因此SPI从机发送的DMA通道,在数据准备完成之后,配置DMA的地址与长度,然后重启SPI外设。

此部分代码如下:

//SPI从机,需要在主机未读取数据之前,将数据准备好,待主机发起读取数据。 void SPI_Slave_Load_1st_Data(uint8_t *pu8Data) { DMA_SetSrcAddr(SPI3_TX_DMA_UNIT, SPI3_TX_DMA_CH, (uint32_t)(pu8Data)); // 设置DMA目的地址 DMA_SetTransCount(SPI3_TX_DMA_UNIT, SPI3_TX_DMA_CH, SPI3_TX_BUF_SIZE); // 设置DMA传输长度 CLR_REG32_BIT(CM_SPI3->CR1, SPI_CR1_SPE);//注意需要将SPI关闭再使能,才可以重新加载移位寄存器的数据 SET_REG32_BIT(CM_SPI3->CR1, SPI_CR1_SPE); }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 3:45:36

微前端架构的落地实践与性能优化指南

目录 一、微前端架构概述 1.1 什么是微前端 1.2 核心优势 二、主流微前端方案对比 2.1 方案分类 2.2 方案选择建议 三、微前端落地实践 3.1 项目结构设计 3.2 主应用配置(基于qiankun) 3.3 微应用配置 3.4 通信机制设计 四、性能优化策略 4…

作者头像 李华
网站建设 2026/5/1 1:39:50

中文优化做得好!LobeChat对国产大模型特别友好

LobeChat为何能成为国产大模型的“最佳拍档”? 在AI应用爆发的今天,越来越多企业和开发者开始尝试构建自己的智能助手。然而,直接调用大模型API往往面临诸多现实问题:接口不统一、中文支持弱、部署复杂、数据安全难保障……尤其是…

作者头像 李华
网站建设 2026/5/1 3:44:53

少儿编程Scratch3.0教程——04 声音积木(基础知识)

在前面的课程中我们学习了动作积木和外观积木,使用它们做了一些动画,不过就像是无声电影一样,我们的动画也没有声音。假如你现在每天玩的游戏、看的动画也没有声音,估计你就不会喜欢它们了。所以,我们今天的课程就来学…

作者头像 李华
网站建设 2026/5/1 1:36:00

EmotiVoice开源TTS项目结构与配置详解

EmotiVoice开源TTS项目结构与配置详解 在语音合成技术飞速发展的今天,用户不再满足于“能说话”的机械音,而是期待更自然、更有情绪的表达。EmotiVoice 正是在这一背景下脱颖而出的开源项目——它不仅支持多情感语音生成,还能通过短短几秒音频…

作者头像 李华
网站建设 2026/5/1 4:43:21

PyTorch安装踩坑指南:为YOLO运行保驾护航

PyTorch安装踩坑指南:为YOLO运行保驾护航 在工业视觉、智能安防甚至自动驾驶的开发前线,一个看似不起眼的问题——PyTorch装不上GPU支持——常常让项目卡在起点。你辛辛苦苦下载了最新的YOLOv8代码,满怀期待地运行detect.py,结果却…

作者头像 李华
网站建设 2026/5/1 6:51:54

CSRF漏洞总结复盘

一.什么是CSRF漏洞及利用流程CSRF(cross site request forgery)跨站(客户端)请求伪造,指攻击者在用户信息未失效的情况下(如cookie等信息),诱导用户点击某些链接,让用户在不知情的情况下,以用户身份像服务器发送请求,执…

作者头像 李华