使用LPC812 SCT的state特性 Ø 问题 客户使用LPC812中的SCT模块想实现以下功能: - State 0 -> rising edges detected on input -> counter L started -> advance to state 1
- State 1 -> Counter L reaches limit value -> output set high -> advance to state 2
- State 2- > Falling edge on input -> output set low & counter reset -> set state to 0
复制代码 根据上述描述,可看出要实现的功能其实并不复杂,所以客户通过参考SDK软件库中multi_state_pwm工程较快的创建了如下工程代码: - /*
- * Copyright (c) 2016, Freescale Semiconductor, Inc.
- * Copyright 2016-2017 NXP
- * All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * Modified -- P0_13 now as input to counter to start it,
- *
- * State 0 -> rising edges detected on input -> counter L started -> advance to state 1
- * State 1 -> Counter L reaches limit value -> output set high -> advance to state 2
- * State 2- > Falling edge on input -> output set low & counter reset -> set state to 0
- */
- #include "fsl_debug_console.h"
- #include "board.h"
- #include "fsl_sctimer.h"
- #include "pin_mux.h"
- /*******************************************************************************
- * Definitions
- ******************************************************************************/
- #define SCTIMER_CLK_FREQ CLOCK_GetFreq(kCLOCK_Irc)
- #define DEMO_FIRST_SCTIMER_OUT kSCTIMER_Out_2
- #define DEMO_SECOND_SCTIMER_OUT kSCTIMER_Out_3
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- /*******************************************************************************
- * Code
- ******************************************************************************/
- /*!
- * @brief Main function
- */
- int main(void)
- {
- sctimer_config_t sctimerInfo;
- uint32_t riseEvent, fallEvent; // Modified
- uint32_t stateNumber; // Modified
- uint32_t eventCounterL;
- uint32_t sctimerClock;
- uint32_t matchValueL;
- /* Board pin, clock, debug console init */
- /* Enable clock of uart0. */
- CLOCK_EnableClock(kCLOCK_Uart0);
- /* Ser DIV of uart0. */
- CLOCK_SetClkDivider(kCLOCK_DivUsartClk, 1U);
- BOARD_InitPins();
- BOARD_BootClockIRC12M();
- BOARD_InitDebugConsole();
- /* Enable clock of sct. */
- CLOCK_EnableClock(kCLOCK_Sct);
- sctimerClock = SCTIMER_CLK_FREQ;
- /* Print a note to terminal */
- // PRINTF("\r\nSCTimer example to use it in 16-bit mode\r\n");
- // PRINTF("\r\nThe example shows both 16-bit counters running and toggling an output periodically ");
- SCTIMER_GetDefaultConfig(&sctimerInfo);
- /* Add judgment for change clock source*/
- #if defined(SCTIMER_NEED_CHANGE_CLOCK_SOURCE)
- sctimerInfo.clockMode = DEMO_CLOCK_MODE;
- sctimerInfo.clockSelect = DEMO_CLOCK_SEL;
- #endif
- /* Switch to 16-bit mode */
- sctimerInfo.enableCounterUnify = false;
- /* Calculate prescaler and match value for Counter L for 10ms */
- matchValueL = MSEC_TO_COUNT(100U, sctimerClock);
- sctimerInfo.prescale_l = matchValueL / 65536;
- matchValueL = matchValueL / (sctimerInfo.prescale_l + 1) - 1;
- // Switch off synchronization for inputs to speed up TODO: Necessary??
- // sctimerInfo.inputsync = 0x0U;
- /* Initialize SCTimer module */
- SCTIMER_Init(SCT0, &sctimerInfo);
- stateNumber = SCTIMER_GetCurrentState(SCT0);
- // STATE 0 /////////////////////////////////////////////////////////////////////////////////
- // event 0
- /* Schedule an event to look for a rising edge on input 1 in this state */
- if (SCTIMER_CreateAndScheduleEvent(SCT0, kSCTIMER_InputRiseEvent, 0u, kSCTIMER_Input_1, kSCTIMER_Counter_L,
- &riseEvent) == kStatus_Fail)
- {
- return -1;
- }
- /* Transition to next state when a rising edge is detected on input 1 */
- SCTIMER_SetupNextStateAction(SCT0, stateNumber + 1, riseEvent);
- // Goto next state
- SCTIMER_IncreaseState(SCT0);
- // STATE 1 /////////////////////////////////////////////////////////////////////////////////
- // event 1
- /* Schedule a single match event for Counter L */
- if (SCTIMER_CreateAndScheduleEvent(SCT0, kSCTIMER_MatchEventOnly, matchValueL, 0, kSCTIMER_Counter_L,
- &eventCounterL) == kStatus_Fail)
- {
- return -1;
- }
- // Set output in this state
- SCTIMER_SetupOutputSetAction(SCT0, kSCTIMER_Out_0, eventCounterL);
- /* Reset Counter L when Counter L event occurs TODO: Should counter be reset?? */
- //SCTIMER_SetupCounterLimitAction(SCT0, kSCTIMER_Counter_L, eventCounterL);
- /* Transition to next state when a rising edge detected on input 1 */
- SCTIMER_SetupNextStateAction(SCT0, stateNumber + 2, eventCounterL);
- // Goto next state
- SCTIMER_IncreaseState(SCT0);
- // STATE 2 /////////////////////////////////////////////////////////////////////////////////
- // event 2
- /* Schedule an event to look for a falling edge on input 1 in this state */
- if (SCTIMER_CreateAndScheduleEvent(SCT0, kSCTIMER_InputFallEvent, 0u, kSCTIMER_Input_1, kSCTIMER_Counter_L,
- &fallEvent) == kStatus_Fail)
- {
- return -1;
- }
- // Clear output when event occurs in this state
- SCTIMER_SetupOutputClearAction(SCT0, kSCTIMER_Out_0, fallEvent);
- // Transition to next state when event occurs in this state, i.e. loop back to initial state
- SCTIMER_SetupNextStateAction(SCT0, 0u, fallEvent);
- ///////////////////////////////////////////////////////////////////////////////////////////
- /* Start the L counter */
- SCTIMER_StartTimer(SCT0, kSCTIMER_Counter_L);
- while (1)
- {
- __asm("NOP"); /* delay */
- }
- }
复制代码 浏览上述代码后,小编并未发现任何错误,但客户在debug时候却发现,进入state 2后,event(Falling edge on input)始终就未被触发,这是什么原因导致的呢??
Ø 问题分析解决 在对比了LPC MCU的各个参考手册后发现,LPC812最多支持的state数仅为2,而在客户工程代码中,使用了state 0, state 1和state 2,这已然超出了LPC812的性能范围,经客户与小编更进一步的测试后可确认,此为引发问题的原因。
|