news 2026/3/22 5:22:47

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/3/18 8:17:26

Zynq MPSoC 调试实录:AXI 寄存器地址重叠与 Vitis Bitstream 版本陷阱

1. 问题背景 在调试 Zynq MPSoC 的视频通路时,遇到一个诡异的现象:无法配置 v_frmbuf_wr (Video Frame Buffer Write) IP 核的 Width (0x10) 和 Height (0x18) 寄存器。 故障表现: 软件写入 Width = 800 (0x320)。 软件回读 Width,得到的值却是 0x00 或者与 Control 寄存…

作者头像 李华
网站建设 2026/3/14 11:15:46

爱舞功小程序+SaaS管理系统项目平台介绍说明书

爱舞功小程序SaaS管理系统项目平台介绍说明书一: 项目背景及简介随着舞蹈行业的发展,舞蹈机构在日常运营中面临着会员管理、课堂预约、数据统计、营销获客等多方面的挑战。传统的管理方式效率低下,难以满足机构高效盈利的需求。爱舞功项目应运而生&#…

作者头像 李华
网站建设 2026/3/16 1:36:36

一文搞懂AI大语言模型工作原理,初中生都能看懂

01 神经网络1,神经元:神经网络的最小单元神经网络的灵感来源于人类大脑的神经元,每个神经元就像一棵 “小树”,树突接收其它神经元的信号,细胞体处理信号,轴突把处理后的信号传给下一个神经元。生物神经元示…

作者头像 李华
网站建设 2026/3/20 8:38:36

3.2IT审计

1、IT审计范围的确定:总体范围、组织范围、物理范围、逻辑范围、其他相关内容 2、IT审计风险主要包括:固有风险、控制风险、检查风险和总体审计风险。 3、常用审计方法包括:访谈法、调查法、检查法、观察法、测试法、程序代码检查法 4、常用的…

作者头像 李华
网站建设 2026/3/12 23:49:20

深入理解类加载器

目录 一、回忆类加载过程 二、类加载器 1、定义与本质 2、JVM内置类加载体系 3、自定义类加载器 ClassLoader类中的两个关键方法: 核心原则: 4、类加载器加载的顺序 (1)核心:双亲委派模型下的委托与加载顺序 1&#xff…

作者头像 李华