STM32
直播中

杨万富

7年用户 1525经验值
擅长:526774
私信 关注
[问答]

stm32f407VET6如何改用DMA获取的方法?

请教各位,使用STM32f407VET6 用的tiM1  脉冲输入引脚为PA11(TIM1_CH4),目前已实现中断读取CC4的数值,因为中断太频繁想改用DMA获取的方法,不知道怎么操作?
TIM_HandleTypeDef  TIM_PWMINPUT_Handle;
DMA_HandleTypeDef TIM_DMA_Handle;

uint32_t IC4_value[2];
//定时器配置
static void TIM_PWMINPUT_Config(void)
{
    TIM_IC_InitTypeDef TIM_ICInitStructure;
    TIM_SlaveConfigTypeDef TIM_SlaveConfigStructure;

    __TIM1_CLK_ENABLE();
    TIM_PWMINPUT_Handle.Instance = TIM1;
    TIM_PWMINPUT_Handle.Init.Period = 0xFFFF;
// 高级控制定时器时钟源 TIMxCLK = HCLK=168MHz
// 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=1MHz
    TIM_PWMINPUT_Handle.Init.Prescaler = 168 - 1;
    TIM_PWMINPUT_Handle.Init.ClockDivision = 0;
    TIM_PWMINPUT_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    HAL_TIM_IC_Init( TIM_PWMINPUT_Handle);

    TIM_ICInitStructure.ICPolarity = TIM_ICPOLARITY_RISING;
    TIM_ICInitStructure.ICSelection = TIM_ICSELECTION_DIRECTTI;
    TIM_ICInitStructure.ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStructure.ICFilter = 0x0;
    HAL_TIM_IC_ConfigChannel( TIM_PWMINPUT_Handle,  TIM_ICInitStructure, TIM_CHANNEL_4);
//    HAL_TIM_IC_Start_IT( TIM_PWMINPUT_Handle, TIM_CHANNEL_4);   
}


//DMA配置
void tim_dma_config(void)
{
    __DMA2_CLK_ENABLE();
    TIM_DMA_Handle.Instance = DMA2_Stream4;
    TIM_DMA_Handle.Init.Channel = DMA_CHANNEL_6;
    TIM_DMA_Handle.Init.Direction = DMA_PERIPH_TO_MEMORY;
    TIM_DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
    TIM_DMA_Handle.Init.MemInc = DMA_MINC_ENABLE;
    TIM_DMA_Handle.Init.PeriphDataAlignment = DMA_MDATAALIGN_WORD;
    TIM_DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    TIM_DMA_Handle.Init.Mode = DMA_CIRCULAR;
    TIM_DMA_Handle.Init.Priority = DMA_PRIORITY_MEDIUM;
    TIM_DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    TIM_DMA_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    TIM_DMA_Handle.Init.MemBurst = DMA_MBURST_SINGLE;
    TIM_DMA_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE;

    __HAL_LINKDMA( TIM_PWMINPUT_Handle,hdma[TIM_DMA_ID_CC4], TIM_DMA_Handle);

    HAL_DMA_Init(TIM_PWMINPUT_Handle.hdma[TIM_DMA_ID_CC4]);
    HAL_TIM_IC_Start_DMA( TIM_PWMINPUT_Handle,TIM_CHANNEL_4, IC4_value,4);
//    HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);

}


接下来,在主函数不断读取IC4_value的值明显不对。请教大家有没有错







回帖(1)

孙成红

2024-4-10 10:49:05
可以通过以下步骤来配置DMA来获取TIM1的CC4值:

1. 初始化TIM1和DMA模块:

```c
TIM_HandleTypeDef TIM_PWMINPUT_Handle;
DMA_HandleTypeDef TIM_DMA_Handle;
uint32_t IC4_value[2]; // 存储CC4的值

static void TIM_PWMINPUT_Config(void) {
    // 使能TIM1的时钟
    __TIM1_CLK_ENABLE();

    // 初始化TIM1的参数,包括时钟分频、计数器模式等等
    TIM_PWMINPUT_Handle.Instance = TIM1;
    TIM_PWMINPUT_Handle.Init.Prescaler = 0;
    TIM_PWMINPUT_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    TIM_PWMINPUT_Handle.Init.Period = 0xFFFF;
    TIM_PWMINPUT_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    TIM_PWMINPUT_Handle.Init.RepetitionCounter = 0;
    HAL_TIM_Base_Init(&TIM_PWMINPUT_Handle);

    // 配置DMA的参数,包括数据传输方向、数据宽度、传输模式等等
    TIM_DMA_Handle.Instance = DMAx_STREAMy; // 根据具体的DMA通道进行配置
    TIM_DMA_Handle.Init.Channel = DMA_CHANNEL_x; // 根据具体的DMA通道进行配置
    TIM_DMA_Handle.Init.Direction = DMA_PERIPH_TO_MEMORY;
    TIM_DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
    TIM_DMA_Handle.Init.MemInc = DMA_MINC_ENABLE;
    TIM_DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    TIM_DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    TIM_DMA_Handle.Init.Mode = DMA_CIRCULAR;
    TIM_DMA_Handle.Init.Priority = DMA_PRIORITY_HIGH;
    TIM_DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    HAL_DMA_Init(&TIM_DMA_Handle);

    // 连接TIM1和DMA
    __HAL_LINKDMA(&TIM_PWMINPUT_Handle, hdma[TIM_DMA_ID_CC4], TIM_DMA_Handle);

    // 配置DMA中断
    HAL_NVIC_SetPriority(DMAx_STREAMy_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMAx_STREAMy_IRQn);
}
```

2. 配置TIM1的CC4输入功能:

```c
static void TIM_PWMINPUT_Config(void) {
    // ...

    // 配置TIM1的CC4通道
    TIM_IC_InitTypeDef TIM_ICInitStructure;
   
    TIM_PWMINPUT_Handle.Init.ICPrescaler = TIM_ICPSC_DIV1; // 配置输入分频系数
    TIM_PWMINPUT_Handle.Init.ICFilter = 0; // 配置输入滤波器
   
    TIM_ICInitStructure.ICPolarity = TIM_ICPOLARITY_RISING; // 配置输入信号的极性
    TIM_ICInitStructure.ICSelection = TIM_ICSELECTION_DIRECTTI; // 配置捕获输入复用
    TIM_ICInitStructure.ICPrescaler = TIM_ICPSC_DIV1; // 配置输入分频系数
    TIM_ICInitStructure.ICFilter = 0; // 配置输入滤波器
    HAL_TIM_IC_ConfigChannel(&TIM_PWMINPUT_Handle, &TIM_ICInitStructure, TIM_CHANNEL_4);

    // ...
}
```

3. 启动TIM1和DMA:

```c
static void TIM_PWMINPUT_Config(void) {
    // ...

    // 启动TIM1和DMA
    HAL_TIM_Base_Start(&TIM_PWMINPUT_Handle);
    HAL_TIM_IC_Start_DMA(&TIM_PWMINPUT_Handle, TIM_CHANNEL_4, (uint32_t*)IC4_value, 2);

    // ...
}
```

4. 在DMA的中断服务函数中,处理获取到的值:

```c
void DMAx_STREAMy_IRQHandler(void) {
    HAL_DMA_IRQHandler(&TIM_DMA_Handle);
}

void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma) {
    HAL_DMA_IRQHandler(hdma);

    if(hdma->Instance == DMAx_STREAMy) { // 根据具体的DMA通道进行配置
        if(HAL_DMA_GetState(hdma) == HAL_DMA_STATE_READY) {
            /* 处理获取到的值 */
            uint32_t value = IC4_value[1];
        }
    }
}
```

注意:以上代码仅供参考,具体的DMA通道和DMA中断的相关配置需要根据实际情况进行修改。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分