AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU ....

13
AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) ATmega162의 핀 구조 프로그래밍의 설명 ATmega162 프로그램을 설계를 할 때 io.h 헤더파일을 include 하게 된다. io.h 헤더파일 안에는 아래와 같은 부분이 있다. Ex) #elif defined (__AVR_ATmega162__) # include <avr/iom162.h> 즉, 컴파일러에서 ATmega162에 맞게 컴파일 하도록 설정하면 iom162.h라는 또 다른 헤더파일을 include 하게 되어 있다. 그리고 그 iom162.h라는 헤더 파일 안에는 레지스터 이름들이 있는데 이 레지스터들은 아래와 같이 ATmega162의 메모리 주소에 맞게 연결 되어 있다.

Transcript of AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU ....

Page 1: AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU . Atmega162 (DIP Type) ATmega162의 핀 구조 . 프로그래밍의 설명 . ATmega162

AVR로 만들어서 이해하는 CPU

Atmega162 (DIP Type)

ATmega162의 핀 구조

프로그래밍의 설명 ATmega162 프로그램을 설계를 할 때 io.h 헤더파일을 include 하게 된다.

io.h 헤더파일 안에는 아래와 같은 부분이 있다.

Ex)

#elif defined (__AVR_ATmega162__)

# include <avr/iom162.h>

즉, 컴파일러에서 ATmega162에 맞게 컴파일 하도록 설정하면 iom162.h라는 또 다른 헤더파일을

include 하게 되어 있다.

그리고 그 iom162.h라는 헤더 파일 안에는 레지스터 이름들이 있는데 이 레지스터들은 아래와

같이 ATmega162의 메모리 주소에 맞게 연결 되어 있다.

Page 2: AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU . Atmega162 (DIP Type) ATmega162의 핀 구조 . 프로그래밍의 설명 . ATmega162

Ex) #define PORTD _SER _IO8(0x12) //PORTD 라는 변수를 번지수와 연결 시켜 놓았다.

(이제부터 PORTD를 조작하면 지정된 부분을 조작 할 수 있다.)

그러므로 iom162.h라는 헤더파일을 불러 옴으로써 직접 메모리 주소를 찾아가며 레지스터들을

설정하는 수고를 덜어주는 것이다.

이제 자주 사용하게 되는 몇 가지 레지스터 들을 살펴 보자

DDR(@) 레지스터

@는 A, B, C, D 중 하나.

DDR(@) 는 PORT(@)의 입, 출력 모드를 결정한다.

8개의 포트를 8비트 데이터로 설정하며 1이면 출력 0이면 입력이다. (내림차순)

Ex) DDRD = 0xFF // PORTD의 모든 포트를 출력으로 사용

물론 2진수로 직접 입력 해줄 수도 있다.

Ex) DDRD = 0b00111111 //PORTD7, PORTD6만 입력 모드 나머지는 출력 모드로 이용

PORT(@) 레지스터

PORT(@)에 해당하는 실질적인 신호를 다룬다.

TCCR0 레지스터

타이머 제어 레지스터로써 다름과 같은 구조로 되어 있고 역시 8비트로 셋팅한다.

FOC0 WGM0 COM1 COM0 WGM1 CS2 CS1 CS0

① FOC : Normal과 CTC모드에서 이 비트가 1로 셋팅 되는 순간 OC0에 출력값이 나오게 하

는 것으로 그다지 많이 사용 되지 않는다.

② WGM0, WGM1 : 타이머의 동작 모드를 결정하는 비트로써 4가지 모드를 선택 한다.

WGM0 WGM1 MODE

0 0 Normal

1 0 PWM

0 1 CTC

1 1 Fast PWM

Normal 모드 : 0에서 255까지 도달하게 되면 인터럽트를 발생하고 다시 0으로 돌아가는

모드로 초기 값을 조절 하여 주기를 더 짧게 만들 수 있다.

CTC 모드 : 0에서 프로그래머가 셋팅해 둔 값에 도달하면 인터럽트를 발행 시키고 다시

0으로 돌아가는 모드

PWM 모드 : 디지털적으로 아날로그를 제어하는 방법 (전구의 밝기, 모터의 속도..)

Page 3: AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU . Atmega162 (DIP Type) ATmega162의 핀 구조 . 프로그래밍의 설명 . ATmega162

③ COM1, COM0 : OC0 핀의 기능을 정한다.

COM1 COM0 MODE

0 0 범용 I/O 포트로 동작(OC0 핀 차단)

0 1 OC0 핀 출력 토글

1 0 OC0 핀 출력을 0으로 클리어

1 1 OC0 핀 출력을 1로 설정

④ CS0, CS1, CS2 : 클럭의 분주를 설정한다. CPU에 사용한 크리스탈의 주파수를 얼마만큼

분주 할 것인지 설정한다.

CS2 CS1 CS0 기능

0 0 0 클럭 입력 차단(타이머 사용 안함)

0 0 1 시스템클럭 / 1

0 1 0 시스템클럭 / 8

0 1 1 시스템클럭 / 64

1 0 0 시스템클럭 / 256

1 0 1 시스템클럭 / 1024

1 1 0 외부 입력 클럭 하강 엣지

1 1 1 외부 입력 클럭 상승 엣지

OCR0 레지스터

분주된 클럭이 몇 번 발생한 후 인터럽트를 발생하게 하는지를 설정하는 레지스터

Ex) OCR0 = 125; // 클럭이 125번 발생하면 인터럽트를 발생한다.

(결국 분주의 기능을 가지고 있음)

TCNT0 레지스터

TCNT0 레지스터는 프로그램이 실행되는 동안 분주된 클럭의 주기로 0에서 부터 몇 번째 주기

가 발행 했는지 나타낸다. 이 레지스터는 쓸 수도 있고 읽을 수도 있다. 값을 쓰면 주기를 더 빠

르게 할 수 있다. 레지스터의 값은 인터럽트가 걸리면 자동으로 0으로 클리어 되고 다시 분주된

주기마다 한 개씩 값이 늘어난다.

TIMSK 레지스터

TOIE1 OCIE1A OCIE1B OCIE2 TICE1 TOIE2 TOIE0 OCIE0

TOIE0(Timer0 Overflow Interrupt Enable) 비트를 1로 셋팅하고 시스템 인터럽트를 인에이블

하면 Normal모드의 타이머 인터럽트가 작동.

OCIE0(Timer0 Output Compare Match Interrupt Enable) 비트를 1로 셋팅하고 시스템 인터럽

Page 4: AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU . Atmega162 (DIP Type) ATmega162의 핀 구조 . 프로그래밍의 설명 . ATmega162

트를 인에이블 하면 CTC모드의 타이머 인터럽트가 작동.

사용 함수

sei( ) : 인터럽트를 인에이블 시키는 함수

sli( ) : sei의 반대 되는 것으로 시스템 인터럽트를 디스에이블 시킨다.

SIGNAL( ) : 인터럽트가 발생 했을 때 이 함수로 점프한다.

SIG_OUTPUT_COMPARE0 : 내부, 외부 관계 없이 인터럽트가 발생하면 해당 번호에 따른 번지로

점프하게 된다.

AVR CPU로 FND(7segment)를 제어하기

모듈 하나에는 7개의 신호를 표현할 수 있는 led가 있다.

(FND507 모듈에는 dot가 없음)

Signal(sig_output_compare0) //인터럽트에 반응하는 함수

{

If (timer_count == 125) //125가 되면

{

PORTD = count; //PORTD 에 count값을 전달

timer_count = 0; //초기화 시킴(125까지 센다)

count++; //count를 증가 시킴

if(count == 10) //count는 10이 되면 초기화

cout = 0;

}

timer_count++; //인터럽트에 의해 카운트가 된다.

}

Int main( void )

{ timer_count = 0; //전역 변수로 선언되었고 앞에서 카운트

DDRD = 0xFF; //PORTD를 출력 모드로 쓰겠다!

PORTD = 0X00; //8개의 핀 모드 0의 값을 출력 시키겠다

cli( ); //시스템 인터럽트를 꺼놓고 아래의 셋팅

Page 5: AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU . Atmega162 (DIP Type) ATmega162의 핀 구조 . 프로그래밍의 설명 . ATmega162

TCCR0 = 0x0D; //00001101

//com1,com0=0,0범용 I/O포트 동작

//WGM0,WGM1=0,1 타이머 모드 CTC

//CS2,1,0 = 1,0,1 – 시스템 클럭 1024 분주

OCR0 = 125; //출력 비교 레지스터 (클럭 125번 발생후 인터럽트)

TCNT0 = 0x00; //0으로 리셋 해둔다.

TIMSK = 0x01; //CTC모드의 타이머 인터럽트를 작동 시킨다.

sei( ); //인터럽트를 인에이블 시킨다.

while(1);

return 1;

}

시스템 클럭 16Mhz -- 1/16M x 1024 x 125 x 125 = 1s

count 변수는 1초마다 10까지 카운트 되고 PORTD에 값을 전한다.

입력 회로의 제작과 실험 PORTD 를 이용해 입력을 받는 실험을 한다.

- PORTD 0~5까지는 출력 모드로 하고 6,7은 입력 모드로 한다.

- 6,7 이 1일때 출력을 보내(스위치) led를 점등 한다.

- Unsigned char switch_input = 0;

Int main(void){

DDRD = 0b00111111; //PORTD 를 7,6은 입력 모드, 나머지는 출력

while (1)

{

switch_input = PIND; //입력 받는 변수

If (switch_input == 0b11000000) //7,6이 1이면

PORTD = 1; //출력 LED점등

else

PORTD = 0; //출력 안함

}

return 1;

}

Page 6: AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU . Atmega162 (DIP Type) ATmega162의 핀 구조 . 프로그래밍의 설명 . ATmega162

RS232 시리얼 통신

RS232의 통신 방식

다음과 같이 설정한다.

보레이트 9600 데이터 비트는 8비트 패리티 비트 사용 안 함 STOP비트는 1로 설정한 모습

Page 7: AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU . Atmega162 (DIP Type) ATmega162의 핀 구조 . 프로그래밍의 설명 . ATmega162

MAX 232

PC와 마이컴 시리얼 통신에는 MAX232 라는 IC가 필요 하다.

마이컴과 컴퓨터가 인식하는 0과 1의 값이 다르기 때문에..

마이컴 컴퓨터

0 0V -10V

1 5V 10V

이 차이를 해결해주는 것이다.

IC 내부에는 VOLTAGE DOUBLER와 VOLTAGE INVERTER가 있다.

DOUBLER는 5V를 10V로 증폭 INVERTER는 증폭된 신호를 반전

내부에 5V를 충전했다 10V로 보내기 위한 콘덴서가 있다.

MAX232는 전압을 바꾸어 주는 역할만을 하며 통신을 하는것은 아님에 주의!

시리얼 통신을 위한 레지스터

ATmega162에는 시리얼 통신용 컨트롤러가 포함 되어 있다.

CPU 내부에서 CPU의 코어 부분과 시리얼 통신용 컨트롤러가 데이터를 주고 받고, 컨트롤러는

RxD, TxD의 핀을 통해 외부와 통신을 하고 있다.

시리얼 통신을 위한 레지스터에는 설정용 레지스터와 데이터 통신용 레지스터가 있고 설정용 레

지스터를 이용해 설정을 하고 통신용 레지스터를 이용해 실제 통신을 한다

UCSR 레지스터

UCSR은 A,B,C세 개로 구성 되어 있고, 상태 설정과 제어의 기능을 한다.

UCSRA 7 6 5 4 3 2 1 0

RXC TXC UDRE FE DOR PE U2X MPCM

7. RXC : 수신 완료 표시 비트

6. TXC : 송신 완료 표시 비트

5. UDRE : 송신 데이터 레지스터 준비 완료 표시 비트

4. FE : 프레임 에러 표시 비트

3. DOR : 데이터 오버런 에러 표시 비트

2. PE : 패리티 에러 표시 비트

1. USX : 송신 속도 2배 설정

0. MPCM : 멀티 프로세서 통신 모드

*1번과 0번을 설정하고 나머지는 읽기 전용이다. (사용 할 때 1 아닐 때 0)

Page 8: AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU . Atmega162 (DIP Type) ATmega162의 핀 구조 . 프로그래밍의 설명 . ATmega162

UCSRB 7 6 5 4 3 2 1 0

RXCIE TXCIE UDRIE RXEN TXEN UCSZ2 RXB8 TXB8

7. RXCIE 수신 완료 인터럽트 인에이블 비트

6. TXCIE 송신 완료 인터럽트 인에이블 비트

5. UDRIE 송신 데이터 레지스터 준비 완료 인터럽트 인에이블 비트

4. RXEN 수신기 인에이블

3. TXEN 송신기 인에이블

2. UCSZ2 전송 데이터 길이 선택 비트

1. RXB8 수신 데이터 비트 8

0. TXB8 송신 데이터 비트 8

UCSRC 7 6 5 4 3 2 1 0

URSEL UMSEL UPM1 UPM0 USBS UCSZ1 UCSZ0 UCPOL

7. UREL 레지스터 선택 비트

6. UMSEL 시리얼 통신 모드 설정 비트

5. UPM1 패리티 모드 설정 비트

4. UPM0 패리티 모드 설정 비트

3. USBS 정지 비트 선택

2. UCSZ1 전송 데이터 비트 수 설정

1. UCSZ0 전송 데이터 비트 수 설정

0. UCPOL 클럭 극성 선택

보레이트 속도 설정 관련 레지스터

보레이트 - 신호 하나의 속도

보레이트 속도를 조절 하는 레지스터는 UBRRH와 UBRRL 2개로 이루어져 있다. UBRRH의 4비트와

UBRRL의 8비트를 합친 12비트를 이용하여 속도를 설정한다.

UBBRH 7 6 5 4 3 2 1 0

URSEL 사용하지 않음 ( 0 ) UBRR의 값 (11 ~8 비트)

UBBRL 7 6 5 4 3 2 1 0

UBRR의 값 (7 ~0 비트)

Page 9: AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU . Atmega162 (DIP Type) ATmega162의 핀 구조 . 프로그래밍의 설명 . ATmega162

UBRRH는 UCSRC레지스터와 같은 번지를 사용 하고 있다. 그렇기 때문에 UCSRC로 사용 할 것인

지 UBRRH로 사용 할 것인지 선택을 해야 하는데, 이 기능을 하는 것이 7번 URSEL비트이다.

URSEL이 0일 때 UBRRH의 기능을 갖고 1일 때 UCSRC의 기능을 갖는다.

UBRR의 값은 보레이트와 시스템 클럭을 이용하여 계산 한다.

UBRR시스템 클럭

16 보레이트1

UBRR1600000016 9600

예를 들어 시스템 클럭이 16Mhz 이고 보레이트를 9600 bps로 잡았을 때

1 103.1666…

들 때에는

대쪽 커넥터에 연결하기 전에 한번 교차 시켜야 한다.

UBRR의 값은 103.1666.... 이 된다.

여기서 소수점 이하를 버리고 103을 2진수로 변환하면 1100111이 된다.

결국 UBRRH의 4 비트에는 모두 0이 들어가고 UBRRL에는 01100111이 들어가므로, 다음과 같이

입력 한다.

UBRRH=0;

UBRRH=103; //물론 0b01100111으로도 입력 가능하다.

데이터 전송 레지스터

UDR

UDR레지스터는 데이터를 입력하면 설정한 값에 맞게 데이터를 전송하는 레지스터이다.

시리얼 통신 회로의 제작 케이블 제작

CPU에 ‘Hello’라는 문자를 입력 하고 컴퓨터에서 수신

시리얼 케이블 커넥터

2번 과 3번이 Rx(수신), Tx(송신) 이다.

그러므로 케이블을 만

(Rx ->Tx , Tx->Rx)

Page 10: AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU . Atmega162 (DIP Type) ATmega162의 핀 구조 . 프로그래밍의 설명 . ATmega162

시리얼 통신 프로그램

신 프로그램

#include <avr/io.h>

oid Put 는 부분

/*0x20

DR0 = data; // 송신 레지스터, 전송 후 비게 되면 UDRE에 1를 전송

a (v

“Hello\r\n”;

ch *p t

티프로세서 통신모드)OFF

0 001000;

; //UBRR(보레이트 속도 조절)값 103

R0 = ;

S r = r n

i e

P t (*pStr++); //다음 문자를 가리킴

while(1);

}

롤러(PORTD, 핀 10, 11)를 사용할 것인지 판단 하는 것 이다.

의 핀 구성을 참고 하자)

수신 프로그램

de <avr/io.h>

id Putch(char data) //문자 송신 함수

{

UDR0 = data; //UDR에 데이터를 넣어 전송

}

V ch(char data) //글자를 보내

{ while(!(UCSR0A & 0x20));

= 00010000 5번 비트(UDRE) 가 1이 되기를 기다린다.

U

}

Int m in oid)

{ char string[] =

ar s r;

UCSR0A = 0x00; //USX(송신 속도 2배) OFF MPCM(멀

UCSR B = 0b00 //TXEN(송신모드)만 ON

UBRR0L = 103

UBR H 0

p t st i g;

wh l (*pStr) //pStr이 0이 아닌 동안

u ch

레지스터 변수를 보면 뒤쪽에 숫자가 붙어 있다. 이것은 1번 시리얼 컨트롤러(PORTA, 핀 3, 4)

를 사용할 것인지 0번 시리얼 컨트

(1페이지

#inclu

vo

while(!(UCSR0A & 0x20)); //UDRE가 1일때

Page 11: AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU . Atmega162 (DIP Type) ATmega162의 핀 구조 . 프로그래밍의 설명 . ATmega162

char Getch(void) //문자 수신 함수

A & 0x80)) 비트)가 1일때

return UDR0; //UDR의 값을 리턴한다.

t main(void)

] = "Hello\r\n";

tr;

011000; //TXEN, RXEN ON (송,수신 둘 다 사용)

;

UBRR0H = 0;

;

동안 다음 문자를 가리키고 0이면 넘어감

Putch(*pstr++);

hile(1) 작

Putch(Getch( ) + 1); //Getch( )의 문자에 1을 더해서 Putch로 보냄

올수 있으므로 (true = 1 false = 0) 직접 1을 넣으면 전원을 차단 할 때까지 명령을 반복 한다.

터럽트를 사용한 송수신 프로그램

>

nclude<avr/signal.h>

x = 0; //rx라는 문자 변수 선언

oid Putch (char data) //문자 송신 함수

{

while(!(UCSR0 ; //RXC(수신완료 표시

}

in

{

char string[

char *Ps

UCSR0A = 0x00;

UCSR0B = 0b00

UBRR0L = 103

pStr = string

while(*pStr) //pStr이 0이 아닌

w //무한 루프 시

}

while(1)은 무한 루프를 의미한다. while(true) 일 때 아래의 포함된 명령이 실행 되고 false일때

#include<avr/io.h>

#include<avr/interrupt.h

#i

char r

v

{

Page 12: AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU . Atmega162 (DIP Type) ATmega162의 핀 구조 . 프로그래밍의 설명 . ATmega162

while(!(UCSR0A & 0x20));

UDR0 = data;

GNAL(SIG_USART0_RECV) //데이터를 받으면 하던 일을 중단하고 이 함수를 실행한다.

세지 잘 받았습니다. --> "; //문자 배열

char *pStr;

x = UDR0;

while(*pStr) Putch(*pStr++); //string 의 내용을 송신

DR0의 내용 송신

Putch('\n');

t main (void)

녕하세요\r\n";

char *pStr;

0xFF; //??

011000; //RXCIE(수신 완료 인터럽트 인에이블 비트)사용, 송수신사용

;

UBRR0H = 0;

에이블 시킨다.

while (*pStr) Putch(*pStr++); //"안녕하세요" 전송

while(1); //무한 루프

}

SI

{

char string[ ] = "\r\n메

r

pStr = string;

Putch(rx); //U

Putch('\r');

}

in

{

char string[ ] = "\r\n안

DDRB = 0xFF; //??

PORTB =

UCSR0A = 0x00;

UCSR0B = 0b10

UBRR0L = 103

sei( ); //인터럽트를 인

pStr = string;

}

Page 13: AVR로 만들어서 이해하는 CPU Atmega162 (DIP Type) · AVR로 만들어서 이해하는 CPU . Atmega162 (DIP Type) ATmega162의 핀 구조 . 프로그래밍의 설명 . ATmega162

먼저 안녕하세요 문자 출력 후 무한 루프로 들어 가게 된다. 데이터를 받으면 그때 무한루프를

벗어나 SIGNAL(SIG_USART0_RECV) 함수가 작동하고 함수가 끝이 나면 다시 무한 루프로 들어가

다음 신호를 기다리는 상태가 된다. while( )문의 자리에 CPU가 다른 일을 할 수 있도록 프로그램

을 작성할 수도 있다