- I/O Port 란?
- Register 란?
- Register 사이의 Data 전달과 I/O Operation
- Microprocessor I/O Port와 Input/Output Operation
- Programmable I/O Port와 Input/Output Operation
- ATmega2560 I/O Port 개요
- ATMega2560 I/O Ports의 특징
- AVR port architecture
- Port Pin 구성(Input/Output Port 설정과 설정에 따른 Pin 상태)과 부가 기능
- Inpout/Output Port로 사용하기 위한 설정과 동작
- Port 이용 프로그램 작성시 고려 할 사항과 Coding 예
- LED Interfacing
- Switch Interfacing
- ATmega2560 Input/Output Port(Push Button Switch 와 LED) 프로그램 예
- AVR I/O port programming(Push Button Switch 와 LED) 예:
- SW를 사용하여 LED의 회전 방향을 제어 하는 프로그램 예:
- SW를 사용하여 LED의 회전 방향을 제어 하는 C++ 프로그램 예:
- OR, AND Function를 이용하여 LED를 On(Set), Off(Clear) 하는 프로그램 예:
- XOR Function를 이용하여 LED를 Toggle 하는 프로그램 예:
- I/O Port의 이해와 프로그래밍: Switch, LED 관련 페이지 보기
- 10개의 8비트 양방향 병렬 I/O 포트(PORTA~F,H,J,K,L)
- 1개의6비트 양방향 병렬 I/O 포트(PORTG)
- 각 PORT별 3개 I/O 레지스터:Data Rgister, Data Direction Register, Input Pins Register
- DDR(Data Direct Register) : 해당 Pin(Port)을 입력 Rg의 입력으로 사용 할지, 출력 Port의 출력 Pin으로 사용 할지를 결정
- PORT(Data Register) : 데이터 출력 Port Rg
- PIN(Port Input Pins Register) : 입력 핀에 연결된 Input Port Rg
- DDR, PORT : 읽기/쓰기 가능, PIN : 읽기만 가능
- 이 자료에서 I/O Port Rg 설명에 사용 하는 표기 방법
- PORTxn와 같이 표기 하는 경우 x는 PORT의 순서를 표시 하는 문자 이다. 예: A, B, C ... , L
- n은 Bit 번호를 표시 한다.
- 예: PORTB3은 PORT B의 3번 Bit를 표시 한다.
- 특징
- 최대 40mA 구동 전류
- LED 1개 구동 가능
- 선택 가능한 Pull Up 저항(20K – 100K Ohm) 내장
- Vcc, GND 사이에 입력단 보호 Diode 내장
- Read-Modified-Write Cycle 지원
- 다른 pin에 영향을 주지 않고 한 port 핀의 방향을 바꿀 수 있음
- DDRD &= (~0x03); // Input Port : PD0, PD1
- DDRL |= 0x03; // Output Port : PL0, PL1
- 모든 Port는 다음과 같은 특성을 갖는다.
- Bit-selectable pull-up resistors
- Bit-selectable tri-state outputs
- Schmitt trigger input
- Synchronized to the system clock : 입력신호의 안정성에 기여(Pin Read Operation 시 1.5Cycle 이전에 Pin 신호가 안정화 되어야 함)
- 같은 port에 write한 다음 바로 read 시 nop instruction 필요(1,5Cycle Delay) : __no_operation();
- Symmetrical DC drive capability
- PINxn에 1(High)을 Write 하면 대응 되는 Data Rg(PORTxn)의 Bit 가 Toggle 된다.
- Pull-up Disable: MCUCR Rg의 PUD Bit가 Set(1) 되면 모든 Port의 Pull-up 기능이 Disable 된다.
- 대부분의 Pin은 I/O Port 이외의 다른 기능(예: Timer I/O Pin, Interrupt Pin, 각종 통신 장치의 I/O Pin 등) 으로 사용(Miltiplexed) 될 수 있다.
- 아래 그림은 각 Port(소문자 x는 A - L 까지 Port를 표시 한다.)의 1 Bit 회로도 이다.
- 각 PORT는 다음과 같은 기능을 갖는 3개의 Rg을 갖는다.
- DDR(Data Direct Register) : 해당 Port의 각 Pin을 입력 Pin으로 사용(Input Port) 할지, 출력 Pin으로 사용(Output Port)할지를 설정 하는데 사용 하는 Rg.
- PORT(Data Register) : Microprocessor 내부 Rg로 부터 Data를 받아 외부 Interface 회로에 Data를 출력 하는 Rg(Output Port)
- PIN(Port Input Pins Register) : 입력 핀으로 부터 Data를 받아 Input 명령이 실행 될 때 Microprocessor 내부 Rg에 Data를 전달 하는 Rg(Input Port)
- 아래 그림은 Port A을 구성 하는 3개 Rg(PORTA, DDRA, PINA)의 구성과 기능을 보여 주는 예 이다.
- Port A 부터 Port L(Port G Rg는 6 Bit 구조 임) 까지 11개 Rg 가 모두 같은 구성과 기능을 같는다.
- PORTA와 DDRA Rg는 Rg에 저장된 내용을 읽거나(Read) 새로운 Data를 쓸(Write) 수 있다.
- PINA Rg는 읽기(Read Operation)만 가능 하고, Data를 쓸(Write) 수 없다.
- Reset 시 PORTA와 DDRA Rg는 0로 초기화 된다. 그러나 PINA Rg는 초기화 할 수 없다.
- I/O Port 보호 회로와 Pull-up Resistor
- Protection diodes: 입력 회로에 원하지 않은 높은(or 낮은) 전압이 인가 되는 경우 입력 I/O Port 회로를 보호 하기 위한 Diode 이다.
- Pin에 (Vcc + 0.7V) 보다 높은 전압이 인가 된 경우 D1이 On 상태로 되어 Vin 전압이 (Vcc + 0.7V) 이상 높아 지지 않도록 한다.
- Pin에 (GND - 0.7V) 보다 낮은 전압이 인가 된 경우 D2가 On 상태로 되어 Vin 전압이 (GND - 0.7V) 보다 낮아 지지 않도록 한다.
- 위 결과 Pin에 인가 되는 전압이 과도하게 높아 지거나 낮아 지지 않도록 하여 I/O Port 회로를 보호 한다.
- Programmable pull-up resistor
- FET Switch가 On 인 경우: FET Switch가 On 상태가 되면 Pull-up resistor를 통하여 Pin 외부에 연결된 Switch 가 Pull-up 상태(외부 Switch 가 Open 인 경우 Pin 전압은 High가 되고, Switch 가 Closed 상태 인 경우 Pin 전압이 Low가 된다.)가 된다.
- FET Switch가 Off 인 경우: FET Switch와 Pull-up resistor 회로는 Open 상태가 되어 Pin 전압에 영향을 미치지 않는다.
- DDRxn과 PORTxn, PUD(MCUCR Rg)에 따른 Port Pin 구성과 상태.
- Pull-up disable Bit(PUD): I/O Port의 Pull-up 기능을 제어(Enable or Disable 상태로 설정) 하는 Bit 이다.
- PUD Bit가 0 이고, DDRx의 해당 Bit가 0, PORTx 의 해당 Bit가 1 이면 I/O Port의 Pull-up 기능을 Enable 상태(윗 1 Bit 회로도의 FET Switch 가 Closed 상태)로 설정 된다.
- PUD Bit가 1 이면, DDRx와 PORTx 의 상태에 상관 없이 I/O Port의 Pull-up 기능은 Disable 상태(윗 1 Bit 회로도의 FET Switch 가 Open 된 상태)로 설정 된다.
- PUD: I/O Port의 Pull-up 기능을 제어(Enable or Disable 상태로 설정) 하는 Bit 이다.
- PUD를 1로 설정 하면 모든 I/O Port의 Pull-up이 Disable 상태로 설정 된다.
- PUD를 0로 설정 하면 각 I/O Port의 DDxn 과 PORTxn 의 설정에 따라 원하는 Bit의 Pull-up을 Enable 상태로 설정 할 수 있다.
- DDxn = 0, PORTxn = 1로 설정되어도 PUD bit가 우선함
- I/O Port의 Pin은 I/O Port 기능 이외에 부가 기능 갖고 있다.
- Microcontroller chip과 외부 장치를 연결 하는 Pin의 수가 제한 되어 있기 때문에 하나의 Pin에 2 가지 이상의 기능을 부여 한다.
- PORTB의 7번 Bit(PB7)의 예를 보면 이 Pin은 OC0A/OC1C/PCINT7(Timer/Counter0의 Output Compare A와 PWM Output A, Timer/Counter1의 Output Compare C와 PWM Output C, Pin Change Interrupt 7) 출력 Pin으로 사용 된다.
- Pin의 기능 설정은 각 장치의 기능을 제어 하는 Control Rg의 설정에 의하여 결정 되기 때문에 여기에서는 생략 한다. 추가 정보가 필요한 사람은 ATmega2560 Datasheet을 참고 하기 바람.
MCU Control Register
Port Pin Configurations
Embedded computer chip은 물리적(Chip 크기와 Pin 수)인 제약 때문에 외부로 연결되는 Pin 수가 제한 된다.
그러므로, 이 문제를 해결 하기 위하여 하나의 Pin을 다른 목적(부가 기능)으로 사용 할 수 있도록 설계 되었다.
- Output Port로 사용하기 위한 설정과 동작
- Output Port로 사용 하고자 하는 Port의 DDR Rg에 1을 Write 하여 해당 Port를 Output Port로 설정 한다.
- Output Port에 Data를 출력 한다.
- PL0(Port L의 0번 Bit)를 Output Port로 설정 하고 PL0에 1을 출력 하는 Coding 예
- Input Port로 사용하기 위한 설정과 동작
- Input Port로 사용 하고자 하는 Port의 DDR Rg에 0을 Write 하여 해당 Port를 Input Port로 설정 한다.
- Input Port(PIN)으로 부터 Data를 입력 받는다.
- PD0(Port D의 0번 Bit)를 Input Port로 설정 하고 PIND의 0번 Bit의 Data를 입력 받아 PL0에 출력하는 Coding 예
- Pull-up Resistor 사용을 위한 설정
- Pull-up Resistor는 Switch 등을 연결하는 경우 외부에서 부가되는 회로를 최소화 하기 위한 것 이다. 아래 Switch Interfacing Circuit 예를 참고 할 것.
- 윗 회로에서 Pull-up Resistor를 Active 상태로 하는 FET Switch를 Turn On 상태로 하기 위한 조건은 PUD이 0이고, DDRx Rg의 값이 0, PORTx의 값이 1 인 상태 이다.
- PD0(Port D의 0번째 Bit)에 Push Button Switch를 연결 하고 이 SW의 상태를 읽어 PL0에 출력 하는 Coding 예
DDRL |= 0x01; // PL0를 Output Port로 설정 한다. DDRL의 0번째 Bit가 1로 설정 됨.
PORTL |= 0x01; // PL0 값이 1이 된다. PL0 이외 다른 Bits는 변동 되지 않는다.
DDRD &= (~0x01); // PD0를 Input Port로 설정 한다.
DDRL |= 0x01; // PL0를 Output Port로 설정 한다.
PORTL &= (~0x01); // Port L의 PL0를 0로 Clear 한다.
PORTL |= (PIND & 0x01); // PL0 이외 PORTL 다른 Bits 값은 병경되지 않고, PL0 Bit 만 PIND의 0번 Bit(PD0) 값과 같도록 Setting 된다.
DDRD &= (~0x01); // PD0를 Input Port로 설정 한다.
PORTD |= 0x01; // Pull-up 저항을 Active 상태로 하기 위함. PUD는 Reset 시 0으로 초기화 되기 때문에 이 예에서는 PUD를 0로 하는 Coding을 생략 하였다.
DDRL |= 0x01; // PL0를 Output Port로 설정 한다. DDRL의 0번째 Bit가 1로 설정 됨.
FORTL &= (~0x01); // Port L의 PL0를 0로 Clear 한다.
FORTL |= (PIND & 0x01); // PIND의 0번 Bit 값과 PL0 값이 같도록 Setting 한다.
- Input pins time delay.
- Read Operation을 실행하기 1.5 clock cycle 전에 Input Pin의 상태가 안정 되어야 한다.
- I/O 관련 프로그램을
- Transportable,
- Readable,
- More bug free
- PORTF의 PF0,PF1를 Output Port로 정의 하는 경우
- DDRF |= b00000011; 와 같이 코딩 하는 것 보다 아래 와 같이 코딩 하는 것이 보다 적정 하다.
- DDRF |= ( 1<< PF0) | (1 << PF1);
- ATmega2560 Header File
- Header File 예
- iomxx0_1.h에서 #define을 이용하여 정의한 Symbol은 아래와 같이 이해하기 쉬운 프로그램 작성을 가능하게 한다.
- Coding 예
- AND, OR, XOR 논리 연산을 이용한 Bit Operation
- Coding 예
- Mask를 사용 하여 개별 Bit 값을 알 수(Testing 할 수) 있다.
- Coding 예
- avr-libc function bit_is_set() 과 bit_is_clear() 를 사용 하여 아래와 같이 프로그램 할 수도 있다.
- AVR I/O port interfacing
- Pull-up 기능은 Switch를 외부 저항 없이 Input Port에 Interface 할 수 있게 한다. 그러나 Leakage current 가 증가 할 우려가 있다.
- 외부 조건(정전기, 부하에 의한 고전압 발생 등)에 대한 I/O Port protection에 대한 고려가 필요 함.
- Motor or relay drive circuits
- Inductive에 의한 고전압을 제거 하는 Diode 필요
- LED Drive Circuits
- 적절한 Current Limit Resistors의 선택이 필요함.
- 5V to 3.3V or 3.3V to 5V interfacing
- Voltage thresholds 가 같은 logic families Chip을 사용 하거나,
- Interface Chip : 74LVC244, TXB0108 등 이용
하게 작성 하기 위한 예
WinAVR\avr\include\avr\iom2560.h와 iomxx0_1.h File에 Port 사용에 관련된 정의가 있다.
define PORTB _SFR_IO8(0x05)
#define PB7 7
#define PB6 6
#define PB5 5
#define PB4 4
#define PB3 3
#define PB2 2
#define PB1 1
#define PB0 0
PORTB = 0x05;
DDRB = 0x0A;
DDRB |= (1 << DDB2) | (1 << DDB0);
temp0 = PINB;
// PORTB의 5번 Bit를 Toggle(XOR 연산을 이용) 하는 예
PORTB = PORTB ^ 0x20; // invert
PORTB ^= 0x20; // 웟 Coding을 압축 한 Coding 예, 윗 Coding과 동일한 결과을 얻는다.
// PORTB의 7번 Bit와 2번 Bit를 1로 Setting(OR 연산을 이용) 하는 Coding 예
PORTB = PORTB | 0x84;
PORTB |= (1 << PB7)|(1 << PB2) ; // 윗 Coding과 동일한 결과를 얻는다. 그러나 보다 읽기(프로그램을 이해 하기) 쉽고 보다 Portable 한 Code 이다.
// PORTB의 0번 Bit와 1번 Bit를 0로 Clear(AND 연산을 이용) 하는 Coding 예
PORTB = PORTB & 0xfc;
PORTB &= ~((1 << PB0)|(1 << PB1)); // 윗 Coding과 동일한 결과를 얻는다. 그러나 보다 읽기(프로그램을 이해 하기) 쉽고 보다 Portable 한 Code 이다.
// Port D 의 PD0 bit 가 1 인가를 Test 한다.
if(PIND & 0x01){take_some_action();}
위 예에서 와 같이 Data의 특정 Bit가 연산 결과에 중요한 영향을 미치 도록 하는 상수를 Mask라 한다.
이 예에서는 PIND Rg의 특정 Bit(이 예에서는 0번째 Bit)가 if 연산 결과를 결정 하도록 하기 위한 상수(이 예에서는 0x01)가 Masking 목적으로 사용 되었다.
// D5 Bit가 0 인가를 Test 한다.
if(~PIND & 0x20){take_action();} // 0x20 이 Mask로 사용 되었다.
if (bit_is_set(PINC, PC2)) {return 0;}
while (bit_is_clear(SPSR,SPIF)) {}
- LED Interfacing Circuit 예
- LED와 LED의 전류를 제한 하는 저항(예 에서는 330옴)을 사용 한다.
- PL0를 Output Port로 설정 한다.
- PL0 가 0(Low) 일때: LED(PL0)는 꺼진 상태가 되고,
- PL0 가 1(High) 일때: LED(PL0)는 켜진 상태가 된다.
- Switch Interfacing Circuit 예
- PD0와 GND 사이에 Push Button Switch를 연결 한다.(내부 Pull-up 저항을 사용 하는 경우)
- PD0를 Input Port로 설정 한다.
- Switch 가 Push 상태 일때 PD0는 0(Low) 상태가 되고,
- Switch 가 Release 상태 일때 1(High) 상태가 된다.
- 이 패이지의 예는 SWitch를 Close 하거나 Open 할때 발생 하는 Bouncing 문제 해결을 위한(Debouncing) Code를 구현 하지 않았기 때문에 SW의 동작이 정확 하지 않다. SW를 한번 눌렸는데 2,3번 누른 것처럼 동작 하기도 하고, SW를 CLose 할 때의 실행 하여야 할 동작이 SW를 Open 할 때 실행 될 수도 있다.
- ATmega2560 I/O port programming(Push Button Switch 와 LED) 예: cho_pio_basic_led_sw2560.zip
실험을 위한 회로 구성 예
// cho_pio_basic_led_sw2560.c
// S/W Environment : AVR Studio 7 + WINAVR Compiler
// Target : AATmega2560
// Crystal: 16Mhz
//
// 이 프로그램은 PD0에 연결된 외부 Switch의 상태를 읽어 PL0에 출력 하는 예 이다.
// 필요한 Hardware 설정 1: PD0와 GND 사이에 Push button switch를 연결 한다.
// Switch 가 Open 상태 일때 PD0 <- 1 ,
// Switch 가 Closed 상태 일때 PD0 <- 0 상태가 된다.
// 필요한 Hardware 설정 2: PL0(Pin 49)에 와 GND 사이에 LED와 LED의 전류를 제한 하는 저항(330옴)을 직렬로 연결 한다.
// PL0 가 0(Low) 일때: LED(PL0)는 꺼진 상태가 된다.
// PL0 가 1(High) 일때: LED(PL0)는 켜진 상태가 된다.
// 실험 방법: PD0에 연결된 외부 Switch를 Push 하거나 Release 하며 LED(PL0)의 상태를 관찰 한다.
// Switch 가 Release 상태 일때 LED(PL0)가 켜진 상태 이고,
// Switch 가 Push 상태 일때 LED(PL0)가 꺼진 상태 이다.
#include <avr/io.h>
// Port Initialize
void port_init(void)
{
DDRD &= (~0x01); // PD0를 Input Port로 설정 한다.
PORTD |= 0x01; // External SW를 사용 하기 위하여 Pull-up Resistor enable
// PUD Bit는 Reset 시 0로 초기화 되기 때문에 Coding을 생략 하였음
DDRL |= 0x01; // PL0를 Output Port로 설정 한다.
PORTL = 0x00; // PORTL(PL0)를 0 으로 초기화 한다.
}
int main(void)
{
port_init();
while(1){
PORTL &= (~0x01); // Port L의 PL0를 0로 Clear 한다.
PORTL |= (PIND & 0x01); // PIND의 0번 Bit 값을 PL0에 출력 한다.
}
}
- 실험을 위한 준비
- PD0에 Push button switch를 연결한다.
- PL0에 저항(330Ω)과 LED를 연결한다.
- 실험 방법
- cho_pio_basic_led_sw2560.zip 파일을 Download하여 압축을 해제한다.
- cho_pio_basic_led_sw2560.hex를 개발 보드에 Upload 한다.
- 실험: Push button switch(PD0)를 On(Push), Off(Release) 하면 PD0의 상태가 LED에 출력된다.
Arduino Mega 2560를 사용하는 경우 2560 Pin name과 Mega board pin name mapping table을 참고하여 신호선을 연결한다.
참고자료: Arduino Mega 2560 PIN mapping table
Text File: cho_led_basic_shift_2560_c.txt
Push button switch와 LED array를 사용하는 실험을 위한 회로 구성 예
- 실험을 위한 준비
- PD0와 PD1에 Push button switch를 연결한다.
- PORTL에 저항(330Ω)과 LED Array(8Bits)를 연결한다.
- 실험 방법
- cho_led_basic_shift_2560.zip 파일을 Download하여 압축을 해제한다.
- cho_led_basic_shift_2560.hex를 개발 보드에 Upload 한다.
- 실험: Push button switch(PD0)를 누르면 LED가 Left로 회전 하고,Push button switch(PD1)를 누르면 LED가 Right로 회전 한다.
- 실험을 위한 준비와 방법은 위 "SW를 사용하여 LED의 회전 방향을 제어 하는 프로그램 예"를 참고하기 바람.
Text File: cho_pio_basic_sw_on_off_2560_c.txt
- 실험을 위한 준비
- PD0와 PD1에 Push button switch를 연결한다.
- Mega Board에 있는 LED(PB7: Pin 13)LED를 사용하기 때문에 별도로 LED를 연결할 필요가 없다.
- 실험 방법
- cho_pio_basic_sw_on_off_2560.zip 파일을 Download하여 압축을 해제한다.
- cho_pio_basic_sw_on_off_2560.hex를 개발 보드에 Upload 한다.
- 실험: Push button switch(PD0)를 누르면 LED가 Turn on 되고,Push button switch(PD1)를 누르면 LED가 Turn off 된다.
Text File: cho_pio_basic_sw_toggle_2560_c.txt
- 실험을 위한 준비
- PD0에 Push button switch를 연결한다.
- Mega Board에 있는 LED(PB7: Pin 13)LED를 사용하기 때문에 별도로 LED를 연결할 필요가 없다.
- 실험 방법
- cho_pio_basic_sw_toggle_2560.zip 파일을 Download하여 압축을 해제한다.
- cho_pio_basic_sw_toggle_2560.hex를 개발 보드에 Upload 한다.
- 실험: Push button switch(PD0)를 누르면 LED의 상태가 Toggle 된다.