ATmega 시리즈는 ATMEL사에서 직접 설계한 AVR 프로세서를 사용하는 MCU로
8비트 구조로 설계되어있다.
ARM과 같이 롬라이터 없이 프로그램을 삽입할 수 있는 In-System Programmable Flash를 장착하고 있으며,
ARM의 SAM-BA보다 훨씬 사용하기 편리하다.
GNU에서 만든 GCC컴파일러인 WinAVR을 설치하고 그 Makefile만 가져다 코딩하면 될 정도로 사용이 무척 간편하다.
우선 WinAVR의 Makefile을 살펴보자.
43 # MCU name
44 MCU = atmega2560
47 # Processor frequency.
48 # This will define a symbol, F_CPU, in all source code files equal to the
49 # processor frequency. You can then use this symbol in your source code to
50 # calculate timings. Do NOT tack on a 'UL' at the end, this will be done
51 # automatically to create a 32-bit value in your source code.
52 # Typical values are:
53 # F_CPU = 1000000
54 # F_CPU = 1843200
55 # F_CPU = 2000000
56 # F_CPU = 3686400
57 # F_CPU = 4000000
58 # F_CPU = 7372800
59 # F_CPU = 8000000
60 # F_CPU = 11059200
61 # F_CPU = 14745600
62 # F_CPU = 16000000
63 # F_CPU = 18432000
64 # F_CPU = 20000000
65 F_CPU = 16000000
68 # Output format. (can be srec, ihex, binary) 실행파일 형식
69 FORMAT = ihex
수정해줄 부분은 44, 65라인의 MCU 명과 그에 맞는 클럭속도만 손봐주면 된다.
그리고 69라인에서 컴파일된 실행파일은 .hex파일인 것을 확인 할 수있다.
#define PORTA (*((volatile unsigned char *)0x22))// 데이터 출력시 사용하는 레지스터
#define DDRA (*((volatile unsigned char *)0x21))// 입출력 방향 지정 레지스터(1: 출력, 0: 입력)
#define PINA (*((volatile unsigned char *)0x20))// 데이터 입력시 사용하는 레지스터
int main()
{
volatile unsigned int uiCnt1; // int 크기 : 16bit (0 ~ 65535)
volatile unsigned int uiCnt2; // delay 루프를 위한 변수
DDRA = 0xFF; // PA0~PA7 모두 출력으로
PORTA = 0xFF; // PA0~PA7 출력값을 모두 HIGH로 지정
while(1)
{
// int가 16비트라 이중 for문으로 만들어 줌
for(uiCnt1 = 0; uiCnt1 < 10000; ++uiCnt1)
for(uiCnt2 = 0; uiCnt2 < 100; ++uiCnt2);
PORTA = 0; // ON : low가 되야 전압차가 생겨서 켜짐
for(uiCnt1 = 0; uiCnt1 < 10000; ++uiCnt1)
for(uiCnt2 = 0; uiCnt2 < 100; ++uiCnt2);
PORTA = 0xFF; // OFF : High - High가 되므로 OFF
}
while (1); // main() 종료 방지를 위한 코드
return 0;
}
위의 소스에서 define문으로 정의한 세 레지스터는 다음과 같은 기능을 한다.
#define PORTA(*((volatile unsigned char *)0x22))// PORTA의 주소
#define DDRA (*((volatile unsigned char *)0x21))// 입출력 방향 지정 레지스터(1: 출력, 0: 입력)
#define PINA (*((volatile unsigned char *)0x20))
PORTA 레지스터는 ATMEGA2560의 PORTA핀에서 데이터를 출력할 때 사용하는 레지스터로
주소는 0x22로 정의되어 있고 각 비트는 각 핀 번호를 제어한다.
ARM에서 PIO_CODR과 PIO_SODR의 두개의 레지스터로 각각 핀의 LOW,
HIGH를 설정하던 것과는 다르게
각 비트에 1을 대입하면 HIGH로 세팅되고(5V) 0은 LOW(0V)로 세팅된다.
DDRA 레지스터는 이름처럼 PORT A 핀의 데이터의 방향을 설정하는 레지스터로
1은 데이터 출력을, 0은 데이터 입력을 의미한다.
여기서 PORT A란 아래의 PA0~PA7번 핀을 모두 묶어서 말하는 것이다.
PINA 레지스터는 PA0~PA7 핀에서부터 데이터를 입력받을 때 사용하는 레지스터로 시작 주소는 0x20 이다.
DDRA = 0xFF; // PA0~PA7 모두 출력으로
PORTA = 0xFF; // PA0~PA7 출력값을 모두 HIGH로 지정
우선 LED를 점등시키려면 PA0~7번 핀을 출력으로 지정하고
PORTA의 값을 모두 HIGH로 세팅해준다.
// int가 16비트라 이중 for문으로 만들어 줌
for(uiCnt1 = 0; uiCnt1 < 10000; ++uiCnt1)
for(uiCnt2 = 0; uiCnt2 < 100; ++uiCnt2);
위의 시간 지연용 반복문은 ARM에서왕는 다르게 이중 for문으로 구성되어 있는데,
이는 주석에서처럼 int형으로 변수를 선언하더라도 8비트 MCU인 관계로 16비트로
인식되므로 그 표현한계가 0~65535 밖에 안된다.
그러므로 사람의 눈으로 인식할 정도의 시간을 끌려면 위와 같이 이중for문을 이용한다.
PORTA = 0; // ON : low가 되야 전압차가 생겨서 켜짐
......
PORTA = 0xFF; // OFF : High - High가 되므로 OFF
PORTA를 0으로 클리어하면 LOW로 세팅되서 전류가 흘러 LED를 켜는 역할을 하고
1로 세팅하면 HIGH가 되므로 전압들어오는 LED의 VCC와 GND의 전압이 같아지므로
전류가 흐르지 않아 LED는 켜지지 않는다.
'Embedded 실습 > ATmega 2560' 카테고리의 다른 글
계산기 프로젝트 (0) | 2013.08.23 |
---|