버튼의 연결 방식은 회로에 있어서 2가지 방식이 있다
저항 | 스위치 ON | 스위치 OFF |
---|---|---|
없음 | 1 | 플로팅 |
풀업 | 0 | 1 |
풀다운 | 1 | 0 |
ATmega128의 범용 입출력 핀은 프로그램으로 제어가 가능한 풀업 저항을 가지고 있다. 필요한 경우 프로그램을 통해 사용 여부를 설정할 수 있다.
풀업저항이 풀다운에 비해 덜 직관적이지만, 풀다운에 비해 구현이 간단하고, GND가 VCC보다 안정적인 전압을 유지하는 장점 떄문에 주로 풀업을 많이 사용한다.
GPIO 핀은 개별적으로 내부 풀업 저항의 사용 여부를 정할 수 있다.
ATmega128의 레지스터중 SFIOR(Special Funtion IO Register) 에는 전역적으로 풀업저항을 사용할 수 없도로 하는 비트가 있다.
비트 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
이름 | TSM | ACME | PUD | PSR0 | PSR321 | |||
읽기/쓰기 | R/W | R | R | R | R/W | R/W | R/W | R/W |
초기값 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
SFIOR 레지스터 구조
비트 | 번호 | 역할 |
---|---|---|
PUD(Pull-Up Disable | 2 | 0 : 풀업 사용(기본) 1 : 풀업 저항 사용 안함 |
PSRn (Prescaler Reset Timer.Counter n) | n = 1, 2 | 타이머/카운터 동작관련 비트 |
ACME(Analog Comparator Multiplexer Enable) | 0 | 비교기에서 사용하는 비트 |
TSM(Timer/Counter Synchronization Mode) | 7 |
이전에 작성되었던 LED 제어 포스터에서 처럼 PORTx의 값을 1이면 출력 0이면 입력인것을 이야기 하였다.
추가적으로 입력받은 핀에대한 정보를 저장하는 레지스터 또한 존재한다.
이는 PORT INPUT(이하 PINx)[x= A,B,...,G] 이다.
PINx는 PORTx와 DDRx와 달리 초기 값이 정해져 있지 않다.
비트 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
이름 | PINx7 | PINx6 | PINx5 | PINx4 | PINx3 | PINx2 | PINx1 | PINx0 |
읽기/쓰기 | R | R | R | R | R | R | R | R |
초기값 | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
PINA~PINF
비트 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
이름 | PING7 | PING6 | PING5 | PING4 | PING3 | PING2 | PING1 | PING0 |
읽기/쓰기 | R | R | R | R | R | R | R | R |
초기값 | 0 | 0 | 0 | N/A | N/A | N/A | N/A | N/A |
PING
즉 PINx는 현재 입력받는 핀의 비트 상태를 확인할 수 있는 명렬어인 것 이다.
버튼 이용하여 2개의 LED 제어하기#include <avr/io.h>
int main(void)
{
DDRD=~(0x03); //PB0, PB1 OUTPUT 설정
DDRB=0x0ff;
while(1){
PORTB=PIND;
}
}
버튼 이용하여 LED Shift 제어하기
#include <avr/io.h>
int main(void)
{
DDRB=0xff;
DDRD=~0x03;
int led=0x01;
while(1){
if(PIND==0x01){
while(PIND);
led>>=1;
if(led<0x01){
led=0x80;
}
}
if(PIND==0x02){
while(PIND);
led<<=1;
if(led>0x80){
led=0x01;
}
}
PORTB=led;
}
}