maomao190190 发表于 2023-2-21 21:25:24

求方案:用STM32H7想实现定时器触发DMA,向 SPI-DR 寄存器写数据

用STM32H7想实现定时器触发DMA,向 SPI-DR 寄存器写数据,也就是通过SPI发送数据, 同时定时器输出PWM波形,用作外部芯片的同步信号,写数据之前拉低,写完数据在拉高。最好是双缓冲的DMA发送,因为要每次更新发送数据,或者其他方法能实现就行,万分感谢!

Himem 发表于 2023-2-21 21:25:25

本帖最后由 Himem 于 2023-2-23 14:45 编辑

maomao190190 发表于 2023-2-23 12:59
请问您这个LPTIMER1和TRGO信号关了是如何关联的?我现在用的是Timer12,想用OC比较信号关联,请问这个怎么 ...
(引用自16楼)


当时这个工程是lptim直接分频就输出event,不需要再设置trgo源

(request number = 3 * spi8bit, 一次读写3字节)


连续读部分:
#define DMA_POINTS 256*3
uint32_t dmanull @ 0x30047ff0;
uint8_t dmabuf @ 0x30047000; //max 4k

....

void ad_dmainit(int Period, int Pulse)
{
//dma timebase 153600hz/ 64 = 2400
//HAL_LPTIM_PWM_Start(&hlptim1, 31, 16);
HAL_LPTIM_PWM_Start(&hlptim1, Period, Pulse);

memset(dmanull, 0, sizeof(dmanull));
memset(dmabuf, 0xaa, sizeof(dmabuf));

HAL_SPI_Transmit_DMA(&hspi1, (void*)dmanull, 12);//sck base
   
__HAL_DMA_DISABLE(hspi1.hdmarx);

HAL_DMAEx_MultiBufferStart(hspi1.hdmarx, (uint32_t)&hspi1.Instance->RXDR, (uint32_t)dmabuf, (uint32_t)dmabuf, DMA_POINTS);

SET_BIT(hspi1.Instance->CFG1, SPI_CFG1_RXDMAEN);
__HAL_SPI_ENABLE(&hspi1);
SET_BIT(hspi1.Instance->CR1, SPI_CR1_CSTART);
}

liuzhijun2008 发表于 2023-2-21 21:54:23

帮顶,没有这样用过

maomao190190 发表于 2023-2-21 22:08:50

定时器直接触发DMA,会比在定时器中断里面启动DMA传输效率高很多,应该是可以直接触发的

saccapanna 发表于 2023-2-21 22:42:05

我用过定时器产生PWM信号作为ADC的采样时钟,然后通过ADC的BUSY信号触发外部中断,用外部中断触发DMA传输,DMA读取SPI采集ADC结果。你用EXIT0触发DMA即可实现。前不久才用过。

maomao190190 发表于 2023-2-22 08:48:27

saccapanna 发表于 2023-2-21 22:42
我用过定时器产生PWM信号作为ADC的采样时钟,然后通过ADC的BUSY信号触发外部中断,用外部中断触发DMA传输, ...
(引用自4楼)

我这个是挂的DAC芯片dac80502,需要内部的timer定时触发,还有用同一个timer产生PWM信号作为外部的数据同步信号

saccapanna 发表于 2023-2-22 09:55:58

没用过 timer触发,我也不用CubeMX做驱动,都是直接玩寄存器,所以没法说得更细。如果确定触发源没有问题,就差一下你的数据在哪个存储区,H7的DTCM是不支持DMA的,如果使用DMA1/2,可以用AXI 或 D2域的RAM。如果确定RAM和SPI可以DMA访问,那就查查DMA的配置,看触发源和模式对不对,SPI初始化有没有问题,SPI的寄存器访问数据位数,DMA中也要设置。

yan2112000 发表于 2023-2-22 10:47:32

可以的,timer设置为比较模式,输出片选信号,输出低沿的同时触发DMA传输,dma设置为双buffer模式,在buffer切换时更新数据

maomao190190 发表于 2023-2-22 11:08:09

yan2112000 发表于 2023-2-22 10:47
可以的,timer设置为比较模式,输出片选信号,输出低沿的同时触发DMA传输,dma设置为双buffer模式,在buffe ...
(引用自7楼)

是的,我就想这么实现,现在SPI和DMA以及timer3都配置好了,用这个函数发送:HAL_DMAEx_MultiBufferStart_IT(&DMA_Handle, (uint32_t)SPI1TxBuf, (uint32_t)&hspi1.Instance->TXDR,(uint32_t)SPI1TxBuf, 1);
开启后中断函数void DMA1_Stream1_IRQHandler(void)可以进,也拉高了同步信号线,SPI信号始终测不到,您有类似的例程吗?

ssaiwo 发表于 2023-2-22 11:32:27

可以,之前用h7外部ad采集这么实现过,印象中硬汉的例程里好像就有

Himem 发表于 2023-2-22 11:36:02

本帖最后由 Himem 于 2023-2-22 11:43 编辑

750+ad7124,定时器触发dma双缓冲,没问题


cubemx配置如上

yan2112000 发表于 2023-2-22 13:15:04

maomao190190 发表于 2023-2-22 11:08
是的,我就想这么实现,现在SPI和DMA以及timer3都配置好了,用这个函数发送:HAL_DMAEx_MultiBufferStart ...
(引用自8楼)

看一下dma的标志和spi的标志,确认在哪里出问题了

风过不留痕z 发表于 2023-2-23 09:18:52

Himem 发表于 2023-2-22 11:36
750+ad7124,定时器触发dma双缓冲,没问题


(引用自10楼)

有程序可以分享下吗

Himem 发表于 2023-2-23 09:55:31

风过不留痕z 发表于 2023-2-23 09:18
有程序可以分享下吗
(引用自12楼)

遇到什么问题大家可以帮忙

风过不留痕z 发表于 2023-2-23 10:31:54

Himem 发表于 2023-2-23 09:55
遇到什么问题大家可以帮忙
(引用自13楼)

目前用7124组成的官方推荐电路(三线制传感器pt1000,ain0/3输出iout=250ua,ain1/2构成channel 0,配置单极性or双极性),参考选择ref1/2,pga=1,采集电压总是和万用表量的差几个mv,导致换算温度就少了好几度
ps:按万用表的电压换算温度是对的,所以暂定万用表是准确的电压

maomao190190 发表于 2023-2-23 12:56:05

现在用的是timer12,想用溢出中断和OC1比较中断,其中OC1 作为TRGO的信号,但是没找到如何配置,现在用STM32CUBE配置了SPI,timer12和DMA,其中DMA是在SPI1中配置的,现在进不来void DMA1_Stream0_IRQHandler(void)中断函数,启动传输实在这样写的:
HAL_DMAEx_MultiBufferStart_IT(&hdma_spi1_tx, (uint32_t)SPI1TxBuf, (uint32_t)&SPI1->TXDR,(uint32_t)SPI1TxBuf, 1);
HAL_TIM_Base_Start(&htim12);
请帮忙看一下,谢谢!
STM32CUBE配置如下:


maomao190190 发表于 2023-2-23 12:59:35

Himem 发表于 2023-2-22 11:36
750+ad7124,定时器触发dma双缓冲,没问题


(引用自10楼)

请问您这个LPTIMER1和TRGO信号关了是如何关联的?我现在用的是Timer12,想用OC比较信号关联,请问这个怎么关联,谢谢

maomao190190 发表于 2023-2-23 13:01:00

ssaiwo 发表于 2023-2-22 11:32
可以,之前用h7外部ad采集这么实现过,印象中硬汉的例程里好像就有
(引用自9楼)

有例程,我导入到我的工程里面,发现void DMA1_Stream1_IRQHandler(void)只进入两次后面就不进入了

maomao190190 发表于 2023-2-23 13:02:07

yan2112000 发表于 2023-2-22 10:47
可以的,timer设置为比较模式,输出片选信号,输出低沿的同时触发DMA传输,dma设置为双buffer模式,在buffe ...
(引用自7楼)

我贴出配置页面来了,您能帮我看一下问题出在哪里了吗?

maomao190190 发表于 2023-2-23 17:20:03

本帖最后由 maomao190190 于 2023-2-23 18:14 编辑

太感谢了,我按照您的写法做的现在可以看到SPI发出数据了,我把您写的函数改成了中断模式,HAL_LPTIM_PWM_Start_IT和HAL_DMAEx_MultiBufferStart_IT,想在里面把CS实现了,用的是软件控制CS,LPTIM1_IRQHandler中断正常,DMA 发送完成中断也正常,在LPTIM1_IRQHandler中断里面拉低CS,在DMA 发送完成中断里面拉高CS,但是还是不行,这个CS的时序应该是有问题,请问LPTIM1_IRQHandler中断触发的时间是LPtim1溢出的时间点吗?DMA 发送启动的时间点也是LPtim1溢出的时间点吗?

请指点一下吧!感谢感谢

Himem 发表于 2023-2-23 19:19:38

本帖最后由 Himem 于 2023-2-23 20:10 编辑

maomao190190 发表于 2023-2-23 17:20
太感谢了,我按照您的写法做的现在可以看到SPI发出数据了,我把您写的函数改成了中断模式,HAL_LPTIM_PWM_S ...
(引用自20楼)

我印象中是这样触发 SPI的硬NSS 其实在SPI每次数据中间的空闲时会释放,或者SPI本身有这个配置,
可能直接用硬NSS就解决了

好像是cubemx的NSSP Mode这个使能

maomao190190 发表于 2023-2-23 21:07:56

Himem 发表于 2023-2-23 19:19
我印象中是这样触发 SPI的硬NSS 其实在SPI每次数据中间的空闲时会释放,或者SPI本身有这个配置,
可能直 ...
(引用自21楼)

是的,如果硬NSS估计直接就能用了,我板子设计的时候就近选了PD6,现在只能用软NSS了,所以找两个合适的中断来控制同步信号

Himem 发表于 2023-2-24 10:29:50

本帖最后由 Himem 于 2023-2-24 10:39 编辑

maomao190190 发表于 2023-2-23 21:07
是的,如果硬NSS估计直接就能用了,我板子设计的时候就近选了PD6,现在只能用软NSS了,所以找两个合适的中 ...
(引用自22楼)

我的理解传输过程中是DMA始终是开,是SPI没给时钟,所以DMA中断只有标准的完成中断过半中断等,和每个小帧时序无关

当TIM触发传输时,这是再操作片选,已经来不及了
我的想法是再用一个同步开启的LPTIM2,将触发点提前一些操作片选

当然,PD3是SPI3_MOSI,再开一路DMA,每帧字节多一点,调整好LPTIM2时间点直接输出0,中断不参与也没问题

maomao190190 发表于 2023-2-24 14:06:37

Himem 发表于 2023-2-24 10:29
我的理解传输过程中是DMA始终是开,是SPI没给时钟,所以DMA中断只有标准的完成中断过半中断等,和每个小 ...
(引用自23楼)

可以了,真是太感谢了!!!
页: [1]
查看完整版本: 求方案:用STM32H7想实现定时器触发DMA,向 SPI-DR 寄存器写数据