周期性闪烁LED的方式有一下两种,但第二种方式有问题由此引发C语言在32位机中计算时间间隔时的问题,此现象在PIC32和STM32中都有且一致
u32 TickCounter_32;
u16 TickCounter_16;
void SysTickHandler(void)
{
TickCounter_32++;
TickCounter_16++;
}
/**
* @brief LED闪烁1
*/
void RefreshLed1(void)
{
static u32 TickBase_32=0;
if( TickCounter_32 - TickBase_32 > 1000){
TickBase_32 = TickCounter_32;
LED_TOGGLE();
}
}
/**
* @brief LED闪烁2
*/
void RefreshLed2(void)
{
static u16 TickBase_16=0;
if( TickCounter_16 - TickBase_16 > 1000){
TickBase_16 = TickCounter_16;
LED_TOGGLE();
}
}
RefreshLed1在32位机中工作正常,两个u32相减结果仍是u32
RefreshLed2异常,表现现象为闪烁一段时间后不再闪烁
当TickCounter_16大于65535变为0,自增到500后,但TickBase_16 = 65000左右时
计算过程如下 500-65000 = -535, -535>1000,Flase所以程序不会再进入LED闪烁程序
具体计算过程如下 0x01F4 - 0xFDE8 = 0xFFFF040C(数据总线为32位)
500 - 65000 = -64500 >1000 条件不成立
可更改为以下RefreshLed2_1 or RefreshLed2_2:
两种方式本质是一种方式,要将TickCounter_16 - TickBase_16的结果强制转化为u16
具体计算过程如下 0x01F4 - 0xFDE8 = 0xFFFF040C = (u16)0xFFFF040C = 0x040C = 1036
500 - 65000 = 1036 >1000 条件成立
/**
* @brief LED闪烁2_1
*/
void RefreshLed2_1(void)
{
static u16 TickBase_16=0;
if( (u16)(TickCounter_16 - TickBase_16) > 1000){
TickBase_16 = TickCounter_16;
LED_TOGGLE();
}
}
/**
* @brief LED闪烁2_2
*/
void RefreshLed2_2(void)
{
static u16 TickBase_16=0;
u16 TickInterval;
TickInterval = TickCounter_16 - TickBase_16;
if( TickInterval > 1000){
TickBase_16 = TickCounter_16;
LED_TOGGLE();
}
}