UC/OS-III Systick & Периферийный таймер0 для ШИМ вмешиваться

У меня проблемы с получением сигнала PWM для светодиодов, работающих без сбоев на NXP LPC1857 с ОС uC/OS-III. Только когда я отключаю ОС, работающую на 1 мс, мерцание, которое происходит регулярно, прекращается.

Я настроил свой таймер с 4 регистрами совпадений: по одному для каждого цвета (красный, зеленый, синий) и по одному на полный период. Первые три соответствующих выхода очищают физические выходные выводы для каждого цвета. При совпадении последнего периода генерируется прерывание для установки всех трех цветовых выходов для следующего периода.

я попытался отключить прерывания от ОС во время прерывания timer0, добавив следующий код вокруг прерываний:

void TIMER0_IRQHandler(void)
{
    CPU_SR_ALLOC();
    OS_CRITICAL_ENTER();
    OSIntEnter();
    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_RED))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_RED);
        PWM_TIMER->EMR &= ~(((uint32_t) 0x01) << PWM_RED);
    }
    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_GREEN))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_GREEN);
        PWM_TIMER->EMR &= ~(((uint32_t) 0x01) << PWM_GREEN);
    }
    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_BLUE))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_BLUE);
        PWM_TIMER->EMR &= ~(((uint32_t) 0x01) << PWM_BLUE);
    }
    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_MATCH))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_MATCH);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_RED);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_GREEN);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_BLUE);
    }
    OS_CRITICAL_EXIT();
    OSIntExit();
}

У кого-нибудь есть идея, почему помада может вызвать мерцание в сигнале ШИМ?

2 ответа

Решение

Наконец нашел решение, хотя я не совсем понимаю, почему:P.

После полного удаления ОС из моих собственных задач, за исключением задачи ШИМ, проблемы все еще оставались. Поэтому я вернулся к коду таймера.

Единственное, что мне нужно было добавить, чтобы избавиться от мерцания, это сброс таймера после прерывания периода:

Старый:

if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_MATCH))
{
    Chip_TIMER_ClearMatch(PWM_TIMER, PWM_MATCH);
    PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_RED);
    PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_GREEN);
    PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_BLUE);
}

Новое:

if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_MATCH))
{
    Chip_TIMER_ClearMatch(PWM_TIMER, PWM_MATCH);
    PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_RED);
    PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_GREEN);
    PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_BLUE);
    Chip_TIMER_Reset(PWM_TIMER);
}

Может кто-нибудь объяснить, зачем нужен этот сброс?

Я ожидал, что следующая строка позаботится об этом (что входит в мою процедуру инициализации):

Chip_TIMER_ResetOnMatchEnable(PWM_TIMER, PWM_MATCH);

Вы не должны использовать OS_CRITICAL_ENTER() и OS_CRITICAL_EXIT(). Вместо этого вы должны использовать CPU_CRITICAL() и CPU_CRITICAL_EXIT(), чтобы отключить прерывания во время критической секции.

Кроме того, этот ISR не сигнализирует о какой-либо задаче, поэтому вам не нужно вызывать OSIntEnter () и OSIntExit (). Я считаю, что ваш код должен быть просто:

void TIMER0_IRQHandler(void)
{
    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_RED))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_RED);
        PWM_TIMER->EMR &= ~(((uint32_t) 0x01) << PWM_RED);
    }
    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_GREEN))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_GREEN);
        PWM_TIMER->EMR &= ~(((uint32_t) 0x01) << PWM_GREEN);
    }
    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_BLUE))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_BLUE);
        PWM_TIMER->EMR &= ~(((uint32_t) 0x01) << PWM_BLUE);
    }
    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_MATCH))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_MATCH);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_RED);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_GREEN);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_BLUE);
    }
}

джинсовый

Другие вопросы по тегам