定时器PWM输入捕获DMA模式下的异常记录

问题出现在AT32F403中,STM32系列的暂未尝试

问题描述使用定时器PWM输入捕获+DMA传输数据,共3路输入捕获,仅其中有1路出现问题。具体表现为,占空比部分的数据能通过DMA存入数组,但是周期部分的数据全为0,且使用DMA过半中断时,仿真不能准确的及时暂停,等停下来的时候占空比数组已全部填满并可能重复填写过。

使用的定时器通道为TMR2_CH1、TMR5_CH2、TMR4_CH1,其中为TMR5_CH2的周期数据错误。

后续调试时发现是因为程序在配置过程中配错了一个数据导致问题出现:

配置滤波器时,配置范围为0~F,误将其配置为0xFF。将其改为0xF则错误消除。

但是又不禁思考起一个问题,为什么只有TMR5_CH2通道出现这个错误

于是我点开了函数TMR_PWMIConfig:

 再点开函数TI1_Config:

 与函数TI2_Config:

找出TMR_ICFilter所配置到的寄存器为TMRx->CCM1。然后在数据手册中找出关于该寄存器的描述,CCM1有两种描述:输入和输出。查看描述输入的部分:

正常情况下 TMR_ICFilter 应该会被配置入 位7:4与15:12中,但由于此次配置错误,配置数值超过最大值0xF,配置为0xFF,,所以导致在TI1_Config中会将11:4配置为FF,但在TI2_Config中,0xFF左移12位,超出了一部分,所以只会将15:12配置为F。

当配置TMR2_CH1通道的TMR_PWMIConfig时,TMR_PWMIConfig中的部分流程为:

  if (TMR_ICInitStruct->TMR_Channel == TMR_Channel_1)
  {
    /* TI1 Configuration */
    TI1_Config(TMRx, TMR_ICInitStruct->TMR_ICPolarity, TMR_ICInitStruct->TMR_ICSelection,
               TMR_ICInitStruct->TMR_ICFilter);
    /* Set the Input Capture Prescaler value */
    TMR_SetIC1DIV(TMRx, TMR_ICInitStruct->TMR_ICDIV);
    /* TI2 Configuration */
    TI2_Config(TMRx, icoppositepolarity, icoppositeselection, TMR_ICInitStruct->TMR_ICFilter);
    /* Set the Input Capture Prescaler value */
    TMR_SetIC2DIV(TMRx, TMR_ICInitStruct->TMR_ICDIV);
  }

其中函数TMR_SetIC1DIV为配置输入捕获预分频系数,此时配置预分频系数为0,在寄存器中的的具体表现为将TMRx->CCM1的11:10与3:2配置为0。

按照这段代码的流程走下来:

TI1_Config会将TMR2->CCM1配置为0x0FF1,同时会将C1EN置位,并且会配置其捕获的边沿。

TMR_SetIC1DIV在此会将TMR2->CCM1的 3:2位置0,此处TMR2->CCM1依旧为0x0FF1。

TI2_Config会将TMR2->CCM1配置为0xFEF1,同时会将C2EN置位,并且会配置其捕获的边沿。

被配置为0xFEF1而不是0xFFF1的原因为,TI2_Config的过程中会先将TMR2->CCM1的9:8位与15:12复位再重新配置,所以得到了0xFEF1。

TMR_SetIC2DIV在此会将TMR2->CCM1的 11:10位置0,此处TMR2->CCM1将被配置为0xF2F1。

到此,TMR2_CH1配置的效果与TMR_ICFilter配置为0xF时的效果一致。

TMR4_CH1的效果同TMR2_CH1一样。所以没有出现问题。

当配置TMR5_CH2通道的TMR_PWMIConfig时,TMR_PWMIConfig中的部分流程为:

  else    //(TMR_ICInitStruct->TMR_Channel == TMR_Channel_2)
  {
    /* TI2 Configuration */
    TI2_Config(TMRx, TMR_ICInitStruct->TMR_ICPolarity, TMR_ICInitStruct->TMR_ICSelection,
               TMR_ICInitStruct->TMR_ICFilter);
    /* Set the Input Capture Prescaler value */
    TMR_SetIC2DIV(TMRx, TMR_ICInitStruct->TMR_ICDIV);
    /* TI1 Configuration */
    TI1_Config(TMRx, icoppositepolarity, icoppositeselection, TMR_ICInitStruct->TMR_ICFilter);
    /* Set the Input Capture Prescaler value */
    TMR_SetIC1DIV(TMRx, TMR_ICInitStruct->TMR_ICDIV);
  }

按照这段代码的流程走下来:

TI2_Config会将TMR5->CCM1配置为0xF100,同时会将C2EN置位,并且会配置其捕获的边沿。

TMR_SetIC2DIV在此会将TMR5->CCM1的 11:10位置0,此处TMR5->CCM1依旧为0xF100。

TI1_Config会将TMRx->CCM1配置为0xFDF2,同时会将C1EN置位,并且会配置其捕获的边沿。

被配置为0xFDF2而不是0xFFF2的原因为,C2EN在之前已经被置位,根据寄存器的描述,位9:8 C2SEL 仅在C2EN=0时才是可写的,所以得到了0xFDF2。

TMR_SetIC1DIV在此会将TMRx->CCM1的 3:2位置0,此处TMRx->CCM1依旧被配置为0xFDF2,与预期不同,表现为多将 输入捕获2预分频器IC2DIV配置为11。由此引发错误。

虽然问题本应该在这里完结,本以为是因为输入捕获通道1分频器与输入捕获通道2分频器设置不同导致的错误,但是随后测试时发现,在其他配置都相同的情况下,将输入捕获预分频器设置成TMR_ICDIV_DIV1之外的2分频、4分频、8分频都会出现一开始,周期数据全部为0的情况。尚未寻明原由。

  TMR_ICStructInit(&TMR_ICInitStructure);
  TMR_ICInitStructure.TMR_Channel = TMR_Channel_2;
  TMR_ICInitStructure.TMR_ICPolarity = TMR_ICPolarity_Falling;
  TMR_ICInitStructure.TMR_ICSelection = TMR_ICSelection_DirectTI;
  TMR_ICInitStructure.TMR_ICDIV = TMR_ICDIV_DIV2;//或者TMR_ICDIV_DIV4  TMR_ICDIV_DIV8
  TMR_ICInitStructure.TMR_ICFilter = 0xf;	
	
  TMR_PWMIConfig(TMR5, &TMR_ICInitStructure);

另外:在单片机退出仿真的过程中,DMA仍在高速运转,所以单片机停稳的时候,DMA存储地址内的数据很容易出现数据与满足触发断点的那一时刻对不准的情况。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值