본문 바로가기
MCU/AVR

[AVR128DB48] RTC 사용 방법 및 예제 코드

by linuxgo 2025. 8. 20.
반응형

1. AVR128DB48 RTC 모듈 개요

Microchip의 AVR128DB48은 AVR DB 시리즈의 8비트 마이크로컨트롤러로, RTC(Real-Time Clock) 모듈을 내장하여 시간 추적, 주기적 인터럽트, 타이머 애플리케이션에 적합합니다. RTC 모듈은 저전력 모드에서 동작하며, 외부 32.768kHz 크리스털 또는 내부 오실레이터를 클럭 소스로 사용할 수 있습니다. 이 문서에서는 AVR128DB48의 RTC 설정 방법, Bitfield 구조를 활용한 레지스터 설정, 그리고 실용적인 예제 코드를 제공하여 초보자와 숙련된 개발자 모두 쉽게 활용할 수 있도록 돕습니다.

주요 사양

  • 클럭 소스:
    • 외부 32.768kHz 크리스털 오실레이터 (XOSC32K)
    • 내부 32.768kHz 오실레이터 (OSC32K)
  • 동작 모드:
    • 실시간 클럭 (RTC)
    • 주기적 인터럽트 타이머 (PIT)
  • 주요 레지스터:
    • RTC.CTRLA: RTC 제어 설정
    • RTC.CLKSEL: 클럭 소스 선택
    • RTC.CNT: 카운터 값
    • RTC.PER: 주기 값 (오버플로우)
    • RTC.CMP: 비교 값 (인터럽트)
    • RTC.INTCTRL: 인터럽트 제어
    • RTC.PITCTRLA: PIT 제어 설정
  • 인터럽트:
    • 오버플로우 인터럽트 (OVF)
    • 비교 일치 인터럽트 (CMP)
    • PIT 인터럽트
  • 전력 관리: 저전력 모드 (Sleep 모드)에서 RTC 동작 지원
  • 전압 레벨: 1.8V~5.5V 동작 지원

2. RTC Bitfield 설정 상세

AVR128DB48의 RTC 레지스터는 Bitfield 구조로 정의되어 있으며, <avr/io.h> 헤더 파일을 통해 접근합니다. 주요 레지스터는 다음과 같습니다:

2.1 RTC.CTRLA (RTC 제어 레지스터)

  •   bit.RTCEN: RTC 활성화 (1: 활성화)
  •   bit.RUNSTDBY: 스탠바이 모드에서 RTC 동작 (1: 활성화)
  •   bit.PRESCALER: 프리스케일러 설정 (예: 0x0A = DIV32768, 1초 단위)

2.2 RTC.CLKSEL (클럭 소스 선택 레지스터)

  •   bit.CLKSEL:
    •   0x00: OSC32K (내부 32kHz 오실레이터)
    •   0x02: XOSC32K (외부 32kHz 크리스털)

2.3 RTC.CNT (카운터 레지스터)

  •   16비트 카운터 값 (실시간 클럭 값 저장/읽기)

2.4 RTC.PER (주기 레지스터)

  • 16비트 주기 값 (오버플로우 발생 시점 설정)

2.5 RTC.CMP (비교 레지스터)

  •   16비트 비교 값 (CMP 인터럽트 발생 시점 설정)

2.6 RTC.INTCTRL (인터럽트 제어 레지스터)

  •   bit.OVF: 오버플로우 인터럽트 활성화
  •   bit.CMP: 비교 일치 인터럽트 활성화

2.7 RTC.PITCTRLA (PIT 제어 레지스터)

  •   bit.PITEN: PIT 활성화
  •   bit.PERIOD: PIT 주기 설정 (예: 0x09 = 1초)

3. RTC 설정 절차

  1. 시스템 초기화:
    •   set_system_clock()로 시스템 클럭 설정 (24MHz, XOSC32K 오토튜닝)
    •   인터럽트 비활성화 (cli())
  2. RTC 클럭 소스 선택:
    •   RTC.CLKSEL로 클럭 소스 설정 (XOSC32K 또는 OSC32K)
  3. RTC 활성화:
    •   RTC.CTRLA로 RTC 활성화 및 프리스케일러 설정
  4. 카운터/주기/비교 값 설정:
    •   RTC.CNT, RTC.PER, RTC.CMP 설정
  5. 인터럽트 설정 (필요 시):
    •   RTC.INTCTRL로 OVF 또는 CMP 인터럽트 활성화
    •   PIT 사용 시 RTC.PITCTRLA 설정
  6. RTC 실행:
    •   설정 후 즉시 동작

4. RTC 설정 고려사항

  • 클럭 안정화: XOSC32K 사용 시 안정화 대기 필수
  • 프리스케일러: 32.768kHz 클럭에 대해 1초 단위로 설정 권장 (DIV32768)
  • 인터럽트: 다중 인터럽트 사용 시 우선순위 주의
  • 저전력: RUNSTDBY 활성화로 Sleep 모드에서 RTC 동작
  • 정확성: 외부 크리스털(XOSC32K) 사용 시 더 높은 정확도

5. 실용적인 RTC 예제 코드 (Bitfield 구조)

아래는 AVR128DB48 RTC 모듈을 Bitfield 구조로 설정한 3개의 예제 코드입니다. 각 예제는 Atmel Studio 또는 MPLAB X IDE와 AVR-GCC 환경에서 실행 가능합니다.

5.1 예제 1: 기본 RTC 카운터 (1초마다 LED 토글)

// File: rtc_basic_counter.c
// Description: AVR128DB48 RTC 기본 카운터 예제 (1초마다 LED 토글)
// Compiler: AVR-GCC
// Target: AVR128DB48

#include <avr/io.h>        // AVR 입출력 관련 헤더 파일 (레지스터 정의 포함)
#include <avr/interrupt.h> // 인터럽트 처리 관련 헤더 파일

#define F_CPU 24000000UL  // 시스템 클록 주파수를 24 MHz로 정의 (타이밍 계산 정확도를 위해)

void set_system_clock(void) {
    // 외부 32.768 kHz 크리스털 오실레이터(XOSC32K) 활성화
    _PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, CLKCTRL_ENABLE_bm | CLKCTRL_RUNSTDBY_bm);
    // CLKCTRL.XOSC32KCTRLA: XOSC32K 제어 레지스터
    // CLKCTRL_ENABLE_bm: XOSC32K 활성화
    // CLKCTRL_RUNSTDBY_bm: 스탠바이 모드에서도 동작 유지
    
    // XOSC32K 안정화 대기
    while (!(CLKCTRL.MCLKSTATUS & CLKCTRL_XOSC32KS_bm)) {
        ; // XOSC32KS_bm 비트가 1이 될 때까지 대기 (안정화 확인)
    }
    
    // 내부 OSCHF를 24 MHz로 설정, XOSC32K 오토튜닝 활성화
    _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, CLKCTRL_FRQSEL_24M_gc | CLKCTRL_AUTOTUNE_bm);
    // CLKCTRL.OSCHFCTRLA: 내부 오실레이터 제어 레지스터
    // CLKCTRL_FRQSEL_24M_gc: 24 MHz 주파수 선택
    // CLKCTRL_AUTOTUNE_bm: XOSC32K 참조 오토튜닝
    
    // 시스템 클럭 소스를 OSCHF로 설정
    _PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSCHF_gc);
    // CLKCTRL.MCLKCTRLA: 시스템 클럭 소스 선택 레지스터
    // CLKCTRL_CLKSEL_OSCHF_gc: OSCHF 선택
    
    // 클럭 프리스케일러 비활성화 (24 MHz 그대로 사용)
    _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0x00);
    // CLKCTRL.MCLKCTRLB: 프리스케일러 설정 (0 = 비활성화)
}

void rtc_init(void) {
    // PB3(LED0)를 출력으로 설정
    PORTB.DIRSET = PIN3_bm; // PB3 핀을 출력으로 설정 (Curiosity Nano의 LED0)
    
    // RTC 클럭 소스로 XOSC32K 선택
    RTC.CLKSEL = RTC_CLKSEL_XOSC32K_gc; // 외부 32.768 kHz 크리스털 사용
    
    // RTC 주기 설정: 1초 주기 (32768 / DIV32768 = 1Hz)
    RTC.PER = 32767; // 주기 값 (32768 - 1)
    
    // RTC 활성화 및 프리스케일러 설정
    RTC.CTRLA = RTC_RTCEN_bm | RTC_PRESCALER_DIV32768_gc;
    // RTC_RTCEN_bm: RTC 활성화
    // RTC_PRESCALER_DIV32768_gc: 32.768kHz를 1Hz로 분주
    
    // 오버플로우 인터럽트 활성화
    RTC.INTCTRL = RTC_OVF_bm; // OVF 인터럽트 활성화
}

ISR(RTC_CNT_vect) {
    // RTC 오버플로우 인터럽트 서비스 루틴
    PORTB.OUTTGL = PIN3_bm; // PB3 LED 상태 토글 (켜짐/꺼짐)
    RTC.INTFLAGS = RTC_OVF_bm; // 오버플로우 인터럽트 플래그 클리어
}

int main(void) {
    set_system_clock(); // 시스템 클럭 초기화
    rtc_init();         // RTC 초기화
    sei();              // 글로벌 인터럽트 활성화
    
    while (1) {
        // 무한 루프: 인터럽트로 LED 제어
    }
    return 0; // 프로그램 종료 (실제로는 도달하지 않음)
}

설명:

  • 기능: RTC를 사용해 1초마다 PB3에 연결된 LED를 토글
  • 설정: PB3 출력, RTC 클럭(XOSC32K), 1초 주기 오버플로우 인터럽트
  • 출력: PB3에 LED가 1초 간격으로 점멸

5.2 예제 2: RTC 비교 인터럽트 (0.5초마다 LED 토글)

// File: rtc_compare_interrupt.c
// Description: AVR128DB48 RTC 비교 인터럽트 예제 (0.5초마다 LED 토글)
// Compiler: AVR-GCC
// Target: AVR128DB48

#include <avr/io.h>        // AVR 입출력 관련 헤더 파일 (레지스터 정의 포함)
#include <avr/interrupt.h> // 인터럽트 처리 관련 헤더 파일

#define F_CPU 24000000UL  // 시스템 클록 주파수를 24 MHz로 정의 (타이밍 계산 정확도를 위해)

void set_system_clock(void) {
    // 외부 32.768 kHz 크리스털 오실레이터(XOSC32K) 활성화
    _PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, CLKCTRL_ENABLE_bm | CLKCTRL_RUNSTDBY_bm);
    // CLKCTRL.XOSC32KCTRLA: XOSC32K 제어 레지스터
    // CLKCTRL_ENABLE_bm: XOSC32K 활성화
    // CLKCTRL_RUNSTDBY_bm: 스탠바이 모드에서도 동작 유지
    
    // XOSC32K 안정화 대기
    while (!(CLKCTRL.MCLKSTATUS & CLKCTRL_XOSC32KS_bm)) {
        ; // XOSC32KS_bm 비트가 1이 될 때까지 대기 (안정화 확인)
    }
    
    // 내부 OSCHF를 24 MHz로 설정, XOSC32K 오토튜닝 활성화
    _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, CLKCTRL_FRQSEL_24M_gc | CLKCTRL_AUTOTUNE_bm);
    // CLKCTRL.OSCHFCTRLA: 내부 오실레이터 제어 레지스터
    // CLKCTRL_FRQSEL_24M_gc: 24 MHz 주파수 선택
    // CLKCTRL_AUTOTUNE_bm: XOSC32K 참조 오토튜닝
    
    // 시스템 클럭 소스를 OSCHF로 설정
    _PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSCHF_gc);
    // CLKCTRL.MCLKCTRLA: 시스템 클럭 소스 선택 레지스터
    // CLKCTRL_CLKSEL_OSCHF_gc: OSCHF 선택
    
    // 클럭 프리스케일러 비활성화 (24 MHz 그대로 사용)
    _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0x00);
    // CLKCTRL.MCLKCTRLB: 프리스케일러 설정 (0 = 비활성화)
}

void rtc_init(void) {
    // PB3(LED0)를 출력으로 설정
    PORTB.DIRSET = PIN3_bm; // PB3 핀을 출력으로 설정 (Curiosity Nano의 LED0)
    
    // RTC 클럭 소스로 XOSC32K 선택
    RTC.CLKSEL = RTC_CLKSEL_XOSC32K_gc; // 외부 32.768 kHz 크리스털 사용
    
    // 비교 값 설정: 0.5초 (32768 / 2 - 1)
    RTC.CMP = 16383; // 0.5초 주기 설정
    
    // RTC 활성화 및 프리스케일러 설정
    RTC.CTRLA = RTC_RTCEN_bm | RTC_PRESCALER_DIV32768_gc;
    // RTC_RTCEN_bm: RTC 활성화
    // RTC_PRESCALER_DIV32768_gc: 32.768kHz를 1Hz로 분주
    
    // 비교 인터럽트 활성화
    RTC.INTCTRL = RTC_CMP_bm; // CMP 인터럽트 활성화
}

ISR(RTC_CNT_vect) {
    // RTC 비교 인터럽트 서비스 루틴
    PORTB.OUTTGL = PIN3_bm; // PB3 LED 상태 토글 (켜짐/꺼짐)
    RTC.INTFLAGS = RTC_CMP_bm; // 비교 인터럽트 플래그 클리어
}

int main(void) {
    set_system_clock(); // 시스템 클럭 초기화
    rtc_init();         // RTC 초기화
    sei();              // 글로벌 인터럽트 활성화
    
    while (1) {
        // 무한 루프: 인터럽트로 LED 제어
    }
    return 0; // 프로그램 종료 (실제로는 도달하지 않음)
}

설명:

  • 기능: RTC 비교 인터럽트를 사용해 0.5초마다 PB3에 연결된 LED를 토글
  • 설정: PB3 출력, RTC 클럭(XOSC32K), 0.5초 비교 인터럽트
  • 출력: PB3에 LED가 0.5초 간격으로 점멸

5.3 예제 3: RTC PIT (주기적 인터럽트 타이머)

// File: rtc_pit.c
// Description: AVR128DB48 RTC PIT 예제 (1초마다 LED 토글)
// Compiler: AVR-GCC
// Target: AVR128DB48

#include <avr/io.h>        // AVR 입출력 관련 헤더 파일 (레지스터 정의 포함)
#include <avr/interrupt.h> // 인터럽트 처리 관련 헤더 파일

#define F_CPU 24000000UL  // 시스템 클록 주파수를 24 MHz로 정의 (타이밍 계산 정확도를 위해)

void set_system_clock(void) {
    // 외부 32.768 kHz 크리스털 오실레이터(XOSC32K) 활성화
    _PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, CLKCTRL_ENABLE_bm | CLKCTRL_RUNSTDBY_bm);
    // CLKCTRL.XOSC32KCTRLA: XOSC32K 제어 레지스터
    // CLKCTRL_ENABLE_bm: XOSC32K 활성화
    // CLKCTRL_RUNSTDBY_bm: 스탠바이 모드에서도 동작 유지
    
    // XOSC32K 안정화 대기
    while (!(CLKCTRL.MCLKSTATUS & CLKCTRL_XOSC32KS_bm)) {
        ; // XOSC32KS_bm 비트가 1이 될 때까지 대기 (안정화 확인)
    }
    
    // 내부 OSCHF를 24 MHz로 설정, XOSC32K 오토튜닝 활성화
    _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, CLKCTRL_FRQSEL_24M_gc | CLKCTRL_AUTOTUNE_bm);
    // CLKCTRL.OSCHFCTRLA: 내부 오실레이터 제어 레지스터
    // CLKCTRL_FRQSEL_24M_gc: 24 MHz 주파수 선택
    // CLKCTRL_AUTOTUNE_bm: XOSC32K 참조 오토튜닝
    
    // 시스템 클럭 소스를 OSCHF로 설정
    _PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSCHF_gc);
    // CLKCTRL.MCLKCTRLA: 시스템 클럭 소스 선택 레지스터
    // CLKCTRL_CLKSEL_OSCHF_gc: OSCHF 선택
    
    // 클럭 프리스케일러 비활성화 (24 MHz 그대로 사용)
    _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0x00);
    // CLKCTRL.MCLKCTRLB: 프리스케일러 설정 (0 = 비활성화)
}

void rtc_pit_init(void) {
    // PB3(LED0)를 출력으로 설정
    PORTB.DIRSET = PIN3_bm; // PB3 핀을 출력으로 설정 (Curiosity Nano의 LED0)
    
    // RTC 클럭 소스로 XOSC32K 선택
    RTC.CLKSEL = RTC_CLKSEL_XOSC32K_gc; // 외부 32.768 kHz 크리스털 사용
    
    // PIT 활성화 및 1초 주기 설정
    RTC.PITCTRLA = RTC_PITEN_bm | RTC_PERIOD_CYC32768_gc;
    // RTC_PITEN_bm: PIT 활성화
    // RTC_PERIOD_CYC32768_gc: 1초 주기 (32768 사이클)
    
    // PIT 인터럽트 활성화
    RTC.PITINTCTRL = RTC_PI_bm; // PIT 인터럽트 활성화
}

ISR(RTC_PIT_vect) {
    // RTC PIT 인터럽트 서비스 루틴
    PORTB.OUTTGL = PIN3_bm; // PB3 LED 상태 토글 (켜짐/꺼짐)
    RTC.PITINTFLAGS = RTC_PI_bm; // PIT 인터럽트 플래그 클리어
}

int main(void) {
    set_system_clock(); // 시스템 클럭 초기화
    rtc_pit_init();     // RTC PIT 초기화
    sei();              // 글로벌 인터럽트 활성화
    
    while (1) {
        // 무한 루프: 인터럽트로 LED 제어
    }
    return 0; // 프로그램 종료 (실제로는 도달하지 않음)
}

설명:

  • 기능: RTC PIT를 사용해 1초마다 PB3에 연결된 LED를 토글
  • 설정: PB3 출력, RTC 클럭(XOSC32K), 1초 PIT 인터럽트
  • 출력: PB3에 LED가 1초 간격으로 점멸

6. 사용 방법

6.1 환경 설정

  • AVR-GCC 설치: Atmel Studio 또는 MPLAB X IDE에 AVR-GCC 툴체인 설치
  • 헤더 파일: <avr/io.h>, <avr/interrupt.h> 포함
  • 프로젝트 설정: AVR128DB48 타겟으로 프로젝트 생성
  • 클럭 정의: #define F_CPU 24000000UL로 시스템 클럭 설정

6.2 코드 실행

  • 각 예제를 별도의 .c 파일로 저장하거나, main.c에 복사
  • 다른 예제 코드 주석 처리
  • Atmel Studio/MPLAB X IDE에서 빌드 및 플래싱

6.3 하드웨어 준비

  • LED 출력: PB3에 LED 및 전류 제한 저항(예: 330Ω) 연결
  • 클럭 소스: 외부 32.768kHz 크리스털(XOSC32K) 연결 권장
  • 전원: 1.8V~5.5V 전원 공급

6.4 디버깅

  • Atmel Studio/MPLAB X IDE의 디버거 사용
  • RTC.CNT, RTC.INTFLAGS, RTC.PITINTFLAGS 레지스터 확인
  • 오실로스코프 또는 로직 분석기로 LED 신호 점검

7. 추가 팁

  • 클럭 안정화: XOSC32K 사용 시 CLKCTRL.MCLKSTATUS로 안정화 확인
  • 저전력: RTC.CTRLA.RUNSTDBY 활성화로 Sleep 모드에서 RTC 동작
  • Microchip 리소스: AVR128DB48 데이터시트, Application Notes (AN), AVR-GCC 예제
  • 문제 해결:
    •   RTC 동작 안 함: RTC.CTRLA.RTCEN, RTC.CLKSEL 확인
    •   인터럽트 실패: RTC.INTCTRL, RTC.PITINTCTRL, 플래그 확인
    •   부정확한 타이밍: XOSC32K 연결 및 안정화 확인
  • 커뮤니티: Microchip Community, AVR Freaks 포럼 참고

8. 결론

이 문서는 AVR128DB48 RTC 모듈의 설정 방법과 Bitfield 구조를 활용한 예제 코드를 제공하여 시간 추적 및 주기적 타이머 애플리케이션에 적용 가능하도록 구성했습니다. 초보자는 기본 카운터 예제부터 시작하고, 숙련자는 비교 인터럽트 및 PIT를 활용하여 복잡한 시스템을 구현할 수 있습니다.

키워드: AVR128DB48, RTC, Real-Time Clock, AVR, 마이크로컨트롤러, Atmel Studio, MPLAB X IDE, 인터럽트, XOSC32K, PIT, 저전력

반응형