1. AVR128DB48 UART 고급 기능 개요
Microchip의 AVR128DB48은 AVR DB 시리즈의 8비트 마이크로컨트롤러로, 최대 4개의 USART(Universal Synchronous and Asynchronous serial Receiver and Transmitter) 모듈을 포함하여 다양한 직렬 통신 기능을 제공합니다. 이 문서는 LIN, IrDA, RS485, 멀티프로세서 통신 모드(MPCM), 스타트 프레임 감지, 동기 모드의 설정 방법과 실제 디바이스(예: LED, 버튼, 외부 모듈)를 사용한 예제 코드를 제공합니다. 예제는 AVR128DB48 Curiosity Nano 평가 키트(EV35L43A)를 기반으로 하며, 상세 주석을 통해 초보자와 숙련된 개발자 모두 쉽게 활용할 수 있도록 돕습니다.
주요 사양
- 수량: 최대 4개의 USART 모듈 (USART0, USART1, USART2, USART3)
- 고급 기능:
- LIN: 자동 Break 및 동기 필드 감지, 자동 체크섬
- IrDA: 적외선 통신, 최대 115.2 kbps
- RS485: 외부 트랜시버 제어 지원
- MPCM: 주소 기반 멀티프로세서 통신
- 스타트 프레임 감지: 저전력 모드에서 수신 시작 감지
- 동기 모드: 외부 클럭(XCK) 기반 통신
- 레지스터:
- USARTn.CTRLA: 인터럽트, MPCM, 스타트 프레임 감지 설정
- USARTn.CTRLB: 송수신 활성화, 동기 모드 설정
- USARTn.CTRLC: 프레임 형식, 동기/비동기 모드
- USARTn.BAUD: 보드레이트 설정
- USARTn.CTRLD: LIN 및 Break 설정
- 핀 (Curiosity Nano 기준):
- PB2: TXD (USART0)
- PB3: RXD (USART0)
- PB1: XCK (동기 모드)
- PB4: RS485 DE (드라이버 활성화)
- 전력 관리: 스타트 프레임 감지로 저전력 모드 지원
- 전압 범위: 1.8V~5.5V
2. UART 고급 기능 Bitfield 설정 상세
AVR128DB48의 UART 레지스터는 Bitfield 구조로 정의되어 있으며, <avr/io.h> 헤더 파일을 통해 접근합니다. 주요 레지스터는 다음과 같습니다:
2.1 USARTn.CTRLA
- RXSIE: 스타트 프레임 감지 인터럽트 활성화
- MPCM: 멀티프로세서 통신 모드 활성화
- LBME: LIN Break 감지 활성화
- RS485: RS485 모드 활성화
2.2 USARTn.CTRLB
- TXEN: 송신 활성화
- RXEN: 수신 활성화
- SFDEN: 스타트 프레임 감지 활성화
- RXMODE: 동기/비동기 모드 설정
2.3 USARTn.CTRLC
- CMODE: 통신 모드 (비동기: 0x00, 동기: 0x40, IrDA: 0xC0)
- CHSIZE: 데이터 비트 (5~9비트)
- SBIT: 정지 비트 (1 또는 2비트)
- PARITY: 패리티 설정 (없음, 짝수, 홀수)
2.4 USARTn.BAUD
- 16비트 보드레이트 설정
- 공식: Baud Rate = (f_PER / (N × (BAUD + 1)))
2.5 USARTn.CTRLD
- ABW: LIN 자동 보드레이트 폭 설정
- FSD: 프레임 시작 감지 설정
3. UART 고급 기능 설정 절차
- 시스템 초기화:
- set_system_clock()로 24MHz 클럭 설정
- 인터럽트 비활성화 (cli())
- 포트 설정:
- PB2(TXD), PB3(RXD), PB1(XCK), PB4(DE) 설정
- UART 설정:
- USARTn.BAUD로 보드레이트 설정
- USARTn.CTRLC로 프레임 형식 및 모드 설정
- USARTn.CTRLA로 고급 기능 설정
- USARTn.CTRLB로 송수신 활성화
- 인터럽트 설정 (필요 시):
- RXCIE, TXCIE, RXSIE 활성화
- 실행:
- 설정 후 즉시 동작
4. UART 고급 기능 설정 고려사항
- LIN: 정확한 클럭 소스와 Break 감지 타이밍 확인
- IrDA: 외부 IrDA 모듈(예: TFDU4101) 연결 및 보드레이트 제한
- RS485: 트랜시버(예: MAX485)와 DE 핀 연결
- MPCM: 9비트 프레임 및 주소 설정 주의
- 스타트 프레임 감지: 저전력 모드에서 전력 소모 최소화
- 동기 모드: XCK 핀 클럭 안정화
- 에라타: TWI와 UART 핀 충돌 가능성 확인
- 하드웨어: Curiosity Nano의 PB0(SW0), PB3(LED0) 활용
5. 실용적인 UART 고급 기능 예제 코드
아래는 AVR128DB48 Curiosity Nano 평가 키트와 실제 디바이스를 사용한 4개의 예제 코드입니다. 각 예제는 LED(PB3), 버튼(PB0), 외부 모듈(LIN 노드, IrDA 모듈, RS485 트랜시버)을 활용하며, 상세 주석을 포함합니다.
5.1 예제 1: LIN 통신 (Curiosity Nano + LIN 노드, LED 출력)
// File: uart_lin_device.c
// Description: AVR128DB48 USART0로 LIN 통신, Curiosity Nano PB3 LED로 데이터 수신 표시
// Hardware: AVR128DB48 Curiosity Nano (PB2 TXD, PB3 RXD, PB3 LED0), LIN 노드
// Compiler: AVR-GCC
// Target: AVR128DB48
#include <avr/io.h> // AVR 입출력 관련 헤더 파일
#include <avr/interrupt.h> // 인터럽트 처리 관련 헤더 파일
#define F_CPU 24000000UL // 시스템 클럭 주파수 정의 (24 MHz)
volatile uint8_t lin_data = 0; // 수신된 LIN 데이터 저장
void set_system_clock(void) {
// 시스템 클럭을 24 MHz로 설정, XOSC32K 오토튜닝 활성화
_PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, CLKCTRL_ENABLE_bm | CLKCTRL_RUNSTDBY_bm);
// CLKCTRL.XOSC32KCTRLA: 외부 32.768 kHz 크리스털 설정
// CLKCTRL_ENABLE_bm: XOSC32K 활성화
// CLKCTRL_RUNSTDBY_bm: 슬립 모드에서 동작 유지
while (!(CLKCTRL.MCLKSTATUS & CLKCTRL_XOSC32KS_bm)) { ; }
// XOSC32K 안정화 대기
_PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, CLKCTRL_FRQSEL_24M_gc | CLKCTRL_AUTOTUNE_bm);
// OSCHFCTRLA: 내부 오실레이터 24 MHz 설정, 오토튜닝 활성화
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSCHF_gc);
// MCLKCTRLA: 시스템 클럭 소스로 OSCHF 선택
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0x00);
// MCLKCTRLB: 프리스케일러 비활성화
}
void lin_init(void) {
// USART0 설정: LIN 모드, 19200 baud, PB2 TXD, PB3 RXD
PORTB.DIRSET = PIN2_bm | PIN3_bm; // PB2(TXD) 출력, PB3(LED0) 출력
PORTB.DIRCLR = PIN3_bm; // PB3(RXD) 입력 (Curiosity Nano의 PB3는 LED와 공유, UART RXD로 사용 시 주의)
PORTMUX.CTRLB = PORTMUX_USART0_ALT1_gc; // 대체 핀(PB2 TXD, PB3 RXD) 선택
USART0.BAUD = (uint16_t)((float)(F_CPU * 64 / (16 * 19200)) + 0.5);
// USART0.BAUD: LIN 표준 19200 baud 설정
// 공식: Baud Rate = (f_PER / (N × (BAUD + 1)))
USART0.CTRLC = USART_CMODE_ASYNCHRONOUS_gc | USART_CHSIZE_8BIT_gc;
// USART0.CTRLC: 비동기 모드, 8비트 데이터, 패리티 없음, 1 정지 비트
USART0.CTRLD = USART_ABW_4CYCLES_gc;
// USART0.CTRLD: 자동 보드레이트 폭 4 사이클 (LIN 동기화 최적화)
USART0.CTRLA = USART_LBME_bm | USART_RXCIE_bm;
// USART0.CTRLA: LIN Break 감지 활성화, 수신 완료 인터럽트 활성화
USART0.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
// USART0.CTRLB: 수신 및 송신 활성화
}
ISR(USART0_RXC_vect) {
// USART0 수신 완료 인터럽트 서비스 루틴
if (USART0.STATUS & USART_BDF_bm) {
// Break 필드 감지됨
USART0.STATUS = USART_BDF_bm; // Break 플래그 클리어
PORTB.OUTCLR = PIN3_bm; // PB3 LED 끔 (Break 감지 표시)
} else {
lin_data = USART0.RXDATAL; // 수신된 LIN 데이터 저장
PORTB.OUTSET = PIN3_bm; // PB3 LED 켬 (데이터 수신 표시)
}
}
int main(void) {
set_system_clock(); // 시스템 클럭 설정
lin_init(); // LIN 초기화
sei(); // 글로벌 인터럽트 활성화
while (1) {
// 무한 루프: LIN 데이터 수신 시 PB3 LED로 표시
}
return 0; // 프로그램 종료 (도달하지 않음)
}
하드웨어 요구사항:
- 보드: AVR128DB48 Curiosity Nano (EV35L43A)
- 연결: PB2(TXD), PB3(RXD)를 LIN 노드(예: LIN 트랜시버 MCP2003)와 연결
- 출력: PB3(LED0)로 데이터 수신 시 점등, Break 감지 시 소등
- 설명: LIN 노드로부터 데이터 수신 시 Curiosity Nano의 PB3 LED가 켜지고, Break 필드 감지 시 꺼짐
5.2 예제 2: IrDA 통신 (Curiosity Nano + IrDA 모듈, 버튼 입력)
// File: uart_irda_device.c
// Description: AVR128DB48 USART0로 IrDA 통신, PB0 버튼으로 데이터 송신, PB3 LED로 상태 표시
// Hardware: AVR128DB48 Curiosity Nano (PB2 TXD, PB3 RXD, PB0 SW0, PB3 LED0), IrDA 모듈 (TFDU4101)
// Compiler: AVR-GCC
// Target: AVR128DB48
#include <avr/io.h> // AVR 입출력 관련 헤더 파일
#include <util/delay.h> // 지연 함수 관련 헤더 파일
#define F_CPU 24000000UL // 시스템 클럭 주파수 정의 (24 MHz)
void set_system_clock(void) {
// 시스템 클럭 설정 (24 MHz, XOSC32K 오토튜닝)
_PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, CLKCTRL_ENABLE_bm | CLKCTRL_RUNSTDBY_bm);
// CLKCTRL.XOSC32KCTRLA: 외부 크리스털 설정
while (!(CLKCTRL.MCLKSTATUS & CLKCTRL_XOSC32KS_bm)) { ; }
_PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, CLKCTRL_FRQSEL_24M_gc | CLKCTRL_AUTOTUNE_bm);
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSCHF_gc);
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0x00);
}
void irda_init(void) {
// USART0 설정: IrDA 모드, 115200 baud, PB2 TXD, PB3 RXD
PORTB.DIRSET = PIN2_bm | PIN3_bm; // PB2(TXD), PB3(LED0) 출력 설정
PORTB.DIRCLR = PIN0_bm; // PB0(SW0) 입력 설정
PORTB.PIN0CTRL |= PORT_PULLUPEN_bm; // PB0 풀업 저항 활성화
PORTMUX.CTRLB = PORTMUX_USART0_ALT1_gc; // 대체 핀(PB2 TXD, PB3 RXD) 선택
USART0.BAUD = (uint16_t)((float)(F_CPU * 64 / (16 * 115200)) + 0.5);
// USART0.BAUD: IrDA 표준 115200 baud 설정
USART0.CTRLC = USART_CMODE_IRDA_gc | USART_CHSIZE_8BIT_gc;
// USART0.CTRLC: IrDA 모드, 8비트 데이터, 패리티 없음, 1 정지 비트
USART0.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
// USART0.CTRLB: 수신 및 송신 활성화
}
void irda_send(uint8_t data) {
// IrDA 데이터 송신 함수
while (!(USART0.STATUS & USART_DREIF_bm)) { ; }
// USART0.STATUS: 데이터 레지스터 비움 플래그 대기
USART0.TXDATAL = data; // 데이터 송신
PORTB.OUTSET = PIN3_bm; // PB3 LED 켬 (송신 표시)
_delay_ms(50); // LED 점등 시간
PORTB.OUTCLR = PIN3_bm; // PB3 LED 끔
}
int main(void) {
set_system_clock(); // 시스템 클럭 설정
irda_init(); // IrDA 초기화
while (1) {
if (!(PORTB.IN & PIN0_bm)) { // PB0 버튼 누름 (Low)
irda_send('A'); // IrDA로 'A' 송신
_delay_ms(200); // 디바운싱 대기
}
}
return 0; // 프로그램 종료 (도달하지 않음)
}
하드웨어 요구사항:
- 보드: AVR128DB48 Curiosity Nano (EV35L43A)
- 연결: PB2(TXD), PB3(RXD)를 IrDA 모듈(예: TFDU4101)과 연결
- 입력: PB0(SW0) 버튼
- 출력: PB3(LED0)로 송신 시 점등
- 설명: PB0 버튼 누름 시 IrDA로 'A' 송신, 송신마다 PB3 LED 깜빡임
5.3 예제 3: RS485 통신 (Curiosity Nano + RS485 트랜시버, 버튼 입력)
// File: uart_rs485_device.c
// Description: AVR128DB48 USART0로 RS485 통신, PB0 버튼으로 데이터 송신, PB3 LED로 상태 표시
// Hardware: AVR128DB48 Curiosity Nano (PB2 TXD, PB3 RXD, PB4 DE, PB0 SW0, PB3 LED0), RS485 트랜시버 (MAX485)
// Compiler: AVR-GCC
// Target: AVR128DB48
#include <avr/io.h> // AVR 입출력 관련 헤더 파일
#include <util/delay.h> // 지연 함수 관련 헤더 파일
#define F_CPU 24000000UL // 시스템 클럭 주파수 정의 (24 MHz)
void set_system_clock(void) {
// 시스템 클럭 설정 (24 MHz, XOSC32K 오토튜닝)
_PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, CLKCTRL_ENABLE_bm | CLKCTRL_RUNSTDBY_bm);
while (!(CLKCTRL.MCLKSTATUS & CLKCTRL_XOSC32KS_bm)) { ; }
_PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, CLKCTRL_FRQSEL_24M_gc | CLKCTRL_AUTOTUNE_bm);
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSCHF_gc);
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0x00);
}
void rs485_init(void) {
// USART0 설정: RS485 모드, 9600 baud, PB2 TXD, PB3 RXD, PB4 DE
PORTB.DIRSET = PIN2_bm | PIN4_bm | PIN3_bm; // PB2(TXD), PB4(DE), PB3(LED0) 출력
PORTB.DIRCLR = PIN0_bm | PIN3_bm; // PB0(SW0) 입력, PB3(RXD) 입력
PORTB.PIN0CTRL |= PORT_PULLUPEN_bm; // PB0 풀업 저항 활성화
PORTMUX.CTRLB = PORTMUX_USART0_ALT1_gc; // 대체 핀(PB2 TXD, PB3 RXD) 선택
USART0.BAUD = (uint16_t)((float)(F_CPU * 64 / (16 * 9600)) + 0.5);
// USART0.BAUD: RS485 표준 9600 baud 설정
USART0.CTRLC = USART_CMODE_ASYNCHRONOUS_gc | USART_CHSIZE_8BIT_gc;
// USART0.CTRLC: 비동기 모드, 8비트 데이터, 패리티 없음, 1 정지 비트
USART0.CTRLA = USART_RS485_bm;
// USART0.CTRLA: RS485 모드 활성화
USART0.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
// USART0.CTRLB: 수신 및 송신 활성화
}
void rs485_send(uint8_t data) {
// RS485 데이터 송신 함수
PORTB.OUTSET = PIN4_bm; // PB4(DE) High: 송신 모드
while (!(USART0.STATUS & USART_DREIF_bm)) { ; }
// 데이터 레지스터 비움 대기
USART0.TXDATAL = data; // 데이터 송신
while (!(USART0.STATUS & USART_TXCIF_bm)) { ; }
// 송신 완료 대기
PORTB.OUTCLR = PIN4_bm; // PB4(DE) Low: 수신 모드
PORTB.OUTSET = PIN3_bm; // PB3 LED 켬 (송신 표시)
_delay_ms(50); // LED 점등 시간
PORTB.OUTCLR = PIN3_bm; // PB3 LED 끔
}
int main(void) {
set_system_clock(); // 시스템 클럭 설정
rs485_init(); // RS485 초기화
while (1) {
if (!(PORTB.IN & PIN0_bm)) { // PB0 버튼 누름 (Low)
rs485_send('B'); // RS485로 'B' 송신
_delay_ms(200); // 디바운싱 대기
}
}
return 0; // 프로그램 종료 (도달하지 않음)
}
하드웨어 요구사항:
- 보드: AVR128DB48 Curiosity Nano (EV35L43A)
- 연결: PB2(TXD), PB3(RXD), PB4(DE)를 RS485 트랜시버(예: MAX485)와 연결
- 입력: PB0(SW0) 버튼
- 출력: PB3(LED0)로 송신 시 점등
- 설명: PB0 버튼 누름 시 RS485로 'B' 송신, 송신마다 PB3 LED 깜빡임
5.4 예제 4: MPCM 및 스타트 프레임 감지 (Curiosity Nano + 버튼 및 LED)
// File: uart_mpcm_start_frame_device.c
// Description: AVR128DB48 USART0로 MPCM 및 스타트 프레임 감지, PB0 버튼으로 주소 송신, PB3 LED로 데이터 수신 표시
// Hardware: AVR128DB48 Curiosity Nano (PB2 TXD, PB3 RXD, PB0 SW0, PB3 LED0)
// Compiler: AVR-GCC
// Target: AVR128DB48
#include <avr/io.h> // AVR 입출력 관련 헤더 파일
#include <avr/interrupt.h> // 인터럽트 처리 관련 헤더 파일
#define F_CPU 24000000UL // 시스템 클럭 주파수 정의 (24 MHz)
#define MY_ADDRESS 0x01 // MPCM 주소 설정
volatile uint8_t received_data = 0; // 수신 데이터 저장
void set_system_clock(void) {
// 시스템 클럭 설정 (24 MHz, XOSC32K 오토튜닝)
_PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, CLKCTRL_ENABLE_bm | CLKCTRL_RUNSTDBY_bm);
while (!(CLKCTRL.MCLKSTATUS & CLKCTRL_XOSC32KS_bm)) { ; }
_PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, CLKCTRL_FRQSEL_24M_gc | CLKCTRL_AUTOTUNE_bm);
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSCHF_gc);
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0x00);
}
void mpcm_init(void) {
// USART0 설정: MPCM 및 스타트 프레임 감지, 9600 baud, PB2 TXD, PB3 RXD
PORTB.DIRSET = PIN2_bm | PIN3_bm; // PB2(TXD), PB3(LED0) 출력 설정
PORTB.DIRCLR = PIN0_bm | PIN3_bm; // PB0(SW0), PB3(RXD) 입력 설정
PORTB.PIN0CTRL |= PORT_PULLUPEN_bm; // PB0 풀업 저항 활성화
PORTMUX.CTRLB = PORTMUX_USART0_ALT1_gc; // 대체 핀(PB2 TXD, PB3 RXD) 선택
USART0.BAUD = (uint16_t)((float)(F_CPU * 64 / (16 * 9600)) + 0.5);
// USART0.BAUD: 9600 baud 설정
USART0.CTRLC = USART_CMODE_ASYNCHRONOUS_gc | USART_CHSIZE_9BIT_gc;
// USART0.CTRLC: 비동기 모드, 9비트 데이터 (MPCM 주소/데이터 구분)
USART0.CTRLA = USART_MPCM_bm | USART_RXSIE_bm | USART_RXCIE_bm;
// USART0.CTRLA: MPCM 활성화, 스타트 프레임 감지 및 수신 완료 인터럽트
USART0.CTRLB = USART_RXEN_bm | USART_SFDEN_bm | USART_TXEN_bm;
// USART0.CTRLB: 수신, 송신, 스타트 프레임 감지 활성화
}
void mpcm_send_address(uint8_t address) {
// MPCM 주소 송신 함수
while (!(USART0.STATUS & USART_DREIF_bm)) { ; }
// 데이터 레지스터 비움 대기
USART0.TXDATAH = (1 << 0); // 9번째 비트 1: 주소 프레임
USART0.TXDATAL = address; // 주소 송신
}
ISR(USART0_RXS_vect) {
// 스타트 프레임 감지 인터럽트 서비스 루틴
PORTB.OUTSET = PIN3_bm; // PB3 LED 켬 (스타트 프레임 감지 표시)
_delay_ms(50); // LED 점등 시간
PORTB.OUTCLR = PIN3_bm; // PB3 LED 끔
USART0.STATUS = USART_RXSIF_bm; // 스타트 프레임 플래그 클리어
}
ISR(USART0_RXC_vect) {
// 수신 완료 인터럽트 서비스 루틴
if (USART0.RXDATAH & (1 << 0)) {
// 9번째 비트가 1: 주소 프레임
uint8_t address = USART0.RXDATAL;
if (address == MY_ADDRESS) {
USART0.CTRLB |= USART_RXEN_bm; // 주소 일치 시 수신 활성화
} else {
USART0.CTRLB &= ~USART_RXEN_bm; // 주소 불일치 시 수신 비활성화
}
} else {
// 9번째 비트가 0: 데이터 프레임
received_data = USART0.RXDATAL; // 데이터 저장
PORTB.OUTSET = PIN3_bm; // PB3 LED 켬 (데이터 수신 표시)
_delay_ms(100); // LED 점등 시간
PORTB.OUTCLR = PIN3_bm; // PB3 LED 끔
}
}
int main(void) {
set_system_clock(); // 시스템 클럭 설정
mpcm_init(); // MPCM 및 스타트 프레임 감지 초기화
sei(); // 글로벌 인터럽트 활성화
while (1) {
if (!(PORTB.IN & PIN0_bm)) { // PB0 버튼 누름 (Low)
mpcm_send_address(MY_ADDRESS); // MPCM 주소 송신
_delay_ms(200); // 디바운싱 대기
}
}
return 0; // 프로그램 종료 (도달하지 않음)
}
하드웨어 요구사항:
- 보드: AVR128DB48 Curiosity Nano (EV35L43A)
- 연결: PB2(TXD), PB3(RXD)를 다른 AVR128DB48 또는 UART 장치와 연결
- 입력: PB0(SW0) 버튼
- 출력: PB3(LED0)로 스타트 프레임 또는 데이터 수신 시 점등
- 설명: PB0 버튼 누름 시 MPCM 주소 송신, 데이터 수신 또는 스타트 프레임 감지 시 PB3 LED 깜빡임
5.5 예제 5: 동기 모드 (Curiosity Nano + 외부 장치, LED 출력)
// File: uart_sync_mode_device.c
// Description: AVR128DB48 USART0로 동기 모드 통신, PB3 LED로 송신 표시
// Hardware: AVR128DB48 Curiosity Nano (PB2 TXD, PB3 RXD, PB1 XCK, PB3 LED0), 외부 동기 장치
// Compiler: AVR-GCC
// Target: AVR128DB48
#include <avr/io.h> // AVR 입출력 관련 헤더 파일
#include <util/delay.h> // 지연 함수 관련 헤더 파일
#define F_CPU 24000000UL // 시스템 클럭 주파수 정의 (24 MHz)
void set_system_clock(void) {
// 시스템 클럭 설정 (24 MHz, XOSC32K 오토튜닝)
_PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, CLKCTRL_ENABLE_bm | CLKCTRL_RUNSTDBY_bm);
while (!(CLKCTRL.MCLKSTATUS & CLKCTRL_XOSC32KS_bm)) { ; }
_PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, CLKCTRL_FRQSEL_24M_gc | CLKCTRL_AUTOTUNE_bm);
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSCHF_gc);
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0x00);
}
void sync_init(void) {
// USART0 설정: 동기 모드, 9600 baud, PB2 TXD, PB3 RXD, PB1 XCK
PORTB.DIRSET = PIN2_bm | PIN1_bm | PIN3_bm; // PB2(TXD), PB1(XCK), PB3(LED0) 출력
PORTB.DIRCLR = PIN3_bm; // PB3(RXD) 입력
PORTMUX.CTRLB = PORTMUX_USART0_ALT1_gc; // 대체 핀(PB2 TXD, PB3 RXD, PB1 XCK) 선택
USART0.BAUD = (uint16_t)((float)(F_CPU * 64 / (16 * 9600)) + 0.5);
// USART0.BAUD: 9600 baud 설정
USART0.CTRLC = USART_CMODE_SYNCHRONOUS_gc | USART_CHSIZE_8BIT_gc;
// USART0.CTRLC: 동기 모드, 8비트 데이터, 패리티 없음, 1 정지 비트
USART0.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
// USART0.CTRLB: 수신 및 송신 활성화
}
void sync_send(uint8_t data) {
// 동기 모드 데이터 송신 함수
while (!(USART0.STATUS & USART_DREIF_bm)) { ; }
// 데이터 레지스터 비움 대기
USART0.TXDATAL = data; // 데이터 송신
PORTB.OUTSET = PIN3_bm; // PB3 LED 켬 (송신 표시)
_delay_ms(50); // LED 점등 시간
PORTB.OUTCLR = PIN3_bm; // PB3 LED 끔
}
int main(void) {
set_system_clock(); // 시스템 클럭 설정
sync_init(); // 동기 모드 초기화
while (1) {
sync_send('C'); // 동기 모드로 'C' 송신
_delay_ms(1000); // 1초 대기
}
return 0; // 프로그램 종료 (도달하지 않음)
}
하드웨어 요구사항:
- 보드: AVR128DB48 Curiosity Nano (EV35L43A)
- 연결: PB2(TXD), PB3(RXD), PB1(XCK)를 동기 통신 지원 장치(예: 다른 MCU)와 연결
- 출력: PB3(LED0)로 송신 시 점등
- 설명: 동기 모드로 'C' 송신 시 PB3 LED 깜빡임
6. 사용 방법
6.1 환경 설정
- AVR-GCC 설치: Atmel Studio 또는 MPLAB X IDE에 AVR-GCC 툴체인 설치
- 헤더 파일: <avr/io.h>, <avr/interrupt.h>, <util/delay.h> 포함
- 프로젝트 설정: AVR128DB48 타겟으로 프로젝트 생성
- 클럭 정의: #define F_CPU 24000000UL
6.2 코드 실행
- 각 예제를 별도의 .c 파일로 저장하거나 main.c에 복사
- 다른 예제 코드 주석 처리
- Atmel Studio/MPLAB X IDE에서 빌드 및 플래싱
6.3 하드웨어 준비
- 보드: AVR128DB48 Curiosity Nano (EV35L43A)
- 연결:
- LIN: PB2(TXD), PB3(RXD) to LIN 노드 (예: MCP2003)
- IrDA: PB2(TXD), PB3(RXD) to IrDA 모듈 (예: TFDU4101)
- RS485: PB2(TXD), PB3(RXD), PB4(DE) to RS485 트랜시버 (예: MAX485)
- 동기 모드: PB2(TXD), PB3(RXD), PB1(XCK) to 동기 장치
- 입출력: PB0(SW0) 버튼, PB3(LED0)로 상태 표시
- 전원: 5V USB (Curiosity Nano 내장), VREF 안정화 확인
- 테스트: USB-to-UART 브릿지, 오실로스코프, 로직 분석기
6.4 디버깅
- Atmel Studio/MPLAB X IDE 디버거 사용
- USARTn.STATUS, USARTn.CTRLA 레지스터 확인
- 오실로스코프로 TXD, RXD, XCK, DE 신호 점검
- LED 점등 확인
7. 추가 팁
- 클럭 설정: set_system_clock()로 XOSC32K 안정화 및 24MHz 설정 확인
- 노이즈 감소: RXD 핀에 풀업 저항 또는 필터 추가
- Microchip 리소스: AVR128DB48 데이터시트, Application Notes, AVR-GCC 예제
- 문제 해결:
- 통신 실패: 보드레이트, 프레임 형식, 핀 설정 확인
- 인터럽트 실패: USARTn.CTRLA, USARTn.STATUS 확인
- RS485 방향 제어: DE 핀 타이밍 확인
- 커뮤니티: Microchip Community, AVR Freaks 포럼 참고
- 에라타: TWI와 UART 핀 충돌 가능성 확인
8. 결론
이 문서는 AVR128DB48의 UART 고급 기능(LIN, IrDA, RS485, MPCM, 스타트 프레임 감지, 동기 모드)을 Curiosity Nano 평가 키트와 실제 디바이스를 활용한 예제 코드로 제공하여 실용적인 통신 애플리케이션에 적용 가능하도록 구성했습니다. 초보자는 LED 및 버튼 기반 예제부터 시작하고, 숙련자는 외부 모듈을 활용한 복잡한 시스템을 구현할 수 있습니다.
키워드: AVR128DB48, UART, LIN, IrDA, RS485, MPCM, 스타트 프레임 감지, 동기 모드, Curiosity Nano, AVR, 마이크로컨트롤러, Atmel Studio, MPLAB X IDE
'MCU > AVR' 카테고리의 다른 글
[AVR128DB48] OPAMP 및 아날로그 비교기 사용 방법 및 예제 코드 (0) | 2025.08.20 |
---|---|
[AVR128DB48] PWM 사용 방법 및 예제 코드 (0) | 2025.08.20 |
[AVR128DB48] 이벤트 시스템 사용 방법 및 예제 코드 (0) | 2025.08.20 |
[AVR128DB48] ADC 및 DAC 사용 방법 및 예제 코드 (0) | 2025.08.20 |
[AVR128DB48] Watchdog 사용 방법 및 예제 코드 (0) | 2025.08.19 |
[AVR128DB48] SPI 사용 방법 및 예제 코드 (0) | 2025.08.19 |
[AVR128DB48] I2C 사용 방법 및 예제 코드 (0) | 2025.08.19 |
[AVR128DB48] UART 사용 방법 및 예제 코드 (1) | 2025.08.19 |