求助个TIM产生方波的诡异问题

2019-12-12 18:23发布

本帖最后由 tomzbj 于 2018-4-24 18:24 编辑

STM32F103RE,用PB0/TIM3_CH3输出1kHz 占空比50%的方波,设置定时频率2kHz,Toggle模式输出

结果莫名其妙地没有输出,如果在进主循环前加个while(1);则方波一切正常
继续缩小范围,发现在主循环里调某个pid控制程序前加while(1);则正常,加在后面无输出

继续在pid控制程序里加while(1),发现在sum_err += err;一句前加while(1);则正常输出, 加在后面无输出。

在主循环前、TIM初始化之后加2秒延时,用示波器监视, 发现方波只产生了不到一个周期就一直拉高了,说明应该是编译期就有问题。

两种情况下用串口输出TIM3和GPIOB的所有寄存器,都完全一致。

现在不知道该如何继续下手了。。。

编译器是gcc version 4.9.3 20150303

补充: 手里有两块相同的板,问题一样,所以应该不是硬件故障。

再补充: 从Toggle模式换成PWM模式,问题照旧。

输出波形如图,输出了不到一个周期就一直拉高 DSC04812.jpg (731.02 KB, 下载次数: 0) 下载附件 2018-4-24 17:23 上传

TIM3初始化程序:
  1. #include "misc.h"

  2. void COMP_CLK_Config(int freq, int phase_diff)
  3. {

  4.     int period = SystemCoreClock / 2 / freq - 1; // PCLK1 = SYSCLK / 2
  5.     int pulse_diff = (int) ((period + 1.0) / 360.0 * phase_diff);

  6.     // PB0(TIM3_CH3) as COMP_CLK
  7.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  8.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  9.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  10.     GPIO_Init(GPIOB, &GPIO_InitStructure);

  11.     TIM_DeInit(TIM3);
  12.     TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  13.     TIM_OCInitTypeDef TIM_OCInitStructure;

  14.     TIM_TimeBaseStructure.TIM_Period = period;
  15.     TIM_TimeBaseStructure.TIM_Prescaler = 0;
  16.     TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  17.     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  18.     TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  19.     // PWM1 Mode configuration: Channel1
  20.     TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
  21.     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  22.     TIM_OCInitStructure.TIM_Pulse = period / 2 + pulse_diff;
  23.     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  24.     TIM_OC3Init(TIM3, &TIM_OCInitStructure);
  25.     TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
  26.     TIM_ARRPreloadConfig(TIM3, ENABLE);

  27.     TIM_Cmd(TIM3, ENABLE); // TIM3 enable counter
  28. }
复制代码

PID程序:
  1. void PID_CJR(float tempset, float tempnow)
  2. {
  3.     // KP = 3600 / 2.2 = 1600, KI = 1.2 * 1600 / 250 = 8
  4.     const int KP = 1600, KI = 2;    //, KD = 0;
  5.     static int tempctrl = 500;
  6.     static float err = 0;    //, err1 = 0;//, err2 = 0; //本次、上次、上上次误差

  7.     err = tempset - tempnow;

  8.     if(fabs(err) < 0.5) {        // 误差小于0.5度时启用I
  9.         sum_err += err;
  10.     }
  11.     else {
  12.         sum_err = 0;
  13.     }
  14.     tempctrl = (int) (KP * err + KI * sum_err);
  15.     if(tempctrl > 950)
  16.         tempctrl = 950; //限幅
  17.     if(tempctrl < 50)
  18.         tempctrl = 50;
  19.     CJR_SetDuty(tempctrl);
  20. //    err2 = err1; //保存误差
  21. //    err1 = err;
  22. }
复制代码

在PID这个函数的前面某个位置插入while(1);则输出方波正常, 去掉就无方波。但是每次找出的位置还不一样,和整体代码量、编译优化选项是Os还是O0都有关。

--------------4.24 18:23更新---------------------
没有方波输出时, 如果把主循环前面的外设初始化函数去掉几个,则输出又正常了。估计是某个地方内存越界了?但奇怪的是我总共用了六七个TIM,只有TIM3出问题。
于是在串口输出CONTROL IPSR APSR xPSR PSP MSP PRIMASK BASEPRI FAULTMSK等寄存器的值,发现输出正常/不正常时,这些寄存器的值完全相同。还得另找原因。
明天继续吧。。。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
12条回答
小小菜
2019-12-13 22:15
遇到和楼主有点相似的问题,也是输出不到一个周期的PWM后就拉高。
由于是用于升级的APP程序,在没有设置偏移地址的时候,一切正常。设置偏移地址后,出现了上面说的这种情况,没有PWM输出,且诡异的是只有TIM1异常,TIM4和TIM10均正常。
搞了一整天之后发现库函数写入寄存器的数据不对,在仿真模式下,看到写入的数据和写入后寄存器的数值不同,不懂汇编,不会看汇编语句,后来放弃,TIM1的初始化直接自己操作寄存器,问题解决。
MDK:5.25.2.0
MCU:STM32F407ZET6
库版本:1.8.0

一周热门 更多>