qintian0303 发表于 2024-11-17 21:45:19

【Avnet | NXP FRDM-MCXN947试用活动】非阻塞式点灯

       在上一章节中,我们采用的是阻塞式方法来实现点灯的功能,即在延时期间程序只能停滞不前,依赖于在while循环中插入延时操作。这种阻塞式的循环灯实现方式,主要适用于点灯这类基础操作。然而,其对系统实时性的影响颇为显著,不够理想。本章节,我们将引入定时器的方式来实现循环灯操作。通过定时器达到预设时间后,再执行相应的操作。定时器定时功能展现出多方面的优势:首要的是定时精准度高,相较于我们之前看似精准实则存在较大偏差的延时方法,定时器能够实现更为精确的定时控制,无需繁琐的调整即可达到理想效果;其次,定时器在定时时间到达后,是在中断中处理任务内容,这赋予了其更高的优先级,进一步提升了系统的响应速度和稳定性。
       接下来我们就实现循环点亮LED(定时器,循环间隔500mms)。
       使用配置工具添加外设——LPTMR:

       并配置为基础定时器功能(10ms):

       上图的“复制到剪贴板”有没有看到,这也是官方IDE的一个小细节,我们直接可以把中断回调函数复制过去,非常的方便:
/* LPTMR0_IRQn interrupt handler */
void LPTMR0_IRQHANDLER(void) {
uint32_t intStatus;
/* Reading all interrupt flags of status register */
intStatus = LPTMR_GetStatusFlags(LPTMR0_PERIPHERAL);
LPTMR_ClearStatusFlags(LPTMR0_PERIPHERAL, intStatus);

/* Place your code here */

/* Add for ARM errata 838869, affects Cortex-***, Cortex-***F
   Store immediate overlapping exception return operation might vector to incorrect interrupt. */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
    __DSB();
#endif
}       上述只是一个例程,我们在其中进行修改就可以了,最后如下:
void LPTMR0_IRQHANDLER(void) {
uint32_t intStatus;
/* Reading all interrupt flags of status register */
LPTMR_ClearStatusFlags(LPTMR0_PERIPHERAL, kLPTMR_TimerCompareFlag);
cnt++;
if(cnt >= 50)
{
      cnt = 0;
      LED_state++;
}

/* Place your code here */

/* Add for ARM errata 838869, affects Cortex-***, Cortex-***F
   Store immediate overlapping exception return operation might vector to incorrect interrupt. */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
    __DSB();
#endif
}       这样就可以是先定时器的定时初始化以及中断响应了,这里有一些地方需要注意,相关的外设初始化是在peripherals.c和peripherals.h,我们需要再主程序中调用相关的初始化函数BOARD_InitBootPeripherals(void),生成的初始化代码并没有在这里进行更新:

       这样就实现了和上一章节一样的功能,不过这种定时器的方法实时性会更好,为了区分这次定时为500ms进行变换,效果如下:
页: [1]
查看完整版本: 【Avnet | NXP FRDM-MCXN947试用活动】非阻塞式点灯