简体   繁体   中英

STM32 Blinking LEDs with a Timer

I'm trying to blink 4 LEDs with a Timer Interrupt, at different frequencies.

I came up with this code

/*********** Includes  ****************/
#include "stm32f4xx.h"
#include "stm32f4_discovery.h"


/*********** Defines  *****************/
#define TIM3_CK_CNT 50000


/*********** Declarations *************/
/*------ Function prototypes ---------*/
void TimerConfiguration(void);


/* ----- Global variables ----------- */
volatile uint16_t CCR1_Val = 50000;
volatile uint16_t CCR2_Val = 40000;
volatile uint16_t CCR3_Val = 30000;
volatile uint16_t CCR4_Val = 20000;

 /************ Main *********************/
int main(void)
{

// LED initialization
STM_EVAL_LEDInit(LED3);     // Orange
STM_EVAL_LEDInit(LED4);     // Green
STM_EVAL_LEDInit(LED5);     // Red
STM_EVAL_LEDInit(LED6);     // Blue

/* TIM3 Configuration */
TimerConfiguration();



while (1);
}



/*********** Functions *****************/

/**
  * @brief  Configure the TIM3 TIMER.
  * @param  None
  * @retval None
  */
void TimerConfiguration(void)
{
uint16_t PrescalerValue = 0;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

/* TIM3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

/* Prescaler configuration */
PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / TIM3_CK_CNT) - 1;
TIM_PrescalerConfig(TIM3, PrescalerValue, TIM_PSCReloadMode_Immediate);

/* Output Compare Timing Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);
/*Channel2 */
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
/*Channel3 */
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
TIM_OC3Init(TIM3, &TIM_OCInitStructure);
/*Channel4 */
TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
TIM_OC4Init(TIM3, &TIM_OCInitStructure);

/* Configure the TIM3 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

/* TIM Interrupts enable */
TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_CC3, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_CC4, ENABLE);
/* TIM3 counter enable */
TIM_Cmd(TIM3, ENABLE);



}


int LedCount6 = 0;
int LedCount5 = 0;
int LedCount4 = 0;
int LedCount3 = 0;

/************ Interrupt Handlers *************/

/**
* @brief  This function handles TIM3 global interrupt request.
* @param  None
* @retval None
*/

void TIM3_IRQHandler(void)
{
uint16_t capture = 0;
LedCount6++;
LedCount5++;
LedCount4++;
LedCount3++;

if ((TIM_GetITStatus(TIM3, TIM_IT_CC2)  != RESET) && (TIM_GetITStatus(TIM3, TIM_IT_CC1)  != RESET) && (TIM_GetITStatus(TIM3, TIM_IT_CC3)  != RESET) && (TIM_GetITStatus(TIM3, TIM_IT_CC4)  != RESET))
{
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);

    int val6 = 100000;
    int val5 = 70000;
    int val4 = 60000;
    int val3 = 50000;





    if (LedCount6 >= val6 ) {
    /* LED6 toggling */
    STM_EVAL_LEDToggle(LED6);

    LedCount6 = 0;

    /* Update CH1 OCR */
    capture = TIM_GetCapture1(TIM3);
    TIM_SetCompare1(TIM3, capture + CCR1_Val);}


    if (LedCount5 >= val5) {

    /* LED5 toggling */
    STM_EVAL_LEDToggle(LED5);

    LedCount5 = 0;

    /* Update CH2 OCR */
    capture = TIM_GetCapture2(TIM3);
    TIM_SetCompare2(TIM3, capture + CCR2_Val);}

    if (LedCount4 >= val4) {

    /* LED4 toggling */
    STM_EVAL_LEDToggle(LED4);

    LedCount4 = 0;

    /* Update CH3 OCR */
    capture = TIM_GetCapture3(TIM3);
    TIM_SetCompare3(TIM3, capture + CCR3_Val);}

    if (LedCount3 >= val3 ) {

    /* LED3 toggling */
    STM_EVAL_LEDToggle(LED3);

    LedCount3 = 0;

    /* Update CH4 OCR */
    capture = TIM_GetCapture4(TIM3);
    TIM_SetCompare4(TIM3, capture + CCR4_Val);}
}


}

Now, all the code that blinks the 4 leds is inside the interrupt handler (void TIM3_IRQHandler(void)). The 4 LEDs blink, but blink all at the same time, how can i change their frequencies to be all different?

Changing the TIM3_CK_CNT value will change the frequency of all 4, but because it's a define i cannot manipulate it through the code to change for each led.

The TIMER (TIM3) has 4 channels which all can cause an interrupt, but the interrupt handler will be the same one for all channels.

Replace your IRQ handler like this (Change the LED toggle as you wish):

void TIM3_IRQHandler(void)
{

    uint16_t capture = 0;

    if (TIM_GetITStatus(TIM3, TIM_IT_CC2)  != RESET)
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
       /* LED6 toggling */
       STM_EVAL_LEDToggle(LED6);


       /* Update CH1 OCR */
       capture = TIM_GetCapture1(TIM3);
       TIM_SetCompare1(TIM3, capture + CCR1_Val);
    } 
    else if (TIM_GetITStatus(TIM3, TIM_IT_CC1)  != RESET)
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
        /* LED5 toggling */
        STM_EVAL_LEDToggle(LED5);


        /* Update CH2 OCR */
        capture = TIM_GetCapture2(TIM3);
        TIM_SetCompare2(TIM3, capture + CCR2_Val);
    }
    else if (TIM_GetITStatus(TIM3, TIM_IT_CC3)  != RESET)
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
        /* LED4 toggling */
        STM_EVAL_LEDToggle(LED4);


        /* Update CH3 OCR */
        capture = TIM_GetCapture3(TIM3);
        TIM_SetCompare3(TIM3, capture + CCR3_Val);

    }
    else if (TIM_GetITStatus(TIM3, TIM_IT_CC4)  != RESET)
    {

        TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
        /* LED3 toggling */
        STM_EVAL_LEDToggle(LED3);


        /* Update CH4 OCR */
        capture = TIM_GetCapture4(TIM3);
        TIM_SetCompare4(TIM3, capture + CCR4_Val);

    }
}

With this change, LED will toggle with respect to each channel interrupt. ie Only one LED blinks at each interrupt. In order to Blink with different frequencies, you need to check the datasheet, how configure different frequency for different LED channel.

The code is too large to place it here.

Here is my solution: https://www.diymat.co.uk/arm-blinking-led-driver/

Any number of LEDs, any frequencies (off and on time can be different) any number of blinks (+continous) and the callbacks at the end of the sequence.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM