전기전자/Atmega128

[0X02] 입력하기 기초

jemin0619 2024. 2. 10. 17:50

일단 시작하기에 앞서서 되도록 B포트를 입력으로 사용하지 말라는 것을 기억하자.

 

1. 푸시버튼으로 LED 1개 켜기

#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>
int main(void){
	DDRA = 0x01; //출력
	DDRC = ~0x01; //입력
	while (1){
		PORTA = ~PINC;
	}
}

DDRX = 0b 0000 0000

 

X에는 포트가 온다. (A,B,C,D,E,F,G) 0b는 binary, 2진수를 의미한다. 0x로 10진수 표현을 할 수도 있다.

입력으로 사용할 핀에 0을 적어준다.

ex)0번 핀을 입력으로 사용한다. 0b 1111 1110

ex)모든 핀을 입력으로 사용한다. ~0xFF

NOT 연산을 사용해 0을 1로, 1을 0으로 만들면 편하다.

 

PINX

X에는 포트가 온다. (A,B,C,D,E,F,G)

핀의 현재 상태(HIGH, LOW)를 보여준다.

우리는 스위치에 풀업 저항을 달아서 사용할 것이기에 해당 코드에서 버튼을 누르지 않았을 때의 PINC==0b0000 0001일 것이다. 눌렀을 경우엔 PINC==0b1111 1110일 것이다. 지금 이 부분을 꼭 이해해야 한다. 

 

버튼을 누르지 않았을 경우: PINC == 0b 0000 0001

버튼을 눌렀을 경우:  PINC == 0b 1111 1110

버튼을 누르면 PORTA에 0x01 신호를 주어야 하므로 PINC에 NOT 연산자를 사용한다. 이 부분을 진짜 꼭 이해해야 한다...

2. 푸시버튼 4개로 LED 4개 켜기

#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>
int main(void){
	DDRA = 0x0F; //출력
	DDRC = ~0x0F; //입력
	while (1){
		int led_on=0x00;
		int btn= ~PINC & 0x0F;
		if(btn&0x01) led_on= led_on|0x01;
		if(btn&0x02) led_on= led_on|0x02;
		if(btn&0x04) led_on= led_on|0x04;
		if(btn&0x08) led_on= led_on|0x08;
		PORTA=led_on;
	}
}

쉽지 않다. 일단 왜 0x0F와 ~0x0F를 사용했는지는 위를 참고하면서 생각하자.

led_on은 현재 LED의 상태를 나타내주는 변수이다. 

마지막에 PORTA에 led_on의 값을 넣으면서 LED를 제어한다. 

입력이 들어오지 않았을 경우에는 led_on이 0이므로 아무것도 켜지지 않는다는 것을 알 수 있다.

 

&마스킹

코드를 보면 AND(&)를 사용한 것을 볼 수 있다. 

먼저 btn에서 &를 사용한 이유는 하위 4비트의 값만을 가져오기 위함이다. 

~PINC가 0b 1111 1111 이었을 경우, &마스킹을 시행하면 0b 0000 1111로 하위 4비트의 값만을 가져올 수 있다.

이 코드에서는 상위 4비트를 사용하지 않으므로 굳이 쓸 필요는 없지만 알아두어야 한다.

 

다음으로 if문에서의 & 사용은 해당 핀의 입력이 들어왔는지 확인하기 위함이다.

예를 들어 btn == 0b 0000 1111일 때 &0x01로 마스킹을 하면 0b 0000 0001이 된다.

C언어에서는 int값이 1 이상이면 true, 아니면 false로 보기 때문에 동작한다. 

마찬가지로 btn == 0b 0000 1110일때 &0x01로 마스킹을 하면 0b 0000 0000이 된다.

이 값은 0이므로 false가 되어 if문이 동작하지 않는다. 지금 이 부분이 굉장히 중요하다. 

 

| (OR) 연산

코드를 보면 OR( | )를 사용한 것을 볼 수 있다. 

예를 들어 PORTA에 0b 0000 0001을 넣고, 0b 0000 0010을 넣었을 경우 0번 핀의 LED가 꺼지게 된다. 지금은 여러 버튼을 누르면 해당하는 LED가 켜져야 하기 때문에 이러면 안된다. 이 점을 해결하기 위해 OR 연산자를 사용해 0b 0000 0001에 0b 0000 0010이 들어왔을 때 0b 0000 0011이 되어 0번과 1번 핀의 LED를 모두 켤 수 있다.