MCUXpresso_LPC54102/boards/lpcxpresso54102/driver_examples/sctimer/pwm_with_dutycyle_change/cm4/sctimer_update_dutycycle.c
2022-05-14 22:28:55 +08:00

157 lines
4.9 KiB
C

/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_debug_console.h"
#include "board.h"
#include "fsl_sctimer.h"
#include "pin_mux.h"
#include <stdbool.h>
/*******************************************************************************
* Definitions
******************************************************************************/
#define SCTIMER_CLK_FREQ CLOCK_GetFreq(kCLOCK_BusClk)
#define DEMO_SCTIMER_OUT kSCTIMER_Out_4
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief delay a while.
*/
void delay(void);
/*******************************************************************************
* Variables
******************************************************************************/
volatile bool sctimerIsrFlag = false;
volatile bool brightnessUp = true; /* Indicate LED is brighter or dimmer */
volatile uint8_t updatedDutycycle = 10U;
uint32_t eventNumberOutput;
/*******************************************************************************
* Code
******************************************************************************/
void delay(void)
{
volatile uint32_t i = 0U;
for (i = 0U; i < 80000U; ++i)
{
__asm("NOP"); /* delay */
}
}
/* The interrupt callback function is used to update the PWM dutycycle */
void SCTIMER_LED_HANDLER()
{
sctimerIsrFlag = true;
if (brightnessUp)
{
/* Increase duty cycle until it reach limited value, don't want to go upto 100% duty cycle
* as channel interrupt will not be set for 100%
*/
if (++updatedDutycycle >= 99U)
{
updatedDutycycle = 99U;
brightnessUp = false;
}
}
else
{
/* Decrease duty cycle until it reach limited value */
if (--updatedDutycycle == 1U)
{
brightnessUp = true;
}
}
if (SCTIMER_GetStatusFlags(SCT0) & (1 << eventNumberOutput))
{
/* Clear interrupt flag.*/
SCTIMER_ClearStatusFlags(SCT0, (1 << eventNumberOutput));
}
}
/*!
* @brief Main function
*/
int main(void)
{
sctimer_config_t sctimerInfo;
sctimer_pwm_signal_param_t pwmParam;
uint32_t sctimerClock;
/* Board pin, clock, debug console init */
/* attach 12 MHz clock to USART0 (debug console) */
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
BOARD_InitPins();
BOARD_BootClockPLL150M(); /* Rev B device can only support max core frequency to 96Mhz.
Rev C device can support 150Mhz,use BOARD_BootClockPLL150M() to boot core to 150Mhz.
DEVICE_ID1 register in SYSCON shows the device version.
More details please refer to user manual and errata. */
BOARD_InitDebugConsole();
sctimerClock = SCTIMER_CLK_FREQ;
/* Print a note to terminal */
PRINTF("\r\nSCTimer example to output center-aligned PWM signal\r\n");
PRINTF("\r\nYou will see a change in LED brightness if an LED is connected to the SCTimer output pin");
PRINTF("\r\nIf no LED is connected to the pin, then probe the signal using an oscilloscope");
SCTIMER_GetDefaultConfig(&sctimerInfo);
/* Initialize SCTimer module */
SCTIMER_Init(SCT0, &sctimerInfo);
/* Configure PWM params with frequency 24kHZ from output */
pwmParam.output = DEMO_SCTIMER_OUT;
pwmParam.level = kSCTIMER_HighTrue;
pwmParam.dutyCyclePercent = updatedDutycycle;
if (SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 24000U, sctimerClock, &eventNumberOutput) ==
kStatus_Fail)
{
return -1;
}
/* Enable interrupt flag for event associated with out 4, we use the interrupt to update dutycycle */
SCTIMER_EnableInterrupts(SCT0, (1 << eventNumberOutput));
/* Receive notification when event is triggered */
SCTIMER_SetCallback(SCT0, SCTIMER_LED_HANDLER, eventNumberOutput);
/* Enable at the NVIC */
EnableIRQ(SCT0_IRQn);
/* Start the timer */
SCTIMER_StartTimer(SCT0, kSCTIMER_Counter_L);
/* Code below updates the PWM dutycycle for Out */
while (1)
{
/* Use interrupt to update the PWM dutycycle on output */
if (true == sctimerIsrFlag)
{
/* Disable interrupt to retain current dutycycle for a few seconds */
SCTIMER_DisableInterrupts(SCT0, (1 << eventNumberOutput));
sctimerIsrFlag = false;
/* Update PWM duty cycle */
SCTIMER_UpdatePwmDutycycle(SCT0, DEMO_SCTIMER_OUT, updatedDutycycle, eventNumberOutput);
/* Delay to view the updated PWM dutycycle */
delay();
/* Enable interrupt flag to update PWM dutycycle */
SCTIMER_EnableInterrupts(SCT0, (1 << eventNumberOutput));
}
}
}