使用 ATMEL 2549 微控制器的秒表

Stopwatch using a ATMEL 2549 Microcontroller

我正在尝试理解一个程序,但我有一些问题,也许你可以帮助我。使用的微控制器是 ATMEL 2549 - 8 位。提前谢谢你。

Atmel-2549 8-bit AVR Microcontroller ATmega640 1280-1281-2560-2561 datasheet

Set up a stop watch with the following features:

• There are three push buttons: START, STOP, and RESET

• Your system generates an interrupt every 100ms by using Timer1.

• There is an LCD at port A. Use the usual library for controlling the LCD!

• On the LCD, you display the time that has elapsed since the START button was pushed. Show minutes, seconds and tenth of seconds.

• After 59 min 59.9 s, the display starts from scratch again.

#include <stdint.h>
#include <avr/io.h>
#include "lcd.h"
#include <stdio.h>
#include <avr/interrupt.h>

void timer1_config(void);
void exinterrupt_config(void);
void send_string(void);

display myLCD;
volatile char text[20];
volatile uint8_t minute=0,sekunde=0,zehnt=0;

ISR(TIMER1_COMPA_vect) {     //Interrupt for a timer with minute, second and decisecond.
  zehnt++;                   //from 0 to 59min 59,9sec. After that time is elapsed,
  if (zehnt>9) {             //it should be showed on LCD display.
    zehnt=0;
    sekunde=sekunde+1;
  } 
  if (sekunde>59) {
    sekunde=0;
    minute=minute+1;
  }
  if (minute>59) {
    minute=0;
    sekunde=0;
    zehnt=zehnt+1;
  }
  send_string();
}

ISR(INT0_vect) {             //Interrupt for starting the timer.
  // --- No. *1 ---
  TCCR1B|= (1<<CS11);
}

ISR(INT1_vect) {             //Interrupt for stopping the timer.
  TCCR1B&=~((1<<CS10)|(1<<CS11)|(1<<CS12));
}

ISR(INT2_vect) {             //Interrupt for resetting the timer.
  minute=0;                  //Sets everything to 0 and shows time on LCD display.
  sekunde=0;
  zehnt=0;
  TCNT1=0;
  send_string();
}

int main(void) {

  // --- No. *2 ---
  DDRD&=~((1<<PIN0)|(1<<PIN1)|(1<<PIN2));

  timer1_config();            //Load all three functions.
  exinterrupt_config();
  send_string();

  lcd_init(&myLCD ,&PORTA);   //Start the LCD display on port A.
  lcd_send_string(&myLCD,"-------Watch-------",1,1);

  sei();

  for(;;){};

  return(0);
}

void timer1_config(void){
  TCCR1B|=(1<<WGM12);
  OCR1A=12499;
  // --- No. *3 ---
  TIMSK1|=(1<<OCIE1A);
}

void exinterrupt_config(void){
  EIMSK|=((1<<INT0)|(1<<INT1)|(1<<INT2));       //Enable all 3 interrupts.
  // --- No. *4 ---
  EICRA|=((1<<ISC01)|(1<<ISC11)|(1<<ISC21));
}

void send_string(void){                       //Sends text to LCD display.
  sprintf(text,"%i.min %i.sek %i.zehnt",minute,sekunde,zehnt);  
  lcd_send_string(&myLCD,text,3,1);
}

再次感谢!

1:将 CS11 设置为高电平

Table17-6开始,它确实将时钟设置为clk(I/O)/8。这意味着它将在内部 I/O 时钟的每八个滴答声中增加内部计数器。也许你无法在一秒钟内计算定时器寄存器中的每个滴答声,所以你需要对其进行预缩放。

2:将 DDRD 位设置为输入

那些是按钮。这些按钮必须位于面板的 PIND 上,每个按钮一位。虽然程序不读取PIND,但外部中断处理程序会读取,因此数据方向必须相应设置。

按钮、开关是输入,LED是输出。这取决于您的开发人员面板,它们连接了哪些端口。

3:设置TIMSK1

§17.11.36

• Bit 1 – OCIEnA: Timer/Countern, Output Compare A Match Interrupt Enable When this bit is written to one, and the I-flag in the Status Register is set (interrupts globally enabled), the Timer/Countern Output Compare A Match interrupt is enabled. The corresponding Interrupt Vector (see “Interrupts” on page 101) is executed when the OCFnA Flag, located in TIFRn, is set.

定时器外设可以在不同模式下运行。此设置与输出比较模式有关,当定时器的内部计数器达到限制(限制在 OCR1A 中设置)时,它会告诉硬件发出中断。

定时器在 TCCR1B (Table 17-2) 中设置为 CTC (Clear Timer on Compare) 模式,因此当达到限制时它会重新开始计数。

4:下降沿

下降沿是指信号从高变为低。上升沿是信号从低到高的时候。这些按钮通常为低电平有效,因此下降沿表示按钮已按下。 (上升沿表示按钮被释放)