1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의...

95
1장 기초사항 1.1 로봇제작에 필요한 도구와 기기 1.2 납땝하는 법 1.3 회로도 보는 법

Transcript of 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의...

Page 1: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

1장 기초사항

1.1 로봇제작에 필요한 도구와

기기

1 . 2 납땝하는 법

1 . 3 회로도 보는 법

Page 2: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

1 . 1 로봇을 제작하는 데 필요한 기기 및 도구

- 테스터기와 오실로스코프

테스터기는 기본 소자들의 값과 전압, 전류 등을 측정할 수 있다. 이 테스터기는 그

림과 같이 디지탈테스터와 아날로그테스터 두 가지가 있다. 사용방법은 가운데 원통으

로 생긴 손잡이를 돌려 측정하고자 하는 곳으로 맞추고 측정을 하면 된다. 단 측정할

때에 측정범위가 있는데 이를 초과한 값이면 측정이 안 되므로 먼저 측정범위가 큰 것

부터 측정한다. 또 이 테스터기는 부가적인 기능으로 다이오드 측정과 도통 되었는지를

확인하기위한 기능(도통이 된 곳을 측정하면 ‘삐~’소리가 난다)과 트랜지스터의 극을

찾아주는 기능이 있다. 이중 도통을 확인하는 기능은 납땜을 하면서 많이 사용된다.

<그림 1-1>디지털 & 아날로그 테스터기

오실로스코프는 테스터기로 확인할 수 없는 ‘시간에 대해 갖는 불규칙한 파형’을 측

정할 때 사용된다. 특히 디지털회로에서는 On과 Off의 전압신호를 사용하기 때문에 주

로 오실로스코프를 사용한다. 오실로스코프는 x축은 시간을 y축은 전압으로 표시된다.

Page 3: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

< 오실로스코프 >

- “Power Supply”와 “Function Generator”

로봇을 완성하면 내부독립전원으로 동작을 해야 하므로 베터리가 사용된다. 하지만

완성되기 전이나 실험을 할 때에는 Power Supply를 사용한다. Power Supply는 안정적

인 전원을 공급하고 CC기능으로 일정이상의 전류가 흐르는 것을 막아주어 보드에 손상

을 막을 수 있어 안정적이다.

Function Generator는 원하는 신호(구형파, 삼각파, 사인파등)를 만들어 출력시켜 준

다. 이 Function Generator는 로봇에 어떤 특수한 입력이 필요할 때 사용되지만 거의

사용되지 않는다.

- 롬라이터 및 이레이져

나중에 로봇에 들어갈 프로그램 코드나 Const값등을 저장하기 위해 롬이 필요하다.

이 롬에 해당코드를 라이팅해주는 기계가 롬라이터이다. 롬라이터기의 사용법은 나중에

알아보도록 하자.

롬이레이져는 사용하는 롬이 EPROM 타입일 때 사용된다. EPROM타입은 자외선으로

롬의 내용을 지우기 때문에 이레이져가 따로 필요하다. EEPROM은 전기적으로 지울수

있으므로 롬라이터로 지울수 있다.

Page 4: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

<그림 1-3 롬 라이터와 롬이레이저>

- 제작에 필요한 도구들

인두기 : 실납을 녹이기 위한 도구로 W수와 팁의 굵기, 모양등에 따라 종류가 다양하

다. 이중 IC나 트랜지스터 등의 부품을 납땜할 때에는 18 ~20W가 좋다. 팁 모양은 끝

이 가는 것이 좋은데 이는 보드 납땜을 할 때에 배선이 복잡한 경우에 편리하다.

인두 스탠드 : 뜨거워진 인두기를 세워두는 것으로 안전을 위해 필요하다. 굵은 철사를

구부려 사용해도 된다.

흡입기 : 납땜을 잘못했을 때 사용한다. 인두기로 때어낼 납을 녹인 다음 흡입기로 납

을 빨아들인다.

니퍼 : 부품의 다리를 끊거나 선을 자를 때 사용한다. 주의해야 할 것이 있는데 니퍼는

날이 약하다. 굵은 선이나 다리를 끊으면 니퍼날이 나가므로 주의하자.

롱노즈 : 부품의 다리를 굽히거나 잡을 때 유용하다.

와이어 스트리퍼 : 전선의 피복을 벗겨낼 때 사용된다.

1 . 2 납땝하는 법

- 인두기를 일단 가열한다.

- 부품을 기판에 붙인다. 이때 다리는 모두 깨끗이 잘라서 붙인다.

- 인두기로 먼저 실납이 녹을 곳을 예열한다.

- 살짝 실납을 밀어넣고 납이 녹아서 동그랗게 뭉치면 실납과 인두를 뺀다.

- 인두기에 실납이 묻어나오면 Soldering Paste에 인두기를 살짝 담그고 묻은 실납은 젖

은 휴지나 스폰지로 닦아낸다.

- 납땜에서 선 연결은 주로 피복을 모두 벗긴 선으로 깔아서 연결하고, 어쩔 수 없을 때에

만 래핑와이어를 이용하여 점핑한다.

- 래핑와이어로 점핑을 할 때에는 피복을 너무 많이 벗겨내지 말고 벗겨낸 부분은 실납안

으로 들어가게 한다.

1 . 3 회로도 보는 법

Page 5: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

예제 회로도1을 보자 일단 얇은 파란 사각형이 보통 IC나 기본소자등의 유닛이다. 각 유

닛마다 아래에는 값들이 나와있다. 소자일 경우는 해당 값을 IC일 경우는 IC의 PART

NUMBER가 적혀있다. 또 스위치나 점퍼등의 경우엔 이름을 지어서 넣는 경우가 있

다.(예: 전원스위치, Port0, Setting Switch 등) 그리고 그 유닛들의 핀끼리 연결을 해 놓

은 것이 와이어이다.

예제 회로도1

이 와이어마다 위에 빨간 글씨로 별명(Net Alias)이 붙여져있다. 이는 여러선이 묶여서 그

려져있는 버스간의 연결이나 유닛끼리 너무 멀어서 직접 와이어로 연결을 하지 못하는 경우

에 별명을 보고 연결이 되어있는가를 확인해야 한다. 예제회로도2에 서는 J10과 U7번간에

네개의 와이어가 간접적으로 붙어있음을 알 수 있다. 또 Vcc나 GND등의 전원도 역시 하나

로 연결되어 있는것이다. 납땜을 할 때 자주 연결을 하지않는 실수를 종종 할 때가 있다.

주의하자.

Page 6: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

< 예제 회로도2 >

Page 7: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

2장 디지털회로와 MCU

2 . 1 논리 회로

2 . 2 디지털 회로

2.3 마이크로 컨트롤러와 마이

크로 프로세서

Page 8: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

2 . 1 논리 회로

-디지털 시스템에서는 전자 부품의 물리적 제약과 인간의 논리가 참(True)과 거짓

(False)의 2진이라는 이유때문에 ‘0’,1’의 2개의 값만을 가지도록 제한된다. 이런 2진

정보는 물리적인 량인 전압신호를 이용하여 0, 1로 표시한다.

-논리 게이트 : 디지털 시스템에서는 2진 정보를 Gate라는 논리회로에서 처리하게 된다.

아래 Gate들의 종류와 기호, 진리표를 나타내었다.

-부울 대수 : 2진변수와 논리동작을 취급하는 대수로 AND, OR, NOT의 기본 동작이 있다.

이런 기본동작 등을 사용하여 변수사이의 진리표관계를 대수형식으로 표시한다. 다음 이

를 더 간단한 회로를 찾는데 사용한다.

부울대수의 기본적 관계

1. X + 0 = X 2. X * 1 = X

3. X + 1 = 1 4. X * 0 = 0

5. X + X = X 6. X * X = X

7. X + X’= 1 8. X * X’= 0

9. (X’)’= X

10. X + Y = Y + X 11. X * Y = Y * X

12. X + (Y + Z) = (X + Y) + Z 13. X * (Y * Z) = (X * Y) * Z

Page 9: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

14. X(Y + Z) = X * Y + X * Z 15. X + Y * Z = (X + Y) * (X + Z)

16. (X + Y)’= X’* Y’ 17. (X * Y)’= X’+ Y’

2 . 2 디지털 회로

- 여기서는 플립플럽과 플립플럽으로 구현한 간단한 카운터회로에 대해서 알아보겠다.

- 플립플럽

플립플럽은 안정된 두가지의 상태를 가지는 회로를 의미한다. 그 종류에는 RS플립플

럽, D플립플럽, JK플립플럽이 있다. 아래에는 이 세가지 플립플럽의 심볼과 논리표 그리

고 동작표를 나타내었다.

. RS플립플럽

. D플립플럽

입력 출력

R S Q

0 0 출력 유지

0 1 1(Set)

1 0 0(Reset)

1 1 모름

R Q

S /Q

입력

S

R

출력

Q

/Q

D Q

CK /Q

입력

CK

D

출력

Q

/Q

Page 10: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

동작 : CK단자에 하강엣지가 들어올 때 D에 값으로 출력되고, 그 외에는 출력을 유

지한다.

. JK플립플럽

- 카운터

카운터란 수를 세는 동작을 하는 회로를 말하며 가장 간단한 방법은 아래 그림과 같

이 구성할 수 있다.

< 비동기 카운터의 회로 구성 >

입력 출력

J K Q

0 0 출력 유지

0 1 1(Set)

1 0 0(Reset)

1 1 출력 반전

J Q

CK

K /Q

입력

CK

J

K

출력

Q

/Q

Page 11: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

< 비동기 카운터의 타임차트 >

펄스 입력에 신호가 들어가면 1씩 증가하는 것(업 카운터)을 볼 수 있다. 이 카운터

를 비동기(Ripple)카운터라 부른다. 회로가 간단하여 구성이 쉬우나 출력이 여러 개이

면 딜레이가 생기며 너무 많으면 오동작(Glitch)을 일으킬 수도 있다. 이런 단점을 보완

하는 카운터가 동기(Parallel)카운터이다. 이 카운터는 플립플럽에 들어가는 동기 신호

가 있어서 비동기 카운터가 갖고 있는 단점을 보완할 수 있다. 그 회로 구성은 아래와

같다.

< 동기 카운터의 회로 구성 >

< 동기 카운터의 타임 차트 >

Page 12: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

2 . 3 마이크로 프로세서와 마이크로 컨트롤러

- 마이크로 프로세서 : 마이크로 프로세서는 내부에 산술 및 논리 연산장치(ALU)와

Register I/O bus 및 Data bus, 프로그램 수행에 필요한 제어회로를 내장한 LSI이다.

일반적으로 PC의 main board는 산술연산과 논리연산부, 제어부 그리고 주기억장치를

포함한다. 마이크로 프로세서는 주기억장치는 별도로 하고 연산부와 제어부를 가진 실

제의 CPU만을 말한다. 또 이 마이크로 프로세서를 CPU로 사용하여 만든 소형 컴퓨터

를 마이크로 컴퓨터라고 한다. 1971년 최초로 인텔에서 4004라는 4bit processor를 개

발했고, 그 이후 급속도로 발전하여 많은 변화를 가져오게 되었다. 예로 인텔의 8086,

80286, 80386, 80486, Pentium등과 모토로라의 6800, 68000등이 있다.

- 마이크로 컨트롤러 : 어떤 마이크로 프로세서중에는 1개의 칩내에 CPU기능은 물론 일

정한 용량의 메모리(ROM, RAM) 와 입출력 제어 회로를 내장한 것이 있는데 이를 마이

크로 컨트롤러라 한다. 또는 MCU(Micro Controller Unit)이라고도 한다. MCU로는 인

텔의 MCS-51계열과 MCS-96계열등이 유명하고 삼성의 KS88등의 시리즈가 있다.

- DSP : analog signal을 digital signal로 변환하여 실시간으로 고속 처리하는 전용 프로세

서로 마이크로 컨트롤러의 발전형태라 생각하면 된다. DSP는 처음에는 주로 음성, 화상

처리 같은 많은 데이터처리가 필요한 분야에 많이 사용되었지만 요즘에는 컨트롤러가

사용되는 거의 모든 분야에서 사용되고있다.

Page 13: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

3장 80C196KC

3 . 1 내부 구조

3 . 2 주변 회로

3 . 3 메모리 인터페이스

3 . 4 보드의 제작

3 . 5 프로그램 개발

3 .6 인터럽트

3.7 196의 주요기능

Page 14: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

3 . 1 내부 구조

8096계열 중에 우리는 80C196KC를 사용할 계획이다. 이번 장에서는 이 컨트롤러를

이용하여 실제로 보드를 제작하고 프로그래밍을 하면서 196의 기본에서 활용까지 공부

할 계획이다. 196KC는 Advanced CHMOS기술로 제작되어 20MHz에까지 동작을 하며,

전류소모량이 많이 줄였다. 또한 이 196KC는 8/16비트의 버스폭을 갖고 있어 원하는

폭으로 사용할 수 있다. 아래는 196Kx의 블럭다이어그램이다.

< 80196Kx의 Block Diagram >

그리고 다음은 196코어의 다이어그램이다.

< Core Block Diagram >

위에 블록다이어그램을 보면, 기본적인 Core와 메모리(내부의) 그리고 인터럽트를 관

Page 15: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

리해주는 Interrupt Controller와 인터럽트의 부가기능인 PTS가 있다. 또 발진회로부와

저전력모드등을 관리하는 전원부인 Clock and Power Mgmt. 가 있다. 그 외에 196에는

일반 범용 I/O포트를 32bit를 갖고 있다. 뿐만 아니라 완전이중방식의 직렬포트(Serial

Input/Output)가 있으며 10bit의 AD변환기가 8채널 갖고 있다. 컨트롤러에서 가장 유

용하게 사용되는 타이머/카운터는 Up/Down카운터가 1개, Up 카운터가 1개 갖고 있다.

이 타이머를 이용하여 나오는 HSI 4개 ,HSO가 6개 갖고 있으며 3개의 PWM을 갖고

있는 컨트롤러로써 우리가 제작하는 모발로봇에 필요한 기능을 모두 갖고 있기에 이 모

델을 선택하게 되었다. 실제로 이 장에서는 우리가 사용할 기능에 대해서만 다룰 계획

이며 다른 기능은 매뉴얼이나 다른 서적을 참고하기 바란다.

이 196KC의 핀들에 대해서 간략히 표로 나타내었다.

기 호 기 능

Vcc, Vss 주전원(5V)과 디지털 접지(0V)

Vref, ANGND AD변환기준전압(5V)과 아날로그 접지(0V)

Vpp 전력 절약 회로의 타이밍 핀으로 EEPROM이 내장되어 있을 경우

프로그래밍 전압으로 사용된다.

XTAL1, XTAL2 외부클럭의 입력, 출력

CLKOUT 내부클럭 발생기의 출력, 클럭 주파수의 1/2

RESET 리셋 신호

BUSWIDTH 버스 폭 설정, 1=16bit, 0=8bit (CCR.1 = 1일 때만)

NMI None Mask Interrupt. 최상위 인터럽트

INST 1 = 외부 메모리 읽기, 0 = 데이터 가져오기 상태 표시

EA 외부 일기, ( 0 = 외부, 1 = 내부 ROM )

ALE / ADV 주소 래치 허용, 주소 유효

RD 외부 메모리 읽기

WR / WRL 외부 메모리 쓰기, 외부 하위 메모리 쓰기

BHE / WRH 버스 상위 허용, 외부 상위 메모리 쓰기

READY 외부 메모리와의 사이클 지연

HSI 고속 입력 장치 입력

HSO 고속 출력 장치 출력

P0 / ACH 포트0, AD변환기 입력

P1/ PWM, BREQ,

HLDA, HOLD

포트1, PWM출력, 버스 요청, 홀드 인식, 홀드

P2 / TXD, RXD,

EXINT, T2CLK,

포트2, 직렬포트 TXD, RXD, 외부 인터럽트, 타이머2 클럭, 카이머

2 리셋, PWM출력, 타이머2 증가_감소, 타이머2 기록

Page 16: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

T2RST, PWM,

T2UPDOWN,

T2CAP

P3 / AD0~7 포트3, 데이터와 주소 버스 0~7

P4 / AD8~15 포트4, 데이터와 주소 버스 8~15

P1과 P2는 포트와 기능 핀이 같이 있는걸 볼 수 있는데. 이는 나중에 나오는 sfr중에

ioc이라는 레지스터에 값을 써서 둘 중 하나의 기능으로 사용할 수 있다.

이젠 196의 메모리 영역에 대해서 알아보자. 196계열의 메모리 영역은 a0~a15로 억

세스할 수 있으므로 총 64Kbyte이다. 이 영역에 프로그램 코드 메모리와 데이터 메모

리로 사용할 수 있는데 그 중에 일부는 이미 196에서 예약되어 있는 번지가 있다. 이

들은 인터럽트 벡터나 레지스터 파일등으로 사용되고 있어서 프로그래머 임의로 조작할

수 없는 영역이다. 아래 그림을 참고하자.

메모리 영역 내용

6000

~ FFFF

외부 메모리

2080

~ 5FFF

외부 메모리 / (내부 ROM)

205E ~ 207F 예약된 영역

2040 ~ 205D PTS벡터

2030 ~ 203F 상위 인터럽트 벡터 8개

2020 ~ 202F ROM 보안 열쇠

2019 ~ 201F 예약된 영역

2018 칩 설정 바이트(ccr)

2014 ~ 2017 예약된 영역

2000 ~ 2013 하위 인터럽트 벡터 8개

1FFE ~ 1FFF 포트3, 포트4

0200

~ 1FFD

외부 메모리

0100 ~ 01FF 추가 내부 RAM

0000 ~ 00FF 내부 레지스터 파일

실제 이 영역들은 프로그램 할 때 필요한 부분으로 아주 중요하다. 실제 196의 동작

모드를 결정하기 때문이다. 만약 이를 무시하고 메모리멥을 구성하면 196은 원하는 동

작을 바라긴 힘들 것이다. 이 부분은 나중에 컴파일하고 링크(어셈블을 하여 나온 코드

Page 17: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

값들을 실행할 수 있게 연결해 주는 과정)하는 부분에서 어떻게 메모리멥을 작성하고

링크시에 옵션을 넣는지에 대해서 설명하겠다.

위의 메모리 멥에서 0000 ~ 00FF까지의 영역의 내부 레지스터 파일에는 어큐뮬레이

터(실제 연산을 하기 위해 값을 가져오는 곳)가 억세스 할 수 있는 메모리들이다. 이

중에서 0000 ~ 0017까지 영역에는 특별 기능 레지스터(SFR)이 있는 데. SFR은 어떤

특수한 기능을 설정하거나 값을 기억해 놓은 레지스터들로 196프로그래밍의 대부분이

이 레지스터값을 바꾸면서 사용한다. 이 레지스터 들은 수평창이라는 특수한 구조로 되

어 있다. 이는 8096계열과의 호환성을 유지하면서 공간의 활용도를 증가시키기 위해서

이다. 이 수평창은 ‘wsr(0x14)’이라는 sfr의 레지스터값으로 설정할 수 있다. 특이한 점

이라면 이 수평창에따라 같은 번지를 읽어도 다른 값이 읽힌다는 것이다.

수평창0(read) 수평창0(write) 수평장1 수평창15

(wsr값) 000 0000 000 0000 000 0001 000 1111

0x17 Ios2 Pwm_control Pwm1_control

0x16 Ios1 Ioc1 Pwm2_control

0x15 Ios0 Ioc0

0x14 Wsr

0x13 Imask1

0x12 Ipend1

0x11 Sp_stat Sp_con

0x10 Ioport2

0x0f Ioport1

0x0e Ioport0 Baud_rate

0x0d

0x0c

Timer2

T2control

T2cap

0x0b Ioc2

0x0a

Timer1

Watchdog

0x09 Int_pending

0x08 Int_mask

0x07 Sbuf

0x06 Hsi_status Hso_command

Ptssrv

0x05

0x04

Hsi_time Hso_time Ptssel

0x03 Ad_result_hi Hsi_mode Ad_time

Page 18: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

0x02 Ad_result_lo Ad_command

0x01

0x00

영 레지스터 r0

그래서 원하는 레지스터를 읽거나 쓰려면 일단 wsr레지스터값으로 조정을 한 다음에

읽거나 써야한다. 이 SFR값들은 나중에 각 기능에 대해서 알아보면서 같이 할 수 있을

것이다.

3 . 2 주변 회로

196컨트롤러가 동작하기 위해서 필요한 두가의 주변 회로가 있다.

일단 메인 클럭을 발생시키는 발진회로가 있다. 이 발진 회로가 내장되어 있어 크리

스탈(수정자)와 콘덴서만 달아주어도 클럭이 발생한다. 대신 외부에 오실레이터를 달아

서 직접 클럭을 입력해도 된다. 수정자를 이용한 발진주변 회로는 아래쪽 그림과 같이

구성하면 된다.

그 외에 리셋 회로가 있다. 196의 Reset은 Low액티브이므로

Low신호가 들어가면 모든 동작을 멈추고 안의 레지스터등을

초기화한다. 만약 회로에 high신호가 들어가 있지 않으면 컨트

롤러는 전혀 동작을 하지 않게된다. 리셋 회로는 Low액티브이

므로 오른쪽과 같이 구성하면 된다.

위의 두 주변회로와 전원만 들어간다면 196은 동작을 한다. 그러면 65번핀(PLCC타

입)인 CLKOUT에서 해당 주파수의 클럭이 나온다.

Page 19: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

3 . 3 메모리 인터페이스

196은 16bit와 8bit의 데이터를 사용할 수 있으며, 메모리는 16bit로 구성되어 있다.

196은 어드레스 버스와 데이터 버스가 같은 핀(포트2)을 공유하므로 이 버스를 어드레

스와 데이터로 분리해야한다. 그래서 196은 주소 래치 허용(ALE)을 이용하는데. 이 주

소 래치 허용의 클럭 신호를 입력 받아 주소 값만을 래치시켜서 분리해낼 수 있다.분리

된 주소 버스를 A0 ~ A15, 데이터 버스를 D0~ D15로 부른다.

읽기 동작과 쓰기 동작은 RD와 WR신호로 제어한다. 아래에 있는 버스 타이밍을 보자.

< 버스 타이밍도 >

어드레스가 출력된 후 제어신호(RD, WR)가 low되고 데이터가 나간다. 그 다음에 제어

신호가 high로 되면서 외부의 디바이스와의 읽기 쓰기 동작을 끝낸다.

칩 설정 레지스터(ccr)은 칩의 모드를 설정하는 레지스터로 CPU에 전원이 들어간 후

Page 20: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

처음으로 읽어 오는 데이터이다. 이 ccr은 0x2018번지로 예약 되어 있어 이 번지에 해

당하는 값을 넣어야 한다.

칩 설정 레지스터(ccr) 0x2018

비트 기능 1 0

0 전력 절약 모드 허용 허용 억제

1 버스폭 선택 16비트 버스 8비트 버스

2 쓰기 스트로브 모드 선택 WR과 BHE WRL과 WRH

3 주소 유효 스트로브 선택 ALE ADV

4

5

내부 READY 제어 모드 00: 지연 1상태

01: 지연 2상태

10: 지연 3상태

11: 외부 지연 상태

6

7

프로그램 고정 모드 00: 읽기,쓰기 보안

01: 읽기 보안

10: 쓰기 보안

11: 보안 안됨

이 ccr은 외부에 달아주는 메모리에 값을 기억시켜 놓는다. 이중에 1비트는 버스폭 선

택이다. 만약 설계한 시스템이 16bit를 사용하거나 8/16bit를 사용할 경우에 이 비트를

1로 세트 시키고 196의 핀중에 BUSWIDTH핀으로 16bit와 8bit를 제어 할 수 있다.

또 외부의 메모리가 CPU의 속도보다 느릴경우에 지연(Delay)를 사용하여 사용한다.

지연 상태 n상태이면 n상태만큼 지연해서 메모리를 억세스 한다. 만약 외부 지연 상태

를 한다면 외부의 READY핀이 1이 허용될때까지 기다리다가 실행을 한다.

실제 외부에 메모리를 달려면 아래와 같은 형태로 연결해야 한다.

제 메모리와 래치를 사용하여 설계한 회로도이다.

80C196KC

포트3

포트4

제어 신호

주소 / 데이터

AD0 ~ AD15

주소

A0 ~ A15

래치

데이터

Page 21: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

이 회로도에서는 래치가 74LS573로 사용되었다. 또 27256은 ROM(Read Only

Memory)이고 62256은 RAM(Random Access Memory) 이다. AD0 ~ AD7이라는 Net

Alias를 가진 wire들은 196의 어드레스와 데이터 공유핀이다. 573을 거친 다음에 나오

는 A0~A7과 포트4로 출력되는 A8~A15는 주소값을 의미한다. 위의 회로도는 8bit버

스를 사용하므로 상위 바이트버스는 래치를 사용하지 않았다. 그리고 WR, RD, ALE등

이 제어 신호들이다.

3 . 4 보드의 제작

이 쯤에서 보드를 실제로 제작해보고 다음 장부터는 실제 프로그래밍을 같이 하면서

공부해야 이해가 쉬울 것이다.

먼저 회로를 설계해야 한다. 회로 설계는 자기가 만들 시스템에 대해서 생각해보고,

그 시스템에 필요한 회로를 구성하면 된다. 가령 디지털 시계를 구현한다고 하면 시계

라는 시스템에서 필요한 것은 일단 정확한 시간을 알기 위해 타이머가 있어야 하고 현

제 시간을 출력해줄 부분이 필요하다. 또 시간을 맞추기 위해서 입력받을 버튼도 필요

하다. 이렇게 자기가 설계할 시스템에서 필요한 부분에 대해서 생각하고 그에 맞게 설

계하고 회로를 구성하면 된다. 이번장에서는 간단히 포트로 데이터를 출력하여 동작을

Page 22: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

확인하는 디스플레이부와 외부에서 프로그래머 임의로 신호를 줄 수 있는 버튼(이것 역

시 포트로 입력 받으면 된다) 몇 개, 또 RS232시리얼 통신을 위한 시리얼부분만 있으

면 이번장에서 배울 196의 기능들을 테스트하는 데에는 문제가 없다. 하지만 다음장과

우리가 최종적으로 하려는 Mobile로봇제작을 하기위해서는 모터부와 센서부등 많은 부

분이 필요하다. 그래서 이번장에서 보드를 만들고 다음장에서 다시 보드를 만들수는 없

기 때문에 다음 장에서 필요한 모터부와 센서부까지 회로를 구성하겠다. 그 회로에 대

한 설명과 실제 프로그래밍은 다음 장에서 하고 일단은 회로도에 대해서 간략히 소개하

겠다..

메인 회로도에는 CPU와 메모리 그리고 버튼등의 주변회로가 있다. 와이어의 별명을

보면 대충 그 선의 역할을 짐작할 수 있다. 또 Jumper는 커넥터를 의미하는 데 이는

한 보드에 회로를 다 넣지 않고 여러 개의 보드로 나누었을 때 이 보드끼리 필요한 와

이어들을 연결시켜준다.

모터부 회로도에는. 모터구동드라이버인 SLA7024와 주변회로가 나와있다. 또 모터와

연결하기위한 커넥터도 있다. (커넥터 순서에 주의하자)

센서부에서 센서는 모두 7개를 사용했는 데 그 이유는 나중을 위해서 바닥을 체크하

기 위한 3개의 센서와 옆의 가이드라인을 체크하기 위한 4개의 센서가 있다. 발광부는

고주파로 센서를 켜기위해 Tr로 구셩되어 있고, 수신부에는 형광등등의 왜란을 걸러주

는 필터회로가 있다.

그 외의 이 회로도에는 전원부와 RS232시리얼부와 디스플레이를 위한 LED등이 있다.

전원부는 정전압 레귤레이터7805를 사용하였다. 이는 우리가 만들 Mobile로봇은 독립

전원을 사용하므로 건전지를 사용하게 된다. 이때 건전지에서 일정한 전압을 얻을 수

없기 때문에 레귤레이터로 정전압5V를 얻게 되는 것이다. 또 디스플레이를 하는 데

14094라는 CMOS칩을 사용하였다. 이 칩은 8Stage Shift And Store Bus 로 8비트의 데

이터를 순서대로 쓰고 한 비트씩 쉬프트하다가 원하는 데이터(8비트)를 모두 보내면 병

렬로 출력시킨다. 즉 약간의 제어신호와 한 비트의 데이터 신호만 있어도 8비트의 출력

을 낼 수 있는 장점이 있다. 여기서는 196의 남는 포트가 8비트가 안 되기 때문에 사

용하였다.

Page 23: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

<Main 회로도>

Page 24: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

<Motor 회로도>

Page 25: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

<Sensor 회로도>

Page 26: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

<그 외 회로도>

이렇게 회로도가 모두 그려졌으면 다음에 이 회로대로 보드를 제작해야 한다.

보드를 제작할 때에는 먼저 모든 시스템의 구조을 구상해야 한다. 우리가 만들 Mobile

Page 27: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

로봇에는 센서와 모터가 필요하고 건전지등이 필요하다. 또 센서는 로봇이 정보를 얻을

수 있는 위치에 있어야 한다. 이런 정보들을 모으고 난 다음에 계략적인 모양을 스케치

하고 그것에 맞추어서 보드의 크기와 모양를 정한다. 다른 보드나 외부와 인터페이스할

커넥터등의 위치를 정한다.

위처럼 대략 그림을 스케치하였다면 다음엔 보드에 IC나 커넥터등의 부품을 배치한다.

IC의 경우 다른 IC들과 납땝하기 쉬운 쪽으로 배치하고 그라운드가 지나갈 부분은 남

긴다. 커넥터의 경우 연결이 쉬운 쪽으로 하되 모양도 생각해야 한다. 커넥터의 선들이

복잡하게 띄어져 있으면 보기에도 안 좋고 서로 안 좋은 영향을 미칠 수 있기 때문이다.

또 버튼이나 스위치는 우리가 조작하기 쉬운 곳으로 한다. 이렇게 대충 배치한 것을 위

와 마찬가지로 스케치한다.

< 부품 배치를 스케치한 그림 >

모터

메인보드

센선부보드

바퀴

건전지

바닥

PC RS232

건전

지를

넣기

위한

구멍

CPU Rom&Ram

전원부

버튼

모터드라이버

랫치

Page 28: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

다음에 IC가 꽂힐 라운드핀이나 소켓을 배치한 곳에 납땝한다.(IC의 경우 바로 납땜을

해버리면 IC를 고장나는 수가 있다) 이렇게해서 기본 모양을 낸다.

< 부품의 배치가 끝난 모습 >

다음에 보드에 기본적으로 Vcc와 GND 를 깔아준다. 전원선은 중요하므로 될 수 있으

면 점핑을 하면 안된다. 다음 모든선들을 순서있게 연결한다.

예를 들면 {‘전원’ -> ‘CPU 주변회로’ -> ‘어드레스 버스’ -> ‘데이터 버스‘ -> ‘커넥

터‘ -> ‘모터부’} 이런식으로 선들의 의미로 순서를 구분하면 납땜할 때 실수가 줄어든

다. 점핑을 할 때에는 래핑선의 끝을 짧게 벗겨내고 납땝한다. 납땝을 잘못해서 나중에

디버깅을 하는 것은 어려우므로 납땝을 할 때에는 집중을 해서 실수하지 않도록 하자.

Page 29: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

< 완성된 메인 보드의 모습 >

이렇게 모두 납땜이 끝나면 테스트를 해야 한다. 일단은 전원은 Power Supply를 사용

한다. 커넥터를 만들어 7.5V에 제한 전류값은 500mA정도 걸어서 연결하고, 다음 전원

을 테스트한다. 전원이 잘못 연결되면 IC가 나가는 수가 있기 때문에 IC를 꽂지 않은

상태에서 오실로스코프나 테스터기로 GND와 Vcc를 정확히 0V와 5V가 나오는지 체크

한다. 다음에는 간단한 프로그램을 돌려서 확인을 한다. 여기서 간단한 프로그램이란

CPU와 메모리부외에 회로를 사용하지 않는 프로그램을 말한다. 사용할 프로그램은

196의 포트로 특정한 값을 계속 보내는 프로그램이다. 이 프로그램의 소스는 아래와

같다.

#pragma model(kc)

#include "80c196.h"

void initial(void) {

int_pending = 0x00;

ipend1 = 0x00;

int_mask = 0x00;

imask1 = 0x00;

ioc1 = 0x00;

}

void main(void) {

unsigned char loop1, loop2;

disable();

initial();

enable();

while(1) {

ioport1 = 0x00;

/* Delay */

for(loop1 = 0; loop1 < 0xff; loop1 ++) {

for(loop2 = 0; loop2 < 0xff; loop2 ++);

}

ioport1 = 0xff;

/* Delay */

for(loop1 = 0; loop1 < 0xff; loop1 ++) {

for(loop2 = 0; loop2 < 0xff; loop2 ++);

}

}

}

Page 30: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

이 소스를 컴파일하고 링크하여 나온 Porttest.hex파일을 롬에 굽고 CPU, 메모리,

7404등을 소켓에 꽂고 전원을 넣어본다. 다음에 스코프로 포트1의 출력 파형을 관찰한

다. 일정하게 1과 0값이 바뀌며 출력이 되고 있다면 성공이다. 즉 CPU의 주변회로(발

진회로, 리셋회로)와 메모리 인터페이스부에는 이상이 없는 것이다. 만약에 값이 출력이

안 된다면 디버깅을 해야한다. Power Supply에 CC에 불이 들어 왔는지 확인한다. 이상

이 없으면 CPU의 전원을 확인하고 CLKOUT(65)핀을 확인 해 본다. 이 핀에서 클럭이

나오고 있으면 CPU에는 이상이 없는 것이다. CPU에 이상이 없다면 메모리와 CPU의

핀들이 제대로 납땝이 되었는지 확인한다. 테스터기의 도통확인기능를 이용하여 핀들을

확인한다. 이렇게 보드의 완성이 끝났다.

3 .5 프로그램 개발

보드의 제작이 끝났다. 여기서는 C로 프로그램을 개발하는 방법에 대해서 설명하겠다.

보통 C로 프로그램을 한다면 소스코드를 작성하고 컴파일한다. 이때 나온 obj파일들을

링크라는 과정을 통해서 실제로 동작하는 하나의 프로그램이 완성된다. 이렇게 C가 링

크라는 과정을 거치는 것은 C의 장점인 모듈화와 확장성을 위해서이다.

컴파일이라는 과정은 C소스코드를 CPU가 알수있는 OP코드로 바꿔주는 과정이다. 보

통 C소스파일은 *.c이지만 196에서는 *.c96식으로 사용하기도 한다. 이를 컴파일하면

*.obj라는 오브젝트파일이 된다. 이 오브젝트파일은 다른 목적으로 사용될 수 있게 하

기위해서 절대주소가 아닌 상대 주소를 갖고 있다.

링크라는 과정은 위에서 생성된 오브젝트파일들을 CPU에서 실행할 수 있게 메모리에

절대주소로 연결된다. 이 과정에서 우리가 원하는 메모리영역에 배치할 수가 있다. 이

때 필요한 옵션은 다음에 다시 설명하겠다. 링크라는 과정을 거치면 *.out이라는 파일

이 생성된다. 이젠 이 파일을 Rom Writer기가 알아볼 수 있는 파일포멧으로 변환시켜

줘야 한다. 우리는 인텔헥사포멧을 이용할 것이다. 위와 같은 과정을 그림으로 표현하

면 아래와 같이 나타낼 수 있다.

C 소스 파일

*.C

어셈블리 파일

*.asm

Page 31: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

< C로 개발하는 과정 >

우리가 제작하는 보드에서 프로그램이 실행하려면 메모리(Rom&Ram)에 OP코드들을

넣고 실행을 해야 한다. 보통 프로그램코드는 Rom에 들어가야 한다. 그래서 프로그램

을 수정할 때마다 RomWriter기를 이용해서 롬을 굽고 보드에 꽂아서 사용해야 한다.

이렇게 프로그램을 개발하는 것이 너무 번거러우므로 ‘모니터 프로그램’이라는 일종의

OS라 할 수 있는 프로그램을 사용한다. 이 모니터 프로그램은 Rom영역에서 실행하며

보드에 전원이 들어가거나 리셋이 되면 실행된다. 이 프로그램이 하는 역할은 PC에서

프로그램코드(Opcode)를 시리얼로 다운받아 Ram영역에 써주고 이 Ram영역에 프로그

램을 실행시키고 주는 역할을 한다. 이렇게 하면 프로그램수정 때마다 롬을 구워야하는

번거러움을 줄일 수 있다. 이 프로그램의 소스파일은 monitor.c96파일이다. 좀더 자세

C 컴파일러

cc.exe

어셈블러

asm.exe

오브젝트 파일

*.obj

오브젝트 파일

*.obj

링커

link.exe

라이브러리파일

*.lib

실행 파일

*.out

코드 변환기

obj2hex.exe

인텔 헥사 파일

*.hex

Page 32: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

히 설명하면 리셋벡터에 이 프로그램의 코드가 들어가 있고 이 프로그램은 시리얼이라

는 196의 기능을 이용하여 PC와 데이터를 주고 받을 수 있다. PC에서 프로그램에서

정의된 명령(‘l’)을 주고 실행파일 *.hex파일을 써주면 모니터 프로그램에서는 이 프로

그램 코드를 Ram상의 메모리에 복사를 한다. 또 다운로드한 프로그램을 실행시킬때에

도 정의된 명령(‘g’)를 주고 해당 프로그램의 시작번지를 입력하면 그 번지부터의 프로

그램을 실행시켜준다. 여기서 Rom과 Ram의 어드레스영역이 다르므로 프로그램 코드의

번지가 달라야한다. 즉 롬에서 실행되어야 하는 프로그램은 리셋벡터가 시작번지가 되

고, 모니터 프로그램에 의해서 실행되는 프로그램은 자기가 정의한 Ram번지가 시작번

지가 된다. 우리는 0x9000번지가 Ram프로그램의 시작번지가 될 것이다. 결론적으로

같은 프로그램이지만 롬에 구워서 실행할 때와 모니터 프로그램을 이용해 램에서 실행

할 때 링크를 다르게 해야한다. 아래의 예제는 실제 프로그램을 컴파일하고 링크하는

과정을 보였다.

C소스를 컴파일하는 과정이다.

D:\196>c.bat porttest

ic96 porttest.c96

DOS 7.10 (046-N) iC-96 COMPILER V2.1

Copyright 1980,89,90 Intel Corporation

iC-96 COMPILATION COMPLETE. 0 WARNINGS, 0 ERRORS

D:\196>

c.bat파일로 내용은 아래와 같다.

@echo ic96 %1.c96 %2 %3 %4 %5

@ic96 %1.c96 pw(97) ot(3) %2 %3 %4 %5

파일내용을 보면 알겠지만 인자를 받아서 컴파일러인 ic96을 실행시켜준다. 단지 소스

의 확장자를 인자로 입력할 필요가 없어지게 된다.

ASM소스를 어셈블하는 과정이다.

D:\196>asm cstart

asm96 cstart.a96

Page 33: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

DOS 7.10 (046-N) MCS-96 MACRO ASSEMBLER, V1.3

Copyright Intel Corporation 1983,1990

ASSEMBLY COMPLETED, NO ERROR(S) FOUND.

D:\196>

asm.bat파일내용이다

@echo asm96 %1.a96 %2 %3 %4 %5

@asm96 %1.a96 pw(97) nosb %2 %3 %4 %5

asm.bat역시 단지 어셈블러를 실행시켜준다. 단 .a96이란 확장자를 입력할 필요가 없

어진다.

어셈블과 컴파일을 하면 오브젝트파일인 *.obj파일과 컴파일이나 어셈블의 결과 내용

을 담고 있는 *.lst파일이 생성된다. 마약 소스파일에 에러나 경고가 있다면 그 내용은

*.lst파일에서 찾을 수 있다.

이젠 링크를 하는 과정이다. 링크시에는 전에도 얘기했지만 옵션과 링크될 파일들을

입력시켜줘야 한다. 링커에 이런 정보를 입력시키는 방법은 *.cmd파일내에 이런 내용

을 담아서 링커를 실행시킨다. 또 우리가 얻어야하는 최종 파일은 *.out이란 실행 파일

이 아닌 *.hex파일이다. 링크시에 사용하는 배치파일은 커맨드 파일을 생성시켜 링커를

실행시켜주고 코드변환기로 *.hex파일을 만들어준다.

D:\196>rom porttest

DOS 7.10 (046-N) MCS-96 RELOCATOR AND LINKER, V2.4

Copyright 1983, 1990 Intel Corporation

RL96 COMPLETED, 36 WARNING(S), 0 ERROR(S)

DOS 7.10 (038-N) OH V1.1

Copyright 1986 Intel Corporation

1 file(s) copied

File not found

1 file(s) copied

Page 34: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

1 file(s) copied

D:\196>

rom.bat파일은 롬에 구워서 실행하는 프로그램을 링크할 때 사용한다. rom.bat파일의

내용이다.

@echo off

rem 롬에 구워서 실행하는 프로그램을 링크할 때 사용

rem 인자가 없으면 탈출

if "%1" ==""goto quit

rem 커맨드 파일 생성

if exist %1.cmd del %1.cmd > nul

echo lib\romstup.obj, & > %1.cmd

echo %1.obj, & >> %1.cmd

echo lib\c96.lib & >> %1.cmd

echo to %1.out & >> %1.cmd

echo rom(2000h-2013h, 2018h-2019h, 2030h-203fh, 2080h-6fffh(%1)) &

>> %1.cmd

echo ram(7000h-7fffh, 8000h-8fffh(stack))>> %1.cmd

@echo off

if "%1" == "" goto quit

rem 링커 실행

rl96.exe & < %1.cmd

rem 코드변환기 실행

oh.exe %1.out

rem 기타 작업

copy %1.hex hex

del %1.cmd

del %1.out

del %1.bak

Page 35: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

del %1.obj

copy %1.hex c:\all07\work

copy %1.hex \hex

del %1.hex

:quit

위의 배치파일에서 링크되는 obj파일은 롬스타트업코드인 romstup.obj과 우리가 코딩

한 *.obj 그리고, 196에서 지원되는 기본함수가 정의되어 있는 c96.lib파일이 있다. 또

파일의 마지막부분에는 소스파일과 Hex파일 외에는 모두 삭제한다.

다음은 모니터 프로그램을 이용해서 Ram상에서 실행시킬 프로그램을 링크하는 과정

이다.

D:\196>ram.bat porttest

DOS 7.10 (046-N) MCS-96 RELOCATOR AND LINKER, V2.4

Copyright 1983, 1990 Intel Corporation

RL96 COMPLETED, 36 WARNING(S), 0 ERROR(S)

DOS 7.10 (038-N) OH V1.1

Copyright 1986 Intel Corporation

File not found

1 file(s) copied

1 file(s) copied

D:\196>

아래는 ram.bat파일 내용이다.

@echo off

rem 모니터 프로그램을 이용해서 프로그램을 실행 시킬때 사용

rem 인자가 없으면 탈출

if "%1" ==""goto quit

Page 36: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

rem 커맨드 파일 생성

if exist %1.cmd del %1.cmd > nul

echo lib\psramst.obj, & > %1.cmd

echo %1.obj, & >> %1.cmd

echo lib\c96.lib & >> %1.cmd

echo to %1.out & >> %1.cmd

echo rom(8000h-811fh, 9000h-9fffh(%1)) & >> %1.cmd

echo ram(7000h-7fffh, 8d00h-8fffh(stack), 0a000h-0ffffh) >> %1.cmd

@echo off

if "%1" == "" goto quit

rem 링커 실행

rl96.exe &< %1.cmd

rem 코드변환기 실행

oh.exe %1.out

rem 기타 작업

del %1.cmd

del %1.out

del %1.bak

del %1.lst

copy %1.hex d:\i50\work

copy %1.hex \hex

del %1.hex

:quit

이번엔 psramst.obj파일과 링크를 한다. 이 파일은 스타트업코드로 C로 구성한 프로

그램의 실제 시작하는 부분이다. 이 파일에서 인터럽트 벡터의 정의와 전역변수의 초기

화 및, 스택지정등을 하고 Main()함수를 콜한다. 그래서 위에 롬에 구워 사용하는 프로

그램과는 다른 스타트업코드를 사용하는 것이다. 링크후에 *.out파일과 링크의 결과내

용을 담은 *.m96파일이 생긴다. 컴파일을 할때와 마찬가지로 에러나 경고가 있을 경우

*.m96 파일을 열어서 조사해야 한다. 위와 같은 과정으로 작성한 프로그램소스를 실제

로 동작할 수 있게 한다. 다시 정리를 하면 아래 그림을 보자.

Page 37: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

<

하는 bat파일 >

3 .6 인터럽트

인터럽트란 어떤 프로그램을 순차적으로 수행하고 있는 도중에 현재 처리하고 있는 일

보다 우선순위가 높은 일을 처리해야 하는 경우에 컨트롤러는 우선순위가 높은 일부터

처리하는 기능을 말한다. 인터럽트 소스에서 신호가 나와서 인터럽트가 걸리면 컨트롤

러는 현제 상태를 스택에 저장하고, 해당 인터럽트 루틴으로 가서 그 루틴을 수행한다.

다음 인터럽트 루틴이 모두 끝나면 다시 스택에 저장한 상태들을 읽어와서 원래의 루틴

을 수행한다. 이 인터럽트부에서 익혀야 하는 것들은 다음과 같다.

인터럽트 소스, 인터럽트 벡터, 인터럽트 우선순위. 이렇게 세가지가 있다. 인터럽트

소스는 어떻게 인터럽트가 걸리느냐는 것이다. 외부인터럽트의 경우 외부에 달려있는

외부 인터럽트핀에 해당하는 신호가 들어오면 인터럽트가 걸리는 것이다. 또 시리얼인

터럽트의 경우는 시리얼로 데이터 8비트가 모두 들어오거나 모두 나가면 인터럽트가

걸린다. 다음에 인터럽트 벡터는 해당 인터럽트가 걸리면 어느 번지로 점프해야 하는지

를 가르키는 것이다. 즉 이 인터럽트 벡터에 인터럽트가 걸렸을 때 실행해야하는 루틴

의 메모리 번지를 적어야 한다. 인터럽트 우선순위는 동시나 인터럽트루틴이 실행하고

있을 때 인터럽트가 걸릴 경우 어느 것을 먼저 실행하는가를 정하는 것이다. 즉 더 중

요한 인터럽트를 먼저 실행하게 설정하는 것을 말한다.

소스파일 오브젝트파일

HEX파일 HEX파일

c . b a t

롬에 구 워 서

실행 할 경우

r o m . b a t

모니터 프로그램을 사용

해서 실행 할 경우

r a m . b a t

Page 38: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

196의 인터럽트는 28개의 소스에 15개의 벡터를 갖고 있다. 아래 표에 인터럽트 소스

와 해당 인터럽트 벡터가 표시되어 있다.

인터럽트 소스 인터럽트 벡터

NMI nmi(0x203E)

타이머2 기록 timer2_capture(0x2036)

hsi FIFO 4 hsi_fifo_4(0x2034)

extint1(p0.7)

extint(p2.2)

extint1(0x203A)

extint(0x200E)

받기 인터럽트

시리얼 인터럽트

보내기 인터럽트

receive_interrupt(0x2032)

serial_port(0x200C)

transmit_interrupt(0x2030)

소프트웨어 타이머

타이머2 리셋

AD변환 시작

software_timer(0x200A)

hsi.0 핀 hsi_0_pin(0x2008)

고속출력 high_speed_outputs(0x2006)

hsi FIFO 가득참

hsi 데이터 이용 가능

hsi_fifo_full(0x203C)

hsi_data_available(0x2004)

ad 변환 완료 ad_conversion_complete(0x2002)

타이머2 넘침

타이머 넘침

timer2_overflow(0x2038)

timer_overflow(0x2000)

< 인터럽트소스와 벡터의 관계 >

여러 개의 소스중에서 하나를 제어 비트로 선택하거나 인터럽트 루틴에서 상태레지스

터값을 읽어서 어느 소스에서 인터럽트가 걸렸는 지를 확인해야 한다. 다음은 196인터

럽트의 구조이다. 아래 그림을 보자.

인터럽트 소스 인터럽트 대기 레지스터

인터럽트 거름 레지스터

전체 인터럽트 허용

우선 순위

처리기

상태레지스터값변화

벡터생성,점프

Page 39: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

< 196인터럽트의 구조 >

196은 인터럽트 소스에서 신호가 들어오면 일단 대기 레지스터의 해당 비트를 세트

(‘1’)시킨다. 다음 전체인터럽트 허용 비트가 세트되어 있고 거름 레지스터에 해당 비트

가 세트 되어 있으면 우선순위처리기를 거쳐 각각의 상태 레지스터값을 변화시키고 해

당 벡터 번지로 점프를 한다. 우선순위가 낮은 인터럽트가 걸리면 대기 레지스터에 계

속 1로 세트되어 있어 우선순위가 높은 인터럽트가 끝나면 바로 인터럽크가 걸린다. 이

젠 위에서 나온 인터럽트 대기 레지스터(0x0008/ 0x0012)와 인터럽트 거름 레지스터

(0x0009/ 0x0013)을 살펴보자.

i n t _ p e n d i n g / i n t _ m a s k ( 0 x 0 0 0 9 / 0 x 0 0 0 8 )

비트 기능 벡터 우선순위

0 타이머 넘침 0x2000 15

1 A/D 변환 완료 0x2002 14

2 his 데이터 이용 가능 0x2004 13

3 고속 출력 인터럽트 0x2006 12

4 his.0 핀 0x0228 11

5 소프트웨어 타이머 0x200A 10

6 직렬 포트 0x200C 9

7 외부 인터럽트(extint 또는 p0.7) 0x200E 8

< 인터럽트 대기/ 거름 레지스터 >

i n t _ p e n d i n g 1 / i n t _ m a s k 1 ( 0 x 0 0 1 2 / 0 x 0 0 1 3 )

비트 기능 벡터 우선순위

0 보내기 인터럽트 0x2030 7

1 받기 인터럽트 0x2032 6

2 hsi fifo 4 0x2034 5

3 타이머 2 기록 0x2036 4

4 타이머 2 넘침 0x0238 3

5 extint핀 0x203A 2

6 hsi FIFO 가득참 0x203C 1

7 nmi (0으로 설정) 0x203E 0

< 인터럽트 대기1/ 거름1 레지스터 >

인터럽트 대기 레지스터는 소스로 신호가 들어오면 세트되고 인터럽트가 해당 벡터로

점프를 하면 클리어된다. 이 레지스터는 직접 값을 읽어 현제 대기중인 인터럽트가 무

엇인지를 알 수 있고, 값을 써넣어 대기중인 인터럽트를 취소할 수도 있고 소프트웨어

Page 40: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

적으로 인터럽트를 걸 수도 있다.

인터럽트 거름 레지스터에 비트가 세트되어야만 인터럽트가 걸린다. 즉 사용하는 인터

럽트의 비트만 세트시키고 동작시키면 된다. int_mask1레지스터 7번 비트의 값은 우리

임의로 쓸 수 없고 값은 언제나 0이다. nmi란 Non mask interrupt의 약자로 아주 중요

한 인터럽트를 nmi로 사용하여 마스크할 수 없도록 하는 것이다. 위 레지스터에 우선순

위도 같이 표시 되어 있다. 값이 작은 인터럽트가 우선순위가 높다.

한번에 모든 인터럽트를 허용(enable)하고 불허용(disable)하는 제어 비트가 있는 데

이 비트를 ‘전체 인터럽트 허용 비트’라고 한다. 이 비트는 psw레지스터의 9번 비트로

세트하면 인터럽트 허용, 클리어하면 불허용이다. 비트값을 쓸 때에는 psw레지스터에

그냥 값을 쓰면 되지만 196에서는 EI와 DI라는 명령어를 지원한다. 즉 어셈블에서는

EI라는 명령어를 쓰면 제어 비트가 세트되고, DI라는 명령어를 쓰면 클리어된다. C에서

는 enable()과 disable()이라는 함수를 사용하면 된다. 이 함수는 80196.h파일에 선언

이 되어있고, c96lib에 정의되어 있다.

이제 인터럽트를 처리하는 루틴에 대해서 알아보겠다. 인터럽트를 처리하는 루틴은 C

에서는 인자와 리턴값이 없는 함수를 선언해서 그 주소값을 인터럽트 벡터번지에 써넣

어 주면 된다. 그 방법은 #pragma interrupt( 인터럽트 처리 루틴 명 = 인터럽트 번호)

식으로 사용하면 된다. 즉, 인터럽트가 번호가 25인 받기 인터럽트가 걸리면 처리하는

함수명을 receive_interrupt()로 한다면 다음과 같이 사용한다.

#progma interrupt( receive_interrupt = 25 )

receive_interrupt() {

...

}

C컴파일러에 정의된 인터럽트 번호는 아래와 같다.

#progma interrupt( timer_overflow = 0 )

#progma interrupt( ad_conversion_complete = 1 )

#progma interrupt( hsi_data_available = 2 )

#progma interrupt( high_speed_outputs = 3 )

#progma interrupt( hsi_0_pin = 4 )

#progma interrupt( software_timer = 5 )

#progma interrupt( serial_port = 6 )

#progma interrupt( extint = 7 )

Page 41: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

#progma interrupt( trap_int = 8 )

#progma interrupt( unimplemented_opcode = 9 )

#progma interrupt( transmit_intterupt = 24 )

#progma interrupt( receive_intterupt = 25 )

#progma interrupt( hsi_fifo_4 = 26 )

#progma interrupt( timer2_capture = 27 )

#progma interrupt( timer2_overflow = 28 )

#progma interrupt( extint1 = 29 )

#progma interrupt( hsi_fifo_full = 30 )

#progma interrupt( nmi = 31 )

위 방법을 사용하면 해당 인터럽트 벡터에 인터럽트 처리 루틴의 첫 주소가 들어간다.

하지만 모니터 프로그램을 사용하는 경우 위의 방법을 사용하면 안된다. 왜냐하면 모니

터 프로그램은 램상에 코드가 들어가므로 인터럽트 벡터는 램상의 번지로 바꿔줘야 한

다. 이 역할을 모니터 프로그램이 한다. 우리가 사용하는 모니터 프로그램은 0x8000부

터 다시 인터럽트 벡터를 만들었다. 즉 모니터 프로그램은 인터럽트가 걸리면 자동으로

램상에 우리가 먼저 정의해놓은 인터럽트 벡터(0x8000~)로 점프한다. 또 우리가 위에

서 링크할 때 사용하던 램스타트업코드에서 이 램상의 인터럽트 벡터에 우리가 처리해

야하는 인터럽트 처리 루틴 명을 선언하고 점프시켜 놓았다. 즉 모니터 프로그램을 사

용하는 경우에 인터럽트 처리루틴을 사용하려면 램스타트업코드에 미리 선언한 함수명

을 사용하면 된다. 롬을 구워서 사용하는 경우도 마찬가지로 롬스타트업코드에 같은 함

수명으로 선언을 해 놓았다. 그래서 두가지 경우에 따로 인터럽트벡터 설정을 할 필요

없이 선언된 인터럽트 처리루틴명의 함수를 정의해서 쓰면 된다. 우리가 사용하는 스타

트업코드에 선언되어 있는 함수명은 위에 나온 처리명 그대로 사용하면된다. 즉 25번

인터럽트이면 이제 아무 선언없이 그냥

receive_interrupt() {

...

}

식으로 사용하면 된다.

Page 42: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

3.7 196의 주요기능

Ⅰ 시리얼

시리얼을 사용하려면 일단 별도의 커넥터가 필요하다. 그 이유는 PC의 시리얼의 기

준 전압과 우리가 사용하는 보드의 기준 전압이 다르기 때문이다. 우리가 사용하는

보드는 low레벨은 0V이고 high레벨은 5V를 사용한다. 하지만 PC는 low레벨일 때 �

12V를 high레벨일 때 12V를 사용한다. 그래서 위에 기타회로도를 보면 양 시리얼

입�출력핀 사이에 MAXON사의 Multichannel RS -232 Driver인 MAX232가 연결되어

있다. 보드의 회로를 줄이기 위해서 커넥터에 이 회로를 넣었다. 커넥터 사진은 아래

에 있다.

< 시리얼 케이블 >

위와 같은 시리얼 케이블이 준비되었으면 이제 소프트웨어적인 부분을 살펴보자.

196은 1개의 동기모드와 3개의 비동기모드를 갖고 있는 데, 아래의 표와 같다.

모드 전송 비트 수 비트 내용

동기 모드 모드 0 8 데이터

모드 1 10 시작 � 데이터 � 끝

비동기 모드 모드 2 11 시작 � 데이터 � 9th데이터 � 끝

Page 43: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

모드 3 11 시작 � 데이터 � 패리티 � 끝

196의 시리얼은 특징은 완전 이중 방식으로 되어있어 보내기와 받기를 동시에 할 수

있다. 또 이중 버퍼로 시리얼로 데이터를 주거나 받던중에 값을 읽거나 써서 데이터

가 깨질 염려도 없다. 시리얼 보내기 데이터 핀 TXD가 포트2.0과 공유하므로 ioc1레

지스터 5번 비트를 설정해서 txd로 사용할 건지 일반 io로 사용할 건지를 설정해야

한다.

i o c 1 ( 0 x 0 0 0 0 )

비트 기능 세트(1) 클리어(0)

0 pwm 선택 Pwm P2.5

1 외부 인터럽트 ach7 exint

2 타이머 1 넘침 인터럽트 허용 허용 억제

3 타이머 2 넘침 인터럽트 허용 허용 억제

4 hso.4 출력 허용 허용 억제

5 txd 선택 Txd P2.0

6 hso.5 출력 허용 허용 억제

7 hsi 인터럽트 선택 FIFO 가득참 저장 레지스터에 저장

다음에 시리얼 제어 레지스터 값을 설정해서 어떤방식으로 사용할 건지 정한다.

s p _ c o n ( 0 x 0 0 1 1 )

7 6 5 4 3 2 1 0

0 0 0 8번째 비트

보냄

받기 허용

REN

패리티 허용

PEN 모드 설정

5,6,7비트는 정의되어 있으므로 반드시 0으로 설정한다. 다음은 시리얼 상태 레지스

터이다.

s p _ s t a t e ( 0 x 0 0 1 1 )

7 6 5 4 3 2 1 0

8번째 비트 받음/

패리티 오류

/RB8/RPE

받기 표시

RI

보내기

표시

TI

프레임

오류

FE

보내기 버퍼

비어 있음

TXE

받기

넘침

OE

0 0

위의 두 레지스터는 같은 번지이다. 수평창이 0이면서 값을 쓸 때에는 sp_con이 되

고, 값을 읽을 때에는 sp_state가 된다. 여기서 주의해야 할 점은 sp_state값은 읽으

면 값들이 모두 지워진다는 것이다. 그래서 여러게의 상태를 비교하려면 버퍼에 저장

한 다음에 그 버퍼에 값을 읽어서 체크해야 한다. sp_stater값을 읽어서 현제 시리얼

의 상태를 알 수 있다. 받은 데이터의 에러 체크에서 수신상태등을 알 수 있다.

Page 44: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

다음에 설정해야 하는 부분이 보레이트이다. 이 보레이트는 비동기 모드에서 서로간

에 정해 놓은 통신 속도이다. 이 속도가 일치해야만 데이터를 정확하게 주고 받을 수

있다. 이 보레이트를 발생하기 위해선 baud_rate라는 8비트 레지스터에 원하는 보레

이트에 맞는 값을 구해서 넣어주면 된다. 주의할 것은 16비트의 데이터를 상위값을

먼저 써주고 나중에 하위 바이트 값을 써넣어주면 된다. 보레이트에 맞는 레지스터

값은 아래 식으로 구할 수 있다.

동기 모드 BAUD_VALUE = Fosc / (Baud Rate * 2) or T2CLK / Baud Rate

비동기 모드 BAUD_VALUE = Fosc / (Baud Rate * 16) or T2CLK / (Baud Rate * 8)

위 식으로 구한 다음에 최상위 비트 값으로 클럭 소스를 정한다. 만약 CPU 메인 클

럭을 이용하려면 최상위 비트 를 1로 t2clk핀으로 들어오는 클럭을 소스로 이용하려

면 최상위 비트를 0으로 한다. 우리가 제작한 보드의 메인 클럭은 20MHz 이므로 아

래 대표적인 보레이트에 대한 예가 있다.

보 레이트 보레이트 상위 바이트 값 보레이트 하위 바이트 값

9600 0x00 + 0x80 0x0082

19200 0x00 + 0x80 0x0041

38400 0x00 + 0x80 0x0020

이렇게 하면 모든 시리얼 설정이 끝난다.

196에서 시리얼 인터럽트는 3가지가 있다. 시리얼 인터럽트와 받기 인터럽트, 보내

기 인터럽트가 있다. 받기와 보내기 인터럽트는 sbuf에 값이 모두 나가거나 받으면

걸리는 인터럽트이고 시리얼 인터럽트는 두 경우 모두 인터럽트가 걸린다. 즉 시리얼

인터럽트를 사용하면 sp_state에 값을 읽어와서 ri와 ti값을 읽어서 보내기 인터럽트

인지 받기 인터럽트인지를 구분해야 한다. 아래는 위 인터럽트들의 벡터와 처리루틴

명이다.

보내기 인터럽트 = transmit_interrupt (0x2030)

받기 인터럽트 = receive_interrtup (0x2032)

시리얼 인터럽트 = serial_port (0x200C)

이제 다음 예제를 보면서 실제로 사용을 해보자.

#pragma model(kc)

#include <80c196.h>

typedef unsigned char BYTE;

typedef unsigned int WORD;

Page 45: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

void init_serial(void);

void receive_interrupt(void);

BYTE GetByte(void);

void PutByte(BYTE datum);

void puts(char *str);

void main(void)

{

disable();

wsr = 0x00;

ioc0 = 0x00;

ioc1 = 0x00;

ioc2 = 0x80;

ioport1 = 0x00;

ioport2 = 0x00;

asm pusha;

wsr = 0x0f;

ios0 = 0;

asm popa;

int_pending = 0x00;

ipend1 = 0x00;

init_serial();

enable();

puts("\r\nThis is Serial T.E.S.T. Program~!");

while(1);

}

/* 직렬 통신 정의 */

void init_serial(void)

Page 46: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

{

BYTE data;

int_mask = 0x00;

imask1 = 0x02; /* Receive interrupt Enable */

baud_rate = 0x82; /* WANNING!! BAUD_RATE is 9600 in 20MHz */

baud_rate = 0x80;

sp_con = 0x09; /* Mode 1, R_EN */

ioc1 = 0x20; /* TXD Select */

data = sbuf; /* Buff Clear */

}

/* 받음 인터럽트 처리 루틴 */

void receive_interrupt(void)

{

BYTE data;

data = GetByte();

PutByte(data);

}

/* 직렬 통신 상태 */

#define RI 0x40

#define RECEIVED 0x40

#define TI 0x20

#define SENDED 0x20

BYTE GetByte(void)

{

return sbuf;

}

void PutByte(BYTE datum)

{

sbuf = datum;

while( (sp_stat & TI) != SENDED);

Page 47: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

}

void puts(char *str)

{

int i;

for( i=0; str[i]!=0; i++)

{

PutByte( str[i]);

}

}

위 예제 프로그램은 receive_interrupt인터럽트를 사용하여 시리얼로 받은 데이터를

그대로 시리얼로 보낸다. 그래서 통신 프로그램에서 키보드로 입력한 문자 그대로 출

력시켜주는 프로그램이다. serial_init()함수에서 시리얼 설정과 인터럽트 설정이 되었

다. 또 PutByte()함수와 GetByte()함수는 다음부터 시리얼 설정만 필요에 따라 바꾸

고 이 함수들을 그대로 사용해도 잘 동작한다. PutByte()함수는 데이터를 시리얼로

쓰고는 모든 비트가 출력될 때까지 기다린다. 이는 사용자 편의에 맞게 고쳐서 사용

하면 된다. 또 puts()함수가 있는 데 문자열을 출력시켜주는 프로그램으로 상당히 편

리한 함수이다. 이 함수 역시 다른 소스에 복사해서 사용해도 된다. 또 나중에 디버

깅을 위해서 PutHex()와 PutDec()도 한번 짜보자.

Ⅱ 타이머

타이머는 마이크로 컨트롤러에 있어 아주 중요한 기능을 한다. 아니 중요한 기능보

다는 많은 기능을 갖는다. 196의 기능중에서 시리얼의 보레이트 발생과 HSO, HSI,

AD변환, PWM등 거의 모든 것에 타이머라는 기능이 필요하다. 또 이 타이머를 이용

해서 임의로 위의 기능을 소프트웨어적으로 구현 할 수도 있다.

타이머와 카운터 : 타이머는 일정한 클럭을 소스로 일정한 간격으로 타이머 값을 증

가(혹은 다운)시킨다. 하지만 카운터는 언제 발생할 지 모를 신호를 입력 받아서 그

값을 증가시킨다. 타이머와 카운터는 같은 구조이지만 들어오는 소스에 따라서 구분

을 지을 수 있는 것이다. 용도로서 차이점이라면 타이머는 (소스간격의 시간 * 현제

타이머 값) = 원하는 시간이 되고, 카운터는 들어온 신호 = 원하는 개수가 된다. 타

이머/카운터는 클럭 소스, 증가 or 감소 방향, 리셋, 넘침 등이 중요한 요소가 된다.

Page 48: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

196에는 2개의 타이머를 갖고 있다. 일단 각각 타이머의 특징을 알아보자.

Timer1 � 타이머1은 16비트 자유증가 타이머로 CPU 메인클럭의 1/16이 소스가 된

다. timer1(0x000A / 0x000B)레지스터 값을 읽고 쓸 수 있다. 단 이 타이머1은 자유

타이머로 hsi와 hso의 기준 시간이 되므로 함부로 값을 쓰면 오동작을 일으킬 수 있

다. 타이머1은 클럭 소스가 일정하고 증가되는 방향도 하나로 정해져 있어 기준 타이

머로 많이 사용된다. 또 우리가 제어할 수 있는 부분이 거의 없으므로 설정 레지스터

역시 적다. 아래에 설정하는 레지스터가 나와 있다.

- ios1.5 : 타이머1넘침 상태로 타이머1값이 오버플로우가 발생하면 1로 세트된

다.

- ioc1.2 : 타이머1 넘침 인터럽트 허용으로 1로 세트하면 허용이고 0으로 클리

어시키면 인터럽트 억제가 된다.

Timer2 � 타이머2는 타이머/카운터로 HSO기준시간으로 사용되며 외부 사건 기록용

과 추가의 카운터로 사용된다. 타이머2의 소스는 내부 클럭과 외부 클럭으로 나눌 수

있으며 되부 클럭은 t2clk와 hsi 중에서 선택할 수 있다. 이 소스를 설정하는 것은

아래와 같다.

클럭소스 내부 클럭 선택 외부 클럭 소스 선택

내부 클럭 1 X

t2clk 0 외부 클럭

hsi.1 0

1

또 들어오는 소스는 분주를 할 수 있다. 그러니까 소스로부터 들어오는 신호가 8개

들어 오면 타이머값을 1 변화거나 신호가 들어 올 때마다 1값을 변화시킨다. 이 설정

은 ioc2.0으로 한다. ioc2.0값이 1이면 고속 증가 모드로 신호마다 1씩 값을 변화시

키고, 0이면 8개의 신호가 들어와야 1값을 변화시킨다. 그래서 내부 클럭을 소스로

사용하고 ioc2.0값을 0으로 하면 타이머1과 같은 시간간격으로 동작하게 된다.

다음은 리셋이다. 타이머는 내부적으로 2개, 외부에서 2개의 리셋 소스를 갖고 있다.

리셋 소스를 설정하는 방법은 아래 표에 나타내었다.

리셋 소스 타이머 2 외부 리셋 허용

i o c 0 . 3

타이머 2 리셋 소스 선택

i o c 0 . 5

hso 명령14 내부

ioc0.1 0 X

t2rst 0 외부

hsi.0 1

1

위에 있는 비트들을 설정해서 timer2리셋 소스를 설정 한다.

이젠 타이머2와 관련있는 레지스터들을 밑에 정리하였다.

Page 49: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

- t2control.0 : 타이머2의 소스를 결정한다. 1이면 내부 클럭을 이용하고, 0이면 외

부 클럭을 이용한다. (*주의 t2control레지스터는 수평창1번으로 값을 써야한다)

- ioc0.3 : 타이머2 외부 리셋 허용으로 0이면 내부를 사용하고, 1이면 ioc0.5값에

따라서 외부 리셋을 허용한다.

- ioc0.5 : 타이머2 외부 리셋 소스 선택으로 0이면 t2rst핀이, 1이면 hsi0핀이 외

부 리셋 소스가 된다.

- ioc1.3 : 타이머2 넘침 인터럽트 허용으로 1이면 인터럽트를 허용하고, 0이면 억

제한다.

- ioc2.0 : 타이머 고속 증가 허용으로 1이면 소스 신호 입력마다 타이머값이 1변

화하고, 0이면 8개의 소스가 들어오면 1변화한다.

- ioc2.1 : 타이머2 감소 허용으로 0이면 타이머2는 타이머값은 증가하고, 1이면

p2.6이 1일 때 감소모드로 동작하고, p2.6이 0일 때 증가모드로 동작한다.

- ioc2.5 : 타이머2 8000 인터럽트 허용으로 1이면 허용하고 0이면 억제한다.

8000인터럽트란 타이머2의 값이 8000을 넘었을 때 인터럽트가 걸리는 것을 말한

다.

- ios1.4 : 타이머2 넘침으로 타이머2의 값이 오버플로우가 일어나면 이 비트의 값

은 세트된다.

타이머에 관련된 인터럽트는 타이머 넘침 인터럽트와 타이머2 넘침 인터럽트, 타이

머2 기록 인터럽트가 있다. 타이머 넘침 인터럽트와 타이머2 넘침 인터럽트는 타이머

1과 2의 값이 오버플로우가 일어나면 인터럽트가 걸린다. 단 타이머2는 8000 넘침

인터럽트로 설정되어 있으면 8000에서 8001로 넘어갈 때 인터럽트가 걸린다. 또 타

이머2 기록 인터럽트는 p2.7에 신호(상승 엣지)가 들어오면 이 인터럽트가 걸린다.

이 인터럽트가 걸리면 그 순간의 타이머2값이 r2cap이라는 16비트의 레지스터에 기

록된다. 그래서 리셋을 시킨 다음부터 신호가 들어오는 데까지의 시간을 측정 할 때

많이 사용된다. 다음은 위 인터럽트들의 처리 루틴 명과 인터럽트 벡터이다.

타이머1 넘침 인터럽트 = timer_overflow(0x2000)

타이머2 넘침 인터럽트 = timer2_overflow(0x2038)

타이머2 기록 인터럽트 = timer2_capture(0x2036)

아래는 타이머를 이용한 예제 프로그램이다.

#pragma model(kc)

#include "80c196.h"

Page 50: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

typedef unsigned int uint;

typedef unsigned char BYTE;

typedef unsigned int WORD;

void LED(BYTE led_data );

void initial(void)

{

ioc2 = 0x20;

/* Init Serial */

baud_rate = 0x82; /* WANNING!! BAUD_RATE is 9600 in 20MHz */

baud_rate = 0x80;

sp_con = 0x09; /* Mode 1, R_EN */

}

void init_timer_high_spd(void)

{

int_pending = 0x00;

ipend1 = 0x00;

int_mask = 0x00;

imask1 = 0x10;

ioc0 = 0x00; /* timer reset source is not extn */

ioc1 = 0x28; /* TXD enable, timer2_overflow interrupt enable */

ioc2 = 0x01; /* 타이머 고속증가모드 허용, 타이머증가모드,

8000인터럽트 억제 */

wsr = 0x01;

t2control = 0x01;

wsr = 0x00;

}

void init_timer_low_spd(void)

{

int_pending = 0x00;

ipend1 = 0x00;

int_mask = 0x00;

Page 51: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

imask1 = 0x10;

ioc0 = 0x00; /* timer reset source is not extn */

ioc1 = 0x28; /* TXD enable, timer2_overflow interrupt enable */

ioc2 = 0x00; /* 타이머 고속증가모드 억제, 타이머증가모드,

8000인터럽트 억제 */

wsr = 0x01;

t2control = 0x01;

wsr = 0x00;

}

void main(void)

{

wsr = 0x00;

initial();

init_timer_low_spd();

while(1)

{

while((sp_stat & 0x40) != 0x40);

/* 시리얼 데이터 입력을 기다린다 */

switch(sbuf)

{

case 'u' :

init_timer_high_spd();

break;

case 'd' :

init_timer_low_spd();

break;

default:

break;

}

}

}

Page 52: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

/* Timer2 Overflow Interrupt Routin */

void timer2_overflow(void)

{

static BYTE count;

count ++;

LED(count);

}

/* LED Display Funtion */

void LED(BYTE LED_Data)

{

BYTE loop,DataBuff;

/* Initial Port2 */

/*ioport2 = 0x00;*/

/* STB_SET */

ioport2 |= 0x80;

for(loop = 0; loop < 8; loop++)

{

/* CLK_CLR */

ioport2 &= 0xdf;

DataBuff = LED_Data & 0x80;

LED_Data = LED_Data << 1;

if(DataBuff == 0x00)

ioport2 &= 0xbf;

else

ioport2 |= 0x40;

/* CLK_SET */

ioport2 |= 0x20;

}

Page 53: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

/* STB_CLR */

ioport2 &= 0x7f;

}

이 예제 프로그램은 타이머2를 증가 모드로 사용하여 타이머 넘침 인터럽트가 걸릴

때마다 값을 1증가 시키고 그 값을 LED()라는 함수로 외부 io로 출력시키는 루틴이

다. 단 initial()함수는 시리얼을 초기화 했고, init_timer_low_spd()는 타이머2 고속

증가 모드를 억제한 것이고, init_timer_high_spd()는 타이머2를 고속 증가 모드로 사

용한 것이다. 그래서 출력되는 결과를 보면 일정하게 포트에 값이 증가하는 데 시리

얼로 ‘u’값이 들어 오면 증가모드로 전환해 증가하는 것이 빨라지고, ‘d’값을 시리얼로

보내주면 증가모드 억제로 증가되는 것이 느려진다. LED라는 함수는 우리가 io를 확

장하기 위해서 ioport2. 5,6,7에 4094에 연결해서 시리얼 동기 모드로 사용하듯이 데

이터를 쓰면 8비트의 값을 쉬프트시킨 다음 8비트의 데이터를 병렬로 출력시켜준다.

4094는 8 Stage Shitf And Store Bus Register로 보통 모자라는 io를 확장하기 위해

서 사용한다. 위에서 사용한 LED()라는 함수와 우리가 사용한 회로도를 같이 살펴보

면 4094에 어떤식으로 데이터를 주어야 하는 지 알 수 있다. 4094의 데이터북은

CMOS데이터북에서 찾을 수 있으며 나중에 첨부하겠다.

Ⅲ HSO

HSO는 196에서 유용한 기능중에 하나이다. 이 기능은 어떤 정해진 시각에 이벤트

를 발생시켜 어떤 동작을 수행할 수 있다. HSO는 타이머2를 이용한다. HSO 는 High

Speed Output으로 왜 고속인가하면 CPU의 부하없이 하드웨어로 처리하기 때문이다.

이 기능 역시 타이머를 잘 사용하면 소프트웨어적으로 구현 할 수 있으나 하드웨어로

처리하면 아까 위에서 언급했듯이 CPU의 처리에 영향을 주지 않으므로 아주 유용하

다. 우리가 나중에 사용할 센서와 모터를 사용하는 데 모두 사용되므로 잘 읽어두고

익히자.

HSO는 어떤 정해진 시각에 이벤트를 발생시킨다고 했다. 발생되는 이벤트는 타이머

2 리셋, AD변환, 소프트웨어 타이머 인터럽트 발생, hs o핀으로 펄스 출력 등이 있다.

여기서 hso핀으로 출력하는 것 외에는 모두 내부 이벤트라 하고 hso로 출력하는 것

을 외부 이벤트라고 한다. 이 HSO에서 중요한 것은 [어느 시점이냐?]와 [어떤 이벤

트인가?]가 중요하다.

먼저 HSO가 어느 시점에 이벤트를 발생하는 지 알아보자. 이것은 CAM이라는 내용

변경 메모리를 알아야 한다. 이 메모리는 24비트 * 8개로 구성되어 있다. 그래서 이

벤트를 발생시키는 명령은 8개까지 지정 할 수 있으며 24비트중에서 최상위 8비트는

Page 54: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

명령을 저장하는 곳이고, 그 하위 16비트는 타이머와 비교되는 값을 담고 있다.

그래서 이 16비트의 값과 타이머(1또는 2, 이것은 명령어에서 정의한다)의 값과 일치

하면 상위 8비트의 명령어를 읽어서 해당하는 이벤트를 발생시키는 것이다. 8비트 명

령 레지스터에는 아래의 표와 같다.

H S O 명령 레지스터 ( 0 x 0 0 0 6 )

비트 기능

0

1

2

3

채널 선택

0 : hso.o 선택

1 : hso.1 선택

2 : hso.2 선택

3 : hso.3 선택

4 : hso.4 선택

5 : hso.5 선택

6 : hso.0과 hso.1을 선택

7 : hso.2와 hso.3을 선택

8 : 소프트웨어 타이머 0 선택

9 : 소프트웨어 타이머 1 선택

A : 소프트웨어 타이머 2 선택

B : 소프트웨어 타이머 3 선택

C : hso핀 모두를 선택

D : 예약

E : 타이머2 리셋

F : AD 변환 시작

4 1: 인터럽트 발생 0: 인터럽트 억제

5 1: hso핀 1로 설정 0: hso핀 0으로 설정

6 1: 비교타이머2 0: 비교타이머1

7

명령

1: CAM 내용 고정 0: CAM 내용 변경 가능

CAM은 8개까지의 이벤트를 저장할 수 있는 데, 이벤트를 발생시키면 해당하는 명

령은 지원진다. 만약 지우지 않고 계속 이벤트를 발생시키려면 HSO명령에 7번 비트

를 세트하면 이벤트가 발생하더라도 명령은 지워지지 않는다. 또 이 CAM값이 8개

모두 차있는 데 명령을 또 쓰면 HSO저장 레지스터에 기억되다가 빈 공간이 생기면

값이 들어가게 된다. 저장에 값이 CAM에 들어가기 전에 또 명령을 쓰면 저장레지스

터에 있던 명령은 지워지고 새로 쓴 명령이 덮어쓰게 된다. 그래서 CAM의 상태를

읽어서 이런 실수를 방지해야 한다. ios0.6-CAM 또는 저장 레지스터 가득참과

ios0.7-hso 저장 레지스터 가득참이 있는 데 해당 비트가 세트되어 있으면 가득 차

있다는 것을 표시한다.

이젠 HSO로 발생하는 이벤트들에 대해서 알아보자.

Page 55: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

타이머2 리셋이라는 명령이 걸리면 타이머2의 값을 0으로 리셋하고 인터럽트 허용

으로 되어있으면 소프트웨어 타이머 인터럽트가 걸린다. 다음에 AD변환 시작은 AD

변환 명령어를 쓰고 사용하면 이벤트가 발생하는 순간의 입력값에 대해 AD변환을 한

다. 이 이벤트 역시 소프트웨어 인터럽트가 걸린다. 다음에 소프트웨어 타이머가 있

는 데 이는 단지 인터럽트만 걸린다. 이 인터럽트는 4개를 동시에 걸 수 있는 데 해

당하는 인터럽트는 ios1을 보면 어떤 소프트웨어 타이머 인터럽트가 걸렸는 지 알 수

있다. Hso와 관련된 이벤트는 해당 hso핀에 hso명령 레지스터 5비트 값으로 출력되

고 인터럽트는 고속 출력 인터럽트가 걸린다. hso핀에 출력되고 있는 값을 알고 싶을

때엔 ios0 레지스터를 읽으면 된다.

HSO명령을 쓰려면 아래와 같이 명령을 먼저 쓰고, 다음에 이벤트가 걸릴 타이머 값

을 쓰면 된다.

hso_command = 0x18; /* 소프트웨어 타이머0번 인터럽트 허용 */

hso_time = timer1 + 0x20; /* 지금부터 20개의 클럭이 들어오면 */

이 HSO를 사용할 때, 주의해야 할 것이 있다. 타이머를 기준으로 동작을 하기 때문

에 이 타이머 값을 함부로 바꾸면 원하지 않는 시간에 명령을 실행 할 수 있다. 또

타이머2번는 증가와 감소를 조절 할 수 있으므로 주의하자. 물론 이런 기능을 이용해

서 다른 기능으로 사용할 수도 있다.

HSO와 관련된 인터럽트들을 정리해 보았다.

- 소프트웨어 타이머 = software_timer(0x200A)

- 고속 출력 인터럽트 = high_speed_outputs(0x2006)

HSO를 이용한 예제 프로그램이다.

#pragma model(kc)

#include "80c196.h"

typedef unsigned int uint;

typedef unsigned char BYTE;

typedef unsigned int WORD;

#define ON_TIMER_VALUE 0x4000

#define OFF_TIMER_VALUE 0x0000

void LED(BYTE LED_Data);

Page 56: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

void software_timer(void) /* 소프트웨어 타이머 인터럽트 */

{

BYTE ios1_img;

static BYTE count;

wsr=0;

ios1_img = (ios1 & 0x03); /* 소프트웨어 타이머 0과 1을 유효 */

if((ios1_img & 0x01) == 0x01) { /* 소프트웨어 타이머가 0이면 */

LED(count);

count ++;

hso_command = 0x18;

hso_time = ON_TIMER_VALUE;

}

if((ios1_img & 0x02) == 0x02) { /* 소프트웨어 타이머가 1이면 */

LED(0x00);

hso_command = 0x19;

hso_time = OFF_TIMER_VALUE;

}

}

void main(void)

{

disable();

wsr = 0x00;

ioc0 = 0x00;

ioc1 = 0x00;

ioc2 = 0x80;

int_pending = 0x00;

ipend1 = 0x00;

int_mask = 0x20;

Page 57: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

imask1 = 0x00;

enable();

hso_command = 0x18; /* 소프트웨어 타이머0 인터럽트 허용, CAM 고정 */

hso_time = ON_TIMER_VALUE;

hso_command = 0x19; /* 소프트웨어 타이머1 인터럽트 허용, CAM 고정 */

hso_time = OFF_TIMER_VALUE;

while(1);

}

void LED(BYTE LED_Data)

{

BYTE loop,DataBuff;

/* Initial Port2 */

/*ioport2 = 0x00;*/

/* STB_SET */

ioport2 |= 0x80;

for(loop = 0; loop < 8; loop++)

{

/* CLK_CLR */

ioport2 &= 0xdf;

DataBuff = LED_Data & 0x80;

LED_Data = LED_Data << 1;

if(DataBuff == 0x00)

ioport2 &= 0xbf;

else

ioport2 |= 0x40;

/* CLK_SET */

Page 58: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

ioport2 |= 0x20;

}

/* STB_CLR */

ioport2 &= 0x7f;

}

위의 예제 프로그램은 소프트웨어 타이머0과 1을 이용해서 LED값을 디스플레이하

는 프로그램이다. 실제로 동작하는 것을 보면 LED는 계속 깜박거리며 1씩 증가한다.

타이머 값과 비교해서 나타내면 아래와 같다.

구간은 LED가 모두 꺼진 상태이다.

구간은 LED에 count 값이 출력된다.

스코프로 찍어서 확인을 해 보자.

Ⅳ AD변환기

AD변환기는 아날로그 값을 디지털 값으로 변환시켜 주는 기능을 말한다. 아날로그

입력은 P0과 공유해서 사용하는 AD입력핀이 있고, 변환된 디지털 값은 ad_result_hi,

ad_result_lo라는 레지스터에 저장된다.

196의 AD변환기는 8개 채널의 8/10비트의 분해능을 갖고 있다. AD변환은 한번에

한 채널씩 할 수 있으며 ad_command라는 레지스터에 값을 써넣으므로써 사용할 수

있다.

타이머1 값

Page 59: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

a d _ c o m m a n d ( 0 x 0 0 0 2 )

7 6 5 4 3 2 1 0

0 0 0 1 : 10bit

0 : 8bit

1: 변환 시작

0: hso명령으로 시작 채널 번호

5,6,7번 비트는 예약되어 있으므로 0으로 쓰고 4번 비트로 비트수를 정한다. 8비트

로 변환을 하면 분해능은 떨어지나 변환 시간이 짧아진다. 3번 비트의 변환 시작은 1

로 하면 명령어가 쓰이자 마자 바로 시작을 하지만 hso명령으로 시작하면 hso의 이

벤트발생 순간에 자동으로 시작된다. 나머지 3비트는 채널번호를 써넣으면 된다.

AD변환 결과는 ad_result_lo 와 ad_result_hi에 적힌다. 이 레지스터에는 ad의 현제

상태도 알 수 있다.

a d _ r e s u l t _ l o ( 0 x 0 0 0 2 )

7 6 5 4 3 2 1 0

AD결과 하위

2비트 0 0

1: 변환 중

0: 변환 끝 AD 채널 번호

a d _ r e s u l t _ h i ( 0 x 0 0 0 3 )

7 6 5 4 3 2 1 0

ad 결과 상위 8비트

8비트 분해능으로 사용하면 상위 8비트에 모든 값이 들어간다.

아래는 그외에 AD와 관계있는 레지스터들이다.

a d _ t i m e ( 0 x 0 0 0 3 )

7 6 5 4 3 2 1 0

샘플링 변환 시간

상태 시간수 = 4 * 샘플링 + 비트수 * (변환 +1) + 2.5

i o c 2 ( 0 x 0 0 0 B )

비트 기능 1 0

0 타이머2 고속 증가 허용 고속 증가 보통 모드

1 타이머2 감소 허용 감소 허용 증가

2 Pwm의 주파수 반감 허용 허용 억제

3 ad_time 레지스터 이용 이용 억제

4 ad 변환 모드 선택 고속 모드 보통 모드

5 타이머2 0x8000 인터럽트 허용 허용 억제

6 CAM 내용 고정 허용 허용 억제

7 전체 CAM 지움 지움 억제

ad_time과 ad 변환 모드 모두 kc모델에만 있다. ad_time은 AD하는데 필요한 시간

Page 60: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

을 설정하는 레지스터이고 ad변환 모드로는 고속 변환 모드와 보통 변환 모드가 있

다. 위에 레지스터들은 설정하는 데 약간의 제약이 있다.

ad_time -> ioc2 -> ad명령 순으로 초기와 해야한다.

변환이 진행중일 때 ad 시간 레지스터 ad_time을 사용하여 변환을 시작하며 안된

다.

ad_time 레지스터값이 0이면 안된다.

이상이 AD변환 설정을 하는 방법이다.

이 AD와 관계되는 인터럽트와 처리 루틴명, 인터럽트 벡터를 나타내었다.

AD 변환 완료 인터럽트 = ad_conversion_complete(0x2002)

아래는 예제 소스이다.

#pragma model(kc)

#include "80c196.h"

typedef unsigned int uint;

typedef unsigned char BYTE;

typedef unsigned int WORD;

void LED(BYTE LED_Data);

void high_speed_outputs(void)

{

asm pusha;

wsr = 0x00;

ad_command = 0x10;

hso_command = 0x0F;

hso_time = timer1 + 0x30;

asm popa;

}

void ad_conversion_complete(void)

{

Page 61: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

BYTE ad_data;

asm pusha;

wsr = 0x0f;

ios0=0;

wsr = 0x00;

ad_data = ad_result_hi;

LED(ad_result_hi);

hso_command = 0x30;

hso_time = timer1 + 0x50;

asm popa;

}

void main(void)

{

disable();

wsr = 0x00;

ioc0 = 0x00;

ioc1 = 0x00;

ioc2 = 0x80;

int_pending = 0x00;

ipend1 = 0x00;

int_mask = 0x0a;

imask1 = 0x00;

hso_command = 0x30; /* hso0 세트 */

hso_time = timer1 + 0x20;

enable();

while(1);

Page 62: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

}

void LED(BYTE LED_Data)

{

BYTE loop,DataBuff;

/* Initial Port2 */

/*ioport2 = 0x00;*/

/* STB_SET */

ioport2 |= 0x80;

for(loop = 0; loop < 8; loop++)

{

/* CLK_CLR */

ioport2 &= 0xdf;

DataBuff = LED_Data & 0x80;

LED_Data = LED_Data << 1;

if(DataBuff == 0x00)

ioport2 &= 0xbf;

else

ioport2 |= 0x40;

/* CLK_SET */

ioport2 |= 0x20;

}

/* STB_CLR */

ioport2 &= 0x7f;

}

위의 예제 소스는 AD채널0의 입력갑을 LED로 디스플레이해 주는 프로그램이다.

P0.0에 전압(0~5V)의 전압을 걸어보자. Power Supply를 이용하면 편리하다. 0V에서

천천히 올리면 점점 LED로 출력되는 2진 값이 커짐을 알 수 있다. 위의 예제는 다음

장에서 센서부를 구동할 때 사용하므로 여기서 잘 익혀주자. hso로 이벤트를 발생시

킨뒤 일정 시간후에 AD를 시작한다. 다음 AD변환이 완료되면, AD값을 읽고 LED로

Page 63: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

디스플레이 한 다음에 다시 hso 이벤트를 준비한다.

4장 주변 회로

4 . 1 모터부

4 . 2 센서부

Page 64: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

MF1에서 필요한 주변회로는 모터부와 센서부가 있다. 모터부에서는 모터의 구동원리

와 모터를 간단히 제어하는 방법에 대해서, 센서부에는 회로구성과 센서구동에 대해서

알아보겠다.

4 . 1 모터부

4.1.1 스테핑 모터와 DC 모터

모터에는 여러가지 종류가 있다. 그 중에서 우리는 스테핑모터를 이용하여 로봇을 구

동할 것이다. 일단 스테핑모터와 상당히 대조적인 DC모터의 특성을 비교하면서 각 모

터의 특성을 알아보자.

DC Motor STEPPING Motor

- 소형, 경량이다. 따라서 로보트 전체를

작고 가볍게 만들 수 있다.

- 전력 소모가 적어 배터리를 적게 사용

할 수 있다.

- 고속 회전이 가능하다.

- 구동 회로가 간단하다.

- 가속이 빠르다.

- 제어가 쉽다.

- 정확한 제어가 가능하다. (오차가 적

다.)

- DC와 상대적으로 가격이 저렴하다.

- DC보다 힘이 좋다.

- 자기 유지력

- Hunting이 없다.

- 제어가 어렵다.

- 정확한 제어를 위해서는 복잡한 이론

들이 필요하고, 실제 구동시 많은 계산

이 필요하다.

- 무겁고 많은 전력을 필요로 한다.

- 고속회전이 불가능하다.

- 고속회전시에 약간의 충격에도 탈조현

상이 발생한다.

- 구동회로가 복잡하다.

우리가 스테핑모터를 사용하는 이유는 무엇보다도 쉽고 정확한 제어에 있다. 또 모터

의 크기가 있어서 외부 프레임을 따로 깍을 필요가 없다. 아래는 우리가 사용할 스테핑

모터의 사진이다.

Page 65: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

4.1.2 스테핑모터의 구동원리

Stepping motor에서 그 내부를 구성하는 고정자라고 불리우는 극의 수에 따라 단상

(1상), 2상, 3상, 4상, 5상, 6상 등의 종류가 있으며, 기본적으로 이 극의 수에 따라

motor의 step각 등의 기본 특성이 달라진다. 여기서는 일반적으로 가장 많이 사용되고

있는 4상 stepping motor를 예를 들어 동작원리에 대해 설명하겠다.

4상 스테핑모터를 단순화시켜서 보면 아래와 같다.

모터의 회전자는 영구자석으로 되어있

다. 그리고 회전자 주변의 고정자에는 코

일이 감겨져 있다. 그래서 A고정자에 전

류를 흘려 보내주면 A고정자가 여자되어

회전자의 극이 해당하는 고정자로 돌아가

게 된다. 그래서 A고정자 -> B고정자 ->

/A고정자 -> /B고정자순으로 전류를 흘

려보내주면 회전자는 각 고정자를 쫒아가

면서 회전하게 되는 것이다. 실제 우리가

사용하는 스텝모터는 회전자의 영구자석

이 톱니모양으로 되어있다. 그리고 고정자 역시 톱니개수만큼 나누어져있다. 그래서 작

은 스텝각을 가질 수 있는 데, 스텝각이 작을수록 정밀한 제어가 가능하다. 이 스텝각

은 톱니수와 관계가 있으며 그 관계는 아래와 같다.

스텝각 = 360도 / (상의수 * 회전자의 톱니수)

4.1.3 구동방식

구동방식에는 단극성(Unipolar)와 양극성(Bipolar) 구동방식이 있다. 그림을 보면

이해가 쉬울 것이다.

A

B

/A

/B N

S

단극성 양극성

Page 66: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

쌍극성 구동방식의 모터는 외부로 나오는 선이 모두 4가닥이고, 단극성 구동방식의

모터는 외부로 나오는 선이 모두 6가닥이다. 단극성 모터는 전원의 두 선을 사용하지

않으면 쌍극성으로 사용할 수도 있다.

또 스테핑모터를 구동할 때 어떤식으로 상을 보내주는 지에 따라 여러가지의 상여자

방식이 있다. 일단 기본적인 1상구동방식과 두배의 토크를 낼 수 있는 2상 여자방식,

그리고 스텝각을 반으로하여 더욱 정밀하게 제어할 수 있는 1-2상 구동방식이 있다.

각각의 구동방식의 펄스패턴은 아래 표로 나타내었다.

Clock 0 1 2 3 4

INA H L L L H

/INA L L H L L

INB L H L L L

/INB L L L H L

<1상 구동 펄스 패턴>

<2상 구동 펄스 패턴>

<1-2상 구동 펄스 패턴>

위 표와 같이 펄스를 입력하면 모터는 구동하게 되는 것이다(단 Active High이다).

4.1.4 모터의 간단한 제어

- 모터의 구동

위 절에서 배운 모터의 구동원리로 모터를 구동시켜 보자.

4상 스테핑 모터를 구동시키려면 4개의 상을 원하는 상여자 방식으로 전류를 흘려보

C l o c k 0 1 2 3 4

INA H L L H H

/INA L H H L L

INB H H L L H

/INB L H H H L

C l o c k 0 1 2 3 4 5 6 7 0 1

INA H H L L L L L H H H

/INA L L L H H H L L L L

INB L H H H L L L L L H

/INB L L L L L H H H L L

Page 67: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

내주어야 한다. 196의 입출력포트로 모터에서 필요로하는 전류를 못 보내 주기때문에

모터구동 드라이버를 이용해서 구동하게 된다. 우리가 사용할 드라이버는 SLA7024

라는 4상 정전류 구동 드라이버이다. 아래에 그 주변회로와 함께 나타내었다.

Page 68: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

<모터 구동 회로도>

위와 같이 연결한 뒤에 연결된 포트1로 원하는 상을 입력하면 된다. 위와 같이 납땜

Page 69: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

#pragma model(kc)

#include <80c196.h>

typedef unsigned char BYTE;

typedef unsigned int WORD;

const BYTE Motor_R[] = {0x10,0x40,0x20,0x80};

const BYTE Motor_L[] = {0x08,0x02,0x04,0x01};

register BYTE Motor_Pase_L, Motor_Pase_R, Count_L, Motor_Pase, Count_R;

void software_timer (void)

{

BYTE temp;

wsr=0;

temp= (ios1 & 0x03);

if((temp&0x01)==0x01){

Motor_Pase_L = Motor_L[Count_L];

Count_L++;

if (Count_L >= 4) Count_L = 0;

hso_command = (0x10|8);

hso_time = timer1 + 3000;

}

if((temp&0x02)==0x02){

하였다면 그 외엔 소프트웨어 적으로 구동 해야 한다. 일단 우리는 1상 구동방식을

이용하여 구동해 보는 걸로 하겠다.

스테핑 모터를 구동하기위해서는 일정한 간격으로 상을 바꾸어 주어야 한다. 이 일

정한 간격은 소프트웨어 타이머를 이용해서 인터럽트를 걸어서 처리하면 되는데 실제

인터럽트 처리 루틴에서는 상을 바꾸는 처리를 하면 된다. 아래 예제 소스를 보자.

Page 70: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

Motor_Pase_R = Motor_R[Count_R];

Count_R++;

if (Count_R >= 4) Count_R = 0;

hso_command = (0x10|9);

hso_time = timer1 + 3000;

}

Motor_Pase = Motor_Pase_L + Motor_Pase_R;

ioport1 = Motor_Pase;

}

void main()

{

disable();

wsr = 0x00;

ioc0 = 0x00;

ioc1 = 0x00;

ioc2 = 0x00;

ioport1 = 0x00;

ioport2 = 0x00;

int_pending = 0x00;

ipend1 = 0x00;

int_mask = 0x20; /* 소프트웨어 타이머 */

imask1 = 0x00;

Count_L = Count_R = 0;

enable();

hso_command = 0x18;

hso_time = timer1 + 1000;

hso_command = 0x19;

hso_time = timer1 + 1010;

while(1);

}

Page 71: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

위 루틴에는 많은 전역변수가 사용되는 데 이를 아래 표에서 정리하였다. 단 모터 구

동과 관련된 변수만 정리하였다.

변수명 설명

Motor_R(L) const변수로 모터 구동시 원하는 상구동방식의 상을 순서대로

나열하였다.

Motor_Phase 실제 ioport1에 대입할 변수로 8비트의 한 포트로 4상의 출력

두개를 구현하기 위해 사용되는 변수이다. ioport1에 대입하기

전에 Motor_Phase_L과 Motor_Phase_R을 OR연산으로 묶은 다

음에 대입을 하게 된다.

Motor_Phase_R(L) 오른쪽과 왼쪽 모터의 상을 저장하는 변수로 Motor_Phase_R변

수는 하위 4비트를 Moto r_Phase_L변수는 상위 4비트를 사용한

다.

Count_R(L) 모터의 몇 번째 상이 출력되고 있는 가를 기억하는 변수로

Motor_R이라는 배열의 포인터가 된다.

주의해야 할 점은 하위4비트와 상위4비트로 나뉘어 한 포트로 두개의 모터를 제어

하게 된다는 것이다. 그래서 Motor_R(L)이라는 const변수의 값이 각각 해당 4비트의

값만을 갖게 되는 것이다.

이제 이 소스를 컴파일하고 링크하여 직접 구동 시켜보자.

- 방향과 속도

바퀴가 도는 속도는 상을 언제 바꾸어 주느냐에 따라서 변화한다. 즉 소프트웨어 타

이머 이벤트의 시간 간격에 따라서 모터의 속도가 바뀌게 되는 것이다. 그래서 이 주

기를 변할 수 있게 변수로 선언하고, 이 값을 바꾸어 주면 속도가 바뀌게 된다. 다음

에는 모터가 도는 방향이다. 이는 모터에 상 주는 순서를 반대로 주게 되면 모터는

반대로 돌게 된다. 따라서 이 모터의 방향을 기억해야 할 변수를 전역변수로 선언하

고 이 값을 보고 상 카운트(Count_R(L))값을 변화시키면 된다. 위의 두 변수를 이용

해서 만든 예제 프로그램은 아래에 있다. 이번엔 1-2상 구동방식이다.

===================================================================

# p r a g m a m o d e l ( k c )

# i n c l u d e < 8 0 c 1 9 6 . h >

t y p e d e f u n s i g n e d c h a r B Y T E ;

t y p e d e f u n s i g n e d i n t W O R D ;

v o i d i n i t _ s e r i a l ( v o i d ) ;

B Y T E G e t B y t e ( v o i d ) ;

Page 72: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

v o i d P u t B y t e ( B Y T E d a t u m ) ;

v o i d p u t s ( c h a r * s t r ) ;

v o i d p u t h e x ( i n t h e x , i n t n u m , c h a r n l l ) ;

c o n s t B Y T E M o t o r _ R [ ] = { 0 x 0 1 , 0 x 0 5 , 0 x 0 4 , 0 x 0 6 , 0 x 0 2 , 0 x 0 a , 0 x 0 8 , 0 x 0 9 } ;

c o n s t B Y T E M o t o r _ L [ ] = { 0 x 9 0 , 0 x 8 0 , 0 x a 0 , 0 x 2 0 , 0 x 6 0 , 0 x 4 0 , 0 x 5 0 , 0 x 1 0 } ;

B Y T E M o t o r _ P h a s e , M o t o r _ P h a s e _ L , M o t o r _ P h a s e _ R , C o u n t _ L , C o u n t _ R ;

B Y T E M o t o r D i r _ R , M o t o r D i r _ L ;

W O R D M o t o r _ S p e e d _ L , M o t o r _ S p e e d _ R ;

v o i d s o f t w a r e _ t i m e r ( v o i d ) / * 소프트웨어 타이머 * /

{

B Y T E i o s 1 _ i m g ;

a s m p u s h a ;

w s r = 0 ;

i o s 1 _ i m g = ( i o s 1 & 0 x 0 3 ) ;

i f ( ( i o s 1 _ i m g & 0 x 0 1 ) = = 0 x 0 1 ) / * 소프트웨어 타이머0 * /

{

M o t o r _ P h a s e _ L = M o t o r _ L [ C o u n t _ L ] ;

i f ( M o t o r D i r _ L = = 0 )

{

C o u n t _ L + + ;

i f ( C o u n t _ L > = 8 ) C o u n t _ L = 0 ;

}

e l s e

{

C o u n t _ L - - ;

i f ( C o u n t _ L > = 8 ) C o u n t _ L = 7 ;

}

h s o _ c o m m a n d = ( 0 x 1 8 ) ; / * 고속출력 인터럽트 유효( 소프트웨어 타이머 0 ) * /

h s o _ t i m e = t i m e r 1 + M o t o r _ S p e e d _ L ; / * 속도 값을 적는다. * /

}

i f ( ( i o s 1 _ i m g & 0 x 0 2 ) = = 0 x 0 2 ) / * 소프트웨어 타이머1 * /

{

M o t o r _ P h a s e _ R = M o t o r _ R [ C o u n t _ R ] ;

i f ( M o t o r D i r _ R = = 0 )

Page 73: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

{

C o u n t _ R + + ;

i f ( C o u n t _ R > = 8 ) C o u n t _ R = 0 ;

}

e l s e

{

C o u n t _ R - - ;

i f ( C o u n t _ R > = 8 ) C o u n t _ R = 7 ;

}

h s o _ c o m m a n d = ( 0 x 1 9 ) ;

h s o _ t i m e = t i m e r 1 + M o t o r _ S p e e d _ R ;

}

M o t o r _ P h a s e = M o t o r _ P h a s e _ L | M o t o r _ P h a s e _ R ;

i o p o r t 1 = M o t o r _ P h a s e ; / * p o r t 1 로 지정한 데이터 출력 * /

a s m p o p a ;

}

v o i d i n i t _ s e r i a l ( v o i d )

{

B Y T E d a t a ;

b a u d _ r a t e = 0 x 8 2 ; / * W A N N I N G ! ! B A U D _ R A T E i s 9 6 0 0 i n 2 0 M H z * /

b a u d _ r a t e = 0 x 8 0 ;

s p _ c o n = 0 x 0 9 ; / * M o d e 1 , R _ E N * /

i o c 0 = 0 x 0 0 ;

i o c 1 = 0 x 2 0 ; / * T X D S e l e c t * /

i o c 2 = 0 x 0 0 ;

d a t a = s b u f ;

}

v o i d r e c e i v e _ i n t e r r u p t ( v o i d )

{

a s m p u s h a ;

s w i t c h ( s b u f )

{

c a s e ' e ' : / * U P * /

M o t o r D i r _ R = 0 ;

M o t o r D i r _ L = 0 ;

Page 74: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

M o t o r _ S p e e d _ L = 0 x 6 0 0 ;

M o t o r _ S p e e d _ R = 0 x 6 0 0 ;

b r e a k ;

c a s e ' c ' : / * D O W N * /

M o t o r D i r _ R = 1 ;

M o t o r D i r _ L = 1 ;

M o t o r _ S p e e d _ L = 0 x 6 0 0 ;

M o t o r _ S p e e d _ R = 0 x 6 0 0 ;

b r e a k ;

c a s e ' s ' : / * L E F T * /

M o t o r D i r _ R = 0 ;

M o t o r D i r _ L = 1 ;

M o t o r _ S p e e d _ L = 0 x 8 0 0 ;

M o t o r _ S p e e d _ R = 0 x 8 0 0 ;

b r e a k ;

c a s e ' f ' : / * R I G H T * /

M o t o r D i r _ R = 1 ;

M o t o r D i r _ L = 0 ;

M o t o r _ S p e e d _ L = 0 x 8 0 0 ;

M o t o r _ S p e e d _ R = 0 x 8 0 0 ;

b r e a k ;

c a s e ' d ' : / * S T O P * /

d i s a b l e ( ) ;

b r e a k ;

c a s e ' p ' : / * + * /

M o t o r _ S p e e d _ L + = 0 x 4 0 ;

M o t o r _ S p e e d _ R + = 0 x 4 0 ;

b r e a k ;

c a s e ' ; ' : / * - * /

M o t o r _ S p e e d _ L - = 0 x 4 0 ;

M o t o r _ S p e e d _ R - = 0 x 4 0 ;

b r e a k ;

d e f a u l t :

b r e a k ;

}

p u t h e x ( M o t o r _ S p e e d _ L , 5 , ' ' ) ;

a s m p o p a ;

}

v o i d m a i n ( v o i d )

{

d i s a b l e ( ) ;

Page 75: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

w s r = 0 x 0 0 ;

i n i t _ s e r i a l ( ) ;

i n t _ p e n d i n g = 0 x 0 0 ;

i p e n d 1 = 0 x 0 0 ;

i n t _ m a s k = 0 x 2 0 ;

i m a s k 1 = 0 x 0 2 ;

e n a b l e ( ) ;

C o u n t _ L = 0 ;

C o u n t _ R = 0 ;

M o t o r _ S p e e d _ L = 0 x 0 6 0 0 ;

M o t o r _ S p e e d _ R = 0 x 0 6 0 0 ;

h s o _ c o m m a n d = 0 x 1 8 ;

h s o _ t i m e = t i m e r 1 + 1 0 0 0 ;

h s o _ c o m m a n d = 0 x 1 9 ;

h s o _ t i m e = t i m e r 1 + 1 0 1 0 ;

p u t s ( " T h i s i s m o t o r t e s t p r o g r a m ~ ! " ) ;

w h i l e ( 1 ) ;

}

B Y T E G e t B y t e ( v o i d )

{

r e t u r n s b u f ;

}

v o i d P u t B y t e ( B Y T E d a t u m )

{

s b u f = d a t u m ;

w h i l e ( ( s p _ s t a t & 0 x 2 0 ) ! = 0 x 2 0 ) ;

}

v o i d p u t s ( c h a r * s t r )

{

i n t i ;

f o r ( i = 0 ; s t r [ i ] ! = 0 ; i + + )

{

Page 76: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

P u t B y t e ( s t r [ i ] ) ;

}

}

v o i d p u t h e x ( i n t h e x , i n t n u m , c h a r n l l )

{

c h a r S t r i n g [ 5 ] ;

i n t h e x _ m , l o o p , l o o p _ m = 0 ;

d o

{

h e x _ m = h e x % 1 6 ;

i f ( 0 x 0 0 < = h e x _ m & & h e x _ m < = 0 x 0 9 )

S t r i n g [ l o o p _ m ] = 0 x 3 0 + h e x _ m ;

e l s e

S t r i n g [ l o o p _ m ] = ( ' a ' - 1 0 ) + h e x _ m ;

h e x = h e x / 1 6 ;

l o o p _ m + + ;

}

w h i l e ( h e x ! = 0 ) ;

h e x _ m = n u m - l o o p _ m ;

l o o p _ m - - ;

i f ( l o o p _ m < n u m )

{

f o r ( l o o p = 0 ; l o o p < h e x _ m ; l o o p + + )

P u t B y t e ( n l l ) ;

f o r ( l o o p = l o o p _ m ; l o o p > = 0 ; l o o p - - )

P u t B y t e ( S t r i n g [ l o o p ] ) ;

}

e l s e

{

f o r ( l o o p = l o o p _ m ; l o o p > l o o p _ m - n u m ; l o o p - - )

P u t B y t e ( S t r i n g [ l o o p ] ) ;

}

}

= = = ================================================================

이 프로그램은 시리얼 인터럽트(받기 인터럽트)를 이용해서 프로그래머가 정해놓은

키를 누르면 모터의 속도과 방향을 바꾸게 되어 있다. 속도를 바꿀 때에는

Motor_Speed_R(L)에 값을 쓰면 되고, 방향을 바꿀 때에는 MotorDir_R(L)값을 바꿔

주면 된다. 각자 소스코드를 분석해 보고 로봇에 맞게 수정을 해보자.

Page 77: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

4 . 2 센서부

4.2.1 적외선 센서

센서란 자연계의 물리량이나 화학량을 전기적 신호로 변환해 주는 장치이다. 이 전

기적 신호를 우리가 컨트롤러를 이용해서 제어할 수 있게 되는 것이다. 센서에는 많

은 종류가 있지만 우리는 라인트레이서나 MF1에 사용하기에 적합하고 원리가 간단

한 적외선 센서를 사용하겠다.

적외선 센서부에는 포토 트랜지스터와 적외선 다이오드가 필요하다. 적외선 다이오

드는 적외선을 쏘아주고, 포토 트랜지스터는 빛이 받는다. 포토 트랜지스터에 빛이

들어오면 두 단자에 전류가 흐른다. 즉 일반 NPN트랜지스터와 비슷한 원리이다. 일

반 NPN트랜지스터의 베이스 단자에 흐르는 전류를 빛으로 대신한다고 생각하면 된

다. 가장 간단한 사용 예로 아래 회로를 보자.

기본적인 회로이다. 브

레드 보드에서 직접 테스

트 해보는 것도 괜찮다.

Vout 단자를 오실로스코

프로 찍어서 파형을 관찰

하면 금방 이해가 될 것

이다. 어떤 물체로 적외

선 DIOED와 PHOTO

NPN사이를 가로 막으면

Vout의 신호는 약하게

나온다.(전위가 낮다) 하

지만 직접 두개를 가까이

마주보게 두면 Vout의

신호는 강하게 나온다(전

위가 높다)

Page 78: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

이렇게 사용하는 것 외에도 많은 방법이 있지만 기본 원리는 같은 것이다.

MF1에서 사용하는 적외선 센서는 Vout단자가 196의 AD입력핀에 연결해서 해당

전위값을 디지털값으로 입력 받을 수 있다.

4.2.2 필터 회로

위와 같은 회로만으로도 사용은 가능하다. 하지만 우리가 쏘는 빛 외에 형광등 빛이

나 자연광등의 왜란이 있어서 정확한 값을 얻기가 힘들다. 그래서 이번에는 간단한

필터 회로를 구성하여 오차를 줄여보자.

왜란으로 있을 형광등이나 백열등은 우리나라에선 60Hz로 동작한다.(외국의 경우

보통 50Hz이다) 또 자연광은 직류 성분이므로 하이 패스 필터를 이용하면 되겠다.

즉 우리는 일정 이상의 고주파로 적외선 DIODE를 켜주고 포토 트랜지스터의 출력부

에 하이 패스 필터를 달아주면 우리가 원하는 값만을 입력 받을 수가 있다.

Vin를 포토 트랜지스터의

출력부에 달아주면 된다.

회로는 간단하다. 이 회로

의 R값과 C값으로 원하는

주파수를 정할 수 있다.

그 수식은 다음과 같다.

- Fc = 1 / (2π * R * C)

위에서 나온 Fc의 주파수

의 이상의 값을 70%정도만 보내주고 그 이외에는 모두 걸러낸다.

이제 어느 정도의 기본 회로를 봤으니 실제 196과 인터페이스 하는 방법을 알아보

겠다.

Page 79: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

입력측은 196의 ADCH0~6까지 연결되어 있고, 적외선 DIODE를 켜기 위해서 HSO

핀에 연결하였다. 실제 센서부 회로도는 아래와 같다.

송신부에 있는 ULN2803은 Tr Array로 위에서 나온 센서의 기본 회로의 스위치와

같은 역할이다. 우리가 구성한 하이 패스 회로에서의 R과 C의 값으로 계산을 해보면

3386Hz정도가 된다. 즉 우리는 196으로 센서를 스위칭 할 때 3KHz이상으로 스위칭

해주어야 한다. 회로는 이제 구성되었고 이제 196으로 어떤 처리가 필요한지 알아보

자.

Page 80: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

4.2.3 예제 프로그램

이제 196에서 실제로 어떻게 처리해야 하는지를 알아야 한다.

일단 우리는 HSO로 적외선 DIODE를 켜고, AD를 통하여 입력을 받는다. 또 한가지

잊어선 안 되는 것이 고주파로 3KHz이상으로 켜야 한다는 것이다. 하지만 실제로

196에서 사용하는 시간은 아주 짧은 시간이므로 어느 정도 일정 간격으로 켜고 끄면

문제없이 사용할 수 있다. 하지만 너무 자주 켜고 끄면 전류 소모가 많고 컨트롤러에

부하가 많이 걸린다. 반대로 너무 저주파로 켜면 해당 정보를 원하는 시간에 얻지 못

하는 수도 있다. 그래서 적절히 조정해야 한다.

다시 196의 HSO와 AD기능을 살펴보자. 인터럽트 몇 개를 조합하면 알아서 센서의

값을 인식할 수 있다.

순서도를 그려보자.

먼저 메인 루틴에서 해당 인터럽트의 설정을 하고 HSO인터럽트 설정을 한다. 그러면

다음부턴 HSO서비스 루틴과 AD완료서비스 루틴이 번갈아 걸리면서 자동으로 센서

값을 읽어오게 되는 것이다. 이를 구현한 소스가 아래에 있다. 분석을 해보자.

MAIN 루틴

- AD완료 인터럽트와 HSO인터럽트 설정

- hso핀 출력 결정 HSO명령 설정

HSO서비스 루틴

- AD시작 HSO명령,

AD완료서비스 루틴

- hso핀 출력 초기화

- ad값 읽어오기

- hso핀 출력 결정 HSO명령 설정

Page 81: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

===================================================================

# p r a g m a m o d e l ( k c )

# i n c l u d e " 8 0 c 1 9 6 . h "

t y p e d e f u n s i g n e d i n t u i n t ;

t y p e d e f u n s i g n e d c h a r B Y T E ;

t y p e d e f u n s i g n e d i n t W O R D ;

/ * F u n c t i o n 선언 * /

v o i d i n i t _ s e r i a l ( v o i d ) ;

/ * I n t e r r u p t R o u t i n e * /

v o i d h s o _ e v e n t _ i s r ( v o i d ) ;

v o i d a d _ d o n e _ i s r ( v o i d ) ;

v o i d r e c e i v e _ i n t e r r u p t ( v o i d ) ;

/ * S e r i a l F u n c t i o n * /

B Y T E G e t B y t e ( v o i d ) ;

v o i d P u t B y t e ( B Y T E d a t u m ) ;

v o i d p u t s ( c h a r * s t r ) ;

v o i d p u t d e c ( i n t d e c , i n t n u m , c h a r n l l ) ;

v o i d p u t h e x ( i n t h e x , i n t n u m , c h a r n l l ) ;

/ * E T C F u c t i o n * /

v o i d L E D ( B Y T E ) ;

/ * 전역변수 선언 * /

B Y T E S e n s o r _ C h ;

v o i d h i g h _ s p e e d _ o u t p u t s ( v o i d )

{

a s m p u s h a ;

w s r = 0 x 0 0 ;

a d _ c o m m a n d = 0 x 1 0 | S e n s o r _ C h ;

h s o _ c o m m a n d = 0 x 0 F ;

h s o _ t i m e = t i m e r 1 + 0 x 3 0 ;

a s m p o p a ;

Page 82: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

}

v o i d a d _ c o n v e r s i o n _ c o m p l e t e ( v o i d )

{

B Y T E a d _ d a t a , H S O _ C h ;

a s m p u s h a ;

w s r = 0 x 0 f ;

i o s 0 = 0 x 0 0 ;

w s r = 0 x 0 0 ;

H S O _ C h = S e n s o r _ C h ;

i f ( H S O _ C h > 4 )

H S O _ C h = 4 ;

a d _ d a t a = a d _ r e s u l t _ h i ;

L E D ( a d _ d a t a ) ;

h s o _ c o m m a n d = 0 x 3 0 | H S O _ C h ;

h s o _ t i m e = t i m e r 1 + 0 x 5 0 ;

a s m p o p a ;

}

v o i d r e c e i v e _ i n t e r r u p t ( v o i d )

{

B Y T E d a t a ;

d a t a = G e t B y t e ( ) ;

d a t a - = 4 8 ;

i f ( d a t a < 7 )

{

S e n s o r _ C h = d a t a ;

P u t B y t e ( d a t a + 4 8 ) ;

p u t s ( " t h S e n s o r \ r \ n " ) ;

Page 83: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

}

}

v o i d i n i t _ s e r i a l ( v o i d )

{

B Y T E D a t a ;

b a u d _ r a t e = 0 x 8 2 ; / * W A N N I N G ! ! B A U D _ R A T E i s 9 6 0 0 i n 2 0 M H z * /

b a u d _ r a t e = 0 x 8 0 ;

s p _ c o n = 0 x 0 9 ; / * M o d e 1 , R _ E N * /

D a t a = s b u f ; / * B u f f C l e a r * /

}

v o i d m a i n ( v o i d )

{

d i s a b l e ( ) ;

w s r = 0 x 0 0 ;

i o c 0 = 0 x 0 0 ;

i o c 1 = 0 x 7 0 ;

i o c 2 = 0 x 8 0 ;

i n t _ p e n d i n g = 0 x 0 0 ;

i p e n d 1 = 0 x 0 0 ;

i n t _ m a s k = 0 x 0 a ;

i m a s k 1 = 0 x 0 2 ;

i n i t _ s e r i a l ( ) ;

h s o _ c o m m a n d = 0 x 3 0 ; / * h s o 0 세트 * /

h s o _ t i m e = t i m e r 1 + 0 x 2 0 ;

S e n s o r _ C h = 0 ;

e n a b l e ( ) ;

w h i l e ( 1 ) ;

Page 84: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

}

/ * 직렬 통신 상태 * /

# d e f i n e R I 0 x 4 0

# d e f i n e R E C E I V E D 0 x 4 0

# d e f i n e T I 0 x 2 0

# d e f i n e S E N D E D 0 x 2 0

B Y T E G e t B y t e ( v o i d )

{

r e t u r n s b u f ;

}

v o i d P u t B y t e ( B Y T E d a t u m )

{

s b u f = d a t u m ;

w h i l e ( ( s p _ s t a t & T I ) ! = S E N D E D ) ;

}

v o i d p u t s ( c h a r * s t r )

{

i n t i ;

f o r ( i = 0 ; s t r [ i ] ! = 0 ; i + + )

{

P u t B y t e ( s t r [ i ] ) ;

}

}

v o i d p u t d e c ( i n t d e c , i n t n u m , c h a r n l l )

{

c h a r S t r i n g [ 6 ] ;

i n t d e c _ m , l o o p , l o o p _ m = 0 ;

d o

{

Page 85: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

d e c _ m = d e c % 1 0 ;

S t r i n g [ l o o p _ m ] = 0 x 3 0 + d e c _ m ;

d e c = d e c / 1 0 ;

l o o p _ m + + ;

}

w h i l e ( d e c ! = 0 ) ;

d e c _ m = n u m - l o o p _ m ;

l o o p _ m - - ;

i f ( l o o p _ m < n u m )

{

f o r ( l o o p = 0 ; l o o p < d e c _ m ; l o o p + + )

P u t B y t e ( n l l ) ;

f o r ( l o o p = l o o p _ m ; l o o p > = 0 ; l o o p - - )

P u t B y t e ( S t r i n g [ l o o p ] ) ;

}

e l s e

{

f o r ( l o o p = l o o p _ m ; l o o p > l o o p _ m - n u m ; l o o p - - )

P u t B y t e ( S t r i n g [ l o o p ] ) ;

}

}

v o i d p u t h e x ( i n t h e x , i n t n u m , c h a r n l l )

{

c h a r S t r i n g [ 5 ] ;

i n t h e x _ m , l o o p , l o o p _ m = 0 ;

d o

{

h e x _ m = h e x % 1 6 ;

i f ( 0 x 0 0 < = h e x _ m & & h e x _ m < = 0 x 0 9 )

S t r i n g [ l o o p _ m ] = 0 x 3 0 + h e x _ m ;

e l s e

Page 86: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

S t r i n g [ l o o p _ m ] = ( ' a ' - 1 0 ) + h e x _ m ;

h e x = h e x / 1 6 ;

l o o p _ m + + ;

}

w h i l e ( h e x ! = 0 ) ;

h e x _ m = n u m - l o o p _ m ;

l o o p _ m - - ;

i f ( l o o p _ m < n u m )

{

f o r ( l o o p = 0 ; l o o p < h e x _ m ; l o o p + + )

P u t B y t e ( n l l ) ;

f o r ( l o o p = l o o p _ m ; l o o p > = 0 ; l o o p - - )

P u t B y t e ( S t r i n g [ l o o p ] ) ;

}

e l s e

{

f o r ( l o o p = l o o p _ m ; l o o p > l o o p _ m - n u m ; l o o p - - )

P u t B y t e ( S t r i n g [ l o o p ] ) ;

}

}

v o i d L E D ( B Y T E L E D _ D a t a )

{

B Y T E l o o p , D a t a B u f f ;

/ * I n i t i a l P o r t 2 * /

/ * i o p o r t 2 = 0 x 0 0 ; * /

/ * S T B _ S E T * /

i o p o r t 2 | = 0 x 8 0 ;

f o r ( l o o p = 0 ; l o o p < 8 ; l o o p + + )

{

Page 87: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

/ * C L K _ C L R * /

i o p o r t 2 & = 0 x d f ;

D a t a B u f f = L E D _ D a t a & 0 x 8 0 ;

L E D _ D a t a = L E D _ D a t a < < 1 ;

i f ( D a t a B u f f = = 0 x 0 0 )

i o p o r t 2 & = 0 x b f ;

e l s e

i o p o r t 2 | = 0 x 4 0 ;

/ * C L K _ S E T * /

i o p o r t 2 | = 0 x 2 0 ;

}

/ * S T B _ C L R * /

i o p o r t 2 & = 0 x 7 f ;

}

===================================================================

컴파일하고 링크하여 구동 시켜보면 처음에 HSO0으로 첫번째 센서만을 켜고 끄면

서 LED에 그 값을 디스플레이 해 준다. 자기가 직접 제작한 회로에 맞게 수정하고

디스플레이를 LED말고 시리얼로 출력하는 것도 괜찮다. 각 인터럽트가 걸리는 시간

이 있는 데 이를 잘 조정해야 한다. 처음 hso핀 조정 명령 설정시의 이벤트 시간이

주파수를 결정하게 된다. 또 hso서비스 루틴에서 설정하는 AD시작 명령의 이벤트 시

간은 적외선DIODE에서 빛이 나와 포토 트랜지스터에 값이 들어오는 데까지의 시간

으로 적당히 계산을 하거나 스코프로 찍어서 타이밍을 맞추어야 한다.

이정도만 생각을 해주면 문제없이 구동 된다. 위의 소스는 시리얼 인터럽트를 이용

해서 0~6번 키(키보드)를 누르면 센서의 채널이 바뀌어서 해당 센서값을 디스플레이

한다.

이번엔 로봇에선 어떻게 사용하는지 알아보자. 기본 원리는 위에 나온 소스와 똑같

다. 다만 자동으로 채널을 바꾸어 주어야 한다. 또 센서값을 원하는 시간에 읽을 수

있어야 한다. 일단 자동으로 채널을 바꾸는 것은 ad완료 인터럽트에서 채널을 일정하

게 바꿔주고, AD결과 값을 전역변수에 저장한다. 이때 현제 켜고 있는 센서의 채넗을

기억하는 변수가 SensorCh이고 실제 센서의 값을 저장되는 변수는 SensorData[7]

의 배열이다. 디스플레이는 메인루틴에서 while문으로 돌련서 원하는 채널만 LED로

디스플레이한다. 위의 소스와 비슷하게 시리얼 인터럽트를 이용해서 원하는 채널을

디스플레이 할 수 있다

Page 88: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

===================================================================

# p r a g m a m o d e l ( k c )

# i n c l u d e " 8 0 c 1 9 6 . h "

t y p e d e f u n s i g n e d i n t u i n t ;

t y p e d e f u n s i g n e d c h a r B Y T E ;

t y p e d e f u n s i g n e d i n t W O R D ;

/ * F u n c t i o n 선언 * /

v o i d i n i t _ s e r i a l ( v o i d ) ;

/ * I n t e r r u p t R o u t i n e * /

v o i d h s o _ e v e n t _ i s r ( v o i d ) ;

v o i d a d _ d o n e _ i s r ( v o i d ) ;

v o i d r e c e i v e _ i n t e r r u p t ( v o i d ) ;

/ * S e r i a l F u n c t i o n * /

B Y T E G e t B y t e ( v o i d ) ;

v o i d P u t B y t e ( B Y T E d a t u m ) ;

v o i d p u t s ( c h a r * s t r ) ;

v o i d p u t d e c ( i n t d e c , i n t n u m , c h a r n l l ) ;

v o i d p u t h e x ( i n t h e x , i n t n u m , c h a r n l l ) ;

/ * E T C F u c t i o n * /

v o i d L E D ( B Y T E ) ;

/ * 전역변수 선언 * /

B Y T E S e n s o r C h , D i s p l a y C h ;

B Y T E S e n s o r D a t a [ 7 ] ;

v o i d h i g h _ s p e e d _ o u t p u t s ( v o i d )

{

a s m p u s h a ;

w s r = 0 x 0 0 ;

a d _ c o m m a n d = 0 x 1 0 | S e n s o r C h ;

h s o _ c o m m a n d = 0 x 0 F ;

h s o _ t i m e = t i m e r 1 + 0 x 3 8 ;

Page 89: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

a s m p o p a ;

}

v o i d a d _ c o n v e r s i o n _ c o m p l e t e ( v o i d )

{

B Y T E a d _ d a t a , H S O C h ;

a s m p u s h a ;

w s r = 0 x 0 f ;

i o s 0 = 0 x 0 0 ;

w s r = 0 x 0 0 ;

a d _ d a t a = a d _ r e s u l t _ h i ;

S e n s o r D a t a [ S e n s o r C h ] = a d _ d a t a ;

S e n s o r C h + + ;

i f ( S e n s o r C h > 7 )

S e n s o r C h = 0 ;

H S O C h = S e n s o r C h ;

i f ( H S O C h > 4 )

H S O C h = 4 ;

h s o _ c o m m a n d = 0 x 3 0 | H S O C h ;

h s o _ t i m e = t i m e r 1 + 0 x 5 0 ;

a s m p o p a ;

}

v o i d r e c e i v e _ i n t e r r u p t ( v o i d )

{

B Y T E d a t a ;

d a t a = G e t B y t e ( ) ;

d a t a - = 4 8 ;

i f ( d a t a < 7 )

Page 90: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

{

D i s p l a y C h = d a t a ;

P u t B y t e ( d a t a + 4 8 ) ;

p u t s ( " t h S e n s o r \ r \ n " ) ;

}

}

v o i d i n i t _ s e r i a l ( v o i d )

{

B Y T E D a t a ;

b a u d _ r a t e = 0 x 8 2 ; / * W A N N I N G ! ! B A U D _ R A T E i s 9 6 0 0 i n 2 0 M H z * /

b a u d _ r a t e = 0 x 8 0 ;

s p _ c o n = 0 x 0 9 ; / * M o d e 1 , R _ E N * /

D a t a = s b u f ; / * B u f f C l e a r * /

}

v o i d m a i n ( v o i d )

{

B Y T E c o u n t ;

d i s a b l e ( ) ;

w s r = 0 x 0 0 ;

i o c 0 = 0 x 0 0 ;

i o c 1 = 0 x 7 0 ;

i o c 2 = 0 x 8 0 ;

i n t _ p e n d i n g = 0 x 0 0 ;

i p e n d 1 = 0 x 0 0 ;

i n t _ m a s k = 0 x 0 a ;

i m a s k 1 = 0 x 0 2 ;

n i t _ s e r i a l ( ) ;

Page 91: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

h s o _ c o m m a n d = 0 x 3 0 ; / * h s o 0 세트 * /

h s o _ t i m e = t i m e r 1 + 0 x 2 0 ;

S e n s o r C h = 0 ;

e n a b l e ( ) ;

w h i l e ( 1 )

{

L E D ( S e n s o r D a t a [ D i s p l a y C h ] ) ;

f o r ( c o u n t = 0 ; c o u n t < 0 x f f ; c o u n t + + ) ;

}

}

/ * 직렬 통신 상태 * /

# d e f i n e R I 0 x 4 0

# d e f i n e R E C E I V E D 0 x 4 0

# d e f i n e T I 0 x 2 0

# d e f i n e S E N D E D 0 x 2 0

B Y T E G e t B y t e ( v o i d )

{

r e t u r n s b u f ;

}

v o i d P u t B y t e ( B Y T E d a t u m )

{

s b u f = d a t u m ;

w h i l e ( ( s p _ s t a t & T I ) ! = S E N D E D ) ;

}

v o i d p u t s ( c h a r * s t r )

{

i n t i ;

f o r ( i = 0 ; s t r [ i ] ! = 0 ; i + + )

{

Page 92: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

P u t B y t e ( s t r [ i ] ) ;

}

}

v o i d p u t d e c ( i n t d e c , i n t n u m , c h a r n l l )

{

c h a r S t r i n g [ 6 ] ;

i n t d e c _ m , l o o p , l o o p _ m = 0 ;

d o

{

d e c _ m = d e c % 1 0 ;

S t r i n g [ l o o p _ m ] = 0 x 3 0 + d e c _ m ;

d e c = d e c / 1 0 ;

l o o p _ m + + ;

}

w h i l e ( d e c ! = 0 ) ;

d e c _ m = n u m - l o o p _ m ;

l o o p _ m - - ;

i f ( l o o p _ m < n u m )

{

f o r ( l o o p = 0 ; l o o p < d e c _ m ; l o o p + + )

P u t B y t e ( n l l ) ;

f o r ( l o o p = l o o p _ m ; l o o p > = 0 ; l o o p - - )

P u t B y t e ( S t r i n g [ l o o p ] ) ;

}

e l s e

{

f o r ( l o o p = l o o p _ m ; l o o p > l o o p _ m - n u m ; l o o p - - )

P u t B y t e ( S t r i n g [ l o o p ] ) ;

}

}

Page 93: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

v o i d p u t h e x ( i n t h e x , i n t n u m , c h a r n l l )

{

c h a r S t r i n g [ 5 ] ;

i n t h e x _ m , l o o p , l o o p _ m = 0 ;

d o

{

h e x _ m = h e x % 1 6 ;

i f ( 0 x 0 0 < = h e x _ m & & h e x _ m < = 0 x 0 9 )

S t r i n g [ l o o p _ m ] = 0 x 3 0 + h e x _ m ;

e l s e

S t r i n g [ l o o p _ m ] = ( ' a ' - 1 0 ) + h e x _ m ;

h e x = h e x / 1 6 ;

l o o p _ m + + ;

}

w h i l e ( h e x ! = 0 ) ;

h e x _ m = n u m - l o o p _ m ;

l o o p _ m - - ;

i f ( l o o p _ m < n u m )

{

f o r ( l o o p = 0 ; l o o p < h e x _ m ; l o o p + + )

P u t B y t e ( n l l ) ;

f o r ( l o o p = l o o p _ m ; l o o p > = 0 ; l o o p - - )

P u t B y t e ( S t r i n g [ l o o p ] ) ;

}

e l s e

{

f o r ( l o o p = l o o p _ m ; l o o p > l o o p _ m - n u m ; l o o p - - )

P u t B y t e ( S t r i n g [ l o o p ] ) ;

}

}

v o i d L E D ( B Y T E L E D _ D a t a )

Page 94: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

{

B Y T E l o o p , D a t a B u f f ;

/ * I n i t i a l P o r t 2 * /

/ * i o p o r t 2 = 0 x 0 0 ; * /

/ * S T B _ S E T * /

i o p o r t 2 | = 0 x 8 0 ;

f o r ( l o o p = 0 ; l o o p < 8 ; l o o p + + )

{

/ * C L K _ C L R * /

i o p o r t 2 & = 0 x d f ;

D a t a B u f f = L E D _ D a t a & 0 x 8 0 ;

L E D _ D a t a = L E D _ D a t a < < 1 ;

i f ( D a t a B u f f = = 0 x 0 0 )

i o p o r t 2 & = 0 x b f ;

e l s e

i o p o r t 2 | = 0 x 4 0 ;

/ * C L K _ S E T * /

i o p o r t 2 | = 0 x 2 0 ;

}

/ * S T B _ C L R * /

i o p o r t 2 & = 0 x 7 f ;

}

===================================================================

위처럼 자동으로 채널을 바꿔주면서 자동으로 센서값을 업데이트 해 주면, 우리가

SensorData라는 변수에서 값을 읽는 순간에서 최근의 값으로 읽혀진다.

이렇게 해서 이번 장은 마치고 실제 적용은 다음장에서 하겠다.

Page 95: 1장 기초사항 - icbank.comicbank.com/icbank_data/community/comm_tt/%B7%CE%BA... · 텔의 mcs-51계열과 mcs-96계열등이 유명하고 삼성의 ks88등의 시리즈가 있다.

5장 Micro Fourmula 1

5 . 1 M F 1 이란 ?

5 . 2 라인트레이서

5 . 3 1 차 주행

5 . 4 2 차 주행

5 . 5 해결해야 할 것들