AVR의 SRAM의 메모리 공간은 매우 제한적이기 때문에 다량의 상수 데이터를 SRAM에 저장하여 메모리를 차지하는 것보다 플래시롬에 저장하는 것이 효율적일 수 있다. 플래시롬에 저장된 데이터는 런타임에는 수정될 수 없으므로 상수(즉, 고정된 값)만을 저장해야만 한다. 예를 들어 문자열이라든가, 아니면 크기가 큰 배열을 저장할 때는 플래시롬를 이용할 수 있다.


 플래시롬을 접근하는데 필요한 기능들은 <avr/pgmspace.h>에 정의되어 있으므로 이 헤더파일을 인클루드해줘야 한다. 그리고 사용하는 AVR이 어셈블리명령어인 LPM 혹은 ELPM을 지원하여야 한다. LPM/ELPM은 플래쉬메모리에서 데이터를 레지스터로 읽어오는 동작을 하는 어셈블리 명령어로서 ATmega8A는 LPM명령이 존재한다.


#include <avr/pgmspace.h>


플래시 메모리에 저장될 데이터는 전역 상수로 정의되어야 하며 변수 선언과 동시에 초기화를 해주어야 한다. 그리고 변수의 타잎지정자 뒤에 PROGMEM (스펠링에 주의할 것) 이라는 키워드를 추가하면 된다. 최신 버전의 AVR툴체인에서는 컴파일할 때 경고를 없애기 위해서 반드시 const 키워드를 추가시켜야 한다.


#include <avr/io.h>
#include <avr/pgmspace.h>
const signed char cA PROGMEM = -1;
const unsigned char cB PROGMEM = -1;
const signed int iA PROGMEM = -1;
const unsigned int iB PROGMEM = -1;
const float fA PROGMEM = -1;
const unsigned char cArr[5] PROGMEM =
{0x01,0x02,0x03,0x04,0x05};


 한 가지 주의할 점은 이렇게 저장된 데이터를 읽어내려면 일반 변수와 같이 사용할 수는 없으며 별도로 정의된 다음과 같은 함수들을 사용해야 한다는 점이다.


pgm_read_byte(<pointer>)
pgm_read_word(<pointer>)
pgm_read_dword(<pointer>)
pgm_read_float(<pointer>)

예를 들어서 위의 예에서 cA값을 다른 변수에 저장하려면 다음과 같이 해야 한다.


signed char cX;
cX = pgm_read_byte(&cA);// cX = cA 는 안 됨.


또는 cArr배열의 세번째 요소를 읽어들이려면 다음과 같이 사용한다.


unsigned char cY;
cY = pgm_read_byte(cArr+2); //cY = cArr[2] 는 안 됨


또한 <pgmspace.h>에서는 PSTR()이라는 간결한 매크로가 정의되어 있는데 이 매크로는 플래시메모리에 문자열을 저장하고 그 포인터를 반환한다. 이 경우에는 궂이 전역 변수로 정의할 필요는 없으며 포인터이기 때문에 지역 변수로도 사용할 수 있다.


int main(void) {
   const char *str = PSTR("Hello world!");
   LCD_puts(str);
}


또는 다음와 같이 한 줄로도 줄일 수 있으므로 매우 간편하게 사용할 수 있다. 단, 위의 경우는 포인터 변수 str을 당연히 함수 내부의 여러 곳에서 사용할 수 있으나 다음의 경우는 단 한 번만 사용가능하다.


LCD_puts( PSTR("Hello! world") );


즉, "Hello! world"라는 문자열은 PSTR()이라는 매크로에 의해서 플래시메모리에 저장되고 그 포인터를 반환하여 LCD_puts()라는 함수에서 사용되는 것이다.

 이전 버젼의 WinAVR에서는 [표 1]에 기술한 바와 같이 pgmspace.h에서 typedef명령으로 정의된 별도의 데이터 타잎을 사용할 수 있다. 하지만 Atmel Studio 6.x버젼에 포함된 툴체인에서는 이러한 사용법을 더 이상 권장하지 않고 앞으로 사라질 것이라고 <avr/pgmspace.h>에 기술되어 있다. 단, 이전 프로그램과의 호환성때문에 이러한 데이터형을 사용할 경우에는 <avr/pgmspace.h>를 인클루드하기 전에 상수 __PROG_TYPES_COMPAT__ 를 정의하여야 한다.


[표 1] 플래시롬 상수의 자료형 (권장하지 않음)

자료형

byte

표현 범위

비고

prog_char or prog_int8_t

1

signed char

prog_uchar or prog_uint8_t

1

unsigned char

prog_int16_t

2

signed int

prog_uint16_t

2

unsigned int

prog_int32_t

3

signed long

prog_uint32_t

3

unsigned long

prog_int64_t

4

signed long long

prog_uint64_t

5

unsigned long long


위의 도표에 기술된 데이터 타잎을 사용하는 예는 다음과 같다.


#define __PROG_TYPES_COMPAT__ //반드시 있어야 함.
#include <avr/pgmspace.h>
const prog_char cA = -1;
const prog_uchar cB = 1;
const prog_int16_t iA = -1;
const prog_uint16_t iB = 1;


하지만 전술한 바와 같이 이 방법은 더 이상 사용하지 않는 것이 바람직하다.



Posted by 살레시오
,


 이제 AVR을 구동시키기 위해서는 AVR이 이해할 수 있는 명령어들(어셈블리 명령어)로 이루어진 화일을 내부 플래시 메모리에 다운로드시켜야 한다. 따라서 사용자가 작성한 C/C++ 프로그램을 AVR이 실행할 수 있는 이진 파일로 번역(컴파일)해 주는 컴파일러가 필요하다. 사용자가 작성한 C/C++프로그램은 그 표준이 정해져 있기 때문에 PC용이든 uC용이든 그 외관은 비슷해 보이지만 컴파일러에 따라서 같은 프로그램을 PC에서, uC에서, 혹은 DSP에서와 같이 다양한 플랫폼에서 구동시킬 수 있다.


 이러한 AVR컴파일러는 상업용(예:CodevisionAVR) 과 무료 컴파일러로 크게 구분할 수 있다. avr-gcc/avr-g++ 은 대표적인 오픈소스 기반의 무료 AVR 컴파일러로서 그 성능이 상용 컴파일러에 못지 않고 또 Atmel Studio라는 개발 IDE에 통합되어 편리하게 사용할 수 있기 때문에 널리 사용되고 있다. Atmel studio 6.x버전은 컴파일러를 포한한 여러 도구를 모아 놓은 avr 툴체인(toolchain)이 설치 화일에 포함되어서 Atmel studio를 설치할 때 이것들도 자동으로 설치되며 따라서 WinAVR을 별도로 설치할 필요가 없다.


지원하는 변수형

 avr툴체인은 <표 4.1.1>에 수록된 데이터 형을 지원한다. 표준 C/C++에서 지원하는 거의 모든 데이터형을 지원한다. 또한 C/C++ 에서 상수는 10진수, 8진수, 16진수 세 가지 표현만 지원했으나 gcc/g++는 2진수 표현도 지원하며 0b로 시작한다. PC환경에서는 2진수를 취급하는 것이 그다지 중요하지 않지만 uC 프로그래밍에서는 2진수를 다루는 것은 매우 빈번히 일어나며 중요하다. 예를 들어서 다음 네 가지 변수는 모두 같은 숫자값을 가진다.


byA = 17;
byB = 019;
byC = 0x11;
byD = 0b00010001; //2진수 표현


즉, AVR 프로그램에서 2진수를 취급하는 경우가 상대적으로 많기 때문에 지원하는 기능이며 편리하게 사용할 수 있다.


[표 1] avr툴체인이 지원하는 자료형

종류

데이터형

축약된 표현

바이트 수

비고

signed char

int8_t

1

unsigned char

uint8_t

1

signed short

int16_t

2

unsigned short

uint16_t

2

signed int

int16_t

2

signed short 와 같다

unsigned int

uint16_t

2

un signed short 와 같다

signed long

int32_t

4

unsigned long

uint32_t

4

signed long long

int64_t

8

unsigned long long

uint64_t

8

실수형

float

4

double

4

float형과 같다.

논리형

boolean


1

avr-g++ 에서만 지원


여기서 주의할 것은  avr툴체인의 int형은 short형과 마찬가지로 2byte이고, double형은 float형과 마찬가지로 4byte라는 것이다.

IOCR에의 접근

 IOCR이 무엇인지는 이전 포스트에서 설명한 바가 있다. AVR프로그래밍에서 IOCR을 조작하는 것은 거의 필수적으로 행해지는 일이다. avr-gccs는 IOCR에 접근하는 편리한 방법을 제공하는데 예를 들어 PORTD와 관련된 레지스터(PORTD, DDRD, PIND)값을 읽거나 쓰려면 다음과 같이 하면 된다.


unsigned char byA = 0;
PORTD = byA;
DDRD = 0xFF;
byA = PIND;


이런 식으로 변수를 다루듯이 IOCR의 이름을 사용할 수 있는데 이러한 명령이 내려지면 컴파일러는 해당하는 IOCR의 주소를 참조하여 거기에 접근하는 일련의 명령어들을 자동으로 생성하게 된다.


 <io.h>를 인클루드할 때 자동으로 포함되는 <sfr_defs.h>에는 비트를 조작하는 매크로가 다음과 같이 정의되어 있다.

#define _BV(bit) (1 << (bit))

이 매크로를 이용하면 IOCR의 특정한 비트를 세트(1) 또는 리셋(0)시키는데 다음과 같이 사용할 수 있다.


PORTD |= _BV(0); //0번비트 세트
PORTD &= ~_BV(7); //7번비트 리셋


그리고 같은 헤더파일에 IOCR의 특정 비트가 세트(리셋)되어 있는지 조사하는 매크로가 다음과 같이 정의되어 있어서 조건문과 조합하여 사용할 수 있다.


#define bit_is_set(sfr,bit) (_SFR_BYTE(sfr)&_BV(bit))
#define bit_is_clear(sfr,bit) (!(_SFR_BYTE(sfr) & _BV(bit)))


또한, IOCR의 특정 비트가 세트(리셋)될 때까지 기다리는 매크로도 다음과 같이 정의되어 있다.

#define loop_until_bit_is_set(sfr, bit)
                  do {} while (bit_is_clear(sfr, bit))
#define loop_until_bit_is_clear(sfr, bit)
                  do {} while (bit_is_set(sfr, bit))


이러한 매크로 함수를 이용하면 어떤 특정한 비트가 세트(리셋)될 때까지 대기해야 되는 경우에 편리하게 사용할 수 있다.



Posted by 살레시오
,

 Atmel스튜디오에서 IDE와 컴파일러를 무료로 제공하고는 있지만 실제로 시스템을 개발하려고 하면 하드웨어가 필요하게 된다. Atmel스튜디오를 사용하여 실제 제품을 개발하는 환경을 구성하려면 Atmel사에서 개발하여 공식적으로 판매하고 지원하는 다운로더(downloader, PC상에서 작성된 구동 프로그램을 uC의 내부 롬에 쓰는 기능을 하는 장치)를 사용해야만 하는 다소 불편한 점이 있다. 이러한 장치들은 비교적 고가이고 더구나 고장시 A/S의 불편함 등으로 인하여 시중에서는 그 기능을 복제한 저가의 장치들이 많이 유통되고 있다. 대표적으로 STK500, mkII호환 장치들이 있다. Atmel스튜디오를 이용하여 개발환경을 꾸미는데 있어서 이러한 장치들을 사용하는 것이 가능하기는 하나 설정이 번거롭고 사용상의 불편함도 감수해야 한다.


 Atmel은 AVR 내부 메모리에 프로그램을 다운로드할 수 있는 방법과 프로토콜(protocol)을 매뉴얼에 공개하고 있다. 사실 AVR은 RESET핀이 0값으로 떨어져 있는 동안에는 SPI통신으로 내부메모리에 프로그램을 다운로드 할 수 있으며 여기에 필요한 모든 정보가 공개되어 있다. 이러한 정보를 이용하여 개인 개발자가 개발하여 무료로 개방한 저가의 다운로더가 있어서 일반 사용자도 자유롭게 제작하여 사용할 수 있다. 몇몇 예를 들어보면 USBasp, avrftdi, USBtinyISP 등이 있으며 모두 오픈소스 기반의 프로젝트들이므로 자세한 사항은 인터넷에서 검색을 해보면 금방 얻을 수 있다.


 그 중에서 USBasp라는 프로그래머가 두 가지 측면에서 필자의 눈에 띄었다. 첫째로 USB인터페이스를 가지고 있으며, 둘째로 FTDI사의 serial-to-USB 변환칩 없이 ATmega8(혹은 ATmega8A/48/88)하나와 수동소자 몇 개로 회로가 이루어져 매우 간단하게 제작할 수 있다는 점이다. ATmega8은 시중에서 저가로 구입할 수 있는 흔한 프로세서이므로 USBasp를 직접 제작하고자 한다면 많은 재료비가 들지 않으며 저작권 등의 문제에서도 자유롭게 사용할 수 있다는 장점도 있다. 회로도와 펌웨어도 제작자에 의해서 공개되어 있다. (http://www.fischl.de/usbasp/) 이 사이트에서 회로도만 옮겨보면 다음 그림과 같다.


[그림 1] USBasp 회로도


처음 이것을 발견했을 때 필자는 이 회로도에서 10핀 인터페이스를 6핀으로 바꿔서 시제품을 제작해 보았다. 다음 [그림 2]에서 보다시피 회로는 굉장히 간단하지만 읽고 쓰는 동작은 잘 되며 www.avrfreaks.net 과 같은 싸이트에서 의견을 읽어보면 사용자 개발 다운로더들 중에서 어느 정도 신뢰성을 얻고 있으며 많이 사용되고 있음을 알 수 있다.


[그림 2] 직접 만들어 본 USBasp 다운로더의 외형


 그리고 USBasp 다운로더를 아예 부트로더로서 ATmega8(A)에 수록하여 사용할 수도 있다. 이것은 USBaspLoader라는 이름으로 인터넷에 공개가 되어 있는데 이것을 사용하면 별도의 다운로더 필요 없이 ATmega8(A)의 플래시롬과 EEPROM을 프로그램할 수 있다.


[그림 3] USBaspLoader 의 소개 홈페이지. 아두이노와 비슷한 시제품도 소개되어 있다.


별도의 다운로더를 사용하는 것과 비교해서 USBaspLoader를 사용하는데 따르는 단점은 다음과 같은 것이 있다.

  • 부트로더가 2K바이트의 상위 플래시롬을 차지한다. 따라서 사용자가 작성할 수 있는 프로그램의 길이는 6K바이트로 제한된다.

  • 퓨즈바이트와 락비트를 프로그램할 수 없다. 따라서 제품개발의 용도보다는 순수하게 학습과 실습의 용도로만 사용할 수 있다.

위와 같은 단점에도 불구하고 부트로더 방식을 사용하는 이유는 별도의 다운로더 필요 없이 제공되는 키트만 있다면 PC와 USB로 연결하여 실습을 진행할 수 있다는 편리함 때문이다.


 하지만 문제가 하나 있는데 AVR에 다운로드하는 프로그램 환경이 조금 불편하다는 것이다. USBaps의 소개 홈페이지에 언급된 대로 Khazama AVR Programmer, eXtreme Burner, avrdude와 같은 구동 프로그램이 있으나 AtmelStudio와 연동이 되지 않는다는 단점이 있다.



Posted by 살레시오
,

 특정한 기능을 수행하는 시스템을 uC를 이용하여 구현하려고 할 때 그 기능을 수행하도록 위해서는 물리적인 전기전자 회로를 설계해야 될 것이고 (필요에 따라 기계적인 요소도 들어갈 것이다.) 그 회로를 작동시키는 소프트웨어도 작성해야 한다. 이러한 하나의 제품을 만들어내는 과정을 ‘개발’이라고 한다. 이렇게 uC를 이용하여 제품을 개발할 때 프로그램 언어로서 일반적으로 C/C++언어와 어셈블리어가 많이 사용된다.


 이제 C/C++ 언어와 어셈블리어 중에서 어느 것을 사용할지의 선택의 문제가 발생한다. 각각 나름대로의 장점이 있으며 C/C++언어와 어셈블리어 하나만 아는 것보다는 둘 다 익혀두는 것이 더 유익하겠지만 여건상 한 가지만 집중적으로 해야 한다면 C/C++ 언어를 선택하는 것이 일반적이다. 어셈블리어만을 가지고 복잡한 알고리듬을 구현하기에는 한계가 있기 때문에 그렇다. C/C++언어가 코드를 작성하기 편리하고 하드웨어의 제약에서 어느 정도 벗어나서 알고리듬에만 집중할 수 있는 반면 어셈블리어는 프로그램의 명령어가 단순하고 코드가 짧으며 실행속도가 빠르다는 장점을 가진다. 따라서 프로그램 수행시간이 중요한 응용분야에서는 어셈블리어로 코드를 최적화할 필요가 있다. 또한 어셈블리 프로그램 자체가 단순하기 때문에 배우기 쉬우며 하드웨어에 대한 충분한 이해를 바탕으로 해야만 코드를 작성할 수 있기 때문에 하드웨어를 이해하는 폭을 넓혀준다. 어셈블리어에 익숙하다면 이는 C/C++ 언어로 프로그래밍을 할 때 그 이해의 폭을 깊게 해주므로 C/C++언어와 어셈블리어는 서로 배타적이 아니다. 따라서 uC로 시스템을 개발할 때에는 둘 다 익숙히 다룰 줄 안다면 여러모로 유리할 것이다. 실제로 제품 개발 프로젝트를 수행할 때 전 과정을 모두 어셈블리어로 작성하는 경우도 있겠지만 좀 더 일반적인 경우는 C프로그램으로 전체적인 윤곽을 잡고 실행 속도나 코드의 최적화가 중요한 서브루틴을 어셈블리어로 작성하여 끼워 넣는 경우도 있다.


 AVR uC를 생산하여 공급하는 Atmel사에서는 Atmel Studio (버전이 6.0 밑에서는  AVR Studio 라는 이름이었다.)라는 IDE(integrated development environment, 통합개발환경) 를 무료로 제공한다. Atmel 스튜디오는 텍스트 에디터, 시뮬레이터, 디버거 등을 포함하며 어셈블리어 프로그램까지 개발할 수 있는 Atmel사의 다양한 마이크로컨트롤러 전용 개발 프로그램이다. 사실 AVR 개발 프로그램은 CodevisionAVR과 같은 몇몇 상용 프로그램이 있으나 Atmel  Studio는 개발사에서 제공하고 무료로 사용할 수 있고 다른 상용 프로그램과 견주어 개발 과정에 불편함이 없으므로 교육 현장이나 실제 제품 개발에 많이 사용된다. 이것은 사용자가 작성한 어셈블리어와 C/C++ 언어를 손쉽게 작성하고 디버깅(debugging)이나 시뮬레이션을 수행한 후 실제 시스템에 간편하게 다운로드할 수 있는 환경을 제공한다.

[그림 1] avr studio 4.12


AVR 스튜디오 v4.12에서부터는 gcc계열의 WINAVR 컴파일러를 지원하기 시작하였고 v5.x로 판올림을 하면서부터는 Visual Studio 2010의 에디팅 환경을 차용하여 IDE의 외형 뿐만이 아니라 32비트 uC인 AVR32도 개발 가능하게 되는 등 상당히 많은 변화가 일어났다. 2015년 6월 현재는 다시 판올림을 하면서 이름도 바뀌어 Atmel Studio 6.x 정식 버전이 배포 중이며 이제는 이 프로그램을 이용하여 AVR계열 뿐만 아니라 ARM계열의 프로세서들까지도 개발할 수 있다. 프로그램의 외관은 [그림 2]와 같으며 [그림 1]과 비교하여 외형상으로도 많은 변화가 있음을 확인할 수 있다.


 

[그림 2] atmel studio 6.x

 본 블로그에서는 Atmel Studio 6.0버전을 가지고 실습을 진행한다. 하지만 AVR Studio 5.0을 사용해도 여기에서 제공하는 예제들을 실행하는데 아무런 지장이 없다.



Posted by 살레시오
,

 클럭 신호(clock signal, 이하 clk)란 일정한 주기로 0/1을 단순 반복하는 톱니파 신호로서 이 신호에 AVR의 거의 모든 부분이 동기화되어 동작된다. 일반적으로 다음 그림과 같은 파형을 가지며 1(0)이 시작되는 지점부터 0(1)이 끝나는 지점까지를 한 주기라고 한다.


[그림 1] 클럭 신호


예를 들면 더하기 한 번하는데 클럭 하나가 소요되고, 곱셈 한 번에 네 개의 클럭 신호가 필요하다든가, 또는 클럭신호가 0에서 1로 변하는 순간 어떤 동작을 수행한다거나 하는 등 거의 모든 동작이 클럭 신호를 기준으로 수행되는 것이다. 마치 사람들이 시간이라는 기준에 의해서 생활이 되므로 시계를 자주 보면서 어떤 일을 수행하는 것과 유사하다. 당연한 이야기지만 클럭의 주파수가 높을수록 uC의 동작은 빨라질 것이고 주파수가 낮아지면 동작 속도도 떨어질 것이다. 보통 AVR에는 1MHz ~ 20MHz 주파수의 클럭이 사용되며 16MHz라면 한 주기 파형이 1초에 16x106 개가 발생한다.


 따라서 AVR을 동작시키려면 전원과 함께 반드시 인가하여야 하는 것이 이 클럭 신호이며 클릭 신호를 인가하기 위해서 XTAL1, XTAL2 핀이 사용된다. AVR은 보통 클럭 신호를 외부에서 인가하는 방법, 그리고 내부에서 발생시키는 방법으로 구분할 수 있다. 그리고 클럭 선택과 관련이 있는 퓨즈비트는 CKOPT,와 CKSEL0, CKSEL1,CKSEL2, CKSEL3이 있다.


[표 1] ATmega8(A)의 클럭 소스와 관련 퓨즈비트 설정

구분

클럭소스

주파수

CKOPT

CKSEL3:0

비고

내부

발생

내부 RC 오실레이터

1.0 MHz

1

0001 (a)

(b)

2.0 MHz

0010

4.0 MHz

0011

8.0 MHz

0100

외부

인가

외부 RC 오실레이터

0.1~0.9 MHz

X (c)

0101

0.9~3.0 MHz

0110

3.0~8.0 MHz

0111

8.9~12 MHz

1000

외부 저주파 크리스탈

32.768 KHz

X (c)

1001

32.768

KHz

외부 크리스탈/세라믹 레조네이터

0.4~0.9 MHz

1

101X

(d)

0.9~3.0 MHz

1

110X

12~22pF

3.0~8.0 MHz

1

111X

12~22pF

8.0≤ MHz

0 (e)

101X,110X,111X

12~22pF

외부 클럭

X (c)

0000

※ X는 0과 1 모두 사용가능하다는 의미임.

(a) 공장 출하시 기본값.

(b) 이 경우 CKOPT는 반드시 unprogrammed(1)이어야 한다.

(c) CKOPT=0(program)으로 설정하면 XTAL1과 XTAL2에 36pF의 내부 커패시터가 GND와 연결되므로 외부에서 이들을 따로 연결할 필요가 없음

(d) 이 옵션은 세라믹레조네이터에만 사용됨. (크리스탈은 이 옵션으로 사용불가)

(e) CKOPT가 0임에 주의할 것.

크리스탈오실레이터

 크리스탈 오실레이터는 클럭 인가시 가장 보편적으로 사용되는 소자이다.

[그림 1] 크리스털 오실레이터 사용 회로도


[표 1] 클리스털 오실레이터 설정

CKSEL0

SUT0:1

기동

시간

리셋으로부터의 추가적인 시간지연(vcc=5V)

권장 사용처

비고

0

00

258CK

4.1ms

세라믹레조네이터,

빠른 기동 전원

(1)

0

01

258CK

65ms

세라믹레조네이터,

느린 기동 전원

0

10

1000 CK

-

세라믹레조네이터,

BOD enabled

(2)

0

11

1000 CK

4.1ms

세라믹레조네이터,

빠른 기동 전원

1

00

1000 CK

65ms

세라믹레조네이터,

느린 기동 전원

1

01

16000 CK

-

크리스탈오실레이터,

BOD enabled

1

10

16000 CK

4.1ms

크리스탈오실레이터,

빠른 기동 전원

1

11

16000 CK

65ms

크리스탈오실레이터,

느린 기동 전원

(1) 최대주파수에 근접한다면 이 옵션은 사용하지 말아야 한다. 또한 기동 직후의 안정성이 중요한 계통이라면 역시 사용하지 말아야 한다.

(2) 이 옵션은 세라믹 레조네이터를 위한 것이다. 크리스탈에도 사용가능하나 최대주파수에 가깝거나 기동 직후의 안정성이 중요한 계통이라면 사용하지 말아야 한다.

저주파 크리스탈 오실레이터

 실시간을 측정하는데 사용되는 클럭(32.768KHz)를 사용하려면 이 옵션을 선택해야 한다. 이 경우에 최적화된 내부 커패시터(36pF)이 XTAL1과 XTAL2에 GND사이에 내장되어 있으며 이것을 연결하려면 CKOPT를 프로그램(0)하면 된다. 따라서 외부에 커페시터를 별도로 연결할 필요가 없다.


[그림 2] 저주파 크리스털 오실레이터 회로도


[표 2] 저주파 오실레이터 설정

SUT0:1

기동

시간

리셋으로부터의 추가적인 시간지연(vcc=5V)

권장 사용처

비고

00

1000 CK

4.1ms

빠른 기동 전원

(1)

01

1000 CK

65ms

느린 기동 전원

10

32000 CK

65ms

기동시 안정적인 주파수

11

reserved

(1) 기동시 주파수 안정도가 중요치 않은 시스템에서만 사용 가능.


외부 RC오실레이터

 클럭의 주파수가 정확할 필요가 없는 시스템이라면 다음 그림과 같이 XTAL1핀에 저항(R)과 캐패시터(C)를 연결하는 간단한 회로만으로도 클럭 신호를 발생시킬 수 있다. 발생되는 클럭의 주파수의 근사치는 다음 식과 같이 계산할 수 있다.

여기서 C값은 22pF 이상이어야 한다. 퓨즈비트 CKOPT를 프로그램(0)하면 내부 캐패시터 (36pF)을 XTAL1과 XTAL2 핀에서 GND에 연결할 수 있다. 이 경우에는 외부에서는 XTAL1과 Vcc사이에 저항만 연결하면 된다.


[그림 3] 외부 RC오실레이터 회로도


[표 3] RC오실레이터 설정

SUT0:1

기동

시간

리셋으로부터의 추가적인 시간지연(vcc=5V)

권장 사용처

비고

00

18CK

-

BOD enables

01

18CK

4.1ms

빠른 기동 전원

10

18 CK

65ms

느린 기동 전원

11

6 CK

4.1ms

빠른 기동 전원 혹은

BOD enables

(1)

(1) 최대주파수에 근접한다면 이 옵션은 사용하지 말아야 한다.

보정된 내부 RC오실레이터

 내부 RC오실레이터를 사용한다면 XTAL1, XTAL2 핀에는 클럭신호 발생을 위해서는 아무 외부소자도 연결할 필요 없으며 포트핀(PB6, PB7) 혹은 타이머 오실레이터 핀(TOSC1,TOSC2)으로 사용할 수 있다. 이 경우 1MHz, 2MHz, 4MHz, 8MHz의 정해진 주파수만이 사용되며 5V, 25˚C 환경에서 ±3% 오차 범위의 주파수를 발생한다. 하지만 내부 레지스터(OSCCAL)를 이용하여 오차 범위를 ±1%까지 줄일 수 있다.(datasheet 228페이지 “Calibration byte"참조)


[표 4] 내부 RC오실렝터 설정

SUT0:1

기동

시간

리셋으로부터의 추가적인 시간지연(vcc=5V)

권장 사용처

비고

00

6 CK

-

BOD enables

01

6 CK

4.1ms

빠른 기동 전원

10

6 CK

65ms

느린 기동 전원

(1)

11

reserved

(1) 공장 출고시 기본값

클럭 발생기

 클럭 발생기를 사용한다면 XTAL1핀에만 연결하면 되므로 XTAL2는 포트핀으로 사용가능하다. 또한 퓨즈비트 CKOPT를 프로그램(0)하여 내부 커패시터(36pF)을 연결할 수도 있다.

[그림 4] 클럭 발생기 회로도


[표 4] 클럭발생기 설정

SUT0:1

기동

시간

리셋으로부터의 추가적인 시간지연(vcc=5V)

권장 사용처

비고

00

6 CK

-

BOD enables

01

6 CK

4.1ms

빠른 기동 전원

10

6 CK

65ms

느린 기동 전원

(1)

11

reserved

(1) 공장 출고시 기본값



타이머/카운터 오실레이터 연결

 ATmega8A의 내부 타이머/카운터를 이용하여 실제시간을 측정하는 경우에는 시스템 클럭과 별도로 32.768 KHz의 외부 크리스탈을 TOSC1, TOSC2에 직접 연결하여 사용할 수 있다. 이 경우 CKOPT퓨즈비트를 프로그램(0)하여 내부에서 36pF을 GND에 연결하여 사용할 수 있도록 설계되어 있다. 데이터쉬트에 따르면 TOSC1에 클럭발생기를 연결하는 것은 권장되지 않는다.


전압 대 최대 클럭 주파수

 ATmega8(A)은 최대 클럭 주파수가 16MHz이지만 모든 동작 전압에 대해서 이 최대 주파수를 사용할 수 있는 것은 아니다. 다음 그림은 전압 대 최대 주파수의 그래프를 데이터쉬트에서 발훼한 것이다.


[그림 5] 동작 전압 - 최대 클럭 주파수 관계도


4.5V이상의 동작전압에서 16MHZ 최대 클럭 주파수를 사용할 수 있으며 만약 3.3V 동작 전압을 사용한다면 최대 12MHZ 정도의 클럭을 사용할 수 있음을 알 수 있다.




Posted by 살레시오
,

 AVR을 동작시키기 위한 외부조건으로는 크게 세 가지가 만족되어야 되는데 다음과 같다.


       ① 전원이 적절히 인가되어야 한다.

       ② 클럭이 적절하게 인가되어야 한다.

       ③ 리셋(reset)핀에 ‘1’신호가 인가되어야 한다.


이 세 가지 조건을 만족하면 AVR은 내부 플래시롬에서 프로그램 명령어를 하나씩 꺼내서 실행하기 시작한다.

전원 인가

 ATmega8(A)의 동작 전압은 2.7V~5.5V이므로 정상 동작을 위해서는 이 사이의 전압값을 사용해야하며 보통 5V 또는 3.3V의 전압값을 많이 사용한다. ATmega8A의 전원 관련 핀들을 <그림 3.4.1>에 도시하였다. 여기서 7번 핀은 VCC로서 시스템에서 사용하는 전압에 따라 5V나 3.3V 등을 인가하면 되고 8번 또는 22번 핀에는 그라운드(GND)를 인가하면 된다.


[그림 1] 전원 관련 핀들


그리고 20번 핀은 내부의 ADC에 전원을 인가하는 AVCC핀이다. ADC는 아날로그 전압 값을 디지털 값으로 바꾸는 장치인데 전압 변화에 매우 민감하기 때문에 시스템의 전원과 분리되어 있다. 따라서, ADC를 사용하지 않는다면 연결하지 않아도 상관없으나, 만약에 ADC를 사용한다면 여기에도 전원을 인가해야 한다. 단, ADC는 전원의 잡음에 민감하기 때문에 데이터쉬트에는 다음 [그림 2]와 같이 LC필터를 사용할 것을 권장하고 있다. AREF핀은 ADC에서 기준으로 사용할 전압을 인가하는 핀이다.


[그림 2] AVCC 핀의 LC필터 회로


리셋(reset) 회로

 리셋은 것은 프로세서를 초기화 시켜서 프로그램의 동작을 처음부터 강제로 시작하게끔 하는 것이다. ATmega8(A)의 리셋회로의 구조도를 [그림 3]에 도시하였다.


[그림 3] ATmega8(A)의 리셋 로직


이 그림을 보면 ATmega8A가 리셋이 일어나는 경우는 다음과 같이 네 가지가 있다는 것을 알 수 있다.


       ① 전원을 인가하였을 때

       ② 외부 리셋핀(1번 핀)에 0신호가 인가되었을 때

       ③ 저전압이 감지되었을 때. (brown-out)

       ④ 워치독(watch dog) 타이머에 의해서


워치독 타이머는 퓨즈바이트에서 사용 여부를 설정할 수 있다.




Posted by 살레시오
,

락 비트 (lock bit)

 ATmega8(A)는 6개의 락 비트 (lock bit)가 있다. 락 비트은 플래시롬과 EEPROM을 다시 프로그램할 수 없도록 잠그는데 사용된다. 따라서 제품의 개발이 끝난 다음 다시 프로그램을 변경할 필요가 없거나, 혹은 외부인이 AVR내부의 프로그램을 읽어낼 수 없도록 막기 위해서 사용한다. 주의할 점은 ‘1’이 unprogrammed 이고 ‘0’이 programmed 이라는 것이다. 흔히 반대로 생각하기 쉬우니 주의해야 한다. (이것은 fuse byte에서도 동일하다.)


[표 1] 락 비트

Lock bits

bit

기술

기본 설정 값

7

-

1(unprogrammed)

6

-

1(unprogrammed)

BLB12

5

Boot lock bit 12

1(unprogrammed)

BLB11

4

Boot lock bit 11

1(unprogrammed)

BLB02

3

Boot lock bit 02

1(unprogrammed)

BLB01

2

Boot lock bit 01

1(unprogrammed)

LB2

1

Lock bit 2

1(unprogrammed)

LB1

0

Lock bit 1

1(unprogrammed)


[표 2] 락 비트 설정

memory lock bit

기능설명

LB모드

LB2

LB1

1

1

1

아무런 제한 없음

2

1

0

플래시/EEPROM/퓨즈비트 프로그램 금지. (Fuse byte도 잠김)

3

0

0

플래시/EEPROM/퓨즈비트 프로그램 및 확인(verify) 금지. (Fuse byte도 잠김)

memory lock bit

기능설명

BLB0모드

BLB02

BLB01

1

1

1

아무런 제한 없음

4

0

1

boot loader의 LPM명령이 application section을 읽기 불가. 인터럽트벡터가 boot loader에 있다면 application section 실행 중 인터럽트 불가.

3

0

0

SPM으로 application section에 쓰기 불가. boot loader의 LPM명령이 application section을 읽기 불가, 인터럽트벡터가 boot loader에 있다면 application section 실행중 인터럽트 불가

2

1

0

SPM으로 application section에 쓰기 불가

memory lock bit

기능설명

BLB1모드

BLB12

BLB11

1

1

1

아무런 제한 없음

4

0

1

application section에 위치한 LPM명령으로 부트로더 영영의 읽기 불가, 인터럽트벡터가 application section에 있다면 boot loader 실행 중 인터럽트 불가

3

0

0

SPM으로 부트로더 영역에 쓰기 불가. application section 에 위치한 LPM명령이 부트로더 영역을 읽기 불가, 인터럽트벡터가 application section에 있다면 boot loader 실행 중 인터럽트 불가

2

1

0

SPM으로 부트로더 영역에 쓰기 불가


락비트를 프로그램하면 퓨즈바이트가 잠기기 때문에 반드시 퓨즈 바이트를 먼저 프로그램 한 다음에 필요하다면 락비트를 프로그램해야 한다.


퓨즈 바이트 (fuse byte)

 퓨즈 바이트는 AVR을 동작시키는데 있어서 전반적으로 설정해야 할 사항들을 선택하여 저장하는 내부메모리로서 ATmega8(A)의 경우에는 두 개의 바이트로 구성되어 있다. 각각의 퓨즈비트는 1 또는 0값을 가지게끔 설정할 수 있는데 한 가지 유의할 점은 datasheet상에서 사용하는 용어가 0으로 쓰는 경우를 programmed, 1로 쓰는 경우가 unprogrammed로 되어있다는 점이다. 보통은 반대로 생각하기 쉬우니 유의해야 한다.


 상위 퓨즈 바이트와 하위 퓨즈 바이트와 각각의 비트의 기능을 다음 표에 정리해 놓았다.


[표 3] 상위 퓨즈 바이트 기능

비트명

bit

기능

기본설정값

RSTDISBL (4)

7

PB6핀을 RESET으로 사용할 것인지 포트핀으로 사용할 것인지 설정

1(PB6는 리셋핀)

WDTON

6

Watch Dog Timer 사용

1(사용 안함)

SPIEN (1)

5

SPI통신으로 ISP 가능

0(SPI 다운로드 가능)

CKOPT (2)

4

오실레이터 옵션

1(unprogrammed)

EESAVE

3

칩erase 수행시에 EEPROM의 내용 유지

1 (EEPROM도 지움)

BOOTSZ1

2

부트 사이즈 설정

0 (3)

BOOTSZ0

1

부트 사이즈 설정

0 (3)

BOOTRST

0

리셋벡터 설정

1

(1) 직렬통신 모드에서는 이 비트는 접근 불가임.

(2) CKOPT 비트는 CKSEL3:0 의 설정에 따라 그 기능이 달라짐.

(3) 기본설정값으로는 부트섹터가 최대로 설정된 것임.

(4) 이 비트가 0(programmed)이면 병렬프로그램 모드를 사용해야 함.


시중에 쉽게 구할 수 있는 ISP 기기들은 SPI 통신(직렬통신임)을 사용하고 있고 이러한 직렬 통신 프로그래밍은 리셋 모드일 때 진입할 수 있으며 리셋 핀이 하이(1)일 때 다운로드를 수행하므로 필수적으로 리셋 핀의 기능이 있어야 한다. 따라서 RSTDISBL 비트는 만약 직렬 통신 프로그래머를 사용한다면 1값을 계속 유지해야하며 만약 (실수로라도) 0으로 설정하면 그 다음부터는 SPI를 이용한 프로그래밍이 불가능해진다는 것에 유의하자.


 워치독타이머(watch dog timer, WDT)라는 것은 uC가 예측 불가능한 외부요인(외부 잡음, 온도, 배터리의 소모 등등)으로 인해서 정상적인 동작을 수행하고 있는지 아닌 지를 감시하는 기능을 수행한다. 만약 WDT가 활성화 되어 있다면 여기에서 주기적으로 어떤 신호가 발생하게끔 되어 있으며 따라서 이 신호가 정상적으로 발생한다면 uC가 정상적으로 동작하는 것으로 판단하게 된다. 만약 어떤 요인에 의해서 uC가 오동작을 하게 되면 WDT에서 발생하던 신호가 끊기게 되고 이러한 경우에는 uC를 리셋시키거나 어떤 조치를 취하여 프로그램이 다시 정상적으로 수행하도록 할 수 있는 것이다. WDTON비트는 이러한 시스템 감시기능의 활성화 여부를 설정하는 비트이다.


 SPIEN비트는 직렬통신모드로 ISP를 사용한다면 아예 접근할 수 없도록 막아져있다.


 플래시메모리는 크게 응용프로그램영역과 부트로더영역으로 나뉜다는 것은 앞에서도 설명했었다. 부트로더 영역의 크기를 BOOTSZ1:0 비트를 이용해서 설정할 수 있으며 각각의 경우에 대해서 부트로더의 크기는 다음 그림과 같다.

그리고 BOOTRST비트는 리셋이 걸린 이후 맨 첨음 실행을 시작하는 번지가 응용프로그램의 최하위번지(0번지)인지 부트로더의 최하위번지(이경우는 BOOTSZ1:0의 설정에 따라 달라짐)를 설정하는 비트이다.


[표 4] 부트로더 사이즈 설정

BOOTSZ1

BOOTSZ0

사이즈

페이지

응용프로그램영역

부트로더영역

1

1

128 word

4

0x000~0xF7F

0xF80~0xFFF

1

0

256 word

8

0x000~0xEFF

0xF00~0xFFF

0

1

512 word

16

0x000~0xDFF

0xE00~0xFFF

0

0

1024 word

32

0x000~0xBFF

0xC00~0xFFF


 하위 퓨즈바이트는 크게 클럭소스선택, 기동시간 설정, 그리고 BOD관련 설정 비트들로 이루어져 있다. BOD(brown out detector)는 시스템의 전원전압이 일정레벨 이하로 떨어지는 지를 감시하는 장치이다. 건전지나 충전지로 구동되는 시스템의 경우에는 시간이 지나면 정상 전압 이하로 떨어지고 방치하면 전체 시스템이 오동작을 일으킬 수 있으므로 그 전에 이것을 감지하여 적절한 조치를 취하도록 할 수있다. BODEN은 이러한 감시기능을 활성화 시킬 것인지를 설정하는 비트이고 BODLEVEL은 전압레벨을 설정하는 비트이다.


[표 5] 하위 퓨즈 바이트의 기능

비트명

비트

번호

기능

내정값

BODLEVEL

7

Brown Out Detector Tirgger Level

1

BODEN

6

Brown Out Detector enable

1(BOD disabled)

SUT1

5

기동 시간(start-up time) 설정

1(unprogrammed)

SUT0

4

0(programmed)

CKSEL3

3

클럭 소스 선택 (clock selection)

0(programmed)

CKSEL2

2

0(programmed)

CKSEL1

1

0(programmed)

CKSEL0

0

1(unprogrammed)



 클럭 소스 선택 비트 CKSEL3:0과 기동 시간 설정 비트 SUT1:0에 대해서는 다음 포스트에서 상세히 설명하도록 하겠다.




Posted by 살레시오
,

 메모리맵(memory map)이란 메모리가 어떻게 구성되어 있는 지를 나타내는 그림이다. ATmega8(A)은 프로그램을 저장하는 2Kbyte 플래시메모리, 레지스터와 동적인 데이터를 저장하는 128byte의 SRAM 그리고 128byte의 프로그램 가능한 EEPROM이 내장되어 있다. 이들 메모리의 구조가 [그림 1]에 도시되어 있다. 만약 어셈블리어로 프로그램을 하려면 이들 메모리 구조는 완전히 숙지하고 있어야 한다. 한 가지 주의할 것은 프로그램 메모리는 한주소당 2byte(=1 word) 단위로 구성되어 있고 SRAM과 EEPROM은 1byte단위로 구성된다는 것이다. 메모리 맵의 폭으로 이를 구분해 놓았다.


[그림 1] ATmega8(A)의 메모리맵


이 그림을 보면 프로그램 메모리와 데이터 메모리가 별개로 구성되어 있고 독립된 주소체계를 사용한다는 것을 알 수 있다.


 프로그램메모리는 10,000번 정도 읽고 쓰기를 할 수 있는 플래시롬(flash rom)이며 1Kword(1K×16bit)의 크기를 가진다. AVR은 하나의 어셈블리 명령어가 대부분 16bits로 구성이 되므로 최대 1000개의 어셈블리 명령을 써줄 수 있다는 말이 된다. 따라서 소규모의 프로그램을 개발하기 적합하고 더 큰 규모의 프로그램 작업이 필요할 때는 상위 계열의 uC를 선택해야 할 것이다. AVR의 ISP 기능을 이용하여 PC와 직접 연결한 후 이 플래쉬메모리에 프로그램을 써 넣어줄 수 있다.


 데이터메모리는 SRAM이며 하위에서부터 32byte의 레지스터, 64byte의 I/O레지스터, 그리고 128byte의 사용자메모리로 구성되어 있다. 각각의 주소는 [그림 1]에 도시된 바 대로이다. (레지스터와 I/O레지스터는 아래에서 상세히 설명하도록 하겠다.) 사용자 메모리는 프로그램에 의해서 데이터가 임시로 저장되는 메모리 공간을 지칭한다. 레지스터만으로는 저장공간이 부족할 경우 사용이 되며 변수를 저장하거나 각종 연산에 필요한 데이터와 연산 결과 등을 저장하는 메모리 공간이다.


 또한 SRAM과는 별도로 128byte의 EEPROM이 내장되어 있으며 10만 회 정도 읽고 쓸 수 있는 내구성을 가진다. SRAM과는 달리 EEPROM에 데이터를 읽고 쓸 때에는 별도의 레지스터(주소 레지스터, 데이터 레지스터, 제어 레지스터)를 거쳐야 하며 소요시간이 더 걸린다.

범용 레지스터와 I/O제어 레지스터

 [그림 1]을 보면 SRAM의 최하위 32byte는 범용레지스터이다. 이것의 구성을 더 자세히 도시하면 다음 [그림 2]와 같다.


[그림 2] AVR의 범용 레지스터


레지스터는 ALU와 직접 연결된 특별한 메모리이고 ALU가 산술/논리 연산을 할 때 피연산자를 여기서 읽어오며 연산 결과도 다시 여기로 저장한다. 32개의 8bit로 구성되어 있고 어셈블러에서 주소값($00~$1F)으로 참조하지 않으며 R0, R1, …R31과 같이 이름을 붙여서 참조한다.


 [그림 2]에서 상위 16bye와 하위 16byte를 굵은 선으로 구분해 놓았는데 이것은 어셈블러에서 하위 16byte(R16~R31)에만 직접 상수를 대입할 수 있고 상위 16byte에는 그럴 수 없다는 것을 구분하기 위한 선이다.


 또한 R24~R31은 2개씩 묶어서 16bit단위로 연산을 하기 용이하도록 구성되었으며 특히 R27:R26, R29:R28, R31:R30 쌍은 각각 X, Y, Z레지스터로 명명하여 이들 레지스터를 이용하여 16bit 연산을 할 수 있을뿐만 아니라 주소(pointer)를 지정하거나 주소 연산을 하는데도 사용할 수 있다.


 SRAM에서 범용레지스터 바로 상위에 64byte의 I/O제어레지스터가 있다. 이 레지스터를 이용하여 uC의 상태를 설정하거나 상태값을 읽고 또한 각종 주변기기(입출력포트, 인터럽트, 타이머/카운터, 직렬통신, 아날로그비교기 등)를 설정·제어 할 수 있다. 각각의 레지스터의 용도는 이후에 세세히 설명될 것이다.


 어셈블리어에서 I/O제어레지스터의 번지를 참조할 때 절대번지(physical address)를 사용하는 경우가 있고 상대번지(relative address)를 사용하는 경우가 있다는 것이다. 절대번지는 $20~$5F 이고, 상대번지는 최하위 절대번지인 $20번지를 $0번지로 간주하여 $00~$3F값을 갖는다.


[그림 3] ATmega8(A)의 내부 SRAM 구성도


 만약 어셈블리어로 개발할 부분이 있다면 메모리 구성의 세세한 부분까지 숙지할 필요가 있으나 C/C++로만 개발할 계획이라면 대략만 파악하고 있어도 된다.




'하드웨어 > ATmega8(A)' 카테고리의 다른 글

ATmega8(A)의 전원 인가와 리셋 회로  (0) 2015.06.04
ATmega8(A)의 락 비트와 퓨즈 바이트  (1) 2015.06.04
ATmega8(A)의 세부적인 특징  (0) 2015.06.03
ATmega8(A)의 개략적인 특징  (0) 2015.06.03
AVR 개요  (0) 2015.06.03
Posted by 살레시오
,

 ATmega8(A)의 PDIP(parallel dual in-line, 핀 배치가 평행한 두 줄 모양) 패키지의 외형은 다음 그림과 같이 14 핀씩 두 줄이며, 각 핀의 번호 및 명칭은 다음과 같다.

[그림 1] ATmega8(A) PDIP 패지키의 핀 배열


[표 1] 핀의 이름과 기능

핀이름

기능

비고

Vcc/GND

uC를 구동시킬 전원 연결

동작 필수 기능

/RESET

리셋핀

XTAL1/XTAL2

클럭신호 입력 핀

PB0,PB1,…,PB7

8bit 범용 입출력 포트

포트

PD0,PD1,…PD7

8bit 범용 입출력 포트

PC0,PC1,…PC6

7bit 범용 입출력 포트

RXD, TXD, XCK

시리얼 통신을 위한 핀

통신

SCK,MISO,MOSI, /SS

SPI통신을 위한 핀 (ISP에 사용)

SCL, SDA

Two-Wire Interface (TWI)

INT0, INT1

외부 인터럽트 핀

T0, T1

TOSC0, TOSC1

타이머 클럭 입력 핀

타이머/카운터

OC1A, OC1B, OC2

타이머/카운터 출력핀

ICP1

타이머/카운터 1의 입력캡춰 핀

AVCC

ADC의 전원 인가 핀

ADC

AREF

ADC의 기준전압 인가 핀

ADC0,…,ADC5

ADC를 수행할 노드 연결 핀

AIN0, AIN1

아날로그 비교를 위한 핀


 ATmega8(A)는 AVR계열 중에서 28개의 핀을 가진 uC이다. (AVR중 tiny계열에는 8핀만을 가지는 uC도 있다). 핀의 명칭을 보면 P로 시작하는 핀들이 가장 많이 눈에 띄는데 이들은 포트(port)를 뜻한다. ATmega8(A)는 8bit로 입출력을 제어할 수 있는 2개의 양방향 포트(port)를 가지며 포트B(PB0~PB7), 포트D(PD0~PD6)라고 칭한다. 포트라는 것은 μC가 입력 신호를 받거나 출력 신호를 내보내는 통로라고 이해하면 된다. 하나의 핀은 2가지 전압(0V와 5/3.3V)만을 가질 수 있으므로 하나의 bit를 표현할 수 있다. 8개의 핀을 조합해서 8bits 즉 1byte를 구성한다. 즉 사용자 프로그램에 의해서 포트 핀은 0V 전위를 가질 수도 5V전위를 가질 수도 있으며 (출력일 경우) 외부의 0V 혹은 5V의 전압값을 읽어 들일 수도 있다(입력일 경우). 양방향이라는 것은 동일한 포트가 입력과 출력으로 모두 사용할 수 있다는 의미이다.


 총 28개의 핀들 중에 전원을 인가하는 8/20/21번(VCC, AVCC, AREF)과 8/22번(GND)을 제외한 나머지 23개의 핀이 모두 포트의 기능을 가지고 있다. 또한 핀 수가 28개로 제한이 되어있기 때문에 하나의 핀이 두 개의 기능을 가지는 경우도 있다. 이 경우 내부 I/O레지스터를 조작하여 어떤 기능으로 사용할 것인가를 지정할 수 있다.


[그림 2] ATmega8(A)의 내부 구조도


 [그림 2]에 ATmega8A의 전체 기능별 블럭도가 도시되어 있다. 이 그림을 보면 8bit 데이터버스가 모든 구성요소에 연결되어 있다. 하지만 레지스터와 ALU간에는 전용선로가 깔려있어서 ALU가 레지스터에서 데이터를 읽고 쓰는 것이 가장 빠르다. ALU는 연산에 필요한 데이터를 레지스터에서 읽어오며 또한 연산 결과를 레지스터에 바로 반영한다.


 PC(program counter)는 현재 실행되는 프로그램의 번지를 저장하는 메모리이다. 오류가 없는 프로그램이 어셈블되어서 ISP기능 등을 이용하여 프로그램이 플래쉬롬에, 그리고 데이터가 EEPROM에 저장이 되어 있을 것이다. uC는 전원과 적합한 클럭이 인가되고 리셋핀에 high(5/3.3V) 신호가 인가되면 PC(program counter)는 $000으로 초기화되고 프로그램 메모리의 $000번지부터 명령어를 하나씩 명령레지스터(instruction register)로 읽어 들인다. 이때 현재 실행해야 할 프로그램의 번지가 저장되어 있는 곳이 바로 PC이고 16bit 로 구성되어 있다. 따라서 초기에는 PC에 $0000값이 입력되고 명령어를 하나(대부분 1word 이지만 어떤 명령어는 2word) 읽어 들이고 1(혹은 2)가 증가한다. 읽어 들인 명령어는 명령레지스터에 저장된 후 명령 해독기(instruction decoder)에서 어떤 일을 수행하라는 명령어인지를 해독한다. 해독이 끝나면 해당되는 작업을 수행하기 위해 적절한 제어신호가 제어선(cotnrol lines)에 의해서 전달된다. 현재의 명령어를 해독하고 수행하는 동시에 다음 명령어(즉 PC가 가리키는 번지에 저장된 명령어)를 명령레지스터로 읽어 들인다. 그렇기 때문에 거의 모든 명령어가 1클럭 싸이클에 수행되는 것이고, 만약 시스템이 4MHz 클럭으로 동작한다면 최대 4MIPS의 수행속도를 낼 수 있는 것이다.


 AVR은 하버드 구조(Harvard structure)를 채택하여 프로그램과 데이터를 위한 메모리와 버스가 서로 분리되어 있다. 즉 프로그램메모리와 데이터메모리가 따로 존재하고, 각각의 메모리를 접근하기 위한 주소 및 데이터 버스선도 따로 존재한다. 프로그램 메모리는 2단계 파이프라인(2-stage pipeline) 방식으로 동작하여 프로그램이 수행되는 동안에 다음 명령어를 읽어 들인다. 데이터 버스를 통해서 SRAM이나 EEPROM에서 데이터를 레지스터로 읽어오거나 반대로 쓸 수도 있다. 그리고 모든 주변장치들이 데이터버스를 통해서 레지스터와 연결되어 있다.




Posted by 살레시오
,

 여기에서는 AVR에 입문하는데 적합한 디바이스로 ATmega8(A)의 개략적인 특징에 대해서 설명하도록 하겠다. AVR의 이름을 보면 끝에 A가 붙는 것들이 있는데 (ATmega8A, ATmega128A등) 이것은 기존에는 5V용과 저전압(3.3V)용이 따로 구분되어 있었는데 (ATmega8, ATmega8L이 각각 존재했었다.) ATmega8A는 이 두 AVR을 하나의 uC로 통합한 것이다. 즉, ATmega8A는 5V와 3.3V 두 전압에서 모두 구동이 가능하고 (데이터쉬트상의 구동전압은 2.7V~5.5V이다.) 전력 특성을 개선하였으면서 사용법은 기존의 ATmega8/8L과 동일하다.


 실습용으로 ATmega8A를 선택한 이유는 일단 28핀 PDIP패키지가 제공되어 (TQFP, MLF패키지도 있음) 초보자들이 납땜을 해서 (혹은 빵판에 꽂아서) 실험을 하기에 편리하며 이 칩과 내장 주변기기를 제어하는 방법을 잘 알아두면 상위계열이나 하위 계열의 디바이스들을 모두 쉽게 다룰 수 있게 된다는 점이다. 따라서 만약 ATmega8A의 하드웨어를 충분히 숙지하고 개발이 익숙해진다면 거의 모든 (ATmega2560과 같은 최상위의 디바이스도 포함해서) AVR디바이스를 별다른 추가 학습 없이 다룰 수 있게 된다. 본 절에서는 ATmega8A의 특징에 대해서 알아보도록 한다.


[그림 1] ATmega8(A)의 외형. 좌측으로부터 PDIP, TQFT,  MLF


 ATmega8(A)는 AVR RISC 구조로 제조된 저전력 소모용 CMOS 8bit μC이다. 한 개의 클록 사이클 안에 강력한 명령을 수행하여 1MHz 당 최대 1MIPS(million instructions per second)의 처리속도를 낼 수 있으며 시스템 디자이너가 처리속도 대비 전력 소모를 최적화 할 수 있도록 제조되었다. AVR의 핵심은 산술연산장치 (ALU)에 직렬로 연결된 32개의 범용레지스터를 가지며 이들을 이용한 풍부한 명령어들이 마련되어 있다는 것이다. 단일 클록 사이클 이내 실행되는 한 개의 단일 명령어로써 두 개의 독립적인 레지스터를 처리할 수 있도록 하였다. 이러한 구조는 재래식 CISC uC보다 10배 이상 빠른 처리속도를 낼 수 있을 정도로 보다 효과적인 코드 방식을 지원한다.


 ATmega8(A)는 내부에 프로그램 가능한 8K바이트의 프로그램 가능한 플래시 메모리, 128byte 의 SRAM이 있고 128byte의 프로그램 가능한 EEPROM이 내장되어 있다. AVR계열의 μC는 ISP (in-system programming) 기능을 가지고 있다고 앞에서 말한 바가 있다. 즉 롬라이터(rom writer)같은 부가적인 장비 없이 PC와 연결하여 SPI 직렬 인터페이스를 통해서 내부의 플래시메모리에 프로그램을 써 넣을 수 있어서 편리하게 실험하는데 아주 유용한 기능이다. 한 개의 단일 칩에 기능이 향상된 RISC 8bit μC를 내장형 프로그래머블 플래시 및 다양한 부가장치를 조합함으로 사용자가 사용하기 쉽고 수많은 다른 제어 응용 분야에서도 비용면에서 효과적인 강력한 uC이다.


 데이터쉬트에 소개된 ATmega8A의 하드웨어 특징을 정리하면 다음과 같다.

  • 고성능, 저전력 소모용 RISC 구조 설계

  • 130개의 강력한 명령어 (대부분 단일 클록에 실행 가능)

  • 32×8 범용 레지스터

  • 16MHz에서 최대 16MIPS의 처리 속도

  • 2사이클 곱셈기 내장

  • 데이터와 비휘발성 프로그램 메모리 구조

  • 8K byte 플래시메모리 내장 (최대 10,000번 읽기/쓰기 가능)

  • 512 byte EEPROM 내장 (최대 100,000번 읽기/쓰기 가능)

  • 1K byte의 내부 SRAM

  • 상온(25도)에서 100년간 데이터 보존 (플래시롬/EEPROM)

  • 크기 조절 가능한 부트로더 영역 (부트 프로그램에 의한 ISP가능)

  • 플래시롬과 EEPROM 데이터 보호용 프로그래밍 잠금 기능.

  • 주변장치의 특성

  • 23개의 프로그램 가능한 I/O 포트

  • 2개의 8bit 타이머/카운터 내장

  • 1개의 16bit 타이머/카운터 내장

  • 별도의 오실레이터 연결 가능한 실시간 카운터

  • 6채널(PDIP) 10bit ADC 내장

  • 별도의 오실레이터가 내장된 프로그램 가능한 워치도그 타이머

  • 마스터/슬레이브 SPI (serial programming interface) 내장

  • 프로그램 가능한 직렬 USART 내장

  • 아날로그 비교기 내장

  • 휴식모드 (idle mode) 및 절전모드 (power down mode)로 전환 가능

  • 동작 전압 및 클럭 주파수 : 2.7~5.5V, 0~16 MHz

  • 패키지 : 28핀의 PDIP형, 32핀의 TQFP와 MLF


초보자가 실험하기에는 28핀을 갖는 PDIP 패키지가 좋은데 빵판에 꼽아서 회로를 꾸밀수 있기 때문이다.



Posted by 살레시오
,