硬汉嵌入式论坛

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

[DMA] TIM1产生120MHz启动GPIO外接ADC转换,同时触发TIM3产生4路移相,在TIM3的CH1~CH4的上升沿产生DMA请求去读取GPIO口

[复制链接]

2

主题

8

回帖

14

积分

新手上路

积分
14
发表于 2025-3-12 16:12:12 | 显示全部楼层 |阅读模式
最近有个项目,用Timer读取外部120Madc,方案是GPIO连接外部ADC模块的数据端口,用TIM1产生120MPWM作为ADC的采样同步时钟信号,同时触发TIM3产生4路移相,在TIM3的CH1~CH4的上升沿产生DMA请求去读取GPIO口。


#define FIFO_DBS_0   512
/* SRAM1 as the base */
#define FIFO_BBASE   (0x30000000)

/* tpye define */
#define U8 unsigned char
               
/* Oscilloscope sampling buffer at block 0 */
static U8 * src_fifo0_0 = (U8 *)( FIFO_BBASE );                //定义绝对地址
static U8 * src_fifo0_1 = (U8 *)( FIFO_BBASE + FIFO_DBS_0 );
static U8 * src_fifo0_2 = (U8 *)( FIFO_BBASE + FIFO_DBS_0 * 2 );
static U8 * src_fifo0_3 = (U8 *)( FIFO_BBASE + FIFO_DBS_0 * 3 );



static TIM_HandleTypeDef TIM_Handle; /* USER CODE END PV */
TIM_HandleTypeDef htim;
//TIM_OC_InitTypeDef TIM_OC_Handle;
DMA_HandleTypeDef hdma_ch1;
DMA_HandleTypeDef hdma_ch2;
DMA_HandleTypeDef hdma_ch3;
DMA_HandleTypeDef hdma_ch4;


void MX_DMA_NVIC_Init(void) ;

/* USER CODE BEGIN PFP */
void MX_OSC_FIFO_DMA_CONFIG(void);


//TIM1即作为TIM4的主定时器,也作为TIM2的从定时器
//并根据主定时器TIM2同步触发产生150MHz的PWM
void MX_TIM1_Init(void)
{
        /* enable the clk */
        __HAL_RCC_GPIOA_CLK_ENABLE();                //使能GPIO时钟
        __HAL_RCC_GPIOE_CLK_ENABLE();
        __HAL_RCC_TIM1_CLK_ENABLE();                //使能定时器时钟
  /* define a struction */
        GPIO_InitTypeDef GPIO_Handle = {0};
        TIM_OC_InitTypeDef sConfigOC;
        TIM_MasterConfigTypeDef sMasterConfig = {0};
        /* clear data */
        memset(&sConfigOC,0,sizeof(sConfigOC));
        memset(&sMasterConfig,0,sizeof(sMasterConfig));
        /* define a struction */
        //PWM管脚输出作为ADC工作的时钟读信号
        GPIO_Handle.Pin = GPIO_PIN_9;
        GPIO_Handle.Mode = GPIO_MODE_AF_PP;
        GPIO_Handle.Pull = GPIO_NOPULL;
        GPIO_Handle.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_Handle.Alternate = GPIO_AF1_TIM1;
        HAL_GPIO_Init(GPIOE, &GPIO_Handle);
        HAL_GPIO_Init(GPIOA, &GPIO_Handle);
  /* time INIT */
        TIM_Handle.Instance = TIM1;
        TIM_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //时钟不分频
        TIM_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;         //向上计数
        TIM_Handle.Init.Period = 2 - 1; //fpwm = 240/((2-1+1)*(1-1+1))=120MHz
        TIM_Handle.Init.Prescaler = 1 - 1;
        TIM_Handle.Init.RepetitionCounter = 0;
        TIM_Handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
        HAL_TIM_PWM_Init(&TIM_Handle);
        
        /* msacter config */
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_ENABLE;//配置为TRGO模式,TIM1的EN信号触发
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;        //关闭TRGO2即ADC触发模式
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;        //配置为主模式
  if (HAL_TIMEx_MasterConfigSynchronization(&TIM_Handle, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* PWM init */
        sConfigOC.OCMode = TIM_OCMODE_PWM1;         //PWM输出为PWM1
        sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;         //输出极性为低
        sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
        sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;        //禁止快速模式
        sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
        sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
        sConfigOC.Pulse = 1;                //占空比50%
        /* CHANNEL init */
        HAL_TIM_PWM_ConfigChannel(&TIM_Handle, &sConfigOC, TIM_CHANNEL_1);
        HAL_TIM_PWM_ConfigChannel(&TIM_Handle, &sConfigOC, TIM_CHANNEL_2);
        /* check */
        
  /* start */
        HAL_TIM_PWM_Start(&TIM_Handle, TIM_CHANNEL_1);
        HAL_TIM_PWM_Start(&TIM_Handle, TIM_CHANNEL_2);
        /* return */
//  return FS_OK;
}


//作为从定时器,由主定时器TIM1同步触发产生3路50MHz的PWM波
void MX_TIM3_Init(void)
{
        /* enable the clk */

        __HAL_RCC_TIM3_CLK_ENABLE();
  /* define a struction */
//        GPIO_InitTypeDef GPIO_Handle = {0};
        TIM_OC_InitTypeDef htim_OC_Handle;
  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};        
        /* clear data */
        memset(&htim_OC_Handle,0,sizeof(htim_OC_Handle));
        memset(&sSlaveConfig,0,sizeof(sSlaveConfig));
        memset(&sMasterConfig,0,sizeof(sMasterConfig));

  /* time INIT */
        htim.Instance = TIM3;         //选择定时器3
        htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;         //从定时器不分频
        htim.Init.CounterMode = TIM_COUNTERMODE_UP;         //向上计数
        htim.Init.Period = 8 - 1; //30Mhz
        htim.Init.Prescaler = 1 - 1;
        HAL_TIM_PWM_Init(&htim);
  /* PWM init */
        htim_OC_Handle.OCMode = TIM_OCMODE_PWM1;         //选择PWM1模式
        htim_OC_Handle.OCPolarity = TIM_OCPOLARITY_LOW;         //输出极性
        htim_OC_Handle.OCFastMode = TIM_OCFAST_DISABLE;
        htim_OC_Handle.Pulse = 1;        //移相
        /* CHANNEL init */
        HAL_TIM_PWM_ConfigChannel(&htim, &htim_OC_Handle, TIM_CHANNEL_1);
        
        htim_OC_Handle.Pulse = 3;        //移相
        HAL_TIM_PWM_ConfigChannel(&htim, &htim_OC_Handle, TIM_CHANNEL_2);

        htim_OC_Handle.Pulse = 5;        //移相
        HAL_TIM_PWM_ConfigChannel(&htim, &htim_OC_Handle, TIM_CHANNEL_3);

        htim_OC_Handle.Pulse = 7;        //移相
        HAL_TIM_PWM_ConfigChannel(&htim, &htim_OC_Handle, TIM_CHANNEL_4);
        /* slaver mode */
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;        //从模式,触发模式
  sSlaveConfig.InputTrigger = TIM_TS_ITR0;        //触发源TIM1
        /* disable master mode */
  if (HAL_TIM_SlaveConfigSynchro(&htim, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
        /* disable master mode */
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;        //定时器3不作为主定时器去触发其他定时器
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
        /* disable master mode */
  if (HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  
        /* LINK DMA with TIM CHNN */
  //使能DMA
        __HAL_TIM_ENABLE_DMA(&htim, TIM_DMA_CC1);
        __HAL_TIM_ENABLE_DMA(&htim, TIM_DMA_CC2);
        __HAL_TIM_ENABLE_DMA(&htim, TIM_DMA_CC3);
        __HAL_TIM_ENABLE_DMA(&htim, TIM_DMA_CC4);
        /* 32bit tim init */
        MX_OSC_FIFO_DMA_CONFIG();        
        /* TIM 1 */
        MX_TIM1_Init();
        /* return */
//  return FS_OK;
}


void MX_DMA_NVIC_Init(void)
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();
  __HAL_RCC_DMA2_CLK_ENABLE();
        /* check */
        
        HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 1, 1);
        HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
        
}


void MX_OSC_FIFO_DMA_CONFIG(void)
{
        /* Define initialization structure */
//        DMA_HandleTypeDef hdma_cho;
        /* Set sampling frequency */
        MX_DMA_NVIC_Init();
        /* fill with blank */
//        memset(&hdma_cho,0,sizeof(hdma_cho));
        /* check mode */
        hdma_ch4.Instance = DMA2_Stream0;
        hdma_ch4.Init.Request = DMA_REQUEST_TIM3_CH4;        //TIM3-CH4发送DMA请求
        hdma_ch4.Init.Direction = DMA_PERIPH_TO_MEMORY;                //从外设到存储器
        hdma_ch4.Init.PeriphInc = DMA_PINC_DISABLE;        //外设非增量模式
        hdma_ch4.Init.MemInc = DMA_MINC_ENABLE;                //存储器增量模式
        hdma_ch4.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;                //外设数据长度: 8位
        hdma_ch4.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;        //存储器数据长度: 8位
        hdma_ch4.Init.Mode = DMA_NORMAL;        //DMA_CIRCULAR;        //外设流控模式: 使用正常模式
        hdma_ch4.Init.Priority = DMA_PRIORITY_VERY_HIGH;        //高优先级,用于多通道同时请求时的优先响应
        hdma_ch4.Init.FIFOMode = DMA_FIFOMODE_DISABLE;        //使用FIFO
        hdma_ch4.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;//使能FIFO之后,用于FIFO阀值设置
        hdma_ch4.Init.MemBurst = DMA_MBURST_SINGLE;                //存储器突发单次传输
        hdma_ch4.Init.PeriphBurst = DMA_PBURST_SINGLE;        //外设突发单次传输
        /* enable */
        
        /* 初始化DMA */
    if(HAL_DMA_DeInit(&hdma_ch4) != HAL_OK)
    {

                Error_Handler();                     
                  
    }
        /* INIT */
        HAL_DMA_Init(&hdma_ch4);        
        __HAL_LINKDMA(&htim,hdma[TIM_DMA_ID_CC4],hdma_ch4);
        /* start DMA with buffer */
        /* start */
               
        HAL_DMA_Start_IT(&hdma_ch4, (uint32_t)&GPIOE->IDR,(uint32_t)src_fifo0_3,FIFO_DBS_0);
        
        /* INIT TIM3 CH2 */
        hdma_ch2.Instance = DMA2_Stream1;
        hdma_ch2.Init.Request = DMA_REQUEST_TIM3_CH2; //TIM3-CH2发送DMA请求
        hdma_ch2.Init.Direction = DMA_PERIPH_TO_MEMORY;                //从外设到存储器
        hdma_ch2.Init.PeriphInc = DMA_PINC_DISABLE;        //外设非增量模式
        hdma_ch2.Init.MemInc = DMA_MINC_ENABLE;                //存储器增量模式
        hdma_ch2.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;                //外设数据长度: 8位
        hdma_ch2.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;        //存储器数据长度: 8位
        hdma_ch2.Init.Mode = DMA_NORMAL;//DMA_CIRCULAR;                //外设流控模式: 使用正常模式
        hdma_ch2.Init.Priority = DMA_PRIORITY_VERY_HIGH;        //高优先级,用于多通道同时请求时的优先响应
        hdma_ch2.Init.FIFOMode = DMA_FIFOMODE_DISABLE;        //不使用FIFO(因为外设长度和内存长度一致,可以不使用)
        hdma_ch2.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;//使能FIFO之后,用于FIFO阀值设置
        hdma_ch2.Init.MemBurst = DMA_MBURST_SINGLE;                //存储器突发单次传输
        hdma_ch2.Init.PeriphBurst = DMA_PBURST_SINGLE;        //外设突发单次传输
        /* 初始化DMA */
    if(HAL_DMA_DeInit(&hdma_ch2) != HAL_OK)
    {
                Error_Handler();                     

    }
        /* enable */
        HAL_DMA_Init(&hdma_ch2);
        __HAL_LINKDMA(&htim,hdma[TIM_DMA_ID_CC2],hdma_ch2);
        /* start */
        HAL_DMA_Start_IT(&hdma_ch2, (uint32_t)&GPIOE->IDR,(uint32_t)src_fifo0_1,FIFO_DBS_0);
        /* INIT TIM3 CH3 */
        hdma_ch3.Instance = DMA1_Stream1;
        hdma_ch3.Init.Request = DMA_REQUEST_TIM3_CH3;        //TIM3-CH3发送DMA请求
        hdma_ch3.Init.Direction = DMA_PERIPH_TO_MEMORY;                //从外设到存储器
        hdma_ch3.Init.PeriphInc = DMA_PINC_DISABLE;        //外设非增量模式
        hdma_ch3.Init.MemInc = DMA_MINC_ENABLE;                //存储器增量模式
        hdma_ch3.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;                //外设数据长度: 8位
        hdma_ch3.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;        //存储器数据长度: 8位
        hdma_ch3.Init.Mode = DMA_NORMAL;//DMA_CIRCULAR;                //外设流控模式: 使用正常模式
        hdma_ch3.Init.Priority = DMA_PRIORITY_VERY_HIGH;        //高优先级,用于多通道同时请求时的优先响应
        hdma_ch3.Init.FIFOMode = DMA_FIFOMODE_DISABLE;        //不使用FIFO(因为外设长度和内存长度一致,可以不使用)
        hdma_ch3.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;//使能FIFO之后,用于FIFO阀值设置
        hdma_ch3.Init.MemBurst = DMA_MBURST_SINGLE;                //存储器突发单次传输
        hdma_ch3.Init.PeriphBurst = DMA_PBURST_SINGLE;        //外设突发单次传输
        /* 初始化DMA */
    if(HAL_DMA_DeInit(&hdma_ch3) != HAL_OK)
    {
                Error_Handler();                       
    }
        /* enable */
        HAL_DMA_Init(&hdma_ch3);
        //关联tim4句柄和DMA句柄        
        __HAL_LINKDMA(&htim,hdma[TIM_DMA_ID_CC3],hdma_ch3);
        /* start */
        HAL_DMA_Start_IT(&hdma_ch3, (uint32_t)&GPIOE->IDR,(uint32_t)src_fifo0_2,FIFO_DBS_0);
        /* INIT TIM3 CH4 */
        hdma_ch1.Instance = DMA1_Stream0;
        hdma_ch1.Init.Request = DMA_REQUEST_TIM3_CH1;        //TIM3-CH3发送DMA请求
        hdma_ch1.Init.Direction = DMA_PERIPH_TO_MEMORY;                //从外设到存储器
        hdma_ch1.Init.PeriphInc = DMA_PINC_DISABLE;        //外设非增量模式
        hdma_ch1.Init.MemInc = DMA_MINC_ENABLE;                //存储器增量模式
        hdma_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;                //外设数据长度: 8位
        hdma_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;        //存储器数据长度: 8位
        hdma_ch1.Init.Mode = DMA_NORMAL;//DMA_CIRCULAR;                //外设流控模式: 使用正常模式
        hdma_ch1.Init.Priority = DMA_PRIORITY_VERY_HIGH;        //高优先级,用于多通道同时请求时的优先响应
        hdma_ch1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;        //不使用FIFO(因为外设长度和内存长度一致,可以不使用)
        hdma_ch1.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;//使能FIFO之后,用于FIFO阀值设置
        hdma_ch1.Init.MemBurst = DMA_MBURST_SINGLE;                //存储器突发单次传输
        hdma_ch1.Init.PeriphBurst = DMA_PBURST_SINGLE;        //外设突发单次传输
        /* 初始化DMA */
    if(HAL_DMA_DeInit(&hdma_ch1) != HAL_OK)
    {
                Error_Handler();                     
                  
    }
        /* enable */
        HAL_DMA_Init(&hdma_ch1);        
        __HAL_LINKDMA(&htim,hdma[TIM_DMA_ID_CC1],hdma_ch1);
//        /* start */
        HAL_DMA_Start_IT(&hdma_ch1, (uint32_t)&GPIOE->IDR,(uint32_t)src_fifo0_0,FIFO_DBS_0);
        
}




void OSC_DMA_STOP(void)
{
        /* Disable the TIM1 and TIM4 */
        TIM3->CR1 &=~ 0x1;
        TIM1->CR1 &=~ 0x1;

        /* Synchronize counters for all timers */
        
        TIM1->CNT = 0;
        TIM3->CNT = 0;        

}

void osc_dma_restart(void)        
{
        /* clear */
        
        DMA1->LIFCR = DMA_FLAG_TCIF0_4;
        DMA1->LIFCR = DMA_FLAG_TCIF1_5;
        DMA2->LIFCR = DMA_FLAG_TCIF0_4;
        DMA2->LIFCR = DMA_FLAG_TCIF1_5;
        
  /* check mode */
        
        /* more than 40mhz freq for test */
        DMA1_Stream0->NDTR = FIFO_DBS_0;
        DMA1_Stream1->NDTR = FIFO_DBS_0;
        DMA2_Stream0->NDTR = FIFO_DBS_0;
        DMA2_Stream1->NDTR = FIFO_DBS_0;
        /* enable */
        DMA1_Stream0->CR |= 0x1;
        DMA1_Stream1->CR |= 0x1;
        DMA2_Stream0->CR |= 0x1;        
        DMA2_Stream1->CR |= 0x1;        
        
        /* restart DMA */
        TIM1->CR1 |= 0x1;
        /* end if */
}

unsigned char osc_trig_end_flag = 0;

/**
  * @brief DMA2_Stream0_IRQHandler
        * @param NONE
  * @retval None
  */
void DMA2_Stream0_IRQHandler(void)
{
  /* 传输完成中断 */
        if((DMA2->LISR & DMA_FLAG_TCIF0_4) != RESET)
        {
                /* 清除标志 */
                DMA2->LIFCR = DMA_FLAG_TCIF0_4;
    /* reset */
                /* 当前使用的缓冲0 */
                if((DMA2_Stream0->CR & DMA_SxCR_CT) == RESET)
                {
                        /* DMA pause */
//                        OSC_DMA_STOP();
                        /* set TC flag */
                        osc_trig_end_flag = 1;                //传输完成标志
                        
                        /* end if data */
                }
        }
        
        /* 半传输完成中断 */
        if((DMA2->LISR & DMA_FLAG_HTIF0_4) != RESET)
        {
                /* 清除标志 */
                str0_len = DMA2_Stream0->NDTR;
                DMA2->LIFCR = DMA_FLAG_HTIF0_4;
        }
}




//ADC模块的D0~D7数据线
void        GPIO_EXTERNAL_ADC_Init(void)
{
        GPIO_InitTypeDef GPIO_Handle = {0};
        
        __HAL_RCC_GPIOE_CLK_ENABLE();
        
        //ADC模块的数字输入,通过GPIO来读取
        GPIO_Handle.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
        GPIO_Handle.Mode = GPIO_MODE_INPUT;                //普通输入模式
        GPIO_Handle.Pull = GPIO_NOPULL;                //浮空输入
        GPIO_Handle.Speed = GPIO_SPEED_FREQ_VERY_HIGH;        //高速模式
        HAL_GPIO_Init(GPIOE, &GPIO_Handle);        
}



void         OSC_CURV_TEST(void)
{
        unsigned int i = 0;
        if(osc_trig_end_flag == 1)
        {
               
                for(i = 0; i < FIFO_DBS_0; i ++)
                {
                        printf("<A1>:%d,%d,%d,%d\r\n", src_fifo0_0, src_fifo0_1, src_fifo0_2, src_fifo0_3);
                }
                osc_trig_end_flag = 0;
                osc_dma_restart();
        }


}


调试结果发现与DMA2_Stream1绑定的通道的数据采集频率在传输的前半部分是其他三个通道的一半,后半部分一致,这是什么原因

效果.png
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-3-13 07:41:59 | 显示全部楼层
降低下时钟触发速度试试
回复

使用道具 举报

2

主题

8

回帖

14

积分

新手上路

积分
14
 楼主| 发表于 2025-3-13 09:59:53 | 显示全部楼层
eric2013 发表于 2025-3-13 07:41
降低下时钟触发速度试试

把TIM1的频率降到60M, TIM3为15M时采样一致
回复

使用道具 举报

5

主题

162

回帖

177

积分

初级会员

积分
177
发表于 2025-3-13 11:14:48 | 显示全部楼层
DMA1/DMA2 BDMA跑不了那么快的频率。估计只有40Mhz以下稳定,而且会占用大量的总线带宽
回复

使用道具 举报

5

主题

162

回帖

177

积分

初级会员

积分
177
发表于 2025-3-13 11:18:42 | 显示全部楼层
而且很奇怪的一个问题,你读取的外设宽度为什么是8位,定时器不是16位或者32位吗
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-3-14 07:50:49 | 显示全部楼层
2859932063 发表于 2025-3-13 11:18
而且很奇怪的一个问题,你读取的外设宽度为什么是8位,定时器不是16位或者32位吗

外接的是8bit的ADC,他这个是直接对ADC的读取。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-3-14 07:51:16 | 显示全部楼层
cline 发表于 2025-3-13 09:59
把TIM1的频率降到60M, TIM3为15M时采样一致

先降低到10M,正常后,再提升速度测试。
回复

使用道具 举报

2

主题

8

回帖

14

积分

新手上路

积分
14
 楼主| 发表于 2025-3-14 10:02:18 | 显示全部楼层
eric2013 发表于 2025-3-14 07:51
先降低到10M,正常后,再提升速度测试。

10M的采样是正常的,速度上去了就不行,DMA30M的速率很临界了吗
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-3-15 09:03:35 | 显示全部楼层
cline 发表于 2025-3-14 10:02
10M的采样是正常的,速度上去了就不行,DMA30M的速率很临界了吗

再往上逐步提升试试,看看多少合适。
回复

使用道具 举报

5

主题

162

回帖

177

积分

初级会员

积分
177
发表于 2025-3-15 14:51:19 | 显示全部楼层
你应该用的MDMA,通过触发DMA1/2的DMA触发完成来触发MDMA,这样的速度就可以上去了。
回复

使用道具 举报

2

主题

8

回帖

14

积分

新手上路

积分
14
 楼主| 发表于 2025-3-15 19:59:49 | 显示全部楼层
2859932063 发表于 2025-3-15 14:51
你应该用的MDMA,通过触发DMA1/2的DMA触发完成来触发MDMA,这样的速度就可以上去了。

怎么实现,先触发DMA1/2,然后再使能MDMA?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-3-15 22:16:54 | 显示全部楼层
cline 发表于 2025-3-15 19:59
怎么实现,先触发DMA1/2,然后再使能MDMA?

MDMA不行,限制在DMA1,DMA2上。因为数据搬运还是他们完成的。

应该换个思路,仅用TIM3,让TIM3的CH1,CH2,CH3,CH4定时器同时输出, 通过门电路输出到一个引脚上产生4倍的速度。

通用DMA的速度在40-60MB/S,400MH主频下,你这个显然没有发挥出通用DMA的性能。在一个TIM时钟周期内,4个轮番上,速度还是太低,因为你这个毕竟是DMA1和DMA2都用了,怎么得有80-120MB吧
回复

使用道具 举报

2

主题

8

回帖

14

积分

新手上路

积分
14
 楼主| 发表于 2025-3-17 11:46:01 | 显示全部楼层
eric2013 发表于 2025-3-15 22:16
MDMA不行,限制在DMA1,DMA2上。因为数据搬运还是他们完成的。

应该换个思路,仅用TIM3,让TIM3的CH1,C ...

还是不太理解
回复

使用道具 举报

5

主题

162

回帖

177

积分

初级会员

积分
177
发表于 2025-3-17 12:01:08 | 显示全部楼层

可以这样做,直接使用定时器产生120M的pwm,然后在CH1-CH2,使用DMA1,CH3-CH4使用DMA2.
回复

使用道具 举报

2

主题

8

回帖

14

积分

新手上路

积分
14
 楼主| 发表于 2025-3-17 16:05:38 | 显示全部楼层
2859932063 发表于 2025-3-17 12:01
可以这样做,直接使用定时器产生120M的pwm,然后在CH1-CH2,使用DMA1,CH3-CH4使用DMA2.

目前的做法就是这样
回复

使用道具 举报

5

主题

269

回帖

284

积分

高级会员

积分
284
发表于 2025-3-18 10:09:15 | 显示全部楼层
大概率是dma通道同时触发但是DMA2_Stream1仲裁失败导致的,你的所有通道都是同一个优先级,那么通道序号低的会优先仲裁,stm32的dma就这点不好,必须要等一个通道传完了才能开始传下一通道,遇上多通道高并发的场景就很难用
只能试试把DMA2_Stream1优先级调到VERY_HIGH然后其他几个是HIGH
回复

使用道具 举报

5

主题

162

回帖

177

积分

初级会员

积分
177
发表于 2025-3-18 16:02:49 | 显示全部楼层
我目前觉得最好的方式是CH1 DMA1_CH1 然后DMA2_CH1,DMA1_CH2 ,DMA2_CH2 这样,可以最大化带宽
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-12 22:35 , Processed in 0.062881 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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