通过LED循环

时间:2010-11-08 22:02:33

标签: c embedded

请帮我这个代码,它让我发疯。这是一个非常简单的程序,带有8位定时器,循环通过所有8个LED(一个接一个)。我正在使用ATSTK600板。

我的定时器工作正常,我认为循环存在一些问题(当我使用avr studio-gcc调试此程序时,我可以看到所有的LED工作正如我想要的那样但当我将它传输到板上时...... LED不闪烁)。我对这种行为感到疯狂。

这是我的代码:

#include <avr/io.h>
#include <avr/interrupt.h>

volatile unsigned int intrs, i, j = 0;

void enable_ports(void);
void delay(void);

extern void __vector_23 (void) __attribute__ ((interrupt));

void enable_ports()
{
    DDRB = 0xff;

    TCCR0B = 0x03;

    TIMSK0 = 0x01;

    //TIFR0 = 0x01;

    TCNT0 = 0x00;

    //OCR0A = 61;

    intrs = 0;
}

void __vector_23 (void)
{
    for(i = 0; i<=8; i++)
    {
        while(1)
        {
            intrs++;
            if(intrs >= 61)
            {
                PORTB = (0xff<<i);
                intrs = 0;
                break;
            }

        }
    }
    PORTB = 0xff;
}

int main(void)
{
    enable_ports();
    sei();

    while(1)
    {

    }
}

4 个答案:

答案 0 :(得分:3)

您的中断程序存在缺陷。 intrs仅计算循环执行的次数,而不是其名称所暗示的计时器中断次数。该循环的61次迭代将花费很少的时间。没有示波器,你将看不到任何可感知的东西。

以下内容可能更接近您的需求:

void __vector_23 (void)
{
    intrs++;
    if(intrs > 60)
    {
        intrs = 0;
        PORTB = (0xff<<i);

        i++ ;
        if(i == 8 )
        {
            i = 0 ;
            PORTB = 0xff;
        }
    }
}

虽然在注释掉的代码中将比较寄存器OCR0A设置为61,但可以避免使用中断计数器并减少不必要的软件开销。

答案 1 :(得分:1)

  1. 您确定下载到电路板的代码未经过优化吗?
  2. 您是否已将 volatile 属性附加到PORTB标识符?
  3. 有没有办法让你减慢代码(在调试器之外)?有没有机会它运行但很快你没有看到它?
  4. 您是否可以验证您的目标代码是否正在运行(在调试器之外)?

答案 2 :(得分:0)

如果您在使用avr studio-gcc进行调试时看到了所需的行为,那么您可以确信您的程序“良好”(对某些“好”字的感觉)。所以听起来好像你需要关注一个不同的领域:你的调试环境和你的独立下载有什么区别?

在进行独立下载时,您是否知道您的程序是否正在运行?

LED是否闪烁或完全打开?您没有在您的问题中明确说出,但该问题可能与调试过程非常相关。看起来像是正确的行为,以不同的速度运行?如果是这样,那么你的程序可能没有进行调试器正在进行的某种初始化。

在进行独立下载时,与调试版本相比,是否使用不同的设置编译程序?也许编译器优化设置正在改变程序的时序特性。

(如果您提供有关独立下载正在进行的操作的更多详细信息,那么您的问题会更好。一般来说,当某些人很少或根本没有提供有关正在发生的事情的详细信息时,很难调试远程系统。所有/部分LED都亮了吗?)

答案 3 :(得分:0)

当发生中断时,处理程序非常快速计数62 * 9次并最终将PORTB设置为0x00,因此leds仅执行非常短的闪存,这是不可见的。你在sumulator中看到它只是因为它运行较慢并且不模仿快速端口切换的视觉调光效果。程序有一个设计缺陷:它试图在单个中断中完成整个闪烁周期。那是错的 - 在中断调用中只应该执行一个步骤。因此处理程序应如下所示:

void __vector_23 (void)
{
    intrs++;
    if(intrs >= 61)
    {
        PORTB = (0xff<<i);
        intrs = 0;
        i++;
        if(i>8) i = 0;
    }
}

试试这个。

中断处理程序有指导:中断处理程序应尽可能快速和短。不要在中断中执行复杂的任务(循环循环就是其中之一,如果你在中断循环,尝试删除它)。不要等待或延迟中断。