简体   繁体   English

带有计时器的STM32闪烁LED

[英]STM32 Blinking LEDs with a Timer

I'm trying to blink 4 LEDs with a Timer Interrupt, at different frequencies. 我正在尝试使用计时器中断以不同的频率闪烁4个LED。

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)). 现在,所有使4个LED闪烁的代码都在中断处理程序内(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? 4个LED闪烁,但同时全部闪烁,如何更改它们的频率以使其完全不同?

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. 更改TIM3_CK_CNT值将更改所有4的频率,但是由于这是一个定义,因此我无法通过代码来操纵它以更改每个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. TIMER(TIM3)有4个通道,所有通道均可引起中断,但所有通道的中断处理程序都相同。

Replace your IRQ handler like this (Change the LED toggle as you wish): 像这样替换您的IRQ处理程序(根据需要更改LED切换开关):

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. 进行此更改后,LED将针对每个通道中断进行切换。 ie Only one LED blinks at each interrupt. 即每个中断只有一个LED闪烁。 In order to Blink with different frequencies, you need to check the datasheet, how configure different frequency for different LED channel. 为了以不同的频率闪烁,您需要查看数据表,如何为不同的LED通道配置不同的频率。

The code is too large to place it here. 代码太大,无法在此处放置。

Here is my solution: https://www.diymat.co.uk/arm-blinking-led-driver/ 这是我的解决方案: 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. 任何数量的LED,任何频率(关闭和打开时间可以不同),任何数量的闪烁(+连续)和序列结束时的回调。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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