C 需要计时器的帮助吗
在过去的两周里,我试图学习定时器和中断,并编写了一个程序(据我所知)使ATMEGA2560上的LED闪烁,但无论我做什么,TCNT0从不递增&ISR()函数从未被调用。我哪里出了问题?我该如何解决?这是我的密码:C 需要计时器的帮助吗,c,embedded,avr,C,Embedded,Avr,在过去的两周里,我试图学习定时器和中断,并编写了一个程序(据我所知)使ATMEGA2560上的LED闪烁,但无论我做什么,TCNT0从不递增&ISR()函数从未被调用。我哪里出了问题?我该如何解决?这是我的密码: #include<avr/io.h> #include<avr/interrupt.h> #define READ_ATMEGA(ADDR) *((P_CHAR)(BASE_ADDR + ((ADDR) * ADDR_MULTIPLIER))) #define
#include<avr/io.h>
#include<avr/interrupt.h>
#define READ_ATMEGA(ADDR) *((P_CHAR)(BASE_ADDR + ((ADDR) * ADDR_MULTIPLIER)))
#define WRITE_ATMEGA(ADDR, DATA) *((P_CHAR)(BASE_ADDR + ((ADDR) * ADDR_MULTIPLIER))) = DATA
#define BASE_ADDR 0x20
void init_timer0_ovf_interrupt(void);
void timer0_interrupt_isr(void);
void initialize_ports(void);
void delay(unsigned int no_65_5ms_interrupts);
void __attribute__((ISR)) timer0_interrupt_isr(void);
//#pragma interrupt_handler timer0_interrupt_isr:24
unsigned int delay_timer;
int main(void)
{
initialize_ports();
init_timer0_ovf_interrupt();
delay(46);
return 0;
}
void initialize_ports(void)
{
READ_ATMEGA(4) = 0xff;
WRITE_ATMEGA(5, 0x00);
}
void delay(unsigned int no_65_5ms_interrupts)
{
TCNT0 = 0x00;
delay_timer = 0;
while(delay_timer <= no_65_5ms_interrupts)
{
;
}
}
void init_timer0_ovf_interrupt(void)
{
TCCR0A = 0X00;
TCCR0B = 0x02;
TIMSK0 = 0x01;
TIFR0 = 1<<0;
OCR0A = 25;
sei();
}
void timer0_interrupt_isr(void)
{
delay_timer++;
if(delay_timer >= OCR0A)
{
PORTB = ~(PORTB);
delay_timer = 0;
}
}
#包括
#包括
#定义READ_ATMEGA(ADDR)*((P_CHAR)(BASE_ADDR+((ADDR)*ADDR_乘数)))
#定义WRITE_ATMEGA(ADDR,DATA)*((P_CHAR)(BASE_ADDR+((ADDR)*ADDR_乘数))=DATA
#定义基本地址0x20
无效初始定时器0\u ovf\u中断(无效);
无效定时器0\u中断\u isr(无效);
无效初始化\u端口(无效);
无效延迟(无符号整数无65毫秒中断);
无效属性(ISR)计时器0中断ISR(无效);
//#pragma中断处理程序计时器0中断isr:24
无符号整数延时定时器;
内部主(空)
{
初始化_端口();
初始化计时器0_ovf_中断();
延误(46);
返回0;
}
无效初始化\u端口(无效)
{
READ_ATMEGA(4)=0xff;
写入_ATMEGA(5,0x00);
}
无效延迟(无符号整数无65毫秒中断)
{
TCNT0=0x00;
延时定时器=0;
while(delay_timer如果延迟函数中的while循环不起任何作用,也不会增加delay_timer,那么您将陷入一个无休止的循环中:
void delay(unsigned int no_65_5ms_interrupts)
{
TCNT0 = 0x00;
delay_timer = 0;
while(delay_timer <= no_65_5ms_interrupts)
{
; //Nothing is happening here!!
}
}
void延迟(无符号整数无65毫秒中断)
{
TCNT0=0x00;
延时定时器=0;
而(delay_timer全局变量delay_timer
在中断和非中断代码之间共享。它应该声明为volatile
,因为值可以在delay()之外更改
如果查看为delay()
生成的代码,您可能会看到,在while
循环中旋转时,没有重新读取delay\u timer的值
另外,volatile
是不够的。你有非中断代码和中断代码都在写入同一个变量(延迟计时器)。你需要在非中断代码中保护对变量的写入,那里有竞争条件。简单/懒惰的方法是禁用中断并在非中断代码中恢复它们
(至于设置中断和启动计时器,这些信息应该放在芯片的数据表中。通常这是比较容易正确的部分,而共享数据会让人感到不适。)3-4天前,我写了一个不同的程序,LED灯闪烁,但仍然不确定这是否是使用定时器和中断的正确方式。有人能看到这个并告诉我它是否正确吗?我通过读取定时器和中断的程序来写这个程序
#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint8_t intrs;
ISR(TIMER0_OVF_vect) {
/* this ISR is called when TIMER0 overflows */
intrs++;
/* strobe PORTB.5 - the LED on arduino boards */
if (intrs >= 61){
PORTB = ~PORTB;
intrs = 0;
}
}
int main(void) {
TCCR0B = 0x02;
/* Enable Timer Overflow Interrupts */
TIMSK0 = 0x01;
/* other set up */
DDRB = 0xff;
TCNT0 = 0;
intrs = 0;
/* Enable Interrupts */
sei();
while (1)
; /* empty loop */
}
#包括
#包括
挥发性uint8_t INTR;
ISR(计时器0 OVF vect){
/*当计时器0溢出时调用此ISR*/
intrs++;
/*选通端口B.5-arduino板上的LED*/
如果(整数>=61){
PORTB=~PORTB;
intrs=0;
}
}
内部主(空){
TCCR0B=0x02;
/*启用计时器溢出中断*/
TIMSK0=0x01;
/*其他设置*/
DDRB=0xff;
TCNT0=0;
intrs=0;
/*启用中断*/
sei();
而(1)
;/*空循环*/
}
如果这是正确的方法,那么我可以开始下一步的工作
谢谢FYI-要格式化一段代码,请选中它,然后单击code
按钮;这个看起来像二进制数字的按钮。我真的吓坏了,因为我必须在明天之前提交这个项目&我仍然不能完全理解计时器和中断。(这不是我必须提交的实际项目)。我必须连接LED和开关,循环LED和按下开关时…使用定时器和中断点亮适当的LED,而不使用“avr”头文件。Dan..你在帖子中说的,我仍在考虑。我不熟悉Atmega/Arduino产品,所以我不能确定,但看起来你正在设置定时器频率(TCCROB)、启用定时器中断(TIMSK0)、重置计数器(TCNT0)和启用系统中断(sei)。这应该是让计时器正常工作所必需的一切。就您的原始程序而言,我不确定为什么它不工作,因为您似乎设置了所有相同的寄存器,再加上一些。也许在您的原始程序中,timer0\u中断\u isr与计时器溢出中断没有正确关联?