来源:公众号【鱼鹰谈单片机】
作者:鱼鹰Osprey
ID :emOsprey
标题
根据鱼鹰的经验,定时器没有输出有几个方面:
1、如果通过中断翻转电平输出PWM,那么需要检查是否进入中断(检查中断控制器是否开启中断,外设相应中断是否开启)。
2、如果使用 PWM模式,一般问题出在 IO复用功能和重映射上。如果没有使用 IO的复用功能,那么它是不可能被定时器外设所驱动的。而如果你的 IO不是该定时器默认的输出 IO,那么就需要进行重映射。而STM32F1 和 STM32F4 的重映射机制是不一样的。




1)如果不开启重映射(没有重映射),定时器2默认输出 IO为:PA0、PA1、PA2、PA3。
2)部分重映射1 :PA15、PB3、PA2、PA3。
3)部分重映射2:PA0、PA1、PB10、PB11。
4)完全重映射:PA15、PB3、PB10、PB11。
从中我们也可以看到另一个坑,那就是可能端口换了,而你相应的时钟并没有打开,导致初始化配置失败,最终导致无法输出。而使用 PB3 时必须禁用部分 JTAG引脚才行。
而在重映射上,鱼鹰也确实踩了一个坑,到现在我也没明白为什么。当时在程序开始关闭了部分 JTAG引脚功能,然后再初始化定时器,并且开启相应重映射,最终还是没有任何输出,鱼鹰甚至直接查看最终的 AFIO寄存器的值,但情况就是配置的值一样,但还是无法输出,所幸的是,当我把复用功能在禁用部分 JTAG引脚后再开启所有定时器的重映射功能,发现能用了……
3、GPIO 的时钟没有打开,或者打开错误。
RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOA ENABLE);
比如像这样,用 APB1的函数打开 APB2外设的时钟,当然会出现问题,当然这种坑还是蛮容易检查出来的4、高级定时器的坑:
要想高级定时器输出脉冲,必须在初始化后增加一条语句:TIM_CtrlPWMOutputs(TIM8, ENABLE);没有这个函数,定时器是不可能输出脉冲的。毕竟是高级定时器,很傲娇,也很任性。
而因为它特殊性,鱼鹰也是在这里载了一个大跟头,这也是鱼鹰为什么要写这篇笔记的原因了。
定时器1 和定时器 8 同属于高级定时器,但定时器 8 可以正常输出,而定时器 1 却没法输出,这是怎么回事?为了解决这个问题,鱼鹰专门把定时器初始化部分封装成了一个函数,只留一个定时器作为参数部分:

那到底是什么问题导致的?
最终鱼鹰只能上网查找相关问题了,有可能就有前辈踩过这种坑呢。经过多方查找,鱼鹰尝试了各种办法也没有效果,最终死马当活马医的试了一个完全没有道理的可能:把串口初始化函数屏蔽了。

很多关于栈的话题,基本都是栈溢出,但事实上,还有一个容易忽略的话题是,栈的值不确定。我们都知道,函数进入时会进行压栈操作(用于保持寄存器的值),同时如果函数有局部变量,也可能会从栈中申请空间。

现在鱼鹰解释一下为什么串口函数会影响高级定时器的输出,而其他普通定时器并没有受影响。当串口函数执行时,使用的栈比较大,而在定时器函数执行时,刚好使用了这部分已被修改的栈空间,并且使用时没有初始化它,导致出现了问题。


所以为了解决这个问题,有两个办法:1、使用库函数提前初始化局部变量:


以上就是鱼鹰踩的坑,希望对各位道友有所帮助。咱们下期再见!