uC/OS-III 用于 PWM 干扰的 Systick 和外设定时器 0
uC/OS-III Systick & Peripheral timer0 for PWM interfere
我无法在 NXP LPC1857 运行 uC/OS-III 上顺利获取 LED 运行 的 PWM 信号。只有当我在 1 毫秒禁用 OS 系统杆 运行 时,经常发生的闪烁才会停止。
我已经为我的计时器设置了 4 个匹配寄存器,一个用于每种颜色(红色、绿色、蓝色),一个用于整个周期。前三个匹配输出正在清除每种颜色的物理输出引脚。最后一个 周期匹配 生成中断以设置下一个周期的所有三种颜色输出。
我试图在 timer0 中断期间通过在中断周围添加以下代码来禁用来自 OS 的中断:
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();
}
有谁知道为什么 systick 会导致 PWM 信号闪烁?
您不应使用 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);
}
}
让
终于找到了解决办法,虽然我不完全明白为什么:P.
从我自己的任务中完全剥离 OS 之后,除了 PWM 任务之外,问题仍然存在。所以我转回定时器代码。
为了消除闪烁,我唯一需要添加的是在我收到周期中断后重置计时器:
旧:
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);
我无法在 NXP LPC1857 运行 uC/OS-III 上顺利获取 LED 运行 的 PWM 信号。只有当我在 1 毫秒禁用 OS 系统杆 运行 时,经常发生的闪烁才会停止。
我已经为我的计时器设置了 4 个匹配寄存器,一个用于每种颜色(红色、绿色、蓝色),一个用于整个周期。前三个匹配输出正在清除每种颜色的物理输出引脚。最后一个 周期匹配 生成中断以设置下一个周期的所有三种颜色输出。
我试图在 timer0 中断期间通过在中断周围添加以下代码来禁用来自 OS 的中断:
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();
}
有谁知道为什么 systick 会导致 PWM 信号闪烁?
您不应使用 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);
}
}
让
终于找到了解决办法,虽然我不完全明白为什么:P.
从我自己的任务中完全剥离 OS 之后,除了 PWM 任务之外,问题仍然存在。所以我转回定时器代码。
为了消除闪烁,我唯一需要添加的是在我收到周期中断后重置计时器:
旧:
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);