本帖最后由 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等寄存器的值,发现输出正常/不正常时,这些寄存器的值完全相同。还得另找原因。
明天继续吧。。。
Toggle模式不需要这句,试PWM模式时加了。问题一样。
楼主,在定义了局部结构体变量后,别忘了先初始化这个变量令它有个确定值:
- TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
- TIM_OCStructInit(&TIM_OCInitStructure);
复制代码我告诉你这个秘密,你会省好多时间的!
经验:官方示例仅供参考,未必全对;写代码是件很严谨的事,很多细节不容忽视。
多谢指点
加上这两条,方波正常。
再把两个结构体移到外面,或者在前面加static,则无论加不加这两条,仍然不正常。
不管正常还是不正常,TIM3所有寄存器的值都相同。
实在是诡异,明天得继续把这里搞清楚。
一周热门 更多>