本帖最后由 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初始化程序:
- #include "misc.h"
- void COMP_CLK_Config(int freq, int phase_diff)
- {
- int period = SystemCoreClock / 2 / freq - 1; // PCLK1 = SYSCLK / 2
- int pulse_diff = (int) ((period + 1.0) / 360.0 * phase_diff);
- // PB0(TIM3_CH3) as COMP_CLK
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- TIM_DeInit(TIM3);
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
- TIM_TimeBaseStructure.TIM_Period = period;
- TIM_TimeBaseStructure.TIM_Prescaler = 0;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
- // PWM1 Mode configuration: Channel1
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = period / 2 + pulse_diff;
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
- TIM_OC3Init(TIM3, &TIM_OCInitStructure);
- TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
- TIM_ARRPreloadConfig(TIM3, ENABLE);
- TIM_Cmd(TIM3, ENABLE); // TIM3 enable counter
- }
复制代码
PID程序:
- void PID_CJR(float tempset, float tempnow)
- {
- // KP = 3600 / 2.2 = 1600, KI = 1.2 * 1600 / 250 = 8
- const int KP = 1600, KI = 2; //, KD = 0;
- static int tempctrl = 500;
- static float err = 0; //, err1 = 0;//, err2 = 0; //本次、上次、上上次误差
- err = tempset - tempnow;
- if(fabs(err) < 0.5) { // 误差小于0.5度时启用I
- sum_err += err;
- }
- else {
- sum_err = 0;
- }
- tempctrl = (int) (KP * err + KI * sum_err);
- if(tempctrl > 950)
- tempctrl = 950; //限幅
- if(tempctrl < 50)
- tempctrl = 50;
- CJR_SetDuty(tempctrl);
- // err2 = err1; //保存误差
- // err1 = err;
- }
复制代码
在PID这个函数的前面某个位置插入while(1);则输出方波正常, 去掉就无方波。但是每次找出的位置还不一样,和整体代码量、编译优化选项是Os还是O0都有关。
--------------4.24 18:23更新---------------------
没有方波输出时, 如果把主循环前面的外设初始化函数去掉几个,则输出又正常了。估计是某个地方内存越界了?但奇怪的是我总共用了六七个TIM,只有TIM3出问题。
于是在串口输出CONTROL IPSR APSR xPSR PSP MSP PRIMASK BASEPRI FAULTMSK等寄存器的值,发现输出正常/不正常时,这些寄存器的值完全相同。还得另找原因。
明天继续吧。。。
放弃了,把程序里所有的InitStructure全部改成局部变量了。
由于是用于升级的APP程序,在没有设置偏移地址的时候,一切正常。设置偏移地址后,出现了上面说的这种情况,没有PWM输出,且诡异的是只有TIM1异常,TIM4和TIM10均正常。
搞了一整天之后发现库函数写入寄存器的数据不对,在仿真模式下,看到写入的数据和写入后寄存器的数值不同,不懂汇编,不会看汇编语句,后来放弃,TIM1的初始化直接自己操作寄存器,问题解决。
MDK:5.25.2.0
MCU:STM32F407ZET6
库版本:1.8.0
嗯,我在TIM1和TIM8也出现过类似问题,后来发现原因是TIM1和TIM8的结构体有RepetitionCounter成员变量没有初始化,非零值导致TIM1和TIM8输出几个脉冲就停止。
把所有成员赋初值就正常了。你的TIM1不知道是不是原因一样。
但是我前面的TIM3应该不是这个原因。。。后来只用局部的初始化结构体,也没再出过问题。
这个没试,稍后来试。不过上面兄弟提到的要初始化结构体,是学到了一点,这点之前自己确实没注意到。
一周热门 更多>