硬汉嵌入式论坛

 找回密码
 立即注册
查看: 791|回复: 24
收起左侧

[SPI/QSPI] H7通过SPI连接AD7606,以全DMA的方式实现数据采集

  [复制链接]

62

主题

99

回帖

285

积分

高级会员

积分
285
发表于 2025-8-18 11:30:01 | 显示全部楼层 |阅读模式
大家好,请教:

H7与AD7606之间的SPI和其它硬件连接:
PE7输出10kHz PWM(作为AD7606的转换启动信号CONVST)PB14作为外部中断输入,连接AD7606的BUSY信号(下降沿表示转换完成)PA4作为SPI的硬件NSS提供给AD7606,另外PA5~PA7用作clk、miso 和 mosi

希望不用中断的方式实现H7对AD7606的采样数据读取。开辟一个8*8半字的环形缓冲区,实现方案:

PE7的PWM输出持续启动AD7606转换AD7606转换完成后通过以EXTI14(PB14)激活H7的DMA进行SPI的读写,1次读完8个通道数据到环形缓冲区,DMA使用目的地址递增的方式


问题点:上述EXTI14无法作为信号启动DMA

谢谢!
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
118335
QQ
发表于 2025-8-19 08:35:27 | 显示全部楼层
参考这个

[经验分享]纯硬件实现SPI接口驱动外部ADC以800KSps速度连续采样
https://forum.anfulai.cn/forum.p ... 0226&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

62

主题

99

回帖

285

积分

高级会员

积分
285
 楼主| 发表于 2025-8-19 10:15:06 | 显示全部楼层
谢谢硬汉!
赶紧学习一下
回复

使用道具 举报

62

主题

99

回帖

285

积分

高级会员

积分
285
 楼主| 发表于 2025-8-19 10:24:52 | 显示全部楼层
eric2013 发表于 2025-8-19 08:35
参考这个

[经验分享]纯硬件实现SPI接口驱动外部ADC以800KSps速度连续采样

这位大侠的方案的确很有创意,他利用TIM12来产生PWM启动AD7606转换,并利用TIM12_TRGO同时触发DMA读SPI,但是他没有利用AD7606转换完成后的BUSY信号,可不可以直接利用这个BUSY信号,作为外部的EXTI来触发DMA进行SPI数据接收呢?通过配置 DMAMUX1 能否实现这样的功能呢?

谢谢!
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
118335
QQ
发表于 2025-8-20 08:39:31 | 显示全部楼层
twodiamond 发表于 2025-8-19 10:24
这位大侠的方案的确很有创意,他利用TIM12来产生PWM启动AD7606转换,并利用TIM12_TRGO同时触发DMA读SPI, ...

EXTI触发也有个例子。36楼

哪位大哥,做过用H7 EXTI0同步触发SPI DMA双缓冲的,请教一下
https://forum.anfulai.cn/forum.p ... 0178&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

5

主题

175

回帖

190

积分

初级会员

积分
190
发表于 2025-8-20 17:42:53 | 显示全部楼层
H7的EXTI触发DMA 只有EXTI0 支持 ,EXTI1好像是挂在BDMA上
回复

使用道具 举报

62

主题

99

回帖

285

积分

高级会员

积分
285
 楼主| 发表于 2025-8-21 09:11:31 | 显示全部楼层
@eric2013@2859932063
是呀,这个用法DMA的触发必须得用EXTI0,可惜AD7606的BUSY脚接在了PB14。
请教一下:用EXTI14启动TIM12,然后用TIM12_TROG去触发DMA,这样可以不?

谢谢!
回复

使用道具 举报

5

主题

175

回帖

190

积分

初级会员

积分
190
发表于 2025-8-21 09:47:26 | 显示全部楼层
twodiamond 发表于 2025-8-21 09:11
@eric2013@2859932063
是呀,这个用法DMA的触发必须得用EXTI0,可惜AD7606的BUSY脚接在了PB14。
请教一下 ...

你这个跟中断没什么区别,应该要思考的是PB14支不支持作为外部定时器的触发源,这样触发的情况下就不会产生大量的中断,不然直接使用外部中断就好了
回复

使用道具 举报

62

主题

99

回帖

285

积分

高级会员

积分
285
 楼主| 发表于 2025-8-21 10:03:16 | 显示全部楼层
2859932063 发表于 2025-8-21 09:47
你这个跟中断没什么区别,应该要思考的是PB14支不支持作为外部定时器的触发源,这样触发的情况下就不会产 ...

是呀,这个方案好像行不通,EXTI14不能作为任何定时器的触发源。
那该如何同步AD7606的BUSY信号呢?
回复

使用道具 举报

5

主题

175

回帖

190

积分

初级会员

积分
190
发表于 2025-8-21 13:26:06 | 显示全部楼层
twodiamond 发表于 2025-8-21 10:03
是呀,这个方案好像行不通,EXTI14不能作为任何定时器的触发源。
那该如何同步AD7606的BUSY信号呢?

没办法 TIM12无法触发DMA
回复

使用道具 举报

62

主题

99

回帖

285

积分

高级会员

积分
285
 楼主| 发表于 2025-8-21 15:00:59 | 显示全部楼层
2859932063 发表于 2025-8-21 13:26
没办法 TIM12无法触发DMA

感谢,只能修改硬件了
回复

使用道具 举报

5

主题

175

回帖

190

积分

初级会员

积分
190
发表于 2025-8-21 20:45:03 | 显示全部楼层
twodiamond 发表于 2025-8-21 15:00
感谢,只能修改硬件了

抱歉 刚刚这里描述有点问题,TIM12无法通过直接触发DMA,但是可以通过dmamux进行DMA转发,可以往这方面想想办法
回复

使用道具 举报

5

主题

175

回帖

190

积分

初级会员

积分
190
发表于 2025-8-21 20:53:41 | 显示全部楼层
twodiamond 发表于 2025-8-21 15:00
感谢,只能修改硬件了

应该可以实现的,TIM12设置成输入捕获,捕获到触发一次dmamux,dmamux放行8次,就可以完成你的要求了
回复

使用道具 举报

62

主题

99

回帖

285

积分

高级会员

积分
285
 楼主| 发表于 2025-8-22 11:13:47 | 显示全部楼层
2859932063 发表于 2025-8-21 20:53
应该可以实现的,TIM12设置成输入捕获,捕获到触发一次dmamux,dmamux放行8次,就可以完成你的要求了

感谢感谢,非常感谢!
我们尝试一下
回复

使用道具 举报

5

主题

175

回帖

190

积分

初级会员

积分
190
发表于 2025-8-22 11:21:58 | 显示全部楼层
twodiamond 发表于 2025-8-22 11:13
感谢感谢,非常感谢!
我们尝试一下

大概思路就是输入捕获触发TIM12 TRGO,往这方面试一下,具体看看你们怎么实现了
回复

使用道具 举报

2

主题

9

回帖

15

积分

新手上路

积分
15
发表于 2025-9-15 10:05:58 | 显示全部楼层
回复

使用道具 举报

2

主题

9

回帖

15

积分

新手上路

积分
15
发表于 2025-9-15 14:34:36 | 显示全部楼层
我已经实现在项目中了 可以参考我的CubeMX配置

TIM12配置

TIM12配置
步骤2.png

评分

参与人数 1金币 +100 收起 理由
eric2013 + 100 很给力!

查看全部评分

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
118335
QQ
发表于 2025-9-16 08:41:30 | 显示全部楼层
13540437025 发表于 2025-9-15 14:34
我已经实现在项目中了 可以参考我的CubeMX配置

谢谢分享,也是一个好思路。

另外就是你的AD7606的采样率由那个控制的
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 4 天前 | 显示全部楼层
你好,目前项目中用的方法差不多,AD7606-4,定时器产生1KHz PWM作为convst信号,busy信号做外部中断输入,中断处理中拉低cs片选拉,再开启SPI+DMA2,outA+clk接SPI2,单次传输4路AD值,最后在SPI2中断拉高cs,遇到读值全是0的问题,fisrtdata波形也不是在16个脉冲后输出,而是4个脉冲下降沿就有输出了,4通道64个脉冲总共输出了16个fisrtdata,手头的两片板子都是这样,请问你们测试中有没有遇到类似的情况
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
118335
QQ
发表于 3 天前 | 显示全部楼层
hj_1126 发表于 2025-9-22 16:29
你好,目前项目中用的方法差不多,AD7606-4,定时器产生1KHz PWM作为convst信号,busy信号做外部中断输入, ...

你这个方式的话,使用SPI DMA意义不大,因为会频繁进出中断,测试下不使用DMA,仅SPI读取正常不
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 3 天前 | 显示全部楼层
感谢回复,类似楼主的情况,硬件上之前没考虑触发SPI和DMA,后边会考虑进去
仅用SPI去掉DMA也试过了,一样的结果,数据输出引脚上读取的时候是低电平
甚至怀疑是不是clk毛刺导致7606错误计算脉冲了(0.7*Vdrive -> H,0.3*Vdrive -> L)
firstdata clk.png
firstdata outA.png
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
118335
QQ
发表于 前天 08:40 | 显示全部楼层
hj_1126 发表于 2025-9-23 10:42
感谢回复,类似楼主的情况,硬件上之前没考虑触发SPI和DMA,后边会考虑进去
仅用SPI去掉DMA也试过了,一样 ...

这个 毛刺应该不影响,你把SPI GPIO的上拉使能了,是不是好点。
回复

使用道具 举报

2

主题

9

回帖

15

积分

新手上路

积分
15
发表于 前天 09:48 | 显示全部楼层
eric2013 发表于 2025-9-16 08:41
谢谢分享,也是一个好思路。

另外就是你的AD7606的采样率由那个控制的

采样率本来是通过生成指定频率的PWM控制ADC_CONVST引脚 但是硬件上意外的没有连到PWM外设 然后就用硬汉哥教程中的方法使用DMAMUX来让任意引脚产生PWM波形了
回复

使用道具 举报

2

主题

9

回帖

15

积分

新手上路

积分
15
发表于 前天 10:06 | 显示全部楼层
再贴一个我的详细步骤吧
1、ADC_BUSY配置为定时器12输入捕获引脚,通过下降沿触发,可设置IC_Filter来调整滤波等级
2、SPI配置为硬件CS控制,这样可以保证再下降沿触发的时候CS也自动拉低
3、SPI_DMA的TX和RX都配置为循环模式并且开启DMAMUX的同步事件,选择TIM12_TRGO事件,然后设置8次传输
4、ADC_CONVST可以连接到支持PWM输出的引脚上,也可以通过DMAMUX来控制任意引脚输出PWM(参考硬汉哥H7教程:第43章),我这里使用的是通过LPTIM更新事件来触发PWM
总结:配置完成后,PWM触发ADC_CONVST启动转换,ADC_BUSY拉低后触发输入捕获事件,接着自动触发SPI_DMA的数据读写,这样就完成了全自动流程SPI读写AD7606

下面是一个初始化代码供参考,这里通过DMA半满中断实现了一个双缓冲

[C] 纯文本查看 复制代码
/**
* @name _ad7606_driver_init
* @brief AD7606驱动初始化
* @attention  
* @param 
* @retval 
*/
void _ad7606_driver_init(void)
{
    // 过采样配置 OS[2:0] 100b MaxSampleFreq:12.5kHz
    HAL_GPIO_WritePin(ADC_OS2_GPIO_Port, ADC_OS2_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(ADC_OS1_GPIO_Port, ADC_OS1_Pin, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(ADC_OS0_GPIO_Port, ADC_OS0_Pin, GPIO_PIN_RESET);

    // 关闭待机模式
    HAL_GPIO_WritePin(ADC_STB_GPIO_Port, ADC_STB_Pin, GPIO_PIN_SET);

    // 复位AD7606
    HAL_GPIO_WritePin(ADC_RES_GPIO_Port,ADC_RES_Pin,GPIO_PIN_RESET);
    HAL_Delay(1);
    HAL_GPIO_WritePin(ADC_RES_GPIO_Port,ADC_RES_Pin,GPIO_PIN_SET);
    HAL_Delay(1);
    HAL_GPIO_WritePin(ADC_RES_GPIO_Port,ADC_RES_Pin,GPIO_PIN_RESET);

    // 开启BUSY引脚边沿捕获
    HAL_TIM_IC_Start(&htim12,TIM_CHANNEL_1);

    // 开启SPI传输 
    HAL_SPI_TransmitReceive_DMA(&hspi1,(uint8_t*)&tempData[0][0][0],(uint8_t*)&ad7606Data[0][0][0],AD7606_SAMPLE_COUNTS*AD7606_CHANNEL_NUM*AD7606_BUFFER_NUM);

    // 开启Convst输出 10kHZ
    HAL_DMAEx_EnableMuxRequestGenerator(&hdma_dma_generator0);
    HAL_DMA_Start(&hdma_dma_generator0,(uint32_t)convstPWM,(uint32_t)&ADC_CONV_GPIO_Port->BSRR,2);
    HAL_LPTIM_PWM_Start(&hlptim1,10000-1,1000-1);
}



回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
118335
QQ
发表于 昨天 09:27 | 显示全部楼层
13540437025 发表于 2025-9-24 10:06
再贴一个我的详细步骤吧
1、ADC_BUSY配置为定时器12输入捕获引脚,通过下降沿触发,可设置IC_Filter来调整 ...

谢谢分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-9-26 18:43 , Processed in 0.321866 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表