|
最近做一个东西,要用到好几个Timer的相互Trigger的功能,而Timer的选择又要对Layout作妥协,代码改来改去的
Timer的Trigger关系也是调来调去的,一怒之下准备牺牲代码可阅读来跟上layout的步伐
STM32 的Timer之间可以用一Timer Internal Trigger联系起
各个Timer之间的联系可以用下表表示
(原文件名:ITR.jpg)
如果要用TIM4去触发TIM1,需要将TIM1的Internal Triger配置成ITR3
Timer改来改去容易出错,可以写成一张表,用的时候直接读这张表,由于是宏写的,不会影响运行时的效率,如下:
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/* Just make parameter name shorter */
#define _GetInternalTrigger(S,M) \
(S == TIM1 ? (M == TIM5 ? TIM_TS_ITR0 : (M == TIM2 ? TIM_TS_ITR1 : (M == TIM3 ? TIM_TS_ITR2 :(M == TIM4 ? TIM_TS_ITR3 : (u16)-1)))): \
(S == TIM8 ? (M == TIM1 ? TIM_TS_ITR0 : (M == TIM2 ? TIM_TS_ITR1 : (M == TIM4 ? TIM_TS_ITR2 :(M == TIM5 ? TIM_TS_ITR3 : (u16)-1)))): \
(S == TIM2 ? (M == TIM1 ? TIM_TS_ITR0 : (M == TIM8 ? TIM_TS_ITR1 : (M == TIM3 ? TIM_TS_ITR2 :(M == TIM4 ? TIM_TS_ITR3 : (u16)-1)))): \
(S == TIM3 ? (M == TIM1 ? TIM_TS_ITR0 : (M == TIM2 ? TIM_TS_ITR1 : (M == TIM5 ? TIM_TS_ITR2 :(M == TIM4 ? TIM_TS_ITR3 : (u16)-1)))): \
(S == TIM4 ? (M == TIM1 ? TIM_TS_ITR0 : (M == TIM2 ? TIM_TS_ITR1 : (M == TIM3 ? TIM_TS_ITR2 :(M == TIM8 ? TIM_TS_ITR3 : (u16)-1)))): \
(S == TIM5 ? (M == TIM2 ? TIM_TS_ITR0 : (M == TIM3 ? TIM_TS_ITR1 : (M == TIM4 ? TIM_TS_ITR2 :(M == TIM8 ? TIM_TS_ITR3 : (u16)-1)))): \
(u16)-1))))))
#define GetInternalTrigger(SlaveTimer,MasterTimer) _GetInternalTrigger(SlaveTimer,MasterTimer)
/*---------------------------------------------------------------------------------------------------------------------------------------*/
这样在要用的时候这样写就行了
/*-----------------------------------------------------------------------------------------------------*/
TIM_ITRxExternalClockConfig(TIM1,GetInternalTrigger(TIM1,TIM4)); /* 用TIM4去触发TIM1 */
/*-----------------------------------------------------------------------------------------------------*/
不是每一种Timer的组合都会有这样触发方式,如果写错了需要能够报出这个错误
可以用一种叫做Compile Time Assert的方法
比如:
/*-----------------------------------------------------------------------------------------------------*/
#define compile_assert(exp) {extern char lxyppc_at_163_dot_com[(exp) ? 1:-1];}
/*-----------------------------------------------------------------------------------------------------*/
这里是利用了数组下标必需大于零作为compile check的条件,也可以写成别的形式
代码可以这样写
/*-----------------------------------------------------------------------------------------------------*/
compile_assert((u16)GetInternalTrigger(TIM1,TIM4) != (u16)-1);
TIM_ITRxExternalClockConfig(TIM1,GetInternalTrigger(TIM1,TIM4)); /* 用TIM4去触发TIM1,正确,编译通过 */
compile_assert((u16)GetInternalTrigger(TIM2,TIM5) != (u16)-1);
TIM_ITRxExternalClockConfig(TIM1,GetInternalTrigger(TIM2,TIM5)); /* 用TIM5去触发TIM2,错误,编译报错 */
/*-----------------------------------------------------------------------------------------------------*/
以上代码IAR 4.42 (32K限制版测试通过)
/**
以上写法不一定能被所有编译器支持,本人对此产生的移植性问题不负任何责任
P.S. 以上针对layout的牢骚纯属杜撰,只是为了引言一下:)
*/ |
|