硬汉嵌入式论坛

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

[GPIO] 求助一下,h7使用gpio+dma+tim模拟时序的方式

[复制链接]

2

主题

2

回帖

8

积分

新手上路

积分
8
发表于 6 天前 | 显示全部楼层 |阅读模式
DCLK/OE/LE/dat[0:7]这几个是驱动芯片的时序线
现在想问一下使用gpio+dma+tim,并行能否达到25mhz的速度
void Data_Latch(uint8_t n)
{
        GPIOA->BSRR = LE_PIN;
        for(uint8_t i=0; i<(n); i++)
        {
                GPIOB->BSRR = DCLK_PIN;
                GPIOB->BSRR = DCLK_PIN << 16;
        }
        GPIOA->BSRR = LE_PIN << 16;
        for(uint8_t i=0; i<(n); i++)
        {
                GPIOB->BSRR = DCLK_PIN;
                GPIOB->BSRR = DCLK_PIN << 16;
        }
}

/*初始化37个寄存器,[15:8]为寄存器地址,[7:0]为寄存器值*/
void Reg_Init(void)
{
        *fmc_dat = 0x00;
        for (uint8_t reg_num=0; reg_num<37; reg_num++)            //循环写入7套寄存器
        {
                for(uint8_t c=0;c<Cascades;c++)      //单套寄存器,根据级联IC个数,设定循环写入次数
                {
                        DATA=REG[reg_num];
                  for (uint16_t bits=0; bits<16; bits++)  //写入16bit数据,[15:8]为寄存器地址,[7:0]为寄存器值
            {
                    if(DATA&0x8000)
                          {
                            *fmc_dat = 0xff;                               
                    }
                    else
                    {
                                        *fmc_dat = 0x00;
                    }
                                 if((bits>10)&&(c==(Cascades-1)))       //判断LE锁存信号上升沿位置
                    {
                            GPIOA->BSRR = LE_PIN;
                    }
                    else
                     {
                            GPIOA->BSRR = LE_PIN << 16;
                    }
                                GPIOB->BSRR = DCLK_PIN;
                                GPIOB->BSRR = DCLK_PIN << 16;
                                DATA=DATA<<1;
                  }
                        GPIOA->BSRR = LE_PIN << 16;
          }
  }
}

/*定义单次锁存函数,单次锁存128颗LED*/
void Display_Send()
{
        uint8_t i, j, k;
       
        for (i=0; i<2; i++)
        {
                for (j=0; j<16; j++)
                {
                        GPIOA->BSRR = OE_PIN;;
                        for(uint8_t k=0; k<16; k++)
                        {
                                GPIOB->BSRR = DCLK_PIN;
                                GPIOB->BSRR = DCLK_PIN << 16;
                                if((i+j)!=0&&(k==3))
                                {
                                        GPIOA->BSRR = OE_PIN << 16;
                                        k = 16;
                                }
                                else if((i+j)==0&&k==9)
                                {
                                        GPIOA->BSRR = OE_PIN << 16;
                                        k = 16;
                                }
                        }
                        uint8_t bits;
                        for(uint8_t c=0;c<Cascades;c++)   
                        {       
                                DATA = 0x0100;
                                for (bits=0; bits<16; bits++)   
                                {

                                        if(DATA&0x8000)
                                        {
                                                *fmc_dat = 0xff;
                                        }
                                        else
                                        {
                                                *fmc_dat = 0x00;
                                        }                               
                                        GPIOB->BSRR = DCLK_PIN;
                                        GPIOB->BSRR = DCLK_PIN << 16;
                                        DATA=DATA<<1;
                                       
                                        if(c==(Cascades-1) && i==0 && bits==14)
                                        {
                                                GPIOA->BSRR = LE_PIN;
                                        }
                                        else
                                        {
                                                GPIOA->BSRR = LE_PIN << 16;
                                        }
                                }
                                GPIOA->BSRR = LE_PIN << 16;
                        }
                }
        }
        Data_Latch(3);
}

回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
121980
QQ
发表于 3 天前 | 显示全部楼层
推荐映射到FMC,没问题

视频教程第16期:DMA双缓冲实现32路脉冲并行同步控制(2022-05-26)
https://forum.anfulai.cn/forum.php?mod=viewthread&tid=112560
回复

使用道具 举报

2

主题

2

回帖

8

积分

新手上路

积分
8
 楼主| 发表于 3 天前 | 显示全部楼层
eric2013 发表于 2026-4-7 07:45
推荐映射到FMC,没问题

视频教程第16期:DMA双缓冲实现32路脉冲并行同步控制(2022-05-26)

硬汉哥想问一下,dma+tim触发gpio翻转的方式能到25mhz吗这边测了只有十几兆/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    tim.c
  * @brief   This file provides code for the configuration
  *          of the TIM instances.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2026 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "tim.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

TIM_HandleTypeDef htim12;

/* TIM12 init function */
void MX_TIM12_Init(void)
{

  /* USER CODE BEGIN TIM12_Init 0 */

  /* USER CODE END TIM12_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM12_Init 1 */

  /* USER CODE END TIM12_Init 1 */
  htim12.Instance = TIM12;
  htim12.Init.Prescaler = 0;
  htim12.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim12.Init.Period = 9;
  htim12.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim12.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim12) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim12, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_DISABLE;
  sSlaveConfig.InputTrigger = TIM_TS_ITR0;
  if (HAL_TIM_SlaveConfigSynchro(&htim12, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim12, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM12_Init 2 */

  /* USER CODE END TIM12_Init 2 */

}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{

  if(tim_baseHandle->Instance==TIM12)
  {
  /* USER CODE BEGIN TIM12_MspInit 0 */

  /* USER CODE END TIM12_MspInit 0 */
    /* TIM12 clock enable */
    __HAL_RCC_TIM12_CLK_ENABLE();
  /* USER CODE BEGIN TIM12_MspInit 1 */

  /* USER CODE END TIM12_MspInit 1 */
  }
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{

  if(tim_baseHandle->Instance==TIM12)
  {
  /* USER CODE BEGIN TIM12_MspDeInit 0 */

  /* USER CODE END TIM12_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_TIM12_CLK_DISABLE();
  /* USER CODE BEGIN TIM12_MspDeInit 1 */

  /* USER CODE END TIM12_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */



/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    dma.c
  * @brief   This file provides code for the configuration
  *          of all the requested memory to memory DMA transfers.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2026 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "dma.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/*----------------------------------------------------------------------------*/
/* Configure DMA                                                              */
/*----------------------------------------------------------------------------*/

/* USER CODE BEGIN 1 */
ALIGN_32BYTES(__attribute__((section (".RAM_D1"))) uint32_t IO_Toggle[16]) =
{
    0x0000ffe0U, 0xffe00000U, 0x0000ffe0U, 0xffe00000U,
    0x0000ffe0U, 0xffe00000U, 0x0000ffe0U, 0xffe00000U,
    0x0000ffe0U, 0xffe00000U, 0x0000ffe0U, 0xffe00000U,
    0x0000ffe0U, 0xffe00000U, 0x0000ffe0U, 0xffe00000U,
};
/* USER CODE END 1 */
DMA_HandleTypeDef hdma_dma_generator0;

/**
  * Enable DMA controller clock
  * Configure DMA for memory to memory transfers
  *   hdma_dma_generator0
  */
void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* Configure DMA request hdma_dma_generator0 on DMA1_Stream0 */
  hdma_dma_generator0.Instance = DMA1_Stream0;
  hdma_dma_generator0.Init.Request = DMA_REQUEST_GENERATOR0;
  hdma_dma_generator0.Init.Direction = DMA_MEMORY_TO_PERIPH;
  hdma_dma_generator0.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_dma_generator0.Init.MemInc = DMA_MINC_ENABLE;
  hdma_dma_generator0.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  hdma_dma_generator0.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
  hdma_dma_generator0.Init.Mode = DMA_CIRCULAR;
  hdma_dma_generator0.Init.Priority = DMA_PRIORITY_VERY_HIGH;
  hdma_dma_generator0.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  if (HAL_DMA_Init(&hdma_dma_generator0) != HAL_OK)
  {
    Error_Handler();
  }

  /* DMA interrupt init */
  /* DMA1_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
  /* DMA1_Stream3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 1, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
  /* DMAMUX1_OVR_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMAMUX1_OVR_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMAMUX1_OVR_IRQn);

}

/* USER CODE BEGIN 2 */
HAL_DMA_MuxRequestGeneratorConfigTypeDef dmamux_ReqGenParams = {0};
void test(void)
{
        dmamux_ReqGenParams.SignalID  = HAL_DMAMUX1_REQ_GEN_TIM12_TRGO;
        dmamux_ReqGenParams.Polarity  = HAL_DMAMUX_REQ_GEN_RISING;
        dmamux_ReqGenParams.RequestNumber = 1;   
        HAL_DMAEx_ConfigMuxRequestGenerator(&hdma_dma_generator0, &dmamux_ReqGenParams);
        HAL_DMAEx_EnableMuxRequestGenerator (&hdma_dma_generator0);                     
        HAL_DMA_Start(&hdma_dma_generator0, (uint32_t)IO_Toggle, (uint32_t)&GPIOE->BSRR, 16);
}

/* USER CODE END 2 */


回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
121980
QQ
发表于 前天 07:58 | 显示全部楼层
1035916571 发表于 2026-4-7 20:43
硬汉哥想问一下,dma+tim触发gpio翻转的方式能到25mhz吗这边测了只有十几兆/* USER CODE BEGIN Header */ ...

驱动通用GPIO速度确实一般,映射到FMC后,驱动IO速度就快非常多了。
回复

使用道具 举报

2

主题

2

回帖

8

积分

新手上路

积分
8
 楼主| 发表于 前天 10:35 | 显示全部楼层
eric2013 发表于 2026-4-8 07:58
驱动通用GPIO速度确实一般,映射到FMC后,驱动IO速度就快非常多了。

改成fmc之后,测得的周期是10mhz,dma和tim部分还是和之前一样void MX_FMC_Init(void)
{
  /* USER CODE BEGIN FMC_Init 0 */

  /* USER CODE END FMC_Init 0 */

  FMC_NORSRAM_TimingTypeDef Timing = {0};

  /* USER CODE BEGIN FMC_Init 1 */

  /* USER CODE END FMC_Init 1 */

  /** Perform the SRAM1 memory initialization sequence
  */
  hsram1.Instance = FMC_NORSRAM_DEVICE;
  hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
  /* hsram1.Init */

        hsram1.Init.NSBank             = FMC_NORSRAM_BANK1;
        hsram1.Init.DataAddressMux     = FMC_DATA_ADDRESS_MUX_DISABLE;
        hsram1.Init.MemoryType         = FMC_MEMORY_TYPE_SRAM;
        hsram1.Init.MemoryDataWidth    = FMC_NORSRAM_MEM_BUS_WIDTH_32;
        hsram1.Init.BurstAccessMode    = FMC_BURST_ACCESS_MODE_DISABLE;
        hsram1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
        hsram1.Init.WaitSignalActive   = FMC_WAIT_TIMING_BEFORE_WS;
        hsram1.Init.WriteOperation     = FMC_WRITE_OPERATION_ENABLE;
        hsram1.Init.WaitSignal         = FMC_WAIT_SIGNAL_DISABLE;
        hsram1.Init.ExtendedMode       = FMC_EXTENDED_MODE_DISABLE;
        hsram1.Init.AsynchronousWait   = FMC_ASYNCHRONOUS_WAIT_DISABLE;
        hsram1.Init.WriteBurst         = FMC_WRITE_BURST_DISABLE;
        hsram1.Init.ContinuousClock    = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
       
  /* Timing */
  Timing.AddressSetupTime = 0;
  Timing.AddressHoldTime = 1;
  Timing.DataSetupTime = 1;
  Timing.BusTurnAroundDuration = 0;
  Timing.CLKDivision = 2;
  Timing.DataLatency = 0;
  Timing.AccessMode = FMC_ACCESS_MODE_A;
  /* ExtTiming */

  if (HAL_SRAM_Init(&hsram1, &Timing, NULL) != HAL_OK)
  {
    Error_Handler( );
  }

  /* USER CODE BEGIN FMC_Init 2 */

  /* USER CODE END FMC_Init 2 */
}
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
121980
QQ
发表于 昨天 09:18 | 显示全部楼层
1035916571 发表于 2026-4-8 10:35
改成fmc之后,测得的周期是10mhz,dma和tim部分还是和之前一样void MX_FMC_Init(void)
{
  /* USER COD ...

那不行了,你再想想别的办法
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-4-10 13:07 , Processed in 0.721515 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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