8个LED连接到PORTB的PB0-PB7。
一个按钮连接到PD2(外部中断0)。
#include <avr/io.h>
#include <avr/interrupt.h>
#define LED_PORT PORTB
#define LED_DDR DDRB
#define BUTTON_PIN PIND
#define BUTTON_DDR DDRD
#define BUTTON_PORT PORTD
#define BUTTON PD2
volatile uint16_t speed = 100; // 初始速度(单位:ms)
volatile uint8_t timer_overflow_count = 0;
// 初始化定时器0
void init_timer0() {
TCCR0A = 0x00; // 普通模式
TCCR0B = (1 << CS02) | (1 << CS00); // 分频系数为 1024
TIMSK0 = (1 << TOIE0); // 使能溢出中断
}
// 定时器0溢出中断服务程序
ISR(TIMER0_OVF_vect) {
timer_overflow_count++;
}
// 外部中断0服务程序
ISR(INT0_vect) {
// 每次按下按钮,速度增加50ms,最大不超过500ms
speed += 50;
if (speed > 500) {
speed = 100;
}
}
// 初始化外部中断
void init_interrupt() {
EICRA |= (1 << ISC01); // 设置INT0为下降沿触发
EIMSK |= (1 << INT0); // 使能INT0中断
}
// 初始化端口
void init_ports() {
LED_DDR = 0xFF; // 设置PORTB为输出
LED_PORT = 0x00; // 初始关闭所有LED
BUTTON_DDR &= ~(1 << BUTTON); // 设置PD2为输入
BUTTON_PORT |= (1 << BUTTON); // 使能PD2上拉电阻
}
// 定时器延时函数
void delay_ms(uint16_t ms) {
uint16_t required_overflows = ms / 16; // 每个溢出大约16ms(1024分频,256计数)
timer_overflow_count = 0;
while (timer_overflow_count < required_overflows) {
// 等待溢出次数达到要求
}
}
// 流水灯效果
void flow_led() {
while (1) {
for (uint8_t i = 0; i < 8; i++) {
LED_PORT = (1 << i); // 点亮第i个LED
delay_ms(speed); // 延时
}
}
}
int main(void) {
init_ports();
init_interrupt();
init_timer0();
sei(); // 使能全局中断
flow_led();
return 0;
}
|