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

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); }
http://www.jsqmd.com/news/100208/

相关文章:

  • 毅硕HPC | NVIDIA DGX Spark 万字硬核评测:将AI超级工厂带上桌面
  • 大模型Agent强化学习完全指南:从PPO到GRPO的工具使用技术解析
  • 新国标电动车爬坡困境:当限速25km/h遭遇安全危机,无责伤亡谁来买单?
  • 腾讯云国际站代理商的定制化技术支持服务的成功案例有哪些?
  • VonaJS是如何做到文件级别精确HMR(热更新)的?
  • 41、FreeBSD 用户资源与常用命令指南
  • 一文搞懂AI大语言模型工作原理,初中生都能看懂
  • UVa 1396 Most Distant Point from the Sea
  • YT29B凿岩机吕梁精准检测稳定性能解析
  • RuoYi v1.2.0 全端开发神器:让多端适配从未如此简单!
  • 自定义重载运算符--《python语言程序设计》2018版--第8章20题使用Rational类求和数列之一
  • LobeChat能否申请基金?开源项目融资渠道
  • 爱舞功小程序+SaaS管理系统项目平台介绍说明书
  • VonaJS: Election
  • HunyuanVideo-Foley:高保真拟音生成扩散模型
  • 认知导向即面向服务——规避未来AI发展路径上的拟人化陷阱
  • 少儿编程Scratch3.0教程——03 外观积木(基础知识)
  • 电脑实用软件
  • 2025高温保护气氛箱式炉厂家TOP5权威推荐:超高温箱式炉 - 工业推荐榜
  • Docker与本地PaddleOCR环境配置指南
  • HLS的ready无法随机握手解决办法
  • 2025年天津十大保安服务联营合作企业推荐:知名的保安服务联 - myqiye
  • GPU算力租赁推荐:低成本训练YOLO大模型
  • HunyuanVideo-Foley:AI自动生成同步音效全解析
  • LobeChat能否用于生成APP界面文案?UX写作助手
  • API测试完整流程解析与最佳实践
  • 讯飞星火认知引擎如何通过LobeChat对外提供服务?
  • Web应用安全测试指南
  • 【Python办公自动化】PyQt5 TXT Word 转 PDF 转换器
  • 零日漏洞的崛起:网络安全的永恒军备竞赛