본문 바로가기
Embedded 실습/ATmega 2560

ATmega2560으로 LED 깜빡이기

by 중동콜링 2013. 5. 29.

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의 두개의 레지스터로 각각 핀의 LOWHIGH를 설정하던 것과는 다르게 

각 비트에 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