STM32 Мигающие светодиоды с таймером - PullRequest
0 голосов
/ 26 апреля 2018

Я пытаюсь мигать 4 светодиода с прерыванием по таймеру на разных частотах.

Я придумал этот код

/*********** 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);}
}


}

Теперь весь код, который мигает 4 светодиода, находится внутри обработчика прерываний (void TIM3_IRQHandler (void)). 4 светодиода мигают, но мигают все одновременно, как я могу изменить их частоты на разные?

Изменение значения TIM3_CK_CNT изменит частоту всех 4, но, поскольку это определение, я не могу манипулировать им через код для изменения каждого светодиода.

TIMER (TIM3) имеет 4 канала, которые могут вызывать прерывание, но обработчик прерываний будет одинаковым для всех каналов.

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

Код слишком велик, чтобы разместить его здесь.

Вот мое решение: https://www.diymat.co.uk/arm-blinking-led-driver/

Любое количество светодиодов, любые частоты (время выключения и включения могут быть разными), любое количество миганий (+ непрерывный) и обратных вызовов в конце последовательности.

0 голосов
/ 26 апреля 2018

Замените ваш обработчик 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);

    }
}

С этим изменением светодиод будет переключаться относительно каждого прерывания канала. Т.е. только один светодиод мигает при каждом прерывании. Для того, чтобы мигать с разными частотами, вам необходимо проверить таблицу данных, как настроить разные частоты для разных светодиодных каналов.

...