|
|
atmega8多個(gè)按鍵控制多個(gè)LED
#include <iom8v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
// 按鍵和LED定義
#define KEY_PORT PIND
#define LED_PORT PORTC
#define DEBOUNCE_DELAY 10 // 消抖時(shí)間10ms
#define SLEEP_DELAY 5000 // 5秒無(wú)操作進(jìn)入睡眠
// 延時(shí)函數(shù)
void delay_ms(uint ms) {
uint i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 114; j++); // 約1ms@8MHz
}
// 初始化外部中斷(用于喚醒睡眠)
void wakeup_init(void) {
// 配置INT0~INT2(PD0~PD2)為下降沿觸發(fā)
MCUCR |= (1 << 1) | (1 << 3); // ISC01=1(INT0下降沿), ISC11=1(INT1下降沿)
MCUCSR &= ~(1 << 6); // ISC21=0(INT2下降沿)
GICR |= (1 << 6) | (1 << 7) | (1 << 5); // 使能INT0、INT1、INT2中斷
}
// 進(jìn)入睡眠模式(空閑模式):通過機(jī)器碼直接執(zhí)行sleep指令
void enter_sleep(void) {
// 配置為空閑模式(SM1=0, SM0=0)并允許睡眠(SE=1)
MCUCR &= ~((1 << 1) | (1 << 0)); // 空閑模式
MCUCR |= (1 << 7); // 允許睡眠
// 寫入sleep指令的機(jī)器碼(0x94, 0x8F是AVR sleep指令的16位機(jī)器碼)
*(volatile unsigned short *)0x0000 = 0x948F;
}
// 外部中斷服務(wù)程序(僅用于喚醒)
#pragma interrupt_handler ext_int0_isr:2
void ext_int0_isr(void) {}
#pragma interrupt_handler ext_int1_isr:3
void ext_int1_isr(void) {}
#pragma interrupt_handler ext_int2_isr:4
void ext_int2_isr(void) {}
void main(void) {
uchar i;
uchar key_flag[5] = {0};
uchar key_last[5];
uchar led_state = 0xFF;
uint idle_cnt = 0; // 空閑計(jì)數(shù)器
// 配置IO口
DDRD &= ~0x1F; // PD0~PD4輸入
PORTD |= 0x1F; // 使能上拉
DDRC |= 0x1F; // PC0~PC4輸出
LED_PORT = led_state;
// 初始化按鍵狀態(tài)
for(i = 0; i < 5; i++) {
key_last[i] = (KEY_PORT & BIT(i)) ? 1 : 0;
}
// 初始化喚醒中斷和全局中斷
wakeup_init();
SREG |= (1 << 7); // 使能全局中斷
while(1) {
uchar key_activity = 0; // 按鍵活動(dòng)標(biāo)記
// 按鍵檢測(cè)邏輯
for(i = 0; i < 5; i++) {
uchar key_current = (KEY_PORT & BIT(i)) ? 1 : 0;
if(key_current == 0 && key_last[i] == 1) { // 按下邊緣
delay_ms(DEBOUNCE_DELAY);
if((KEY_PORT & BIT(i)) == 0 && key_flag[i] == 0) {
led_state ^= BIT(i);
LED_PORT = led_state;
key_flag[i] = 1;
key_activity = 1;
}
} else if(key_current == 1 && key_last[i] == 0) { // 釋放邊緣
delay_ms(DEBOUNCE_DELAY);
if((KEY_PORT & BIT(i)) != 0) {
key_flag[i] = 0;
key_activity = 1;
}
}
key_last[i] = key_current;
}
// 無(wú)活動(dòng)時(shí)進(jìn)入睡眠
if(key_activity) {
idle_cnt = 0;
} else {
idle_cnt++;
if(idle_cnt >= SLEEP_DELAY) {
enter_sleep(); // 進(jìn)入睡眠,等待按鍵喚醒
idle_cnt = 0;
}
}
delay_ms(1); // 計(jì)數(shù)基準(zhǔn)
}
}
|
|