MCU기초지식-1. MCU를 배우는 방법

여기에 기술되는 내용은 제가 그동안의 경험을 바탕으로 개인적으로 기술한 내용이므로 상업적인 목적으로 사용시에는 당 홈페 이지 운영자와 협의 하셔야만 합니다.

본 페이지에 구성된 내용중 틀린 내용이 있다면 메일 주십시요... 신속하게 수정 하겠습니다.

단 교육적인 목적이나 개인이 공부할 목적으로 이용하는 것은 제한없이 이용 하실수 있습니다.

기술된 내용중 잘못된 내용이 있다면 게시판에 올려 주시기 바라며 신속히 수정토록 하겠습니다.

MCU를 배우기 전에 익혀야 할 것들을 먼저 공부한 다음에 본격적으로 MC68HC11에 대해 공부하는 절차로 진행해 나가겠습니다.

먼저 익혀두어야 할 것들은 다음과 같습니다.

1. MCU를 배우는 방법

2. Address영역과 Data Memory영역

3. Address의 계산

4. Address Decoder

5. Register의 개념

6. Interrupt의 개념

1. MCU를 배우는 방법

MCU와 관련된 서적은 8051계열을 중심으로 많이 출판이 되고 또한 이러한 서적들을 기초로 하여 공부하는 사람들이 대단히 많습니다. 그러나 그러한 책들을 살펴보면 내용의 형식이 비슷하다는것은 나만이 느끼는 것은 아닐 것입니다.

국내 시장을 잠깐 살펴보면 크게는 두 부류의 MCU가 많은 사람들에 의해 사용이 되고 있으며 그 두가지는 인텔 계열의 그 유명한 8051과 초보자도 손쉽게 배우고 속도도 매우 빠른 마이크로칩스사의 PIC 계열일 것입니다.

이러한 MCU들의 장점은 구현되고 공개된 각종 회로 및 Application이 참으로 많다는데 있습니다. 어떠한 이유에서 그렇게 되었는지는 모르지만 아마도 사용자가 접근하기 쉽고 또 국내 여러업체에서 취급을 하며 이러한 이유로 인하여 사용자가 입수하기 쉽지가 않았을까 하고 개인적으로 생각해 봅니다.

아무튼 국내 MCU시장은 인텔 Core 및 PIC 가 거의 독차지 하고 있다고 해도 과언은 아닙니다. 또한 인텔 Core는 세컨 소스가 많습니다. 오리지널 8051보다 성능이 우수한 제품을 다른 회사에서 앞 다투어 출시하고 있으며 심지어는 8051 Core를 탑재한 FPGA까지 선보이고 있는 상황입니다.

그러나 국내에서는 모터롤라에서 출시한 MC68HC11을 사용하는 업체는 그리 많지 않습니다. 개발환경 또한 굉장히 열악 합니다. 단지 장점이라고는 사용자를 많이 의식한 명령어 …그리고8051보다는 강력한 기능 … .마지막으로 강력한 포인터 기능 및 연산 기능이 있습니다.

개인적인 생각으로 8051과 6811은 그 비교 자체가 무의미 하다고 생각하며 그 이유로는 기능적인 면에서 많은 차이가 있기 때문입니다. 이것은 결코 8051이 나쁘다는 이유는 아니며 단지 객관적인 비교로서 말씀을 드리는 것입니다.

그러니까 6811과 8051은 같은 8bit지만 비교대상이 아니라는 얘기입니다.

처음 MCU를 배우고자 하는 사람의 가장 골칫거리가 어떤 MCU를 배워야 할까 하는 것입니다. MCU의 바탕은 거의가 비슷합니다. RISC니 CISC니 하는것들은 지금부터 굳이 알 필요도 없으며 배우다 보면 여러분이 필요에 의해 자동으로 알 수 있는 것들입니다.

MCU 뿐만 아니라 무엇을 배우든지 마찬가지라 생각 되지만 항상 그 접근방법이 문제가 됩니다. 접근방법을 어떻게 하느냐에 따라서 배우는 시간이 단축이 되거나 중간에 포기 하거나 하게 되는 것입니다.

아마도 이글을 읽으시는 분들중에는 공감을 하시는 분이 많으리라 생각 됩니다만 개인적으로 MCU의 개념을 나눈다면 MCU는 크게 3가지로 나뉩니다. 하나는 Register의 개념이요 또 하나는 Interrupt 개념이며 마지막 한가지는 알고리즘의 구현입니다. 이중 나중에 여러분이 Level Up이 되었을 경우 가장 골치 아픈 부분이 바로 이 알고리즘의 구현 입니다. 이 부분은 누가 가르쳐 주는것도 물론 있겠습니다마는 대개의 경우 여러분 스스로가 해결 해야하는 가장 난해한 부분이 됩니다.

한가지가 또 있군요 … .MCU는 MCU를 배우는것으로 끝나지 않습니다. MCU주변에 붙는RTC,RAM,LCD,ROM, 각종 interface등 배워야 할 Device들이 산적해 있습니다. 프로그램을 짜고 돌리는것도 중요 하지만 주변 Device를 어떤 방식으로 Interface 할 것이냐 하는것 또한 중요 하며 결과적으로 여러분은 프로그램 짜는것만 배울것이 아니라 Hardware도 같이 공부를 해야만 한다는 것입니다. 사실은 이것이 더 중요할 수도 있습니다. 만일 Firmware는 할 줄 아는데 Hardware를 모른다면 그것은 차 바퀴가 하나는 네모고 하나는 동그란것과 같습니다. 그럼 차는 굴러가지 않겠지요. MCU로 프로그램을 짠다는 것은 외부에 부착되는 Device를 제어 하는것과 같지요 그러므로 Hardware를 모르고서는 보드에서 이상 발생시 배우지 않은 사람은 대책이 없는 겁니다.

그럼 답이 나왔군요 … .MCU를 배우려면 Hardware도 같이 배워라 …하는것이 제가 주장하는 바입니다. 아무튼 어떠한 MCU가 되었든 열심히 배우시기 바랍니다. MCU 하나를 똑부러지게 배우면 다른 칩을 배우기가 훨씬 수월 합니다. 금방 배우게 되지요.

MCU를 배우기 위해서는 약간의 공식이 필요 합니다.

먼저 제일 중요한 것이 Address의 개념이며 그리고 Memory 영역의 개념 그리고 MCU 내부에 항상 들어있는 Register의 개념 그리고 마지막으로 Interrupt의 개념 입니다. 명령어를 기입하고 실행하고 하는것은 책을 봐 가면서 해도 되고 알고리즘의 구현이야 머릿속으로 생각하면 된다지만 위에 기술한 개념들은 그렇게 해서는 절대 이해가 안되는 부분이며 프로그램 작성을 위해서는 그 개념을 완전히 이해 하고 넘어가야만 하는 내용들입니다.

만일 이러한 내용을 모르고서 프로그램을 작성 한다면 어려운 문제에 봉착 하였을 경우 해결을 하지 못하는 상황까지 가게 됩니다. 그러므로 어떤 MCU가 됐던지간에 위의 개념은 항상 먼저 터득해야 하는 부분이며 사실 이 부분은 많은 시간을 할애 해서라도 꼭 해결하고 넘어 가야만 하는 부분입니다. 더군다나 MC68HC11은 내부 Register가 많습니다.

그 이유는 그만큼 많은 기능이 내장이 되어 있다는 반증인데 …

이러한 기능들을 익히는것 또한 중요 하므로 지겹더라도 많은 시간이 걸린다 하더라도 꼭 이해하고 넘어 가시기 바랍니다. 어떠한 MCU를 배우던간에 위의 내용은 항상 숙지하고 이해하고 넘어가야 하는 부분입니다. 모든 MCU를 배움에 있어 공통이 되는 부분이지요 …제가 지금부터 기술하는 개념적인 내용은 MC68HC11에만 국한된 내용이 아닙니다. 이것은 거의 모든 8Bit 계열의 MCU에 적용되는 내용이며 이러한 내용을 이해하고 숙지 하셨다면 다른 MCU를 배우는 하나의 밑거름이 될 수 있습니다.

사실 다른 부분보다도 이 개념적인 부분의 이해가 중요 하다고 할 수 있겠습니다.

MCU기초지식_2. Address영역과 Data Memory 영역

2. Address영역과 Data Memory 영역

우리가 MCU를 공부하다 보면 이런말이 많이 나옵니다. 그렇다고 그 개념을 속 시원히 가르쳐 주는 책 또한 없습니다. 처음 MCU를 배우는 사람들이 가장 난해하게 생각하는 부분 또한 바로 Address영역과 Data Memory영역에 관한 개념일 것입니다.

또 확장(Expanded Mode)모드, 단일(Single Chip Mode)칩 모드라는것이 있습니다. 이건 무엇을 말하는 것일까요? 확장모드라는것은 외부에 롬을 장착하여 롬에 여러분이 작성하고 Compile한 프로그램을 내장 프로그램을 동작 시키는것을 말 하며 단일 칩 모드는 MCU내에 프로그램을 장착하여 프로그램을 실행하는것을 말 합니다. 그러므로 단일칩의 경우는 MCU내에 일정량의 Flash Memory영역을 가지고 있고 바로 이곳에 여러분이 작성한 프로그램을 장착 하겠지요 …

가장 대표적인 예가 바로 Atmel에서 출시하고 있는 AT89C51/52/55 시리즈가 되겠습니다. 이것은 내부에 Flash Memory를 내장하여 여러분이 작성하고 Compile한 프로그램을 장착 합니다. 이것의 장점은 무엇일까요? 바로 외부에 롬을 장착하지 않아도 되므로 Board의 Size가 작아진다는 장점과 그만큼 부품이 적게 들어가니까 제품의 가격이 그만큼 떨어지므로 가격 경쟁력이 있습니다.

MC68HC11은 8Bit계열의 칩으로서 외부 또는 내부를 Access할 수 있는 Address의 영역이 64KByte입니다. 이는 Address Bus가 A0 ~ A15까지 출력되기 때문인데 이것을 16진수로 표시하면 $FFFF이고 다시 10진수로 표기하면 65535Byte가 됩니다.

그러나 우리가 지금부터 배우고자 하는것은 10진수가 아닌 16진수와 2진수를 많이 쓰게 됩니다. 여러분은 10진수의 개념에서 벗어나 16진수의 개념을 가지고 이 MCU를 배우는 것이 이해하는데 상당히 도움이 될 것입니다.

우리가 흔히 16진수를 표기할때는 $이란 표시를 쓰게 되며 주로 숫자 앞에 붙이게 됩니다. 이것은 별도로 설명 안해도 16진수라는 말이므로 $이 붙을 경우는 16진수로 생각하시면 됩니다. 또 다른 MCU는 FFFFh 처럼 끝에 h를 붙이는 경우도 있습니다.

이것은 인텔계열이나 PIC 계열등에서 사용 하는 표기 방법인데 h는 hex의 약자로서 16진수라는것을 나타냅니다.

자! 그럼 이제 Address영역에 대해서 구체적으로 살펴 보도록 하겠습니다.

이 Address 영역을 공부할때 Data Memory 영역을 같이 이해해야 쉽게 이해 하실수 있습니다.

<그림 2-1>

<그림 2-1>은 Address 와 Data Memory영역과의 관계를 나타낸 그림입니다.

한 개의 Address는 한 개의 Data Memory 영역을 항상 가지고 있습니다. 여러분은 8Bit MCU하면 그것이 왜 8Bit MCU인지를 아시는지요 …그것은 바로 MCU에서 읽거나 쓸 수 있는 Data Bus가 8개냐 아니면 16개냐에 따라 결정이 됩니다. Data Bus가 16개라면 16bit의 MCU가 되겠지요 …

그럼 우리가 배우고자 하는 MC68HC11은 8bit MCU인데 이것이 8bit인 이유는? 바로 Address가 아니고 Data Memory를 Access할 수 있는 Data Bus가 8개인 이유이기 때문입니다.

MC68HC11A1은 256Byte의 Ram 영역을 가지고 있습니다. 이것을 16진수로 환산하게 되면 $00FF가 되겠지요 …그런데 계산기로 이것을 10진수로 계산 하면 255가 나올것입니다. 항상 16진수로 계산을 할때는 0도 포함이 됨을 주의 하시기 바랍니다. 즉 $0000도 Address이며 이 또한 Data Memory 영역을 가지게 됩니다. 그러므로 Ram 영역은 $0000 ~ $00FF 까지가 되는 것입니다.

자! 그럼 $0000 ~ $00FF라는 것은 무엇일까요? Address일까요? 아닐까요?

이것은 Address입니다. 그런데 따져보니까 256Byte영역을 가지고 있는 Address입니다. 그럼 Data Memory는 어디에 존재할까요? 제가 처음 설명할때 68HC11에는 256 Byte의 RAM이 존재 한다고 하였습니다. 바로 $0000 ~ $00FF영역에 RAM이 존재 하므로 RAM은 Data Memory 가 되는 것입니다.

즉 MCU는 Address $0000 ~ $00FF를 Access하게 되면 바로 RAM을 읽거나 쓰게 될 텐데 이때 바로 RAM이 Data Memory 영역이 되는 것입니다.

그래서 우리가 흔히 생각할때 Data Memory 하면 이 RAM을 생각하기 쉽습니다.

그러나 이것은 어디까지나 어떠한 Device를 Adress 영역의 어디에 붙이느냐에 따라 Data Memory의 종류가 결정이 됩니다. 예를 들어서 MC68HC11의 Control Register 영역은 Address가 $1000 ~ $103F까지 입니다. 그럼 이곳의 Data Memory영역에는 무엇이 있을까요? 바로 Control Register가 Data Memory가 되는 것입니다.

또 있습니다. 여러분들이 가장 많이 사용하는 LCD를 예를 들어 봅시다. 만일 LCD의 Data를 Write하는 번지를 $7000번지에 할당을 하였다면(이 부분은 Decoder와 관련이 있으므로 추후 설명될 것입니다.)여러분은 LCD에 값을 전시하기 위해 Data를 쓸것입니다. 이때 $7000번지에 해당하는 Data Memory는 어디겠습니까? 바로 LCD에 값을 Write 하였으므로 LCD가 Data Memory가 되는 것입니다.

또 여러분이 $2000번지에 74HC245를 달아서 센서입력을 연결 하였다고 생각해 봅시다. 그럼 MCU는 $2000번지를 읽을때 마다 센서의 값을 읽을수 있습니다. 그럼 $2000번지의 Data Memory는 무엇이 되겠습니까? 바로 센서의 값이 Data Memory가 되겠지요?

더 예를 들어 볼까요? $3000번지에 74HC574를 이용해서 LED를 점등 하고자 합니다.

그럼 여러분들은 $3000번지에 값을 쓰겠지요? 뭐 $01도 있을것이고 $0A도 있을 것이고 그럼 이때 Data Memory는 무엇이 될까요? 바로 LED가 되는 것입니다. 이해가 되셨는지요 …위의 예는 좀 더 복잡한 문제가 있습니다마는 여러분의 이해를 돕기 위해서 쉽게 예를 든것입니다.

위의 예를 보시면 아시겠지만 LCD에서 우리가 값을 읽을 필요는 없습니다. 그리고 LED를 제어 하면서 우리가 값을 읽을 필요는 없습니다. 그렇다고 센서값을 읽는데 우리가 그곳에 값을 쓸수는 없지요 …그렇습니다. Data Memory라는 것은 값을 RAM처럼 쓰거나 읽을수도 있지만 어떠한 Device를 붙이느냐에 따라 읽기 전용이냐 쓰기 전용이냐가 됩니다.

그러므로 위의 예들을 정리해 본다면 결국 Data Memory라는 것은 외부에 장착되는 각종 Device라고 이해는 되는데 그러한 Device를 제어하기 위해서는 번지라는 것이 필요하게 됩니다. 즉 내가 LED를 켜고싶다 하면 해당번지를 할당해야 하고 해당번지에 값을 쓴다는 의미는 LED를 켜고 끈다는 의미이며 이것이 곧 Data Memory임을 우리는 알 수 있습니다.

위의 예를 그림을 가지고 다시한번 정리 하겠습니다.

<그림 2-2>

<그림 2-2>를 보면 내부 RAM과 Control Register는 이미 MCU내에 그 위치가 결정이 되어 있습니다. 그러나 나머지 LCD,LED등의 Address는 여러분이 결정하는 것입니다. 그냥 $2000번지를 읽어 드린다고 해서 센서의 값이 읽혀 질까요? 절대 아닙니다. 왜 여러분이 Hardware를 공부해야 하는지가 여기서 나오는 겁니다. 바로 Address가 $2000번지일 경우에는 센서값을 읽을 수 있도록 여러분이 회로설계시 Hardware에서 작업을 해 주어야만 하는 것입니다.

이것을 우리는 Address Decoding이라고 하며 이것을 이용하여 메모리 맵을 잡는다고 하는 것입니다.

자! 이렇게 설명을 해도 아마 개념이 잡히지 않는분이 있을겁니다. 그럼 다음과 같이 설명을 해 보겠습니다.

<그림 2-3>

좀 이해가 되셨는지요 …우선 LED에 Data를 Write하는 방법에 대해서 설명을 해보겠습니다.

우선 회로는 74HC574라는 IC를 사용 했습니다. 이 칩은 D-Flip Flop 회로가 8개 내장된 칩으로서 입력 Clock의 상승 엣지(Lising Edge)에 의해 D(Data)값이 Q에 출력이 되는 칩입니다. 그럼 $3000일때 값을 Latch할수 있게끔 Decoder회로를 만들어 연결한 후 $3000번지에 값을 Write하면 해당값이 LED로서 전시가 되는 것입니다. 이때 우리는 Address Decoding을 하여 $3000번지가 되었을 경우 값을 쓸수 있도록 하였습니다. 이것은 바로 Address영역이라고 말할 수 있습니다.

그럼 74HC574에 써지는 값은? 그것은 Data Memory 영역이라고 말할 수 있습니다.그런데 74HC574는 출력용이지 입력용은 아닙니다. 그러므로 $3000번지에는 값을 쓸 수는 있으나 읽을수는 없습니다.

그러므로 Data Memory의 영역은 우리가 설계를 어떻게 하느냐에 따라 값을 읽거나 쓸 수도 있으며 읽을수만 있고 값을 쓰지 못하게끔 만들수도 있습니다.

지금까지 설명한 제2장 Address영역과 Data Memory영역의 개념은 잘읽어 보시고 개념을 이해 하시기 바랍니다. 만일 이해가 안 간다면 몇번이고 다시 읽어서 여러분의 것으로 만들어야만 하는 부분입니다. 꼭 이해하고 넘어 가세요

MCU기초지식_3. Address의 원리

3. Address의 원리

아마도 MC68HC11A1을 가르쳐 준다더니 영 이상한 것만 가르쳐 주고 있구만 … . 하시는 분이 있을지 모르겠습니다. 하지만 이러한 것이 기본이 되지 않고서는 절대로 MCU를 이해하지 못합니다. 꼭 짚고 넘어가야만 하는 부분입니다. 시간이 얼마가 걸리더라도 꼭 이해하고 넘어 가야지 그렇지 않으면 MCU를 배우시는데 상당히 고생 하실 것입니다.

우리는 전 장에서 64kbyte의 Address영역을 갖는 MCU는 Address가 A0 ~ A15까지 있음을 배웠습니다. 그럼 이것이 과연 뭐길래 MCU마다 붙어있는 것일까요?

아래 <그림 3-1>을 보시기 바랍니다.

<그림 3-1>

우리가 배우게 될 MC68HC11A1의 Address 및 Data Interface 방식은 Address와 Data Bus가 서로 공유하는 Multiplexer 방식입니다. 그러므로 <그림 4>와 같이 74HC573이라는 IC를 이용하여 Address와 Data Bus를 분리하는 방법을 사용해야 합니다.

이것을 Timing도를 가지고 설명을 한다면 아마도 여러분은 헷갈릴테지만 아주 간단하게라도 설명을 해 봅시다.

<그림 3-2>

원래는 <그림 3-2>보다는 더 복잡한 타이밍이지만 우리는 여기서 Address와 Data를 분리하는 원리만 알면 되므로 간단하게 그림으로 나타내었습니다.

MC68HC11은 AS(Address Strob)라는 단자가 있습니다. 이것은 E Clock처럼 일정한 주기로 펄스를 출력 하는데 이 AS 단자가 74HC573의 Latch Enable단자로 입력되며 74HC573은 엣지 출력이 아닌 레벨 출력으로서 AS 단자가 High가 되어야만 입력값이 출력에 나타납니다. 진리표는 Datasheet를 참고 하시기 바랍니다.

먼저 MCU는 AS를 출력 합니다. 그리고 AS가 High가되고 약 70nS후에 AD BUS는 Address를 출력 합니다. 이때 AS는 High가 되어 있으므로 74HC573은 MCU의 Address값을 출력하게 되며 AS는 다시 Low로 떨어지게 됩니다.뒤이어 Data의값이 MCU에서 출력 또는 외부 Device에서 입력이 되지만 74HC573은 Latch Enable 단자가 Low일 경우 출력이 이전값을 가지고 있기 때문에 Data값은 출력이 되지 않습니다.

이때 74HC573은 Address A0 ~ A7까지의 값을 다음 AS가 High 가 되기 전까지는 Latch하고 있으며 이것을 우리가 Address값으로 사용하게 됩니다.

다시 정리를 해 보자면 … .

Address와 Data BUS를 서로 공유하는 Multiplexer방식에서는 Address와 Data를 분리해 줘야 하는 그 무언가가 있어야 합니다. 그것이 MC68HC11A1에서는 AS(Address Strob)라는 것이고 인텔계열의 칩은 ALE라는 단자로 Address와 Data를 분리하고 있습니다. 이러한 방식의 장점은 아무래도 BUS를 공유 하므로 CPU에 연결된 PIN의 개수를 줄일 수 있으며 이로 인하여 CPU Size를 작게 만들수 있는 장점이 있습니다. 그러나 어쨌든 이러한 방식의 단점은 속도 문제를 들 수 있습니다. 한 개의 BUS선을 이용하여 두가지 기능을 사용 하다보니 어쨌든 분리된 BUS보다는 속도가 늦을수 밖에 없습니다. 하지만 이러한 Multiplexer 방식은 단점보다는 장점이 가져다 주는 효과가 크기 때문에 많은 반도체 회사에서 이러한 방식을 채용하고 있으며 실제로 우리가 사용하는 일반적인 MCU또한 Multiplexer방식으로 구현되고 있습니다.

어쨌든 순서를 정리 하자면 아래와 같습니다.

1. AS가 출력이 되어 75HC573의 Latch Enable(LE)을 활성화 한다.

우리가 책을 보면 활성화 한다라는 말을 많이 사용 합니다. 활성화 한다라는 말은 그 기능을 살린다는 의미로서 동작을 시킨다는 것으로 생각 하시면 됩니다.

2. AS가 HIGH가 된 후에 CPU는 Address를 출력한다.

이 의미는 여러분이 지정한 Address가 되었든 CPU가 명령어 처리를 위한 Address가 되었든 해당 Address를 출력 합니다.

3. 이때 74HC573은 AS에 의해 입력값이 출력에 나타나므로 현재 CPU에서 출력된 Address의 값이 74HC573의 출력에 나타 납니다.

4. AS는 다시 Low가 되고 CPU는 Data를 출력 하거나 방금전에 출력한 Address가 외부 Device를 읽는 Address였다면 외부Device의 Data가 BUS에 실리게 됩니다.

이런 원리는 비단 MC68HC11에만 적용되는것은 아니고 Multiplexer방식을 사용하는 거의 모든 MCU에 적용 된다고 보시면 됩니다. 다만 AS가 아닌 다른 이름으로 Address를 분리 합니다.

여러분은 1000번지 2000번지 3150번지 하는 내용들을 어디선가 한번쯤은 들어 보신 적이 있을 겁니다. 그럼 이것이 MCU Address와 어떠한 관계가 있을까요?

우리는 이전에 A0 ~ A15까지가 64kbyte를 Access하는데 필요한 Address영역이라고 배웠습니다. 그럼 A0 ~ A15를 어떻게 조합을 하길래 1000번지니 2000번지니 하는 것들이 나오게 될까요?

A15는 MSB(Most Significant Bit) 즉 최상위 Bit를 말 합니다.

A0는 LSB(Least Significant Bit)는 최하위 Bit를 말 합니다.

그럼 Address가 어떠한 조합으로 번지가 결정되는지 알아 보도록 하겠습니다.

<그림 3-3>

<그림 3-3>을 보면 각각의 Address는 4bit로 번지의 단위가 결정됨을 우리는 알 수 있습니다. 그럼 이제 한가지 예를 들어서 설명을 해 볼까요?

여러분은 BCD(Binary Coded Decimal)에 대해서 아실겁니다. 바로 이진수를 십진법으로 표시하는 기법인데요 … 이 4bit단위로 단위가 결정되는 Address를 BCD를 이용하여 번지를 알아 냅니다.

먼저 $34F2번지를 가지고 어떻게 Address가 Decoding되는지 살펴 보겠습니다.

<그림 3-4>

A12(1), A13(2), A14(4), A15(8) 은 1000단위의 번지 입니다. 보라색으로 된 부분은 현재 High 상태이고 검은색의 Address는 모두 Low상태입니다. 그럼 ()안의 BCD Code를 계산하면 1+2=3이므로 3이되고 이 Address의 단위는 1000단위이므로 3000이 되는데 이것을 16진수로 표기한다면 $3000이 되는 것입니다.

그럼 이번에는 100번지 단위를 계산해 보겠습니다. A8(1), A9(2), A10(4), A11(8) 이므로 $0400이 됩니다. 이것을 1000단위의 값과 더하게 되면 $3400이 됩니다.

이번에는 10번지 단위를 계산 해 보겠습니다. A8(1), A9(2), A10(4), A11(8) 이 모두 보라색이므로 10번지 단위는 현재 High가 출력되고 있습니다. 그러면 1+2+4+8 = $0F가 됩니다. 이것을 $3400과 더하면 $34F0가 되는 것입니다. 그럼 마지막으로 1번지 단위는 어떻게 될까요? 이것은 여러분이 한번 해 보시기 바랍니다. 값이 2가 나오면 되는데 왜 2라는 값이 나오는지를 아셔야 합니다.

이제 다시한번 Address를 추출하는 방법을 정리 하자면

1.먼저 Nible단위(4bit)로 Address 를 분리 합니다.

이때 MSB는 1000번지의 단위를 가지며 LSB는 1번지의 단위를 갖게 됩니다.

2. 이렇게 분리된 각각의 Address는 BCD로 환산하여 내가 원하는 Address를 만들면 됩니다.

그래서 우리가 다른 책들을 보면 LED 제어 포트는 $A000번지 그리고 LCD 제어 포트는 $8000번지 라고 하는것들이 사용자가 임의로 MCU가 사용하지 않는 Address를 할당하여 Decoding을 한후 이것을 이용 외부에 부착된 각종 Device를 제어 하는것입니다.

지금까지 설명한 내용들은 다음 페이지 부터 공부하게 될 Hardware에서의 Address Decoding을 하기 위한 준비 작업으로서 하나라도 이해가 되지 않는다면 자꾸 반복하여 그 원리를 꼭 깨우치시기 바랍니다.

실제로 프로그램시 많은 문제의 발생은 이러한 Address Decoding에서 발견되며 한번 잘못되면 프로그램이 실행도 안되는 사태가 발생하게 되고 만일 이러한 원리를 모른다면 아마도 여러분은 자신의 우매함도 모른채 Board를 어느 구석에 처박을지도 모릅니다.

단언 하건데 …Address Decoding을 이해하는 사람은 MCU를 거의 반은 배웠다고 해도 과언이 아닐 정도로 실은 상당히 중요한 부분입니다.

꼭 이해하고 넘어 가시기 바랍니다. 지금까지 제가 설명드린 부분을 조금이라도 이해 못한다면 다음부터 설명드리는 내용을 전혀 이해 못할지도 모르기 때문입니다.

MCU기초지식_4. Address Decoder

4. Address Decoder

<그림 4-1>

<그림 4-1>은 가장 기본적인 Decoder 회로를 보여주고 있습니다.

우리가 Decoder 회로를 구성할때 가장 많이 쓰는 IC는 74HC138, 74HC139 등입니다. 이것은 Datasheet를 보시면 아시겠지만 BCD입력을 Binary로 바꾸어 주는 역할을 수행하는 Device입니다. 또한 출력이 활성화 되었을 경우 LOW로 되기 때문에 우리가 외부 Device를 Access 하기 위한 조건과 같습니다.

그럼 일단 위의 구조를 말로 풀어서 설명을 해 보겠습니다. 우리는 전장에서 A12,A13,A14,A15는 1000번지의 단위를 갖는다고 배웠습니다. 그럼 위의 Decoder 회로는 1000번지 단위로 이어지는 Address Decoder가 되는 것입 니다. 만일 위의 회로가 이해가 가지 않는 분이 있다면 74HC138의 Datasheet에 있는 진리표를 참고 하시기 바랍니다.

그럼 이중에 두가지만 예를 들어서 설명 하겠습니다. 먼저 $2000번지와 $7000 번지를 예로들면 일단 74HC138에 출력이 나오도록 하려면 G1,G2A,G2B에 활성화용 레벨이 입력 되어야 합니다. 즉 G1에는 High G2A 및 G2B에는 Low의 값이 입력 되어야만 현재 입력된 A12 ~ A15의 값을 해독하여 Yx 단자에 출력 하는 것입니다. 그럼 $2000번지에 Low값을 출력 하려면 입력이 어떻게 되어야 할까요?

E_CLK은 High상태이고 A12,A14,A15는 Low 가 되어야만 Y2에 Low값이 출력이 되겠지요? 즉 다시말해서 Address는 A13을 제외 하고는 모두 Low상태로 있어야만 $2000번지에 Low값이 출력이 된다는 얘기입니다. 이해가 안가십니까?

그럼 이번엔 $7000번지를 가지고 설명을 해 봅시다.

E_CLK은 High상태이고 $07이라는 값이 될 조건은 A12,A13,A14만 High상태로 되어 있어야 합니다. 전장에서 우리는 BCD에 관한것을 배웠습니다. A12(1),A13(2),A14(4)라고 말입니다. 그럼 1+2+4=7이므로 그리고 단위는 1000단위의 번지이므로 결국 $7000번지가 되는데 이것이 실제로 Y7에 Low값이 출력되는 조건이 되는것입니다.

그럼 이것도 이해가 안 된다면 다음은 진리값을 가지고 설명을 해 보겠습니다.

<그림 4-2>

<그림 4-2>는 74138의 진리값을 나타내고 있습니다. 입력부를 한번 볼까요?

출력이 활성화 되기 위해서는 G1이 일단 High값이 입력이 되야하고 G2A,G2B는 Low값이 입력이 되어야 하는 군요 그리고 X라고 되어 있는 것은 무시 입니다. 즉 G2A,G2B 둘중 하나가 무조건 High 상태라면 나머지 X는 값이 High든 Low던 간에 출력이 모두 High상태가 된다는 의미 입니다.

우리는 Decoder를 만들때 G1에 E_CLK이라는것을 입력 하였습니다. 그렇게 되면 출력에 Low값이 나오게 하려면 G1의 값은 High라는 조건이 되어야만 합니다. 그러므로 E_CLK이 High가 되어야만 하겠지요 … 그리고 G2A,G2B의 값이 Low가 되어야만 출력이 활성화 될 수 있는 조건이 되므로 우리는 이 단자에 A15(8)을 입력 하였습니다. 만일 A15가 High 상태라면 어떻게 됩니까? 출력은 모두 High가 되므로 동작이 무의미 하겠지요 … 즉 A15가 High상태라는것은 CPU의 Address가 $8000번지 이상을 현재 Access하고 있다는 의미가 됩니다. 그러므로 지금 우리가 구성한 Decoder는 동작을 하지 않고 있는 상태가 되지요 … 즉 지금의 Decoder 구성으로 $8000번지부터는 Access할 수 없다는 것입니다.

왜냐하면 A15단자가 G2A,G2B에 연결이 되어 있으므로 만일 A15가 활성화 되어 High 상태가 된다면 Gate는 열리지 않기 때문입니다.

그럼 이제 우리가 만든 Decoder회로를 가지고 74138의 진리표에 대입을 해 보도록 하겠습니다.

E_CLK이 High가 되었다고 가정하고 $2000번지의 값을 계산 한다면 A13만 High가 되고 나머지 A12,A14,A15는 모두 Low가 되는것이라고 우리는 전장에서 배웠습니다. 그럼 74138의 A,B,C에 입력되는 단자중 B단자만 High상태이고 나머지 A,C는 모두 Low 상태가 됩니다.

그럼 B만 High일 경우 Y2의 단자는 어떻게 됩니까? 진리표를 보면 Y2만 Low이고 나머지는 모두 High 상태입니다. 바로 이 상태가 CPU가 $2000번지를 Access하여 우리가 흔히 말하는 Chip Select 하고 있다고 표현을 하는 것입니다.

Chip Select란 무엇이냐 CPU가 나라면 내가 맘에 드는 여자를 한명 찜 한거와 같습니다. CPU가 외부에 부착된 Device하나를 선택한 것입니다.

그럼 이번에는 $7000번지를 한번 계산해 보도록 하지요 … 7이라는 숫자를 계산 하려면 BCD 계산법에서 1+2+4=7이 됩니다. 그렇다면 A,B,C 입력 단자 모두가 High상태가 되어야만 합니다. 왜냐구여?

BCD로 계산을 하게되면 A12는 1, A13은 2, A14는 4라고 전장에서 배웠잖습니까 … 그럼 결국엔 A+B+C=Y7이라는 얘기가 되며 이는 곧 A12,A13,A14가 모두 High 상태로 되어 있다는 결론에 도달 합니다. 이러한 조건은 모두 E_CLK이 High상태일때 출력이 된다는 것과 A15가 Low상태로 되어 있어야 한다는 전제조건이 있습니다. 그럼 나머지 Address도 여러분이 한번 계산해 보시기 바랍니다.

참고로 MC68HC11A1은 주변 Device와의 동기를 E Clock이라는 주파수를 가지고 맞춥니다. E Clock이라고 하는것은 우리가 7.3728MHz의 크리스탈이나 O.S.C를 사용할 때 이를 4분주한 것으로서 1.8432MHz의 주파수를 출력하며 실제로 이 주파수가 MC68HC11A1을 동작 시키는 주파수 입니다. 이것은 특별히 Firmware적으로 구현할 부분은 없고 Hardware적으로 전원만 인가되면 자동으로 출력되는 Clock입니다.

<그림 4-3>

지금까지 우리는 1000번지 단위의 Address Decoding에 대해서 배웠습니다.

이제 <그림 4-3>은 100번지 단위의 Address Decoding에 대해서 보여주고 있습니다.

회로는 1000번지 단위와 같고 단지 달라진거라고는 입력되는 Address의 Bit가 바뀌어 있습니다. 전장에서 배웠던 100번지 단위의 Address입니다. 계산하는 방법은 1000번지 단위에서 했던것과 별반 다를것이 없으므로 한가지만 예를 들어 설명토록 해 보겠습니다.

먼저 $x300번지에 대해서 계산을 해 보겠습니다. 일단 74138의 Gate가 열리려면 G1은 High G2A,G2B는 Low 상태가 됩니다. G2A, G2B가 Low상태가 된다는것은 A11(8)이 Low가 되는것을 의미하며 전체 수가 7을 넘지 않음을 뜻합니다. 왜냐하면 A8(1),A9(2),A10(4) 1+2+4=7 이 되므로 절대로 7을 초과할 수 없습니다. 만일 7을 초과 한다면 이것은 A11(8)이 High상태가 되는 것이므로 이때는 Address Decoder로서의 기능을 상실 하는것과 같게 됩니다. 그럼 $x0300에 Low출력이 나오도록 하려면 A8(1),A9(2)가 High 상태가 되어야만 됩니다. 1+2=3이 되므로 Y3에 Low출력이 됨을 우리는 알 수 있습니다.

혹시 잘 모르시는 분이 계시다면 앞페이지의 1000번지 단위를 다시한번 읽어 주시고 여기서 x는 1000번지 단위이고 어떤 것이 될지 모르므로 무시 하셔도 됩니다. 제가 설명 드리고자 한것은 100번지 단위에 대한 내용입니다.

그럼 이제 실제로 실무에 적용하는 Address Decoder에 대해서 알아보도록 하겠습니다.

<그림 4-4>

<그림 4-4>는 MC68HC11 Tranning Kit에서 실제 사용한 Address Decoder 회로도 입니다. 보긴엔 좀 어렵고 복잡해 보이지만 알고나면 이보다 더 쉽고 재미있는것이 없습니다. 지겹고 지루하고 어려워도 참고 이해를 하도록 하세요 … 만일 이 부분에서 포기하게 된다면 여러분의 Level Up은 묘연한 것입니다. 그리고 이 부분을 모른다면 프로그램 하기도 힘들고요 …외부 Chip Select 번지도 모르는데 어떻게 프로그램을 짤 수가 있겠습니까? 그러니까 꼭 이해하고 넘어 가시구여 … 이 부분은 MC68HC11에만 국한된 내용이 아닙니다. 거의 모든 MCU에서 구현해야만 하는 회로들 입니다. 그러니까 차분하게 열심히 공부 하세요 …

그럼 먼저 LED_CS1에 대해서 설명 합니다. 참고로 이 번지는 $1100번지 입니다.

그럼 계산해 볼까요? 먼저 U4를 봐 주시기 바랍니다. 어디서 많이 보았죠? 일단 G1은 E_CLK이 연결 되어 있으므로 Gate1이 열리려면 입력이 High가 되어야만 하고 G2A,G2B는 Low로 되어 있어야 하므로 출력되는 Address Decode의 값은 $7FFF이하임을 우리는 알 수 있습니다. 그럼 출력이 U4의 Y1으로 출력이 되었으므로 이러한 조건이 되기 위해서는 A12(1)는 High, A13(2)는 Low, A14(4)는 Low가 되어야만 합니다. 그럼 이 번지는 몇번지 일까요? 바로 $1000번지가 됩니다. 아직도 모르시는 분은 제4장 처음부터 다시 공부 하세요 …그럼 U4의 Y1은 Low출력이 되고 이것이 다시 U1의 G2A 및 G2B로 입력이 됩니다. U1의 G2A,G2B는 Low가 입력이 되어야만 Gate를 연다고 우리는 배웠습니다.

그럼 이제 U1에 입력되는 Address를 잘 보시기 바랍니다. 모두 100번지 단위의 Address입니다.

U1의 G1은 High가 되어야만 Gate가 열립니다. 그러나 A11이 이러한 조건을 갖추기 위해서는 Low의 값이 되어야 하겠지요 그래야 인버터에 의해 반전 되므로 실제로 U1의 G1에 입력되는 값은 High가 됩니다. 그럼 역으로 계산하면 U1에서 뽑을 수 있는 100번지의 출력은 700번지를 넘지 못하겠군요 … 맞습니까? 역시 U1도 마찬가지로 Y1에서 LED_CS1에 대한 출력을 인출하고 있습니다. 그럼 Y1에 Low의 출력이 되도록 만들려면 Address의 조합이 어떻게 되어야 하겠습니까? A8만 High이고 나머지는 모두 Low가 되어야 하는군요 … 그럼 이 번지는 몇번지가 되겠습니까? 바로 $x100번지가 되는것입니다.

즉 U1은 U4가 $1000번지일경우 선택이 되는 Device이며 U4의 Y1에 출력을 내기 위해서는 $x100이라는 Address를 입력해야 합니다. 그러므로 U1의 Y1에 출력되는 Address의 값은 $1100의 값이 되는 것입니다.

이것으로 끝일까요? 절대 아닙니다.

LED_CS1이 쓰기 전용입니까 아니면 읽기 전용입니까? 우리가 통상적으로 LED를 켤때 값을 쓰겠습니까? 아니면 읽겠습니까? 값을 써야만 합니다. 그러므로 LED_CS1의 Chip Select는 Write Port로서 존재해야 하므로 U1의 Y1 후단에 OR Gate를 연결하고 다시 Or Gate의 또다른 입력에 Write Signal을 연결 합니다.

<그림 4-5>

MC68HC11의 Read/Write는 인텔계열과는 약간 다릅니다. 한 개의 R/W핀에서 Read Write가 출력되는 것이죠 이 핀의 상태가 Low일 경우는 Write상태이고 High일때는 Read 상태입니다. 그러나 출시되고 있는 각종 TTL이나 모터롤라가 아닌 타회사의 각종 Device는 Intel계열과 Interface되는 것이 많습니다.

그래서 이것을 Intel계열과 동일한 방식으로 하기 위해서 위와 같이 사용하면 됩니다.

일단 Low 신호는 Write신호 이므로 이를 반전할 필요없이 그냥 사용 하면 Write신호로서 사용할 수 있습니다. 그러나 Read신호의 경우에는 위와 같이 반전하여 Low신호로 되게끔 만들어 주어야 합니다.

이렇게 Chip Select 도 그렇고 Read Write 신호도 모두 Low로 만들어 주어야 하는 이유는 거의 모든 Device를 선택할때 외부 Device의 Chip Select 입력 단자는 Low에서 활성화 될 수 있도록 구성이 되어 있으며 또한 해당 Device를 읽거나 쓰고자 할 경우에는 대개의 경우 Lising Edge에서 값을 가져오거나 쓰도록 되어 있습니다.

대표적인 예로 74HC574를 들수 있는데 입력값을 출력에 Latch하도록 하려면 CLK라는 단자에 Clock을 입력하고 이 Clock이 Lising Edge시에 값이 Latch되도록 하고 있습니다.

그러므로 만일 여러분이 값을 Write하고자 한다면 Write 단자에 평상시 High로 있다가 값을 쓰는 시간에 Low로 떨어졌다가 다시 High로 올라감을 스코프로 확인 하실수 있습니다.

<그림 4-6>

우리는 이미 $1100번지를 LED_CS1번지로 설정을 했음을 앞페이지에서 공부 하였습니다. 그럼 이것을 우리는 Write Port로 지정을 해야만 합니다. OR Gate의 출력은 입력이 한 개라도 High상태가 되면 출력은 무조건 High가 됩니다. 그럼 외부 Device를 선택 하려면 Low로 만들어야 하는데 이때에는 입력이 모두 Low 상태가 되어야만 합니다. 그럼 일단 $1100번지를 선택 한다면 U1의 Y1은 출력이 Low입니다. 그리고 여러분이 LED_CS1에 값을 쓴다면 MCU는 Write신호를 Low로 만들 것입니다. 그럼 U2/A의 출력은 Low로 떨어질 것이고 이때 바로 외부 Device를 선택함과 동시에 Lising Edge에서 값을 쓰게 되는 것입니다. 이해가 되셨는지요? 이해가 안 되신 분은 다시 처음부터 공부 하시기 바랍니다. 그리고 이해가 되신분은 이제 LED_CS2를 공부 하여 보시기 바랍니다. 제가 말씀드린 내용데로 그대로 따져보게 되면 $1200번지에 LED_CS2가 존재함을 아실겁니다.

만일 저와 같은 결과가 나오지 않는분이 있다면 아직도 이해를 못하신 것이므로 다시 철저히 공부 하셔야 합니다.

<그림 4-7>

<그림 4-7>은 MC68HC11이 RAM과 ROM을 Access하고 있는 회로입니다.

먼저 RAM을 Access하는 방법을 기술 하도록 하겠습니다.

자! 그럼 여러분이 한번 계산해 보시기 바랍니다. RAM을 Access할 수 있는 번지는 얼마 입니까? 예! $2000번지 입니다. 하지만 좀 틀린것이 있죠? Read/Write단자를 묶지 않았습니다. 왜 그럴까요? RAM은 우리가 값을 쓰기도 하고 읽기도 해야 합니다.

그것뿐만이 아니라 RAM은 일정한 용량을 가지고 있습니다. 뭐 32kByte니 하는 용량말이죠 …그렇다면 나머지는 어디다 써야 할까요? 만일 $2001번지를 Access한다면 RAM_CS는 Low로 떨어질까요? 한번 계산해 보십시요 …Low로 떨어지는것이 정답입니다. 위의 회로는 $2000번지로 Ram을 선택하도록 되어 있습니다. 만일 Ram을 선택하지 않기 위해서는 $1000번지나 $3000번지로 번지를 옮겨야만 합니다.

아마도 여러분이 아무리 계산해도 RAM의 번지는 $2000~$2FFF까지는 계속 선택이 될 것입니다. 바로 이것이 Chip Select의 범위 인데요 …

만일 여러분이 딱 한 개의 Address만으로 외부 Device를 선택하고 싶다면 Address 16개를 모두 Decoding해야만 합니다. 즉 RAM_CS를 딱 한 개의 번지에만 지정을 해야 한다는 말입니다.

하지만 RAM이라고 하는것은 우리가 변수도 설정해야 하고 Data도 저장해야 합니다.

그럼 일정한 범위의 Address를 가져야만 합니다.

아! 물론 전에 설명한 LED_CS1,2도 일정한 Address 영역을 가지고 있습니다.

그러나 RAM과 다른점은 RAM의 경우는 Device에 Address단자와 Data단자가 있습니다.

<그림 4-8>

<그림 4-8>과 같이 RAM은 외부에 Address 및 Data핀이 존재 합니다. 그러므로 RAM_CS로 우리가 RAM을 Access할 경우에는 RAM의 Address에 선택한 Address가 입력이 됩니다. 즉 $2000에 RAM이 Select 되도록 설계는 하였습니다마는 $2001을 선택 한다면 RAM도 선택이 되지만 RAM의 Address BUS에는 $2001이라는 Address가 입력되므로 읽기 모드라면 RAM이 해당 번지의 값을 출력하거나 CPU에서 쓰기(Write) 모드일 경우는 해당값을 저장하는 것입니다.

다시한번 정리해 보겠습니다.

LED_CS같은 경우에는 우리가 100번지 단위로 Chip Select를 만들었습니다.

여기에는 중요한 사실이 있습니다. 만일 외부 Device를 Chip Select하는경우가 한두개의 경우가 아니고 20개가 넘는경우 …만일 이것을 1000번지 단위로 잘라서 Decoder를 만든다면 아마도 64KByte 전영역을 할당을 해도 모자랄 겁니다. 하지만 이것을 100번지 단위로 Decoder를 만들어 보시기 바랍니다. 2개의 100번지 단위만 있으면 32개의 Chip Select를 만들수 있습니다. 만일 더 복잡해서 도저히 100번지 단위로는 안되겠다 할 경우에는 10번지 1번지 단위까지도 Chip Select를 만드는 경우도 있습니다.

그러니까 결론은 100번지 단위로 하게되면 하위 10번지나 1번지에 구애받지 않고 다음 100번지로 넘어갈때까지 그 100번지 범위안에서 Chip Select를 하게 되면 계속 같은 Device를 선택할 수 있다는 말입니다. 만일 100번지 단위인 $x100으로 구성 하였다면 $x1FF까지는 계속 같은 Device가 선택이 된다는 것입니다.

예를 한가지만 더 들어 보겠습니다.

만일 10번지 단위인 $xx10으로 Chip Select 를 나누었다면 $xx20이 되기 전까지는 계속 같은 Device를 선택하게 됩니다. 그러므로 Address를 세분화 해서 1번지 단위나 10번지 단위로 나누게 되면 Decoder 회로가 상당히 복잡해 집니다. 즉 74138을 3개 4개를 써야만 하는 경우가 발생을 하므로 이것은 회로설계자가 적절하게 프로그램의 용량등을 계산하여 잡아줘야 하는 부분입니다.

이것을 우리는 Memory Map을 설정 한다고 하는 것이며 이러한것이 사전에 준비없이 설계에 들어 간다면 아마도 나중에 프로그램 작성시 상당한 어려움에 봉착하게 되는 것입니다.

<그림 4-7>을 보시기 바랍니다.

이제 지금부터 제일 중요한 ROM을 읽는 방법에 대해서 설명을 하도록 하겠습니다. 이것이 Decoder의 마지막 부분입니다. ROM이라고 하는것은 읽을수만 있지 쓸수는 없습니다. 그러나 요즘에는 Flash Memory라는 것이 있어서 값도 쓰고 읽을수 있지만 말입니다. 아무튼<그림 4-7>은 좀 특이 합니다. 원래가 MC68HC11은 512K용 ROM을 사용 하도록 되어 있습니다. 왜냐하면 인터럽트 벡터가 $FFD6부분에 자리잡고 있기 때문에 이것을 256K ROM을 사용 한다면 32k용량밖에는 되지 않으므로 $7FFF까지 밖에는 Access가 되질 않습니다. 그렇다면 $FFD6에 있는 것들은 어찌 할까요?

그래서 약간의 변칙을 사용 하였습니다. Address가 $7000~$7FFF, $F000 ~ $FFFF를 다 읽을 수 있도록 Decoder 회로를 만들었습니다.

먼저 U4의 Y7은 잘 계산해 보시면 $7000~$7FFF까지 선택되고 그 출력은 U5/A에 입력됨을 우리는 알 수 있습니다. 그리고 U6의 G2A,G2B를 봅시다. A15단자가 반전되어 입력 되었습니다.

그렇다면 U6의 Y7에 Low가 출력되기 위해서는 A15는 High 상태가 되어야 하고 이것은 U6의 Y0출력이 $8000번지부터 출력됨을 알 수 있습니다.

그렇다면 Y7은 $F000부터 출력이 됩니다. 그리고 이것이 U5/A AND Gate로 입력이 되었고 평상시 U4나 U6에서 출력이 없을경우 High상태를 유지 하므로 U5/A의 입력중 어느 하나가 Low가 되더라도 출력은 Low가 됩니다.

결국 $7000번지가 되든 $F000번지가 되든 둘다 Access하게끔 만들겠다는 의도 입니다.

U5/A의 출력은 다시 OR Gate로 입력 되었고 OR Gate의 다른 입력은 Read 단자와 또 연결이 되어 있습니다. 그렇다면 지금까지 설명한 ROM을 Chip Select할 수 있는 것은 Read 모드일때만 가능 하다는 말이 됩니다.

그렇다면 $F000부터 ROM을 선택할 수 있게끔 하지 왜 $7000번지도 만들어 놨는지 이해 못하시는 분이 계실겁니다. 이것은 여러분의 편의를 위해서 일부러 만들어 놓은 것입니다.

일반 27C512의 경우에는 내부 데이터를 지우려면 지우는 Eraser가 있어야 하고 가격 또한 만만치 않습니다. 그럼 가장 쉽게 할 수 있는 방법은 무엇일까요?

그것은 Flash Memory릉 이용해서 쉽게 지우고 쓰고 해서 프로그램 작성한것을 확인하는데까지 오랜시간이 걸리지 않게끔 하기 위해서 입니다.

그러나 512K를 써야 64KByte를 사용할 수 있는데 256K를 사용해서 32KByte영역밖에 Access할 수 없습니다. 512K나 256K를 8로 나눠 보세요 …

32K라고 하는것은 Address단자가 A14까지 밖에는 없습니다.

그래서 <그림 4-7>과 같이 약간의 변칙적인 방법을 사용 하였고 실제 이러한 방법은 많은 곳에서 사용되고 있습니다.

그러나 어디까지나 우리는 Decoder에 대한 원리를 이해하기 위한 것이므로 지금까지 제가 설명드린 내용들이 머리에 쏙쏙 들어 온다면 여러분은 이미 한단계 Level Up이 된 것입니다. 이제 실무에 적용해서 Decoder를 만드는 일만 남았습니다.

여기까지 공부 하시느라 정말 수고가 많으셨습니다. 만일 이해가 안되는 분이 계시다면 한가지라도 이해가 안 된다면 다시한번 읽어서 완전하게 이해를 하시고 넘어 가시기 바랍니다. 이제부터는 MC68HC11A1에 대해서 본격적으로 Study를 할 것이므로 지금까지 설명한 Address의 원리와 Decoder의 동작 원리를 모르신다면 다음장 부터 배워야 하는 MCU를 이해 하는데 상당한 어려움이 있을겁니다.

그러므로 지겹지만 차분히 읽어서 여러분의 것으로 만드시기 바랍니다.

MCU기초지식-5. Register의 개념

5. Register의 개념

MCU를 보면 항상 이 Register라는것이 존재 합니다. 그럼 이 Register가 하는 역할은 무엇일까요? MCU라고 하는것은 내부에 수많은 기능을 내장하고 있습니다. 대표적인 것으로서 타이머가 있겠고 뭐 시리얼 통신 모듈, 때에 따라서는 AD Converter가 내장이 된것도 있습니다.

그럼 여러분은 이러한 기능을 사용할때 어떻게 사용 하는지에 대해서는 잘 모르실겁니다. 초보자가 항상 MCU를 배우고저 접근할때 많은 고민을 하는 부분이 바로 이 부분이기도 하구요 …

처음에 개념조차 모르니까 어떻게 공부해야 하는지도 모르는경우가 많습니다.

그럼 이제 본론으로 들어가 볼까요?

여러분이 만약에 노래를 듣고 싶다면 오디오 기기를 켜실껍니다. 만일 TV를 보고싶다면 어쩌실껍니까? TV를 켜지도 않았는데 보실수 있습니까? 그렇다면 MCU에서 타이머를 켜지도 않았는데 타이머가 돌아 갈까요? 절대 그렇지 않지요? 위에 예를 든것 모두 전원을 켜 주어야만 TV도 보고 노래도 듣고 합니다. MCU도 마찬가지 입니다. 내가 MCU내에 있는 한가지 기능을 사용하고 싶다 할 경우에 바로 스위치를 올려주고 내려주고 하는것이 바로 이 Register가 하는일입니다. 앞에서도 얘기 했지만 타이머를 사용하고 싶다면 타이머를 켜줘야 하는 것이고 시리얼 통신을 하고 싶다면 시리얼 기능을 On 시켜야만 하는 것입니다. 그 다음 TV도 다 보고 노래도 다 듣고 했다면 애국가가 끝난다음 여러분은 무얼 하시나요? TV를 켜놓고 오디오를 켜놓고 잠자는 사람이 있는가 하면 대부분의 사람들은 전원을 다 끄고 주무실껍니다.

그럼 이것을 Register에 적용을 해 봅시다.

우선 타이머를 사용 하려면 타이머를 활성화 하여야 합니다. 즉 타이머에 전원을 켜야 한다는 의미 입니다. 그 다음 타이머의 타임설정이 있을겁니다. 그리고 시리얼 통신의 경우에는 내가 데이터를 송신하는 방법과 수신하는 방법 두가지가 있습니다. 만일 데이터를 수신 하고자 한다면 수신 전원을 켜야하고 송신 하고자 한다면 송신 전원을 켜야만 합니다. 하지만 시리얼 통신의 경우에는 송신도 해야하고 수신도 해야하고 또 통신속도며 통신방식을 8비트에 Non Parity 1Stop Bit니 하는것들을 설정해야만 합니다. 그러니까 요즘엔 TV를 보려면 리모콘도 있어야 하고 채널도 설정해야 하는것처럼 복잡하게 조작을 하는 경우도 있고 간단하게 전등을 켜는것처럼 스위치만을 켜는 간단한 Register도 있습니다.

만일 TV를 켜놓고 그냥 자면 어찌 될까요? 밤새 TV는 지지직 거리며 전원을 소모할 것이며 오디오 또한 내가 듣지도 않는데 노래는 계속 흘러 나올것입니다.

그러니까 프로그램에서 굳이 필요 없다면 그 기능은 우리가 전원을 OFF해 주어야 할 경우도 있습니다. 그러므로 우리가 Register의 개념을 이해할때는 MCU에 내장된 각종 기능들을 활성화

하거나 아니면 그 기능을 비 활성화 시키거나 하기 위한 하나의 스위치라고 생각 하시면 무리가 없습니다.

그러면 68HC11에는 어떠한 Register가 있을까요?

아마도 MCU에 대해서 아시는 분이라면 Datasheet를 보셨을지 모르겠지만 아마도 8051에 비하면 엄청나게 많을것입니다. 그러나 그런것은 별 문제가 되질 않습니다. 왜냐하면 기능의 많고 적음에 따라 Register의 양이 결정 되므로 양이 많다고 해서 결코 여러분이 주눅들 필요는 전혀 없습니다. 일단 알고나면 내가 왜 그것때문에 고생을 죽어라 하고 했을까? 하고 이해가 되지 않는때가 분명 옵니다. 조금 더 용기를 갖고 누가 끈질기게 하느냐에 따라 눈을 뜨느냐 아니면 장님인채로 생활을 하느냐가 결정이 되는 겁니다.

그럼 이제 한가지 예를 하나만 더 들어 보도록 하겠습니다.

우리가 프로그램을 코딩 하지만 실질적으로 MCU입장에서 보면 이것은 Logic을 구성 한다고 볼 수 있습니다. 그래서 많은 MCU들이 이런 부분을 설명할때 Logic을 가지고 많이 설명을 하는데 이것은 인터럽트를 공부할때도 많은 도움이 됩니다.

<그림 5-1 >

Tmsk1 Register는 MC68HC11A1내부에 있는 Output Compare Timer 5개를 활성화 하거나 비 활성화 시키는 Register 입니다. 만일 Timer를 모두 비 활성화 하고자 한다면 어떻게 하면 될까요? Oc1i ~ oc5i까지 모두 0으로 설정하면 Timer는 동작을 하지 않습니다. 또 내가 사용하고자 하는 비트를 1로 설정하면 해당 타이머만 동작을 하겠지요 …이러한 Register의 구조는 MC68HC11에만 국한된 것이 아니라 거의 모든 MCU에 해당되는 사항입니다. 그러므로 만일 여러분이 이 부분을 이해 하셨다면 아마도 다른 MCU를 공부할때 많은 도움이 되리라 생각 됩니다.

자! 그럼 Timer1을 동작시켜 봅시다. Oc1i는 최상위 비트 즉 MSB가 되는 것이고 X는 LSB가 되는것입니다. 만일 Timer1만을 활성화 하겠다면 여러분은 다음과 같이 설정하므로서 MC68HC11A1내에 존재하는 Timer1을 구동 하게 되는 것입니다.

Ldaa #$80

Staa tmsk1

위와같이 코딩을 하게되면 Timer1은 활성화 되며 Timer1은 내부 시스템 클럭에 의해 자동으로 카운트를 시작하게 됩니다. 이것은 추후에 자세하게 배우게 되겠지만 MCU에 있어서 Timer는 상당히 요긴하게 사용 되어지는 기능입니다. 왜냐하면 일정한 펄스를 출력한다거나 또는 시간계산이 필요한 경우 등등 거의 프로그램 작성이 약방의 감초처럼 안 쓰이는 곳이 없습니다.

그럼 이번에는 Timer1과 Timer2를 같이 사용하고 싶다면 어떻게 하면 될까요?

Ldaa #$C0

Staa tmsk1

위와 같이 작성을 하면 되는 겁니다.

만일 이 부분이 이해가 되지 않는분이 계시다면 BCD에 대해서 앞장에서 기술 했으므로 Address의 개념에 대해서 BCD에 대해서 좀더 공부를 하실 필요가 있습니다.

즉 Register의 설정은 위와같이 되는데 이것이 Timer에만 해당되는 내용이 아니라 거의 전 Register가 이런 방식을 취하고 있습니다.

그러면 Register의 설정은 프로그램 초기에 해야할까요 아니면 중간중간 아무때나 할까요? 보통 Register의 설정은 프로그램의 시작 초기에 합니다.

그러니까 한번 설정하고 다시 Register를 건드리는 일이 없도록 하는것입니다.

처음 프로그램을 접하는 사람들을 보면 MCU 초기화 루틴에 대해서 고민을 많이 하시는 분들이 있습니다. 거의 프로그램 초기화 루틴은 이러한 Register의 설정에 관련된 부분이며 프로그램 예제를 통해 공부를 하다보면 자연스럽게 터득하게 되는 부분이기도 합니다.

아무튼 여러분은 이 장에서 Register의 개념을 확실히 아셨다면 이제 인터럽트에 대한 개념을 익히는데 한발짝 다가섰다고 할 수 있습니다.

MCU기초지식_6. Interrupt의 개념

6. Interrupt의 개념

자! 이제 여러분은 MCU를 배우기 위한 마지막 단계에 이르렀습니다.

지금까지 설명드린 내용들을 모두 이해하고 숙지 하셨나요? 만일 하나라도 이해가 안되신 분은 그 부분을 다시 공부 하셔서 완전하게 이해를 하시기 바랍니다. 보통 초보자분들께서 MCU를 배우고자 할때 무리해서 벅찬 프로젝트를 하시는 분들이 많습니다. 우리는 속된말로 그것을 맨땅에 헤딩한다고 하지요 … .몸으로 부딪혀가며 터득하는 기술입니다. 하지만 맨땅에 헤딩도 기초가 있어야 스스로 문제를 해결 하지요 …아무것도 모르면서 혼자 해결 한다는것은 한계가 있습니다. 또한 그렇게 하다 포기하게 되는 경우도 많구요 …그러면 그 다음부터는 질려서 배우고 싶은 마음이 사라지기도 합니다.

그래서 제가 권장하고 싶은것은 실용적이지는 않더라도 내 자신이 평생을 이것을 배워서 먹고 살겠다 하시는 분은 기초부터 천천히 시간이 걸리더라도 천천히 배우시는 것이 좋다고 생각하며 그 예로 제가 처음 MCU를 접하는 분에게 항상 권하는 것이 LED부터 켜 보세요 라고 하는것입니다.

이것이 실은 아무것도 아닌것 같아도 자세히 들여다 보면 MCU에 있는 거의 모든 기능을 다 배울수 있다는 겁니다. 물론 단순하게 LED를 켜고 끄는것만으로 끝난다면 문제겠습니다마는 이 LED를 가지고 여러가지를 할 수 있습니다.

예전에 우리가 TV에서 보았던 Kit 라는 자동차를 보셨지요? 그렇게 점등되는 LED도 만들수 있고 단순하게 깜빡이는 기능도 할 수 있고 말입니다. 그리고 시리얼 통신으로 LED도 켜고 끄고 말입니다. 응용은 무궁무진 합니다.

전장에서 우리는 Register의 개념에 대해서 배웠습니다. Regsiter는 사실 지금 배우려고 하는 Interrupt와 무진장 관계가 깊습니다. 왜냐하면 Register의 기능을 설정하는것에 따라 Interrupt가 설정되고 안되고가 결정되기 때문입니다.

그럼 Interrupt란 무엇일까요? 사전적인 의미로 본다면 ‘가로채기'란 해석으로 나옵니다.

그럼 가장 쉬운 예를 들어 설명해 봅시다. 동아리에 가입하신 분들을 예로 들겠습니다. 물론 땜쟁이 이므로 그런 유사한 예를 들어야 겠지요? 우리가 동아리에 가입하면 위로 기라성같은 선배들이 많습니다.

그리고 지금도 그런가 모르겠지만 처음엔 청소나 시키고 공구나 닦고 부품이나 정리하고 그런 잡일을 많이 시키지요 .물론 그렇게 하는데는 이유가 있습니다마는...아마도 하루하루 하는일들이 거의 같을 겁니다. 그런데 보면 선배는 재미 있게도 마우스라던가...여하튼 뭔지는 모르니만 열심히 땜질을 하고 있습니다. 우린 상당히 부럽져 …나두 하고 싶은데 … .

어느날 그날도 어김없이 열심히 청소를 하고 있는데 선배가 땜질을 하다보니 부품이 하나 없습니다. “야! 가서 xx부품 하나 가져와라!” 하는 겁니다. 그럼 신속하게 부품을 하나 가져다 주지요 … 왜? 빨리 안하면 선배에게 맞을지도 모르니까 말입니다. 그런데 웃긴건 그 프로젝트가 끝날때까지 그렇게 중간에 불러서 부품을 가져 오라는 지시가 많다는 겁니다. 그러다 보면 청소며 내가 해야할 일들이 자꾸 시간이 뒤로 밀려 가게 마련이지요 … .

이해가 되시나요? 이해가 가신분이라면 MCU를 배우실 수 있는 준비가 되신 분입니다.

우리가 매일같이 청소하고 부품정리하고 하는것들은 현재 MCU가 일정한 프로그램에 의해 돌고 있다는 비유입니다. 대학초년일때는 매일같이 청소하고 하는것들을 반복하겠지요 …그것이 MCU에 비유하게 되면 프로그램이 열심히 자기 할일을 수행하고 있는 겁니다. 하지만 중간에 선배가 무슨 “부품 가져와!”라고 하면 여러분은 빨리 부품을 가져 옵니다. 그리고 부품을 선배에게 준후 다시 본연의 업무인 청소 및 부품정리를 합니다. 그러면 그 선배라는 사람은 무엇에 해당이 될까요? 그것은 바로 Interrupt에 비유할 수 있습니다. Interrupt라는것은 일정한 주기마다 걸리수도 있는것이고 일정하지 않은 시간에 걸릴수도 있는겁니다.

인터럽트 라는것을 전장에서 배운 Timer를 가지고 다시한번 설명하겠습니다.

현재 프로그램이 열심히 돌고 있습니다. 그러다가 Timer라는 녀석이 “야! 빨리 이리와봐!” 했습니다. 그래서 프로그램은 Timer에게 갔고 Timer가 시키는 일을 열심히 한 후에 제자리로 왔습니다. 그리고는 다시 열심히 프로그램을 돌리는 겁니다.

즉 무슨얘긴가 하면 Main Program 운용중에 일정시간마다 Timer Interrupt를 요구받게 됩니다. 그러면 프로그램은 하던일을 중지하고 Timer Interrupt가 위치한 Address로 Jump하여 그곳에 있는 Timer Interrupt 프로그램 명령을 수행하고 아까까지 수행했던 프로그램 위치로 되돌아와서 다시 Main 프로그램 명령을 수행하는 것입니다.

이때 프로그램은 현재까지 수행한 프로그램 Address를 일정장소에 저장하며 또한 현재까지 수행하여 결과값이 남아있는 Accumulator의 값을 또 저장합니다.

바로 이것이 우리가 흔히 말하는 Stack이라고 하지요 … 그러나 MC68HC11은 Stack의 구조가 Address 감소형입니다. 즉 $FF에 처음 위치를 잡아주면 MCU는 이 $FF번지부터 감소하며 Stack에 각종 Data를 저장하게 됩니다.

또한 Stack은 우리 마음데로 정할 수 있으며 이는 RAM의 최상위 Address에 잡아주게 됩니다. 물론 이 부분은 추후에 자세하게 설명이 될 것입니다.

아무튼 다시한번 정리를 해 본다면 Interrupt란 현재 수행하고 있는 프로그램을 일시 중지하고 MCU내의 특정 Module이 요구하는 번지로 Jump해서 특정한 프로그램을 수행하는 것을 말합니다.

이것은 어느시점에 발생하여 점프하게 될지는 아무도 모르며 이러한 Interrupt가 한 개, 또는 두개정도 있는 MCU도 있으나 MC68HC11은 상당히 많은 Interrupt를 가지고 있으며 이는 추후 기술하게 되는 MC68HC11A1의 특징에서 자세하게 기술 될 것입니다.

그럼 이제 인터럽트가 발생하고 소멸시키는것과 인터럽트라는것이 Logic적으로 어떻게 동작하는지를 보도록 하겠습니다.

<그림 6-1 >

<그림 6-1>은 가장 기본적인 Interrupt의 발생구조를 나타낸 그림이며 실제로 이러한 구조에 의해 동작되는 Interrupt는 많습니다. 먼저 Interrupt Enable과 Interrupt Flag라는것이 And Gate에 의해 연결이 되어 있습니다. Interrupt Enable이라고 하는것은 예를들어 Timer Interrupt를 사용하고자 한다면 Timer Interrupt Register중 tmsk1의 ocxi를 1로 설정한 것과 같습니다.

하지만 Interrupt Flag가 0이라면 출력의 Interrupt가 1이 될 수 있을까요?

로직 구조상 절대 그런 현상이 발생될 수 없습니다. 그렇다면 Interrupt가 1로 되어 Interrupt가

발생하려면 어떻게 되어야 할까요? 바로 Interrupt Enable과 Interrupt Flag가 1로 설정이 되어야 Interrupt는 1이 됩니다. 그럼 1이라는 값을 활성화 되는 값이라고 보고 위의 그림을 예로 설명을 좀 더 자세하게 해 보겠습니다.

먼저 우리는 Register중 tmsk1의 ocxi를 1로 설정 하였습니다. 여기서 잠시 우리가 배우고자 하는 MC68HC11의 Timer에 대해서 간단하게 언급토록 하겠습니다.

MC68HC11의 Timer는 Output Compare라고 해서 내부에 자유롭게 시스템 클럭에 맞추어 한 개씩 증가하는 카운터가 있습니다. 그리고 또 다른곳에 여러분이 값을 써넣을 수 있는 Register가 있습니다. 바로 이 Timer는 두 값을 서로 비교해서 같아지는 시점에 Interrupt Flag라는것이 바로 1로 설정이 됩니다.

그럼 이러한 상황이 전개 되었다면 <그림 6-1>의 두 입력단자는 모두 1로 설정이 될 것이고 출력의 Interrupt 역시 1로 설정이 되어 모든 프로그램을 중지하고 바고 Timer Interrupt Service Routine으로 점프할 것입니다.

즉 다시말해서 Interrupt Enable이라는 신호는 Timer를 사용하기 위해 여러분이 Timer Interrupt를 1로 설정하여 활성화 한 것이고 Interrupt Flag라고 하는것은 MCU가 어떠한 조건이 맞으면 1로 설정해 주는 것입니다.

그래서 두개의 입력이 서로 1이 되었을경우 Interrupt는 발생하게 되며 프로그램은 해당 Interrupt를 수행하는 번지로 Jump하여 그 Routine을 수행하게 되는 것입니다.

이러한 Interrupt의 예제는 거의 모든 Interrupt에서 사용하는 기법이며 이러한 구조를 알게 되면 여러분이 Interrupt를 사용하고 이해하는데 있어서 상당한 도움이 될 것입니다.

그런데 만일 여러분이 Interrupt를 수행하고 빠져 나온다면 <그림 6-1>의 Interrupt Flag는 0일까요 1일까요? 1이지요 … . 그럼 어찌 됩니까? Interrupt는 계속 걸리고 프로그램은 Interrupt를 Service하느라고 실제로 동작해야할 Main 프로그램은 수행조차 하지 못할것입니다. 왜냐하면 Interrupt를 빠져나오면 다시 Interrupt가 걸릴것이고 또 수행하고 빠져 나오면 계속 Interrupt Enable과 Interrupt Flag는 1로 설정이 되어 있기 때문에 Interrupt를 Service하기 위해 프로그램은 계속 Jump 할것이기 때문입니다.

그렇다면 이것을 해결하기 위해서는 어떤 방법이 있을까요?

Interrupt Enable을 0으로 하면 된다고 생각 하시는분 … … … …..땡~~~ 틀렸습니다. 바로 Interrupt Flag를 0으로 설정하는겁니다. 이러한 방법은 거의 모든 MCU에서 사용하는 방법으로서 Interrupt Routine을 수행할 경우 초기에 Interrupt Flag를 0으로 설정하면 Interrupt 출력은 0으로 설정이 될 것이며 Interrupt Routine을 수행한후 Main 프로그램으로 빠져 나와도 Interrupt는 걸리지 않을 것입니다. 다음 Interrupt가 걸릴 조건이 되기 전까지는 … .

위와 같은 내용은 별거 아닌것 같지만 실제로 프로그램을 짜보면 많이 발생하는 현상입니다. 그래서 그런 잘못된 부분을 찾기 위해서 며칠을 고생하는 경우도 발생을 하게 되지요 …

그럼 지금까지 설명했던 내용을 순서대로 정리를 해 보겠습니다.

1. 사용하고자 하는 Interrupt를 결정하고 해당 Register를 활성화 한다.

2. 프로그램이 수행되면 Interrupt가 발생이 된다.

3. Interrupt Service Routine에서 초기에 해당 Interrupt Flag를 Clear한다.

4. Interrupt Service Routine을 수행한다.

5. Main 프로그램으로 복귀한다.

Interrupt라는것은 실제로 Main 프로그램의 일부분이긴 하지만 위와 같이 특정 위치에 프로그램된 별개의 프로그램이라고 할 수도 있습니다.

여기서 한가지 알아둘점 일단 Interrupt 를 Service할 경우 최단 시간내에 Main프로그램 으로 복귀 하여야 합니다. 그러므로 Interrupt내에서 Delay Routine을 만드는 것은 오동작의 원인이 될 수 있으며 가른 Interrupt발생이 이의 Service를 지연 함으로서 제품의 신뢰성이 낮아 집니다.:

Interrupt는 신속하게 처리하고 Main Routine으로 복귀한다.

그러므로 Interrupt내에서는 절대 Delay Routine을 사용하지 않는다.

만일 Delay Routine을 사용한다면 그것은 바보같은 짓이다.

지금까지 설명한 1장에서 6장까지의 내용은 상당히 중요한 내용이며 MCU를 배우기 전에 여러분이 꼭 깨우쳐야만 하는 내용입니다.

이러한 내용을 이해하지 못하고 MCU를 배우게 된다면 그 고생은 이루 말 할 수 없으며 아마도 MCU에 대한 흥미가 반감되지 않을까 심히 염려가 됩니다.

출처 : 당근이카페. 여신사랑님.

http://cafe.naver.com/avrall.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=204