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

asm-debouncing-keypad

Switch debouncing and Keypad interfacing - ASM
Switch debouncing 과 Keypad Interfacing - ASM


  • Switch의 Bouncing 현상과 Debouncing 기술
    • Switch Interfacing
      • Switch Interfacing Circuit 예
        • PD0와 GND 사이에 Push Button Switch를 연결 한다.
        • PD0를 Input Port로 설정 한다.
        • Switch 가 Push 상태 일때 PD0는 0(Low) 상태가 되고,
        • Switch 가 Release 상태 일때 1(High) 상태가 된다.

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


    • Switch를 닫(Closed)거나 개방(Open) 할 때 발생하는 Bouncing 현상
    • Switch의 금속 접점은 이상적이지 않기 때문에 Switch를 Closed 하거나 Open 하는 순간에 아래 그림과 같이 Bouncing 현상이 발생 한다.

      Bouncing은 Switch의 상태에 따라 대략 5mSec - 10mSec 사이에 발생 한다.

      Bouncing 신호는 장치 오동작의 중요한 요인 이다.


    • Hardware Debouncing
      • Hardware Debouncing circuits
      • 아래 그림a)와 같이 R-C Low Pass Filter 회로(Bouncing 신호는 Switch의 동작 속도에 비교 하면 높은 주파수 신호 이기 때문에 Low Pass Filter를 사용 하면 Bouncing 신호의 진폭만 크게 감소 한다.)를 사용 하면 Bouncing 신호의 진폭을 크게 감소 시킬 수 있다.

        그러나 a) 회로에서는 Switch가 닫이는 순간 Switch가 Open 상태에서 C에 충전되었던 전하가 아주 짧은 시간에 Switch를 통하여 방전되면서 Switch에 큰 순간 전류(회로를 손상 시키는 원인이 됨)가 흐르게 된다.

        Switch가 닫이는 순간 Switch에 흐르는 큰 전류에 의한 손상을 방지 하기 위하여 그림 b)와 같이 Switch와 직렬로 22옴 정도를 연결 한다.


        a) R-C Low Pass Filter와 Schmitt Trigger 회로를 사용한 Debouncing circuit


        b) 위 Debouncing circuit에서 발생하는 Switch 과도 전류 문제를 개선한 회로

      • Schmitt Trigger 회로에 의한 Debouncing
      • 아래 그림 b)와 같이 Bouncing 신호의 진폭을 R-C 회로를 사용하여 낮게 할 수 있다.

        그러나 R-C 회로를 통과한 Bouncing 신호의 진폭이 입력 Port의 Vt(Gate 입력의 Low(0) High(1)을 구분 하는 경계 전압) 보다 높을 수 있기 때문에 아래 그림 a)와 같은 전달 특성을 같는 Schmitt Trigger 회로를 사용 하여 Noise Margin을 크게 한다.

        그 결과 그림 b)에서와 같이 Switch 에서 발생한 Bouncing 신호를 R-C 회로와 Schmitt Trigger 회로를 사용 하여 그림 c)와 같이 제거 할 수 있게 된다.

        a) Schmitt Trigger 회로의 전달 특성


        b) Hardware Debouncing circuit의 입력 파형


        c) Hardware Debouncing circuit의 출력 파형


    • Software Debouncing
      • Time Delay를 이용한 Debouncing 예
      • uP의 실행 속도에 충분한 여유가 있는 경우, Switch가 동작(Closed or Open)한 순간으로 부터 Bouncing 현상이 없어지는 시간 만큼 Delay 한 후에 Switch의 상태를 읽는 방법(Software적인 방법)으로 Bouncing 현상을 제거 할 수 있다.

        아래 그림 a)는 Switch를 닫을 때(Press) 발생 하는 Bouncing 문제를 해결 하기 위한 예(Block diagram) 이고,

        그림 b)는 Switch를 개방(Release) 할 때 발생 하는 Bouncing 문제를 해결 하기 위한 예(Block diagram) 이다.

        a) Switch를 닫을 때(Press) Debouncing 예                       b) Switch를 개방 할 때(Release) Debouncing 예


      • Gadfly loop와 Time Delay를 이용한 Debouncing 예
      • 아래 Gadfly loop를 이용한 Debouncing 예는 위에서 설명한 Software debouncing 알고리즘을 개선한 방법 이다.

        a) Gadfly loop와 Time Delay를 이용한 Debouncing 예


      • External interrupt와 Timer interrupt를 이용한 Debouncing 예
      • External interrupt 입력 단자와 Timer interrupt를 사용 할 수 있는 Timer 가 있는 경우 아래와 같이 보다 효과 적으로 Bouncing 문제를 해결 할 수 있다. 이 방법을 이해 하기 위하여는 External interrupt와 Timer interrupt에 대한 이해가 필요 하다.

      • External interrupt service routine
        • External interrupt 입력 단자에 연결된 Switch를 동작(Press or Release) 시키면 External interrupt service routine이 실행 된다.
        • 원하지 않는 Bouncing 신호에 의하여 Interrupt Service Routine이 다시 실행 되지 않도록 External interrupt를 Disable 상태로 한다.
        • Timer interrupt에 사용 할 Timer의 Delay Time를 설정 한다. Timer의 Interrupt Service Routine은 여기서 설정한 Delay Time(약 10 - 16mSec) 후에 실행 된다.
        • External interrupt service routine의 실행을 종료 한다.
      • Timer interrupt service routine
        • External interrupt service routine에서 설정한 Delay Time 후에 Timer interrupt Service routine이 실행 된다.
        • Timer interrupt를 Disable 한다. Timer interrupt Routine은 다음 Switch 동작에 의하여 Switch External interrupt에서 Timer interrupt를 Enable 할 때 까지 실행 되지 않는다.
        • 새로운 Switch 동작에 의하여 External interrupt routine이 실행 될 수 있도록 External interrupt를 Enable 한다.
        • Switch의 상태(Pressed or Released)에 따른 동작을 실행 한다.
        • Timer interrupt service routine의 실행을 종료 한다.

        a) External interrupt이 발생 하였을 때의 처리                   b) Timer interrupt이 발생 하였을 때의 처리


    • Time Delay를 이용한 Software Debouncing 프로그램 예

    • External Interrupt와 Timer Interrupt를 이용한 Debouncing 예
      • 주: External Interrupt를 이용하여 Switch의 bouncing 현상을 관찰 하기 위한 프로그램 예는 "Switch를 누른 회수를 LED Bar에 2에 진수로 출력 하는 프로그림 예"를 참고바람.

      • External Interrupt와 Timer Interrupt를 이용한 Debouncing 프로그램 예: AVR_asm_sw_debounce_counter_ext_int.zip

        • 실험을 위한 준비
        • 실험 방법
          • Project(Project name: AVR_asm_sw_debounce_counter_ext_int)를 생성 한다.
          • 위 프로그램을 main.asm에 복사하고 저장한다.
          • INT0, TIMER1_COMPA_vect Interrupt Vector 설정: "avr128_interrupt_table.inc"를 다운로드하여 아래 예와 같이 편집한다.
          • Build → Build Solution 를 실행 하면 main.asm File 이 Assemble 되어 AVR_asm_sw_debounce_counter_ext_int.hex 파일이 생성된다.
          • AVR_asm_sw_debounce_counter_ext_int.hex 파일을 Target Board에 Upload 하고 프로그램을 실행한다.
          • 실험: Push button switch(PD0)를 누르면 LED Array(8Bits)에 누른 회수가 2진수로 출력된다.
          • 주: Debouncing를 기능을 구현하였기 때문에 Push button switch(PD0)를 누른 회수가 비교적 정확히 LED Array(8Bits)에 2진수로 출력된다.


  • Keypad Interfacing
    • 4 by 3 일반 전화기용 Keypad와 ATmega128의 Interfacing 예
      • 아래 그림의 예에서는 Port C(PC4-PC7을 Output Port로 사용)와 Port E(PE4-Pe6 를 Input Port로 사용)를 Keypad 연결 Port로 사용 한다.
      • PC4-PC7을 Output Port로 설정 한다.
      • PE4-Pe6 를 Input Port로 설정 한다.
      • Key Scanning 방식을 이용하여 Keypad의 상태(어느 Key가 Push 되었는지 확인 하고 해당 Key의 Code를 Return 하는 getkey() 함수를 작성 한다.
      • Keypad 동작의 신뢰도를 높이기 위하여 Key 동작시 발생하는 Bouncing 문제를 고려 하여 프로그램을 작성 하여야 한다.(아래 프로그램 예를 참고 할 것.)

      a) Keypad와 Atmega128 I/O Port Interfacing 회로도.                 b) 4 by 3 Keypad Pin.


    • Key Scanning
      • 출력 Port PC4 - PC7에 0111 패턴을 출력 하고 입력 Port PE4, PE5, PE6 읽으면 1,2,3 Key가 눌린 경우에만(1,2,3 이외에 다른 Key가 눌린 경우에는 PE4 - PE6 값이 1이 됨) 해당 위치의 Input port(PE4 - PE6)의 값이 0이 된다.
      • 출력 Port PC4 - PC7에 1011 패턴을 출력 하고 입력 Port PE4 - PE6 읽으면 4,5,6 Key가 눌린 경우에만(4,5,6 이외 다른 Key가 눌린 경우에는 PE4 - PE6 값이 1이 됨) 해당 위치의 Input port(PE4 - PE6)의 값이 0이 된다.
      • 위와 같이 출력 Port PC4 - PC7에 1101 패턴을 출력 하고 입력 Port PE4 - PE6을 읽으면 7,8,9 Key가 눌린 경우에만 해당 위치의 Input port(PE4 - PE6)의 값이 0이 되고, PC4-PC7에 1110 패턴을 출력 하고 입력 Port PE4 - PE6 읽으면 *,0,# Key가 눌린 경우에만 해당 위치의 Input port(PE4 - PE6)의 값이 0이 되기 때문에,
      • 순차적으로 출력 Port에 0111, 1011, 1101, 1110 패턴을 출력 하면서 해당 Row에 있는 Key Switch의 상태를 읽어 어느 Key가 Press 되었는지 판단 한다.

      • 그림 a) 4 By 3 Keypad Interface 회로와 Scanning Code 예


    • key Switch를 press와 release 시 발생 하는 Bouncing 문제
    • Key Switch를 Press 하거나 Release 할 때 입력 Port에 발생 하는 파형 예(Bouncing 문제).


    • Key Switch를 Press 하거나 Release 할 때 입력 Port에 발생 하는 Bouncing 문제의 해결
      • Key Switch 접점의 불안정한 접속으로 Switch를 Press 하거나 Release 할 때 윗 그림과 같이 Bouncing 현상이 발생 한다.
      • Bouncing 문제를 해결하기 위하여는 전자회로 적인 접근(RC Low Pass Filter 이용한 Hardware Debouncing)과,
      • Bouncing 현상은 16mSec 이내 에서 발생 하기 때문에 첫 Press 또는 Release 신호 발생 후 일정 시간(16mSec 정도) 후에 다시 Switch의 상태를 읽어 Press 또는 Release 상태를 판단 하는 기술(Software Debouncing)을 사용 한다.

    • Keypad programming 예:
      • Keypad로 부터 입력되는 문자를 UART 통신을 통하여 모니터(Console)에 출력 하는 실험 구성도

      • 4 by 3 Keypad로 부터 Key 값을 읽어 모니터에 출력하는 프로그램 예: GCC_asm_keypad_uart_soft_basic.zip
      • Keypad 초기화 와 Key scaning 함수, get_key() 함수 예: GCC_asm_get_keypad_soft.s

        • 실험을 위한 준비
          • 실험 구성도를 참고하여 개발보드에 Keypad를 연결한다.
          • 컴퓨터(USB --> UART(RS232) 변환 모듈)의 RXD와 Atmega128의 TXD0(PE1)를 연결한다.
          • 컴퓨터(USB --> UART(RS232) 변환 모듈)의 TXD와 Atmega128의 RXD0(PE0)를 연결한다.
          • 주: 컴퓨터에 Serial Port가 없는 경우 "USB --> UART(RS232) 변환 모듈"를 사용(USB Port를 Serial Port로 변환)하여 연결한다. 개발보드에 따라서는 "USB --> UART(RS232) 변환 모듈"을 내장하고 있는 경우가 많기 때문에 본인이 사용하는 개발보드에서 확인 하여야 한다.

            참고자료: USB - Serial 변환 모듈

          • 컴퓨터(USB --> UART(RS232)의 GND와 Atmega128의 GND를 연결한다. "USB --> UART(RS232) 변환 모듈"를 사용하는 경우 변환 모듈의 GND와 Atmega128의 GND를 연결한다.
        • 실험 방법
          • GCC_asm_keypad_uart_soft_basic.zip 파일을 Download하여 압축을 해제한다.
          • Build → Build Solution 를 실행 하면 프로그램이 Build 되어 GCC_asm_keypad_uart_soft_basic.hex 파일이 생성된다.
          • GCC_asm_keypad_uart_soft_basic.hex를 개발 보드에 Upload 하고 프로그램을 실행한다.
          • 주: 모니터 프로그램(예: OC-Console, Tera Term)과 hex 파일을 Target Board에 Upload 하는 프로그램이 동일한 Port를 사용하기 때문에 모니터 프로그램을 중지하고 Upload를 실행하여야 한다.

          • 모니터 프로그램(예: OC-Console, Tera Term)을 설치(이미 설치되어 있는 경우에는 실행만 하면됨)하고 실행 한다.
          • 모니터 프로그램에서 필요한 설정(Serial Port와 Baudrate 등을 설정)을 한다.
          • 실험:
            • 개발 보드의 Reset SW를 누르면 모니터에 "KeyPad Input Testing" 메세지가 출력된다.
            • Keypad에서 문자를 입력하면 입력된 문자는 UART 통신을 이용하여 모니터에 출력된다.

      • External Interrupt와 Timer Interrupt를 이용한 Key debouncing과 key scan 과정에서 발생 하는 문제
      • External Interrupt와 Timer Interrupt를 이용한 Keypad 제어 시 아래 그림과 같이 Scan enable, disable control 과정(Key를 누르고 있는 상태가 계속되는 상태에서 Key scanning 프로그램 이 실행 되는 경우)에서 원 하지 않는 펄스(S4)가 발생 할 수 있다. 이 신호의 Falling edge(p5)에서 External Interrupt Flag 가 Set 된다. 이 External Interrupt Flag에 의하여 External Interrupt가 실행 되지 않도록 Interrupt routine 이 종료 되기 전에 이 Flag를 Clear 하여야 한다.


      • 4 by 3 Keypad로 부터 Key 값을 읽어(External Interrupt와 Timer Interrupt, circular Buffer를 사용하고 Buffer overflow Testing 기능을 포함 한다.) 모니터에 출력하는 프로그램 예: GCC_asm_keypad_int_buffer_uart_timer3.zip
      • Keypad 초기화 와 Key scaning 함수, get_key() 함수, key_buffer, timer3_init 함수 예: GCC_asm_get_keypad_interrupt.s

        • 실험을 위한 준비
          • 실험 구성도를 참고하여 개발보드에 Keypad를 연결한다.
          • 컴퓨터(USB --> UART(RS232) 변환 모듈)의 RXD와 Atmega128의 TXD0(PE1)를 연결한다.
          • 컴퓨터(USB --> UART(RS232) 변환 모듈)의 TXD와 Atmega128의 RXD0(PE0)를 연결한다.
          • 주: 컴퓨터에 Serial Port가 없는 경우 "USB --> UART(RS232) 변환 모듈"를 사용(USB Port를 Serial Port로 변환)하여 연결한다. 개발보드에 따라서는 "USB --> UART(RS232) 변환 모듈"을 내장하고 있는 경우가 많기 때문에 본인이 사용하는 개발보드에서 확인 하여야 한다.

            참고자료: USB - Serial 변환 모듈

          • 컴퓨터(USB --> UART(RS232)의 GND와 Atmega128의 GND를 연결한다. "USB --> UART(RS232) 변환 모듈"를 사용하는 경우 변환 모듈의 GND와 Atmega128의 GND를 연결한다.
        • 실험 방법
          • GCC_asm_keypad_int_buffer_uart_timer3.zip 파일을 Download하여 압축을 해제한다.
          • Build → Build Solution 를 실행 하면 프로그램이 Build 되어 GCC_asm_keypad_int_buffer_uart_timer3.hex 파일이 생성된다.
          • GCC_asm_keypad_int_buffer_uart_timer3.hex를 개발 보드에 Upload 하고 프로그램을 실행한다.
          • 주: 모니터 프로그램(예: OC-Console, Tera Term)과 hex 파일을 Target Board에 Upload 하는 프로그램이 동일한 Port를 사용하기 때문에 모니터 프로그램을 중지하고 Upload를 실행하여야 한다.

          • 모니터 프로그램(예: OC-Console, Tera Term)을 설치(이미 설치되어 있는 경우에는 실행만 하면됨)하고 실행 한다.
          • 모니터 프로그램에서 필요한 설정(Serial Port와 Baudrate 등을 설정)을 한다.
          • 실험:
            • 개발 보드의 Reset SW를 누르면 모니터에 "KeyPad Input Testing" 메세지가 출력된다.
            • Keypad에서 문자를 입력하면 입력된 문자는 UART 통신을 이용하여 모니터에 출력된다.
            • SW PD0를 누르고 keypad의 key를 입력 하면 입력된 Data가 Buffer에 저장 되고 출력 되지 않는다. 입력된 Data의 수가 Buffer 크기를 초과하면 "Buf Full Error" 메세지가 출력된다.
      • 하나의 Keypad로 부터 서로 다른 2개의 Key code을 읽어 모니터에 출력하는 프로그램 예
        • 4 by 3 Keypad로 부터 Multi Code Key 값을 읽어 모니터에 출력하는 프로그램 예

        • 실험을 위한 준비
          • 실험 구성도를 참고하여 개발보드에 Keypad를 연결한다.
          • 컴퓨터(USB --> UART(RS232) 변환 모듈)의 RXD와 Atmega128의 TXD0(PE1)를 연결한다.
          • 컴퓨터(USB --> UART(RS232) 변환 모듈)의 TXD와 Atmega128의 RXD0(PE0)를 연결한다.
          • 주: 컴퓨터에 Serial Port가 없는 경우 "USB --> UART(RS232) 변환 모듈"를 사용(USB Port를 Serial Port로 변환)하여 연결한다. 개발보드에 따라서는 "USB --> UART(RS232) 변환 모듈"을 내장하고 있는 경우가 많기 때문에 본인이 사용하는 개발보드에서 확인 하여야 한다.

            참고자료: USB - Serial 변환 모듈

          • 컴퓨터(USB --> UART(RS232)의 GND와 Atmega128의 GND를 연결한다. "USB --> UART(RS232) 변환 모듈"를 사용하는 경우 변환 모듈의 GND와 Atmega128의 GND를 연결한다.
        • 실험 방법
          • GCC_c_asm_keypad_multi_uart_io_basic.zip 파일을 Download하여 압축을 해제한다.
          • Build → Build Solution 를 실행 하면 프로그램이 Build 되어 GCC_c_asm_keypad_multi_uart_io_basic.hex 파일이 생성된다.
          • GCC_c_asm_keypad_multi_uart_io_basic.hex를 개발 보드에 Upload 하고 프로그램을 실행한다.
          • 주: 모니터 프로그램(예: OC-Console, Tera Term)과 hex 파일을 Target Board에 Upload 하는 프로그램이 동일한 Port를 사용하기 때문에 모니터 프로그램을 중지하고 Upload를 실행하여야 한다.

          • 모니터 프로그램(예: OC-Console, Tera Term)을 설치(이미 설치되어 있는 경우에는 실행만 하면됨)하고 실행 한다.
          • 모니터 프로그램에서 필요한 설정(Serial Port와 Baudrate 등을 설정)을 한다.
          • 실험:
            • 개발 보드의 Reset SW를 누르면 모니터에 "Input Keypad, Output Uart", ": Key Code Table Change Key ", "# Key: CR Code"메세지가 출력된다.
            • key_code_table1 이 선택된 경우 Keypad에서 문자를 입력하면 숫자가 UART 통신을 이용하여 모니터에 출력되고, key_code_table2 가 선택된 경우 Keypad에서 문자를 입력하면 문자가 모니터에 출력된다.
            • * Key를 누르면 Key code table이 변경되어 현재 숫자가 출력되는 경우 문자가 출력된다. 만약 현재 문자가 출력되는 경우에는 숫자가 출력된다.
            • # Key는 CR Code로 사용된다.

  • Switch debouncing 과 Keypad Interfacing 관련 페이지 보기