반응형


아트멜사의 모든 AVR 마이크로컨트롤러의 포트들은 범용 디지털 입출력 포트로 사용되어질 때 Read-Modify-Write 기능이 있다. 이 기능은 다른 핀들의 값을 수정하지 않고 포트의 특정 핀만 수정할 수 있도록 한다.


다른 핀들의 방향에 영향을 주지 않고 한 포트 핀의 방향을 바꿀 수 있다.


핀이 출력으로 설정되었다면 다른 핀들에 영향을 주지 않고 출력 값을 HIGH/LOW로 변경할 수 있으며, 핀이 입력으로 설정되었다면 다른 핀들에 영향을 주지 않고 풀업 레지스터를 활성화/비활성화 할 수 있다.


각 출력 버퍼는 싱크와 소스가 대칭적인 드라이브 특성을 갖는다.  싱크와 소스 전류 모두 40mA로 대칭적이다. 양쪽 다 흐르는 전류는 LED를 켤 수 있을 정도로 충분하다.


아래 회로에서 PD0핀에 Low 전압 레벨을 출력하면 5V 전원으로부터 핀으로 전류가 흐르게 되어 LED가 켜지게 된다.(싱크)


아래 회로에서 PD0핀에 High 전압 레벨을 출력하면 핀에서 전류가 나와 GND로 흐르면서 LED가 켜지게 된다.(소스)


모든 포트의 핀들은 개별적으로 선택 가능한 풀업 레지스터(RPU)를 가지고 있다.

공급전압에 변함없는 일정한 크기의 저항 크기를 가진다.(?)


모든 입출력 핀에는 VCC와 Ground에 각각 보호 다이오드가 달려있다.



이번 장에서 참조하는 모든 레지스터와 비트는 일반적인 형태로 작성된다.

소문자 “x”는 포트에 대한 분류문자를 의미하며, 소문자 “n”은 비트 숫자를 의미한다.

예를 들어 PORTB3은 포트 B의 세 번째 비트를 의미하는데 본 문서에서는 PORTxn으로 기술된다.


각 포트에는 세 개의 입출력 메모리 주소 위치가 할당되어 있다.

데이터 레지스터 PORTx

데이터 방향 레지스터 DDRx

포트 입력 핀 PINx


데이터 레지스터 PORTx와 데이터 방향 레지스터 DDRx는 읽기/쓰기가 가능한데 반에 포트  입력 레지스터 PINx는 읽기 전용이다.


SFIOR 레지스터에 있는 풀업 비활성(PUD) 비트는 1로 설정되면 모든 포트의 모든 핀에 대해 풀업 기능을 비활성화 한다.


대부분의 포트 핀들은 범용 디지털 입출력 기능 외에  부가 기능을 가진다. 부가 기능에 대한 상세한 설명은 개별적인 모듈 섹션을 보면 된다. 일부 포트 핀의 부가 기능을 활성화하는 것이 범용 디지털 입출력으로써 포트의 다른 핀을 사용하는데 영향을 주지 않는다.



범용 디지털 입출력으로써 포트


포트는 내부 풀업 저항을 선택할 수 있는 양방향 입출력 포트이다.


Configuring the Pin


각 포트 핀은 3개의 레지스터 비트로 구성된다 : DDxn, PORTxn, PINxn

DDxn 비트는 DDRx 입출력 주소에서 접근되어 지고, PORTxn비트는 PORTx 입출력 주소에서 접근되어 지며, PINxn 비트는 PINx 입출력 주소에서 접근되어 진다.


DDRx 레지스터의 DDxn 비트는 핀의 방향을 선택한다. 만약 DDxn이 1로 설정되면, 핀은 출력핀으로 설정된다. DDxn이 0으로 설정되면, 핀은 입력핀으로 설정된다.


핀이 입력 핀으로 설정되어 있을 때, PORTxn을 1로 설정되면 풀업 레지스터가 활성화 된다.풀업 저항을 사용하지 않기 위해서는 핀이 입력핀으로 설정되어 있을 때 PORTxn이 0으로 설정되거나 핀이 출력핀으로 설정되면 된다.


리셋 상태가 활성화 될 때 클록이 동작하고 있지 않음에도 포트핀은 Tri-State이다.

(디지털 회로에는 0과 1 그리고 아주 높은 저항을 가지는 하이 임피던스(High Impedance) 상태가 있다. 세 번째 상태는 전선이 끊져서 전기가 통하지 않는 상태라고 생각하면 되는데 tri-state라고 부른다. )


핀이 출력으로 설정되었을 때 PORTxn에 1을 기록하면, 포트 핀은 HIGH 전압 레벨을 가지게 된다.  핀이 출력으로 설정되었을 때, PORTxn에 0을 기록하면, 포트 핀은 LOW 전압 레벨을 가지게 된다.

tri-state({DDxn, PORTxn} = 0b00)와 HIGH 출력({DDxn, PORTxn} = 0b11)간에 핀의 상태가 변할 때, 중간 상태로 풀업 레지스터 가능({DDxn, PORTxn} = 0b01)이나 LOW 출력({DDxn, PORTxn} = 0b10)이 반드시 발생한다.


보통, 풀업 레지스터 가능 상태는 허용될 수 있다. 하이-임피던스 환경에서는 HIGH 출력 상태와 풀업 레지스터 가능 상태 사이의 차이를 알지 못할 것이기 때문이다(?)


이 경우가 아니라면 SFIOR 레지스터의 PUD 비트를 1로 기록함으로써 모든 포트의 풀업 저항을 비활성화 할 수 있다.


입력과 풀업저항 가능 간에 상태가 변할 때, LOW 출력이 발생하는 문제가 생긴다.   사용자는 중간 단계로써 tri-state 또는 HIGH 출력상태를 반드시 사용해야 한다.




핀의 값 읽기


데이터 방향 비트 DDxn의 설정에 관계없이, 포트 핀의 값을 PINxn 레지스터 비트를 통해 읽을 수 있다.



PINxn 레지스터 비트와 앞에 있는 래치회로가 동기장치를 구성한다.


동기 장치는 내부 클록의 가장자리 근처에서 물리적 핀이 값을 바꿀 때 metastability를 피하기 위해 필요하다. 하지만 딜레이를 야기한다. ( metastability는 출력이 0이 될지 1이 될지 알 수 없는 상태를 의미한다.  )





연결되어 있지 않은 핀


핀이 사용되지 않을 때, 핀들이 정의된 레벨을 갖도록 하는 것이 좋다.

딥 슬립모드에서 대부분의 디지털 입력이 비활성화된다 할지라도, 디지털 출력이 가능한 다른 모드에서 소비 전류를 줄이기 위해 레벨이 정의되지 않은 입력핀은 피해야 한다. (Reset, Active mode and Idle mode)


사용하지 않은 핀의 정의된 레벨을 보장하기 위한 간단한 방법은, 내부 풀업 저항을 사용하도록 하는 것이다. 이 경우, 리셋동안에는 풀업 저항이 비활성화 될 것이다.


리셋동안에 저전력 소모가 중요하다면, 외부 풀업 또는 풀다운 저항을 사용하는 것이 좋다.


사용하지 않는 핀을 직접 VCC 또는 GND에 연결하는 것은 추천하지 않는다. 뜻하지 않게 출력으로 핀이 설정된다면 과도한 전류를 누출을 유발하기 때문이다.




Special Function IO Register – SFIOR


● Bit 2 – PUD: Pull-up disable

이 비트를 1로 설정한다면 입출력 포트의 풀업 저항이 비활성화된다.  DDxn과 PORTxn 레지스터에서 풀업 저항을 사용하도록 설정한다 할지라도 비활성화 된다. ({DDxn, PORTxn} = 0b01)





아래처럼 회로를 구성하고 두가지 소스코드를 테스트 해본다..





1. PORTB4에 연결된 LED가 깜빡이게 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * LED.c
 *
 * Created: 2016-06-15 
 * Author : webnautes
 */ 
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
 
 
int main(void)
{
    DDRB |= (1<<DDB4);
    
    while (1
    {
        PORTB |= (1<<PB4);
        _delay_ms(1000);
 
        PORTB &= ~(1<<PB4);
        _delay_ms(1000);
    }
}
 
 
cs



2. 스위치를 누르면 LED가 켜진다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * BUTTON.c
 *
 * Created: 2016-06-15
 * Author : webnautes
 */ 
 #define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
 
 
int main(void)
{
    DDRB |= (1<<DDB4); //핀을 출력용으로 설정
    DDRC &= ~(1<<DDC5);//핀을 입력용으로 설정
    
    while (1
    {
        if ( PINC & ( 1<<PINC5 ) )//버튼이 눌러졌다면
            PORTB |= (1<<PB4);//LED를 켠다.
        else //아니면
            PORTB &= ~(1<<PB4);//LED를 끈다.
    }
}
 
 
cs


문제 발생시 지나치지 마시고 댓글 남겨주시면 가능한 빨리 답장드립니다.


제가 쓴 책도 한번 검토해보세요 ^^

+ Recent posts