求助个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条回答
cocom
1楼-- · 2019-12-12 21:28
KAO, 要有完整程序才有可能有人帮你分析,你这样让人分析个啥?
tomzbj
2楼-- · 2019-12-12 22:26
 精彩回答 2  元偷偷看……
stevenli
3楼-- · 2019-12-12 23:59
TIM_CtrlPWMOutputs(TIM3, ENABLE);
tomzbj
4楼-- · 2019-12-13 04:13
stevenli 发表于 2018-4-24 17:40
TIM_CtrlPWMOutputs(TIM3, ENABLE);

Toggle模式不需要这句,试PWM模式时加了。问题一样。
love_ourdev
5楼-- · 2019-12-13 08:16
本帖最后由 love_ourdev 于 2018-4-24 18:26 编辑

楼主,在定义了局部结构体变量后,别忘了先初始化这个变量令它有个确定值:
  1. TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  2. TIM_OCStructInit(&TIM_OCInitStructure);
复制代码

我告诉你这个秘密,你会省好多时间的!

经验:官方示例仅供参考,未必全对;写代码是件很严谨的事,很多细节不容忽视。
tomzbj
6楼-- · 2019-12-13 11:36
love_ourdev 发表于 2018-4-24 18:22
楼主,在定义了局部结构体变量后,别忘了先初始化这个变量令它有个确定值:

多谢指点
加上这两条,方波正常。
再把两个结构体移到外面,或者在前面加static,则无论加不加这两条,仍然不正常。

不管正常还是不正常,TIM3所有寄存器的值都相同。
实在是诡异,明天得继续把这里搞清楚。

一周热门 更多>