c-ATmega2560-使用定时器闪烁多个按钮的LED



因此,任务是根据按下的按钮多次闪烁LED。例如,如果我们按下sw3,LED必须闪烁3秒,每隔1/4秒就会产生一次中断。

如果按下了任何按钮,有没有办法激活计时器?只要计时器在运行,按钮就不应该被读取?

我已经写了以下代码,但我不确定它是否能在实验室中工作,所以如果你们中的任何人能提供帮助,那就太好了。非常感谢。非常感谢。

#include <avr/io.h>
#include <avr/interrupt.h>
#define LEDs PORTB
#define KEYs PORTA
#define OUTPUT 0b11111111
#define INPUT  0b00000000
volatile uint8_t count = 0;
volatile uint8_t ready = 0;
volatile uint8_t seconds;
void set_up_the_timer(void);
void blink_or_flash(void);
int main(void)
{
DDRA = INPUT;
DDRB = OUTPUT;
LEDs = 0xFF;
if(!(PINA & (1 << PINA0))) {
set_up_the_timer();
sei(); 
}
while (1) 
{
switch(KEYs) {
case 0b11111110:
seconds = 7;                                        // 0.15 * 7 = 1.05s
blink_or_flash();
break;
case 0b11111101:
seconds = 13;                                       // 0.15 * 13 = 1.95s;
blink_or_flash();
break;
case 0b11111011:
seconds = 20;                                       // 0.15 * 20 = 3s;
blink_or_flash();
break;
case 0b11110111:
seconds = 27;                                       // 0.15 * 27 = 4.05s
blink_or_flash();
break;
case 0b11101111:
seconds = 33;                                       // 0.15 * 33 = 4.95s
blink_or_flash();
break;
case 0b11011111:
seconds = 40;                                       // 0.15 * 40 = 60s
blink_or_flash();
break;
case 0b10111111:
seconds = 47;                                       // 0.15 * 47 = 7.05s
blink_or_flash();
break;
case 0b01111111:
seconds = 53;                                       // 0.15 * 53 = 7.95s
blink_or_flash();
break;  
default:
break;
}
}
}

void set_up_the_timer() {
TCCR1A |= (1 << WGM12);
OCR1A = 2344;                               // an interrupt occurring every 0.15 second

TIMSK1 |= (1 << OCIE1A);
TCCR1B |= (1 << CS12) | (1 << CS10);
}
void blink_or_flash() {
if(ready == 1) {
LEDs = 0x00;
count = 0;
}
}
ISR(TIMER0_COMPA_vect) {
count++;
LEDs = ~(LEDs);
if(count >= seconds) {
ready = 1;
}
}

我不确定我对你问题的解释是否正确,但这可能会有所帮助:

// Datasheet
// https://ww1.microchip.com/downloads/en/devicedoc/atmel-2549-8-bit-avr-microcontroller-atmega640-1280-1281-2560-2561_datasheet.pdf

// Not necessary but important for calculations
#define F_CPU 16000000UL

#define HIGH 0xFF
#define LOW 0x00

#include <avr/io.h>
#include <avr/interrupt.h>
volatile unsigned char loop = 0;
volatile unsigned long counter = 0;     // Need be of type long to prevent overflow
volatile unsigned long milliseconds;    // Need be of type long to prevent overflow
void timer_setup(void);
void timer_start();
void timer_stop();
void timer_blink(void);
ISR(TIMER1_COMPA_vect)
{
PORTB = ~(PORTB);

counter++;

if(counter > milliseconds)
loop = 1;
}
int main(void)
{
// Setup PORTA to input (no pullup resitors)
// @startup alle pins on the controller are inputs,
// so setup pins as input can be omitted
DDRA = LOW;

// Setup PORTB to output and switch all LEDs on
DDRB = HIGH;
PORTB = HIGH;
timer_setup();
while (1)
{
switch(PINA) {
case 0b11111110:    milliseconds = 1005;    // 1.05s
timer_blink();
break;
case 0b11111101:    milliseconds = 1950;    // 1.95s;
timer_blink();
break;
case 0b11111011:    milliseconds = 3000;    // 3s;
timer_blink();
break;
case 0b11110111:    milliseconds = 4050;    // 4.05s
timer_blink();
break;
case 0b11101111:    milliseconds = 4950;    // 4.95s
timer_blink();
break;
case 0b11011111:    milliseconds = 60000;   // 60s
timer_blink();
break;
case 0b10111111:    milliseconds = 7005;    // 7.05
timer_blink();
break;
case 0b01111111:    milliseconds = 7950;    // 7.95
timer_blink();
break;
default:
break;
}
}
}

void timer_setup()
{
// Timer 1 (16 Bit)
// Mode: CTC
// Prescaler: 64 (will be accurate because there is no remainder @datasheet page 146)
// Compare match:            F_CPU                      16000000 Hz
//                 OCR1A = -------------------- - 1 = -------------- = 249
//                            1                          1
//                         ------- * PRESCALER        ------- * 64
//                          T_INT                     0.001 s
// Control: Compare Match Interrupt every 1 ms

OCR1A = 249;

TCCR1A = (1<<WGM12);
TIMSK1 = (1 << OCIE1A);

sei();
}
void timer_start()
{
TCNT1 = 0;
TCCR1B |= (1<<CS11) | (1<<CS10);
TCCR1B &= ~(1<<CS12);
}
void timer_stop()
{
TCCR1B &= ~((1<<CS12) | (1<<CS11) | (1<<CS10));
TCNT1 = 0;
}
void timer_blink()
{
loop = 0;
counter = 0;

timer_start();

// Wait until sequence ended
while(loop != 1)
asm volatile("NOP");

timer_stop();

// Reset LEDs
PORTB = 0x00;
}

目前我无法测试解决方案,所以可能有一些错误。。。

最新更新