打印
[技术讨论]

定时器TIM的DMA连续模式BUG

[复制链接]
854|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
朱景|  楼主 | 2023-11-15 09:35 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 朱景 于 2023-11-15 09:38 编辑

芯片N32G451QE7

我在使用TIM的DMA连续模式时,使用到的寄存器是CCDAT2和CCDAT3;
用到的定时器模式是输出比较模式,实现一个脉冲功能和Z相脉冲功能;
但是在实际应用的时候,DMA本应写到CCDAT2寄存器的数据被写入到了CCDAT3寄存器;
导致实现的波形如下:


实现的功能函数如下:
// ========================================================================
// 函数名称:HAL_InitPlsOut
// 输入参数:无
// 输出参数:无
// 扇    入:无
// 扇    出:无
// 函数描述: 脉冲输出设置  单周期最大25个
// ========================================================================
void HAL_PlsOutNum(bool dir , uint8_t num, uint8_t z_num)
{
        if(z_num > num){
                return ;
        }
        uint32_t TimCnt = (num << 1);
        uint16_t u16CmpValue = PLS_TIMER_PERIOD / TimCnt - 1;        /* 周期 200us = 0.0002s ; 1 / 0.0002s = 5000 */
        uint32_t u32CmpValue = (uint32_t)(0xFFFF0000 | u16CmpValue);
        uint32_t *pDest = (uint32_t *)PlsOutDmaBuf;

    //脉冲输出方向由 plsOutDir功能码P0-21决定正逻辑还是反逻辑
        if(dir ^ (*ptrPlsOutDir) ){
       PLS_OUT_DIR_P();
    }
    else{
       PLS_OUT_DIR_N();
        }

        PLS_OUT_TIM->DCTRL                &= (uint16_t)(~TIM_DMABURST_LENGTH_2TRANSFERS); // 关闭TIM的两个DMA长度传输
        PLS_OUT_DMA_CH->CHCFG   &= (uint16_t)(~DMA_CHCFG1_CHEN);                                   /* 关闭DMA */
        PLS_OUT_TIM->CTRL1      &= (uint32_t)(~((uint32_t)TIM_CTRL1_CNTEN));        /* 关闭TIM */

        PLS_OUT_TIM->AR = u16CmpValue;                        /* TIM的最大计数值初始化 */
        PLS_OUT_TIM->CCDAT2 = u16CmpValue;                /* 比较器初始化 */
        PLS_OUT_TIM->CCDAT3 = u16CmpValue;                /* 比较器初始化 */
       
        /* 脉冲是16位数据, 这里填充的是32位的, 所以直接使用 nPulseCount */
//        int i = 0;
//        for(; i < MAX_PULSE_COUNT_100US; i++) {
//                pDest = u32CmpValue;
//        }
        pDest[0] = u32CmpValue;
        pDest[1] = u32CmpValue;
        pDest[2] = u32CmpValue;
        pDest[3] = u32CmpValue;
        pDest[4] = u32CmpValue;
        pDest[5] = u32CmpValue;
        pDest[6] = u32CmpValue;
        pDest[7] = u32CmpValue;
        pDest[8] = u32CmpValue;
        pDest[9] = u32CmpValue;
        pDest[10] = u32CmpValue;
        pDest[11] = u32CmpValue;
        pDest[12] = u32CmpValue;
        pDest[13] = u32CmpValue;
        pDest[14] = u32CmpValue;
        pDest[15] = u32CmpValue;
        pDest[16] = u32CmpValue;
        pDest[17] = u32CmpValue;
        pDest[18] = u32CmpValue;
        pDest[19] = u32CmpValue;
        pDest[20] = u32CmpValue;
        pDest[21] = u32CmpValue;
        pDest[22] = u32CmpValue;
        pDest[23] = u32CmpValue;
        pDest[24] = u32CmpValue;
        pDest[25] = u32CmpValue;
        pDest[26] = u32CmpValue;
        pDest[27] = u32CmpValue;
        pDest[28] = u32CmpValue;
        pDest[29] = u32CmpValue;
        pDest[30] = u32CmpValue;
        pDest[31] = u32CmpValue;
        pDest[32] = u32CmpValue;
        pDest[33] = u32CmpValue;
        pDest[34] = u32CmpValue;
        pDest[35] = u32CmpValue;
        pDest[36] = u32CmpValue;
        pDest[37] = u32CmpValue;
        pDest[38] = u32CmpValue;
        pDest[39] = u32CmpValue;
        pDest[40] = u32CmpValue;
        pDest[41] = u32CmpValue;
        pDest[42] = u32CmpValue;
        pDest[43] = u32CmpValue;
        pDest[44] = u32CmpValue;
        pDest[45] = u32CmpValue;
        pDest[46] = u32CmpValue;
        pDest[47] = u32CmpValue;
        pDest[48] = u32CmpValue;
        pDest[49] = u32CmpValue;
        pDest[50] = u32CmpValue;
        pDest[51] = u32CmpValue;

        pDest[TimCnt] = 0xFFFEFFFF;                /* 为了效率没判断nPulseCount是否会越界,调用时要注意 */
        if(z_num > 0) {
                pDest[(z_num - 1) << 1] &= u16CmpValue << 16 | 0xFFFF;
                pDest[((z_num - 1) << 1) + 1] &= u16CmpValue << 16 | 0xFFFF;
        }
       
        PLS_OUT_DMA_CH->TXNUM = (TimCnt << 1)  + 2;                /* 重新设置DMA计数值 */
        PLS_OUT_TIM->CNT = 0;                                                        /* 定时器计数值清零 */
        PLS_OUT_TIM->DCTRL                |= (uint16_t)(TIM_DMABURST_LENGTH_2TRANSFERS); // 打开TIM的两个DMA长度传输
        PLS_OUT_DMA_CH->CHCFG         |= DMA_CHCFG1_CHEN;     // 开启DMA
        PLS_OUT_TIM->CTRL1                 |= TIM_CTRL1_CNTEN;            // 开启定时器
}


[size=10.5000pt]

脉冲图.jpg (116.76 KB )

脉冲图.jpg

使用特权

评论回复

相关帖子

沙发
朱景|  楼主 | 2023-11-15 09:40 | 只看该作者
这里面不使用循环是为了让函数运行的更快,并且因为u32CmpValue是可变的,没有使用全局参数

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

2

帖子

0

粉丝