硬汉嵌入式论坛

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

[有问必答] 关于F407使用DMA从内存搬运数据到GPIO口产生时序问题。

[复制链接]
回帖奖励 240 个金币 回复本帖可获得 5 个金币奖励! 每人限 1 次

22

主题

86

回帖

152

积分

初级会员

积分
152
发表于 3 天前 | 显示全部楼层 |阅读模式
看了H7的文档来进行F407的代码编写。但是没有产生波形,我的代码如下。

[C] 纯文本查看 复制代码
/BSSR寄存器数据
static const uint32_t pwmPattern[] = {
    0x0000FFFF,  //16个IO置1
    0xFFFF0000,  //16个IO置0
    0x0000FFFF, 
    0xFFFF0000  
};


static void GPIOE_DMA_PWM_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    DMA_InitTypeDef DMA_InitStruct;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);


    GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_All;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOE, &GPIO_InitStruct);

    DMA_DeInit(DMA2_Stream1);
    while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE);
    DMA_ClearFlag(DMA2_Stream1, DMA_LIFCR_CTCIF1 | DMA_LIFCR_CHTIF1 | DMA_LIFCR_CTEIF1 | DMA_LIFCR_CDMEIF1 | DMA_LIFCR_CFEIF1);

    DMA_StructInit(&DMA_InitStruct);
    DMA_InitStruct.DMA_Channel = DMA_Channel_7;   // TIM8_UP 请求
    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(GPIOE->BSRRL); // GPIOE BSRR寄存器地址
    DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)pwmPattern;
    DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA_InitStruct.DMA_BufferSize = sizeof(pwmPattern) / sizeof(pwmPattern[0]);
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
    DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStruct.DMA_Priority = DMA_Priority_High;
    DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream1, &DMA_InitStruct);

    DMA_Cmd(DMA2_Stream1, ENABLE);
}

static void TIM8_DMA_Trigger_Init(uint16_t arr, uint16_t psc)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
	
    TIM_TimeBaseStructInit(&TIM_TimeBaseStruct);
    TIM_TimeBaseStruct.TIM_Period = arr - 1;
    TIM_TimeBaseStruct.TIM_Prescaler = psc - 1;
    TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStruct);

    TIM_SelectOutputTrigger(TIM8, TIM_TRGOSource_Update);
    TIM_DMACmd(TIM8, TIM_DMA_Update, ENABLE);
    TIM_Cmd(TIM8, ENABLE);
}

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	#if defined(ENABLE_LOG) && (ENABLE_LOG == 1) 
	SEGGER_RTT_ConfigUpBuffer(0, "RTTUP", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
	#endif
	DebugLog("/*-------Release 1.0.0-----Build:%s %s-------------*/\r\n",__DATE__,__TIME__);


    GPIOE_DMA_PWM_Init();
    TIM8_DMA_Trigger_Init(8400, 1); 

    while (1)
    {
        // DMA + TIM8 自动工作,无需主循环干预
    }
}


一开始我是用的DMA1的触发源,死活不行,后来网上看了下,说F4只能用DMA2,但是修改为DMA2也不行。


微信截图_20260409121652.png
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
122007
QQ
发表于 前天 09:11 | 显示全部楼层

回帖奖励 +5 个金币

参考这个例子。


V6-017_AD7606的FMC DMA双缓冲驱动方式实现(8通道同步采样, 16bit, 正负10V).rar (4.74MB)

注意这个问题:


这么多年了,才发现STM32F4系列使用DMA1的大坑,只有DMA2才是完全体
https://forum.anfulai.cn/forum.php?mod=viewthread&tid=97900


回复

使用道具 举报

22

主题

86

回帖

152

积分

初级会员

积分
152
 楼主| 发表于 前天 16:31 | 显示全部楼层
本帖最后由 Hzzz 于 2026-4-10 17:12 编辑

硬汉哥,感谢回复,我上面这个代码是正常的,我的板子可能jlink供电不够,其实系统异常了,我直接用IO口操作发现也没波形,我后来给了额外供电上面的代码出波形了。然后我现在有个疑问,定时器溢出产生一次dma传输请求,dma进行数据搬运,那么这个搬运是溢出事件触发一次,dma搬运数组的一个数据吧,而不是触发一次直接搬运整个数组,是这样吗。我有点不清楚这里。

下午有空,写代码开中断测试了下,是每溢出一次产生一次DMA传输请求,然后DMA搬一个数据。开了下定时器中断和DMA传输完成中断,用IO口作指示,100个数据,定时器溢出电平变了100次,DMA传输完成了一次。
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
122007
QQ
发表于 昨天 09:18 | 显示全部楼层
Hzzz 发表于 2026-4-10 16:31
硬汉哥,感谢回复,我上面这个代码是正常的,我的板子可能jlink供电不够,其实系统异常了,我直接用IO口 ...

对,是触发一次,搬运一个数据。
回复

使用道具 举报

7

主题

175

回帖

196

积分

初级会员

积分
196
发表于 昨天 11:07 | 显示全部楼层

回帖奖励 +5 个金币

这么搞很难用啊
回复

使用道具 举报

22

主题

86

回帖

152

积分

初级会员

积分
152
 楼主| 发表于 1 小时前 | 显示全部楼层

有特定的时序需要驱动,而且是要一直运行,DMA速度够快,而且减少CPU负荷,否则我这的时序估计就要占用70%CPU了
回复

使用道具 举报

22

主题

86

回帖

152

积分

初级会员

积分
152
 楼主| 发表于 1 小时前 | 显示全部楼层
然后还发现个问题,就是触发不要用UP事件,要用CC事件,不然速度上不去
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-4-12 18:29 , Processed in 2.362141 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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