CS/마이크로프로세서

[마이크로프로세서] ATmega 128 디지털 입출력 제어

nowkoes 2023. 10. 14. 00:00

디지털 입출력

개요

 

 지난 시간에 ATmega 128에 다양한 입출력 포트를 제어할 수 있다고 배웠었다. 이번 시간에는 범용 입출력 포트의 LED 기능을 이용해 점등해 보는 시간을 가지도록 해보자. 필자는 ATmega 128을 CPU로 장착한 JKit-128을 기준으로 설명하겠다.


본문

범용 입출력 포트

Data Memeory

 

 데이터 메모리에는 범용 레지스터 영역, I/O 레지스터 영역, 확장 I/O 레지스터 영역, SRAM 영역으로 나뉜다고 했었다. 이중 8비트의 입출력은 PA~PF 6개, 5비트의 입출력 포트는 PG 1개다. 범용으로 사용될 경우 읽기, 수정, 쓰기 기능을 수행할 수 있는데, 이는 포트를 비트 단위로 입/출력으로 자유롭게 설정 가능함을 의미한다. 이러한 기능의 제어는 I/O 레지스터로 설정한다. 

 

 

 물론 해당 제품을 설계한 개발자들이 입출력과 관련된 레지스터의 이름과 주소를 미리 지정해 놨다. 우리가 오늘 사용할 레지스터는 PORTA, DDRA, PINA다. 


입출력 제어 레지스터

 

 AVR 마이크로컨트롤러에서는 DDR 레지스터를 사용하여 핀의 작동 모드(입/출력)를 설정할 수 있다. 따라서 해당 포트를 입력으로 쓸 것인지, 출력으로 쓸 것인지 정해줘야 한다. 이를 제어하는 레지스터를 DDR(Data Direction Register)이라고 한다. DDR 레지스터에서 제어하고자 하는 핀에 대응되는 비트에 0을 쓰면 해당 핀이 입력 모드로, 1을 쓰면 출력 모드로 설정하며, 읽기/쓰기가 모두 가능하다. 

 

DDRA = 0b00001000;  // 이진수 표기법을 사용한 예
DDRA = 0x08;         // 16진수 표기법을 사용한 예

 예를 들어, 포트 A의 3번 핀을 출력으로 설정하려면 다음과 같이 코드로 표현할 수 있다. 이렇게 작성하면 포트 A의 3번 핀이 출력 모드로 설정되고, 이 핀으로 데이터를 출력할 수 있게 된다. 

 

 

 포트의 입/출력 모드를 DDR 레지스터를 이용해 설정했으면, 해당 핀으로 출력하고자 하는 데이터 값을 출력할 수 있다. 이러한 데이터 출력을 위한 레지스터PORT 레지스터다. 이 레지스터는 핀의 실제 전압 상태를 제어하며, 읽기/쓰기가 모두 가능하다. 만약 전압을 HIGH로 출력하려면 1, LOW로 출력하려면 0을 쓰면 된다. 

 

PORTA = 0b00001000 // 이진수
PORTA = 0x08 // 16진수

 PORT 레지스터 또한 DDR 레지스터처럼 값을 할당함으로써, 해당 포트의 핀들에 HIGH 혹은 LOW 상태를 2진수나 16진수로 값을 설정할 수 있다.

 

 

 마지막으로 PIN 레지스터에 대해 알아보자. PIN 레지스터핀의 현재 상태를 읽기 위해 사용되는 레지스터로, 읽기 전용의 특성을 갖고 있다. 이는 프로그래머가 PORT 레지스터를 통해 핀의 출력 상태를 설정하므로, 마이크로컨트롤러 내부에서 이 값은 이미 알고 있는 정보다. 즉, 프로그래머가 설정한 값과 핀의 실제 출력 상태는 일치해야 하므로, 별도로 출력 상태를 읽을 필요가 없기 때문이다. 또한 초기 상태가 N/A으로 정의되어 있는데, PIN 레지스터의 값이 해당 핀의 물리적인 전압 상태를 반영하며, 이는 내부 상태가 아닌 외부 환경에 의해 결정되기 때문이다. 따라서 데이터 시트에서 초기값을 명확히 지정할 수 없다.

 

 

 이 외에 디지털 입출력의 특수 기능을 사용하는 SFIOR(Special Function I/O Register)와 같은 여러 입출력 레지스터가 있다는 점까지 확인해 두자.


Bit Mask

 

 입출력 레지스터를 직접적으로 제어하는 방법은 특정한 상황에서 제약 사항을 가지고 있다. 예를 들어, AVR의 입출력 레지스터는 8비트 단위로만 접근이 가능하여, 개별 핀의 설정이 한계를 가진다. 포트 A의 3번 핀만을 출력으로 설정하고자 할 때, DDRA를 0x08로 설정하면 의도하지 않게 나머지 핀들의 설정도 변경될 수 있다. 이는 기존에 설정되어 있던 핀들이 모두 입력 상태로 전환될 수 있음을 의미한다. 또한, 이런 방식의 설정은 코드의 가독성을 저하시켜, 어떤 핀을 어떻게 설정하는지 명확히 파악하기 어렵게 만든다.

 비트 마스크(Bit Mask)는 이런 문제를 해결하기 위한 방법으로 제시된다. 비트 연산자를 사용하여 특정 비트만을 선택적으로 읽고 쓸 수 있도록 하여, 원하는 비트만 정확하게 제어할 수 있다. 이 방식은 기존의 핀 설정을 그대로 유지하면서, 특정 비트의 상태만을 변경할 수 있게 해, 더욱 정밀한 제어와 높은 가독성을 제공한다. 사용법은 다음과 같다.

 

  • 특정 비트 설정: 특정 비트를 1로 설정하려면 OR 연산을, 0으로 설정하려면 AND 연산과 NOT 연산을 활용
  • 특정 비트 토글: 특정 비트의 상태를 반전시키려면 XOR 연산 ^을 사용
  • 특정 비트 체크: 특정 비트의 상태를 확인하려면 AND 연산 사용

 

 예를 들어, PA의 3번과 5번을 출력으로 설정하고, 이 둘의 LED를 점등하고 싶으면 다음과 같이 비트 마스크를 활용하면 된다.

DDRA = DDRA | ( 1 << DDA3 ) | ( 1 << DDA5);
PORTA = PORTA | (1 << PINA3) | ( 1 << PINA5);
// PORTA = PORTA | (1 << PORTA3) | ( 1 << PORTA5);

 

 만약 여기서 PORTA의 3번 핀과 5번 핀을 소등하고 싶으면, 다음과 같이 코드를 짜면 된다.

PORTA = PORTA & ~(1 << PINA3) & ~( 1 << PINA5);
// PORTA = PORTA & ~(1 << PORTA3) & ~( 1 << PORTA5);

요약

ATmega 128 디지털 입출력 제어
1. DDR 레지스터
 a. 정의: 핀을 입/출력으로 제어할 수 있게 해주는 레지스터
 b. 특징: 1을 할당하면 출력 모드, 0을 할당하면 입력 모드
2. PORT 레지스터
 a. 정의: 핀의 전압 상태를 제어하여 데이터를 출력하는 레지스터
 b. 특징: 1을 할당하면 HIGH, 0을 할당하면 LOW
3. PIN 레지스터
 a. 정의: 핀의 현재 상태를 읽기 위한 레지스터
 b. 특징: 초깃값이 지정되어 있지 않으며(N/A), 입력만 가능
4. 비트 마스크
 a. 정의: 비트 연산자를 이용해, 특정 비트만 제어
 b. 특징: AND와 ~을 이용해 0을, OR을 이용해 1을 씀
반응형