Embedded Programming (AVR)/Atmega 128A 이것저것
LED 와 Button 가지고 놀기 - (1)
유로 청년
2024. 6. 6. 13:08
6월 6일 현충일날, 쉬면서 ATmega 128 가지고 예전에 해보고 싶었던 거를 구현해 보았다.
1. 환경
- PORT F에 LED (KB-1008SR) 연결
- PORT D에 0~2핀에 버튼 연결
2. 동작
- PD 0 : 첫 번째 버튼, PD 1 : 두 번째 버튼, PD 2: 세 번째 버튼 으로 설정
- PD 0 : Low-level interrupt, PD 1 : Falling-edge interrupt, PD 2 : Rising-edge interrupt 를 각각 감지
- PD 0 버튼을 누르면 0핀부터 3핀으로 LED 빛이 accumulation 된다.
- PD 1 버튼을 누르면 7핀부터 4핀으로 LED 빛이 accumulation 된다.
- PD 2 버튼을 누르면 누적되었던 LED들이 점차 사라진다.
3. 구현 영상
4. 소스 코드
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
// Substitute Constant.
#define BUTTON_DDR DDRD
#define LED_DDR DDRF
#define LED_PORT PORTF
#define TIME 300
// Global Variable.
static uint8_t accumulation = 0x00;
static uint8_t is_it_turn_on_LED_right = 0;
static uint8_t is_it_turn_on_LED_left = 0;
// ISR (Interrupt Service Routine)
ISR(INT0_vect) {
for(int i=3; i>=0; i--) {
for(int j=0; j<=i; j++) {
LED_PORT = accumulation | (0x01<<j);
_delay_ms(TIME);
}
accumulation |= (0x01<<i);
}
is_it_turn_on_LED_right = 1;
}
ISR(INT1_vect) {
for(int i=3; i>=0; i--) {
for(int j=0; j<=i; j++) {
LED_PORT = accumulation | (0x80>>j);
_delay_ms(TIME);
}
accumulation |= (0x80>>i);
}
is_it_turn_on_LED_left = 1;
}
ISR(INT2_vect) {
for(int i=0; i<4; i++) {
for(int j=i; j>=0; j--) {
accumulation &= ~(0x01<<j | 0x80>>j);
if(j>0) {
if(is_it_turn_on_LED_right) accumulation |= (0x01<<(j-1));
if(is_it_turn_on_LED_left) accumulation |= (0x80>>(j-1));
}
LED_PORT = accumulation;
_delay_ms(TIME);
}
}
is_it_turn_on_LED_right = 0;
is_it_turn_on_LED_left = 0;
}
// Function prototype.
void init_button();
void init_LED();
// Main method
int main(void){
init_button();
init_LED();
// 전역 인터런트 활성화
sei();
// EICRA = External Interrupt Control Register A
// = INT 0 ~ 3까지의 핀에서 "어떤 Interrupt를 감지할 것인가?"를 결정
// = INT0 : Low-level, INT1 : Falling edge, INT2 : Rising edge.
// = ob0011 1000
EICRA |= (1<<ISC21 | 1<<ISC20 | 1<<ISC11);
// EIMSK = External Interrupt Mask Register
// = "어떤 핀에서 Interrupt를 감지할 것인가?"를 결정
// = ob0000 0111
EIMSK |= (1<<INT2 | 1<<INT1 | 1<<INT0);
while(1) {
}
}
// Initialization for button.
void init_button() {
// PORT D 의 0핀, 1핀, 2핀에 버튼 연결.
BUTTON_DDR &= ~(1<<DDD0 | 1<<DDD1 | 1<<DDD2);
}
// Initialization for LED.
void init_LED() {
// PORT F 에 LED 연결.
LED_DDR = 0xff;
// PORT F 에 연결된 LED 초기 설정
LED_PORT = 0x00;
}