이 블로그는 임베디드 컴퓨터를 이용한 장치(시스템) 개발과 원격제어에 필요한 지식을 공유 하기 위한 블로그 입니다.
실제 개발과 프로그램 예를 위하여 Microchip 사의 ATmega128를 사용한 보드와 Arduino Mega 보드(ATmega2560), Raspberry Pi, Raspberry Pi Pico, WiFi 모듈을 사용 합니다.

asm-ATmega128-IO-port

ATmega128 I/O Port - ASM
ATmega128 I/O Port - ASM


  • ATmega128 I/O Port 개요
    • 6개의 8비트 양방향 병렬 I/O 포트(PORTA~F)
    • 1개의 5비트 양방향 병렬 I/O 포트(PORTG)
    • 각 PORT별 3개 I/O 레지스터 영역
      • DDR(Data Direction Register) : 해당 Pin(Port)을 입력 Rg의 입력으로 사용 할지, 출력 Port의 출력 Pin으로 사용 할지를 결정
      • PORT(Data Register) : 데이터 출력 PORT
      • PIN(Port Input Pins Register) : 입력 핀에 연결된 Input Port Rg
    • DDR, PORT : 읽기/쓰기 가능, PIN : 읽기만 가능
  • ATMega128 I/O Ports의 특징
    • 특징
      • 최대 40mA 구동 전류
        • LED 1개 구동 가능
      • 선택 가능한 Pull Up 저항(20K – 100K Ohm) 내장
      • Vcc, GND 사이에 입력단 보호 Diode 내장
    • Read-Modified-Write Cycle 지원
      • 다른 pin에 영향을 주지 않고 한 port 핀의 방향을 바꿀 수 있음
        • DDRD &= (~0x03); // Input Port : PD0, PD1
        • DDRF |= 0x03; // Output Port : PF0, PF1
    • 모든 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
  • AVR port architecture
    • 각 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 G(Port G Rg는 5 Bit 구조 임) 까지 7개 Rg 가 모두 같은 구성과 기능을 같는다.
    • PORTA와 DDRA Rg는 Rg에 저장된 내용을 읽거나(Read) 새로운 Data를 쓸(Write) 수 있다.
    • PINA Rg는 읽기(Read Operation)만 가능 하고, Data를 쓸(Write) 수 없다.
    • Reset 시 PORTA와 DDRA Rg는 0로 초기화 된다. 그러나 PINA Rg는 초기화 할 수 없다.

  • 아래 그림은 각 Port(소문자 x는 A - G 까지 Port를 표시 한다.)의 1 Bit 회로도 이다.

    • 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 전압에 영향을 미치지 않는다.

    • SFIOR: Special Function IO Reg.
      • Pull-up disable Bit(PUD): I/O Port의 Pull-up 기능을 제어(Enable or Disable 상태로 설정) 하는 Bit 이다.
      • 이 Bit가 0 이고, DDRx의 해당 Bit가 0, PORTx 의 해당 Bit가 1 이면 I/O Port의 Pull-up 기능을 Enable 상태(윗 그림의 FET Switch 가 Closed 상태)로 설정 된다.
      • 이 Bit가 1 이면, DDRx와 PORTx 의 상태에 상관 없이 I/O Port의 Pull-up 기능은 Disable 상태(윗 그림의 FET Switch 가 Open 된 상태)로 설정 된다.
      • SFIOR의 다른 제어 Bit는 Timer(TSM, PSR0, PSR123)와 A/D 변환기(ACME)의 제어에 사용 된다.
      • 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가 우선함

    • Output Port로 사용하기 위한 설정과 동작
      • Output Port로 사용 하고자 하는 Port의 DDR Rg에 1을 Write 하여 해당 Port를 Output Port로 설정 한다.
      • Output Port에 Data를 출력 한다.
      • PF0(Port F의 0번 Bit)를 Output Port로 설정하는 Coding 예
        • lds r16, DDRF // PORTF의 현재 설정 상태를 읽는다.

          sbr r16, 0x01 // DDRF의 0번째 Bit를 1(PF0를 Output Port)로 설정 한다.

          sts DDRF, r16 // DDRF의 새로운 설정을 DDRF에 Write 한다.

          주: PORTF는 Memory Mapped I/O Port 이기 때문에 lds, sts 명령을 사용한다.

          주: DDRF의 다른 Bits의 상태는 변동하지 않고 Bit 0의 설정만 변경하기 위하여는 해당 Port를 읽은 다음 Bit 0 만 Clear 또는 Set 하여 다시 Write 하여야 한다.

    • Input Port로 사용하기 위한 설정과 동작
      • Input Port로 사용 하고자 하는 Port DDR Rg의 해당 Bit에 0을 Write 하여 해당 Port를 Input Port로 설정 한다.
      • 필요한 경우 Input Port로 사용 하고자 하는 Port(원하는 Bit만)의 Pull-up 기능을 Enable 상태로 설정한다.
      • Input Port(PIN)으로 부터 Data를 입력 받는다.
      • PD0를 Input Port로 설정하는 Coding 예
        • cbi DDRD, 0

          주: AVR은 in, out 명령을 사용하는 I/O Register의 특정 Bit를 Clear(cli) 또는 Set(sbi) 하는 명령을 갖고 있기 때문에 하나의 Bit를 설정하는 경우에는 이 명령을 사용하는 것이 좋다. 그러나 여러 Bit를 동시에 설정하는 경우에는 Bit를 설정을 위한 Mask와 AND, OR Operation을 실행하는 CLR, SBR 등의 명령을 사용하는 것이 유리하다.

    • Pull-up Resistor 사용을 위한 설정
      • Pull-up Resistor는 Switch 등을 연결하는 경우 외부에서 부가되는 회로를 최소화 하기 위한 것 이다. 아래 Switch Interfacing Circuit 예를 참고 할 것.
      • 윗 회로에서 Pull-up Resistor를 Active 상태로 하는 FET Switch를 Turn On 상태로 하기 위한 조건은 SFIOR Rg의 PUD 가 0 이고, DDRx Rg 가 0, PORTx 가 1 으로 설정되어야 한다.
      • PD0의 Pull-up 기능을 Enable 상태로 설정하는 Coding 예
        • cbi DDRD, 0

          sbi PORTD, 0

          주: SFIOR Rg의 PUD Bit는 초기 값이 0 이기 때문에 Coding을 생략하였다.

      • PD0, PD1(Port D의 0번째, 1 번째 Bit)에 Push Button Switch를 연결 하고 이 SW의 상태를 읽어 PF0, PF1에 출력 하는 Coding 예
        • 주: Pull-up Resistor를 Enable 하는 SFIOR(Special Function IO Reg)의 PUD Bit는 Zero로 초기화되기 때문에 PUD를 Clear 하는 Code는 생략하였다.

          주: PORTD는 I/O Maped I/O Port 이기 때문에 in, out 명령을 사용하고 PORTF는 Memory Mapped I/O Port 이기 때문에 lds, sts 명령을 사용하였다.

          주: DDRD, DDRF의 다른 Bits의 상태는 변동하지 않고 Bit 0, 1의 설정만 변경하기 위하여는 해당 Port를 읽은 다음 Bit 0, 1 만 Clear 또는 Set 하여 다시 Write 하였다.


    • I/O Port의 Pin은 I/O Port 기능 이외에 부가 기능 갖고 있다.
      • Embedded computer chip은 물리적(Chip 크기와 Pin 수)인 제약 때문에 외부로 연결되는 Pin 수가 제한 된다.
      • 그러므로, 이 문제를 해결 하기 위하여 하나의 Pin을 다른 목적(부가 기능)으로 사용 할 수 있도록 설계 되었다.
    • Port A 부가 기능
      • Port A Pin은 외부 memory 확장시 하위 8 bit address와 8bit data bit 로 사용 된다.

    • Port B 부가 기능
      • Port B Pin은 아래 Table과 같이
        • Timer/Counter Output과
        • SPI Bus Interface에 사용 된다.

    • Port C 부가 기능
      • Port C Pin은 외부 memory 확장시 상위 8 bit address로 사용 된다.
      • 외부 memory 확장
        • 상위 8bit address

    • Port D 부가 기능
      • Port D Pin은 아래 Table과 같이
        • Timer/Counter Input
        • USART Interface
        • External Interrupt
        • TWI Serial Interface에 사용 된다.

    • Port E 부가 기능
      • Port E Pin은 아래 Table과 같이
        • External Interrupt
        • Timer/Counter Input and Output
        • Analog Comparator
        • UART Interface에 사용 된다.

    • Port F 부가 기능
      • Port F Pin은 아래 Table과 같이
        • ADC Input
        • JTAG interface에 사용 된다.

    • Port G 부가 기능
      • Port G Pin은 아래 Table과 같이
        • RTC Oscillator
        • External memory interface의 ALE/RD/WR 신호로 사용 된다.
  • Port 이용 프로그램 작성시 고려 할 사항과 Coding 예
    • Input pins time delay.
      • Read Operation을 실행하기 1.5 clock cycle 전에 Input Pin의 상태가 안정 되어야 한다.
    • I/O 관련 프로그램을
      • Transportable,
      • Readable,
      • More bug free
      • 하게 작성 하기 위한 예

        • PORTF의 PF0,PF1를 Output Port로 정의 하는 경우
        • ldi r16, 0x03; 와 같이 코딩 하는 것 보다 아래 와 같이 코딩 하는 것이 보다 프로그램을 이해하기 쉽게한다.
        • ldi r16, ( 1 << PF0) | (1 << PF1);
    • ATmega128 Definition File: m128def.inc
      • m128def.inc 파일의 경로 예
      • C:\Program Files (x86)\Atmel\Studio\7.0\packs\atmel\ATmega_DFP\1.6.364\avrasm\inc\m128def.inc

      • Definition File 예
    • m128def.inc에서 .equ을 이용하여 정의한 Symbol은 아래와 같이 프로그램을 이해하기 쉽게 한다.
      • Coding 예
        • in r16, DDRD

          out DDRD, r16

          ldi r16, ( 1 << PF0) | (1 << PF1)


    • AND, OR, XOR 논리 연산을 이용한 Bit Operation
      • Coding 예
        • PORTF의 PF5 Bit를 Toggle(XOR 연산을 이용) 하는 예

          lds r16, PORTF

          ldi r17, (1 << PF5)

          eor r16,r17

          sts PORTF, r16


          PORTF의 PF7 Bit와 PF2 Bit를 1로 Setting(OR 연산을 이용) 하는 Coding 예

          lds r16, PORTF

          ori r16, (1 << PF7) | (1 << PF2)

          sts PORTF, r16


          PORTF의 PF7 Bit와 PF2 Bit를 0로 Clear(AND 연산을 이용) 하는 Coding 예

          lds r16, PORTF

          andi r16, ~((1 << PF7) | (1 << PF2))

          sts PORTF, r16


    • Mask를 사용 하여 개별 Bit 값을 알 수(Testing 할 수) 있다.
      • Coding 예
        • Port D의 1번 Pin이 1 인가를 Test 하는 예

          위 예에서 와 같이 Data의 특정 Bit가 연산 결과에 중요한 영향을 미치 도록 하는 상수를 Mask라 한다.

          이 예에서는 상수 0x02((1 << PD1))가 PIND Rg의 특정 Bit(이 예에서는 1번째 Bit)를 Testing 하기 위한 Mask로 사용 되었다.


    • AVR I/O port interfacing
      • Pull-up 기능은 Switch를 외부 저항 없이 Input Port에 Interface 할 수 있게 한다. 그러나 Pull-up 기능을 사용하지 않는 경우에 Enable 상태로 설정하면 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 등 이용
  • LED Interfacing
    • LED Interfacing Circuit 예
      • LED와 LED의 전류를 제한 하는 저항(예 에서는 330옴)을 PF0와 LED 사이에 연결 한다.
      • PF0를 Output Port로 설정 한다.
      • PF0 가 0(Low) 일때: LED(PF0)는 꺼진 상태가 되고,
      • PF0 가 1(High) 일때: LED(PF0)는 켜진 상태가 된다.
  • Switch Interfacing
    • Switch Interfacing Circuit 예
      • PD0와 GND 사이에 Push Button Switch를 연결 한다.(내부 Pull-up 저항을 사용 하는 경우)
      • PD0를 Input Port로 설정 한다.
      • Switch 가 Push 상태 일때 PD0는 0(Low) 상태가 되고,
      • Switch 가 Release 상태 일때 1(High) 상태가 된다.

      a) 외부 Pull Up 저항을 사용한 경우의 예.                       b)프로세서 내부 Pull Up 저항을 사용한 경우의 예.


  • AVR I/O port programming 예
    • Push Button Switch의 상태(PD0)를 읽어 LED(PF0)에 출력 하는 프로그램 예
    • 실험을 위한 회로 구성 예


      • 실험을 위한 준비
        • PD0에 Push button switch를 연결한다.
        • PF0에 저항(330Ω)과 LED를 연결한다.
      • 실험 방법
        • Project(Project name: AVR-asm-sw-led-basic)를 생성 한다.
        • 위 프로그램을 main.asm에 복사하고 저장한다.
        • Build → Build Solution 를 실행 하면 main.asm File 이 Assemble 되어 AVR-asm-sw-led-basic.hex 파일이 생성된다.
        • AVR-asm-sw-led-basic.hex 파일을 Target Board에 Upload 하고 프로그램을 실행한다.
        • 실험: LED(PF0)의 초기상태는 Turn on 상태이다. Push button switch(PD0)를 누르면 LED가 Turn off 된다.

    • OR, AND Function를 이용한 Bit Set(OR), Clear(AND) 예
      • Push button switch(PD0)를 누르면 LED가 Turn on 되고 PD1를 누르면 LED가 Turn off되는 프로그램 예

      • 실험을 위한 준비
        • PD0와 PD1에 Push button switch를 연결한다.
        • PF0에 저항(330Ω)과 LED를 연결한다.
      • 실험 방법
        • Project(Project name: AVR-asm-sw-led-basic)를 생성 한다.
        • 위 프로그램을 main.asm에 복사하고 저장한다.
        • Build → Build Solution 를 실행 하면 main.asm File 이 Assemble 되어 AVR-asm-sw-led-basic.hex 파일이 생성된다.
        • AVR-asm-sw-led-basic.hex 파일을 Target Board에 Upload 하고 프로그램을 실행한다.
        • 실험: LED(PF0)의 초기상태는 Turn off 상태이다. Push button switch(PD0)를 누르면 LED가 Turn on 되고 PD1를 누르면 LED가 Turn off 된다.
        • 주: 이 페이지의 프로그램 예는 Switch의 상태를 테스트 하는 기술, Branch 명령에 대한 이해, 특정한 Bit를 Set 또는 Clear 하는 방법을 이해 하기 위한 예이기 때문에 실제 응용 프로그램에 그대로 사용하기에는 부족하다. 실제 응용 프로그램에 사용하기 위하여는 Switch를 누른는 순간에 정확히 한번만 명령이 실행되도록 개선(External Interrupt 등을 사용하여 Switch를 누르는 순간에만 동작되도록 하고 또한 Switch의 Bouncing 문제 등을 해결하여야 함)되어야 한다.


    • XOR Function를 이용한 Bit Toggle 대한 이해를 위한 예
      • Push button switch(PD0)를 누르면 LED가 상태가 Toggle(현재 off 상태면 Turn on 되고 on 상태면 Turn off 됨) 되는 프로그램 예

      • 실험을 위한 준비
        • PD0에 Push button switch를 연결한다.
        • PF0에 저항(330Ω)과 LED를 연결한다.
      • 실험 방법
        • Project(Project name: AVR-asm-sw-led-toggle)를 생성 한다.
        • 위 프로그램을 main.asm에 복사하고 저장한다.
        • Build → Build Solution 를 실행 하면 main.asm File 이 Assemble 되어 AVR-asm-sw-led-toggle.hex 파일이 생성된다.
        • AVR-asm-sw-led-toggle.hex 파일을 Target Board에 Upload 하고 프로그램을 실행한다.
        • 실험: LED(PF0)의 초기상태는 Turn off 상태이다. Push button switch(PD0)를 누르면 LED의 상태가 Toggle 된다.
        • 주: Switch의 Bouncing 현상 때문에 이 프로그램은 정확히 동작하지 않을 수 있다.


    • Time Delay Routine에 대한 이해를 위한 예
      • LED 가 1 Sec 주기(Software Delay를 사용)로 점멸 하는 프로그램 예: AVR_asm_led_flash_basic.zip
      • 아래 프로그램 예에서는 아직 Timer에 대한 소개를 하지 않았기 때문에 Software time delay를 사용하였다.


      • 실험을 위한 준비
      • 실험 방법
        • Project(Project name: AVR_asm_led_flash_basic)를 생성 한다.
        • 위 프로그램을 main.asm에 복사하고 저장한다.
        • Build → Build Solution 를 실행 하면 main.asm File 이 Assemble 되어 AVR_asm_led_flash_basic.hex 파일이 생성된다.
        • AVR_asm_led_flash_basic.hex 파일을 Target Board에 Upload 하고 프로그램을 실행한다.
        • 실험: LED가 1초 주기로 점멸한다.
        • 주: Interrupt를 사용하는 경우에는 .include "avr128_interrupt_table.inc"의 Comment를 해제하고 main.asm이 있는 폴더에 avr128_interrupt_table.inc 파일을 위치하도록 하여야 한다.

        참고자료: GCC asm 프로그램 예: GCC_asm_led_flash_basic.zip


    • 논리연산( Shift 포함)과 Time Delay에 대한 이해를 위한 예
      • 0.2Sec 간격으로 00000001, 00000010, 00000100 -- 10000000, 00000001과 같이 led 가 Turn On 되는 프로그램 예

      • 실험을 위한 준비
      • 실험 방법
        • Project(Project name: AVR_asm_led_basic_shift)를 생성 한다.
        • 위 프로그램을 main.asm에 복사하고 저장한다.
        • Build → Build Solution 를 실행 하면 main.asm File 이 Assemble 되어 AVR_asm_led_basic_shift.hex 파일이 생성된다.
        • AVR_asm_led_basic_shift.hex 파일을 Target Board에 Upload 하고 프로그램을 실행한다.
        • 실험: LED가 0.2초 주기로 좌측으로 회전한다.

        참고자료: GCC asm 프로그램 예: GCC_asm_led_basic_shift.zip


    • 논리연산(Shift)과 Switch 입력, Time Delay에 대한 이해를 위한 예
      • Push button switch와 LED array를 사용하는 실험을 위한 회로 구성 예

      • Push button switch(PD0)를 누르면 LED가 Left로 회전 하고,PD1를 누르면 LED가 Right로 회전하는 프로그램 예

      • 실험을 위한 준비
      • 실험 방법
        • Project(Project name: AVR-asm-sw-led-shift)를 생성 한다.
        • 위 프로그램을 main.asm에 복사하고 저장한다.
        • Build → Build Solution 를 실행 하면 main.asm File 이 Assemble 되어 AVR-asm-sw-led-shift.hex 파일이 생성된다.
        • AVR-asm-sw-led-shift.hex 파일을 Target Board에 Upload 하고 프로그램을 실행한다.
        • 실험: Push button switch(PD0)를 누르면 LED가 Left로 회전 하고,Push button switch(PD1)를 누르면 LED가 Right로 회전 한다.

        참고자료: GCC asm 프로그램 예: GCC_asm_sw_led_basic_shift.zip


    • Pin I/O와 Testing에 대한 이해를 위한 예
      • SW PD0를 누른 회수를 2진수로 LED(PORTF)에 표시하는 프로그램 예

      • 실험을 위한 준비
      • 실험 방법
        • Project(Project name: AVR_asm_sw_led_push_counter)를 생성 한다.
        • 위 프로그램을 main.asm에 복사하고 저장한다.
        • Build → Build Solution 를 실행 하면 main.asm File 이 Assemble 되어 AVR_asm_sw_led_push_counter.hex 파일이 생성된다.
        • AVR_asm_sw_led_push_counter.hex 파일을 Target Board에 Upload 하고 프로그램을 실행한다.
        • 실험: SW PD0를 누른 회수가 2진수로 LED(PORTF)에 표시된다.
        • 주: SW Bouncing 현상 때문에 SW를 한번 눌러도 누른 회수가 1 이상의 증가할 수 있다.


  • ATmega128 I/O Port - ASM 관련 페이지 보기