当前位置: 首页 > 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.gsyq.cn/news/110931.html

相关文章:

  • 新国标电动车爬坡困境:当限速25km/h遭遇安全危机,无责伤亡谁来买单?
  • 腾讯云国际站代理商的定制化技术支持服务的成功案例有哪些?
  • VonaJS是如何做到文件级别精确HMR(热更新)的?
  • 爱舞功小程序+SaaS管理系统项目平台介绍说明书
  • 认知导向即面向服务——规避未来AI发展路径上的拟人化陷阱
  • Docker与本地PaddleOCR环境配置指南
  • API测试完整流程解析与最佳实践
  • ANT 设备(骑行台 FE-C 场景)开发的重点与难点全解析
  • MASIL玛丝兰发膜:用科技解锁秀发修护新方案 - 海棠依旧大
  • MASIL玛丝兰洗发水:专利护航,精准适配细分洗护需求 - 海棠依旧大
  • LobeChat能否实现AI编剧?电影剧本创意生成与结构优化
  • 2025年北京座椅电梯推荐厂商排行榜,专业座椅电梯加工厂精选 - mypinpai
  • Python安装onnxruntime加速GPT-SoVITS推理
  • 【Java毕设源码分享】基于springboot+vue的学生网课学习效果评价系统设计与实现(程序+文档+代码讲解+一条龙定制)
  • 强推!这117页图解指南对AI Agent的讲解非常透彻!
  • E: Unable to locate package 无法定位包
  • LobeChat能否实现AI评分系统?教育测评自动化尝试
  • 2025天津驻场安保公司TOP5权威推荐:资质齐全、高性价比 - myqiye
  • 系统化提升测试覆盖率:策略与实践路径
  • 【赵渝强老师】Oracle的数据文件
  • 教育机构如何利用LobeChat开展AI辅助教学?
  • 共享打印机成功后,提示“当前账户已锁定”
  • 基于STM32单片机快递柜外卖柜扫码取件语音播报蓝牙无线APP/WiFi无线APP/摄像头视频监控/云平台设计S368
  • 2025高温高压氢脆测试推荐生产厂家/企业推荐榜/行业品牌排行盘点 - 品牌推荐大师1
  • 语义增强词:GEO优化搜索的关键所在
  • 基于STM32单片机快递柜储物柜扫码灯光消毒语音播报蓝牙无线APP/WiFi无线APP/摄像头视频监控/云平台设计S369
  • PaddlePaddle镜像下载加速指南:使用清华镜像快速部署GPU环境
  • Markdown语法详解:为你的TensorFlow技术博客排版加分
  • 手把手教你部署LobeChat镜像,打造专属AI助手门户
  • YOLOv5训练日志分析:Loss曲线怎么看?