通过 LED 循环
请帮助我处理这段代码,它让我发疯。这是一个非常简单的程序,带有 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)
{
}
}
Please help me with this code, it is making me crazy. This is a very simple program with 8-bit timer, cycling through all 8 leds (one-by-one). Am using ATSTK600 board.
My timers are working well, I think there is some problem with the loops (when I debug this program using avr studio-gcc, I can see all the leds working as I want but when I transfer it on board...leds don't blink). Am going crazy with this type of behavior.
Here is my code:
#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)
{
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您在使用 avr studio-gcc 进行调试时看到了您想要的行为,那么这会给您一些信心,让您相信您的程序是“好”的(对于“好”这个词的某种意义)。因此,听起来您似乎需要关注不同的领域:调试环境和独立下载之间有什么区别?
当进行独立下载时,您知道您的程序是否正在运行吗?
LED 是否闪烁或完全亮起?您没有在问题中明确说明,但该问题可能与调试过程非常相关。以不同的速度运行看起来是正确的行为吗?如果是这样,那么您的程序可能没有执行调试器正在执行的某种初始化。
进行独立下载时,与调试版本相比,程序是否使用不同的设置进行编译?也许编译器优化设置正在改变程序的时序特征。
(如果您提供有关独立下载正在执行的操作的更多详细信息,您的问题会更好。一般来说,当某人很少或根本没有有关正在发生的事情的详细信息时,他们很难调试远程系统。执行所有操作/有些 LED 灯会亮吗?)
If you're seeing the behaviour you want when debugging with avr studio-gcc, then that gives you some confidence that your program is "good" (for some sense of the word "good"). So it sounds as though you need to focus on a different area: what is the difference between your debug environment and your stand-alone download?
When doing a stand-alone download, do you know if your program is running at all?
Are the LEDs blinking, or turning on at all? You don't explicitly say in your question, but that question could be very relevant to the debugging process. Does it look like the right behaviour, running at a different speed? If so, then your program is probably not doing some sort of initialisation that the debugger was doing.
When doing a stand-alone download, is the program being compiled with different settings compared to the debug version? Perhaps compiler optimisation settings are changing your program's timing characteristics.
(Your question would be better if you gave more detail about what the stand-alone download is doing. In general, it is hard for someone to debug a remote system when they're given few or no details about what is happening. Do all/some of the LEDs turn on at all?)
你的中断例程有缺陷。
intrs
仅计算循环执行的次数,而不是顾名思义的定时器中断的次数。该循环的 61 次迭代将花费很少的时间。如果没有示波器,您将看不到任何可感知的东西。以下内容可能更接近您的需要:
尽管将比较寄存器 OCR0A 设置为 61(如注释掉的代码中所示)将避免对中断计数器的需要并减少不必要的软件开销。
Your interrupt routine is flawed.
intrs
counts only the number of times the loop has executed, not the number of timer interrupts as its name suggests. 61 iterations of that loop will take very little time. You will see nothing perceivable without an oscilloscope.The following may be closer to what you need:
Although setting the compare register OCR0A to 61 as in your commented out code would avoid the need for the interrupt counter and reduce unnecessary software overhead.
当中断发生时,处理程序很快计数 62*9 次,最后将 PORTB 设置为 0x00,因此 LED 只闪烁很短的时间,这是不可见的。您在模拟器中看到它只是因为它运行速度较慢并且不模拟快速端口切换的视觉调光效果。程序有一个设计缺陷:它试图在单个中断中完成完整的闪烁周期。这是错误的——在中断调用中只应该执行一个步骤。所以处理程序应该如下所示:
试试这个。
关于中断处理程序有一个指导原则:中断处理程序应该尽可能快和短。不要在中断中执行复杂的任务(循环循环就是其中之一,如果中断中出现循环,请尝试将其删除)。不要等待或延迟中断。
When interrupt occurs, handler very quickly counts 62*9 times and finally sets PORTB to 0x00, so leds do only very short flash which is not visible. You see it in sumulator just because it runs slower and do not emulate visual dimming effect of fast port switching. Program has a design flaw: it tries to do full blinking cycle in single interrupt. That's wrong--only a single step should be performed in interrupt call. So handler should look like this:
Try this.
There is guidelin on interrupts handlers: Interrupt handler should be as fast and short as possible. Do not perform complex tasks in interrupts (cycle loop is one of them, if you get cycle in interrupt, try to remove it). Do not wait or delay in interrupts.