본문 바로가기
카테고리 없음

[AD2S1210] Resolver-to-Digital Converter with TMS320F28388D Parallel Interface

by linuxgo 2025. 8. 14.
반응형

1. 소개 (Introduction)

이 문서는 AD2S1210 리졸버-디지털 변환기와 TMS320F28388D 마이크로컨트롤러를 병렬 인터페이스(EMIF)로 통합하는 방법을 설명합니다 (This document explains how to integrate the AD2S1210 Resolver-to-Digital Converter with the TMS320F28388D microcontroller using the parallel interface via EMIF). AD2S1210은 고정밀 위치 및 속도 측정을 제공하며, TMS320F28388D는 EMIF를 통해 고속 병렬 통신을 지원합니다 (The AD2S1210 provides high-precision position and velocity measurements, and the TMS320F28388D supports high-speed parallel communication via EMIF). 

주요 특징 (Key Features)

  • AD2S1210: 해상도 10/12/14/16비트, 최대 추적 속도 3125 rps (10비트, CLKIN=10.24 MHz) (AD2S1210: Resolution 10/12/14/16-bit, max tracking rate 3125 rps at 10-bit, CLKIN=10.24 MHz).
  • TMS320F28388D: 듀얼 C28x CPU(200 MHz), EMIF(16/32비트), 1.5MB 플래시 (TMS320F28388D: Dual C28x CPU at 200 MHz, EMIF 16/32-bit, 1.5MB flash).
  • 인터페이스: 병렬(EMIF), SPI, A-quad-B 출력 (Interfaces: Parallel via EMIF, SPI, A-quad-B output).
  • 오류 감지: LOS, DOS, LOT, 클리핑 (Error detection: LOS, DOS, LOT, clipping).
  • 전원: AD2S1210 AVDD/DVDD=5V, VDRIVE=3.3V; TMS320F28388D 1.2V 코어, 3.3V I/O (Power: AD2S1210 AVDD/DVDD=5V, VDRIVE=3.3V; TMS320F28388D 1.2V core, 3.3V I/O).

2. AD2S1210 핀 기능 (Pin Functions)

AD2S1210은 48-LQFP 패키지로 제공되며, 병렬 인터페이스 핀(DB0~DB15, A0, A1, RD, WR/FSYNC)을 사용합니다 (The AD2S1210 is available in a 48-LQFP package, using parallel interface pins DB0~DB15, A0, A1, RD, WR/FSYNC). 아래 표는 핀 역할과 사양을 설명합니다 (The table below describes pin roles and specifications).

핀 번호 (Pin Number) 핀 이름 (Pin Name) 기능 (Function) 전기적 사양 (Electrical Specs) 연결 주의사항 (Connection Notes)
1, 12, 13, 24, 25, 36 AVDD 아날로그 전원 (Analog power) 4.75V~5.25V, 35 mA 0.1 µF, 10 µF 디커플링 (Decouple with 0.1 µF, 10 µF)
2 SIN 사인 입력 (Sine input, differential) 3.15 V p-p ±27% 차폐 케이블, SINLO와 쌍 (Shielded cable, pair with SINLO)
3 SINLO 사인 입력 접지 (Sine input ground) - AGND와 분리 (Separate from AGND)
4 COS 코사인 입력 (Cosine input, differential) 3.15 V p-p ±27% 차폐 케이블, COSLO와 쌍 (Shielded cable, pair with COSLO)
5 COSLO 코사인 입력 접지 (Cosine input ground) - AGND와 분리 (Separate from AGND)
8 EXC 여기 출력 (Excitation output) 3.6 V p-p, 28 mA max 리졸버 코일 연결 (Connect to resolver coil)
9 EXC 여기 출력 보수 (Excitation output, complement) 3.6 V p-p, 180° phase 리졸버 코일 연결 (Connect to resolver coil)
14 CLKIN 외부 클럭 입력 (External clock input) 6.144 MHz ~ 10.24 MHz 8.192 MHz 권장 (8.192 MHz recommended)
26 RESET 리셋 입력 (Reset input, active low) Min 20 µs pulse TMS320F28388D GPIO 연결 (Connect to TMS320F28388D GPIO)
27 SAMPLE 샘플 트리거 (Sample trigger, active low) Min 20 ns pulse TMS320F28388D GPIO 연결 (Connect to TMS320F28388D GPIO)
28 LOT 추적 손실 출력 (Loss of tracking output) Open-drain, VDRIVE pull-up TMS320F28388D GPIO, 풀업 저항 (TMS320F28388D GPIO with pull-up)
29 DOS 신호 열화 출력 (Degradation of signal output) Open-drain, VDRIVE pull-up TMS320F28388D GPIO, 풀업 저항 (TMS320F28388D GPIO with pull-up)
30 LOS 신호 손실 출력 (Loss of signal output) Open-drain, VDRIVE pull-up TMS320F28388D GPIO, 풀업 저항 (TMS320F28388D GPIO with pull-up)
31~34, 37~42 DB0~DB9 병렬 데이터 출력 (Parallel data output) VDRIVE level (3.3V) TMS320F28388D EMIF 데이터 핀 연결 (Connect to TMS320F28388D EMIF data pins)
35, 43~48 DB10~DB15 병렬 데이터 출력 (Parallel data output) VDRIVE level (3.3V) TMS320F28388D EMIF 데이터 핀 연결 (Connect to TMS320F28388D EMIF data pins)
15 A0 주소 선택 0 (Address select 0) VDRIVE level TMS320F28388D EMIF 주소 핀 (Connect to TMS320F28388D EMIF address pin)
16 A1 주소 선택 1 (Address select 1) VDRIVE level TMS320F28388D EMIF 주소 핀 (Connect to TMS320F28388D EMIF address pin)
17 RD 읽기 제어 (Read control, active low) Min 20 ns pulse TMS320F28388D EMIF OE 핀 (Connect to TMS320F28388D EMIF OE pin)
18 WR/FSYNC 쓰기/프레임 동기 (Write/Frame sync, active low) Min 20 ns pulse TMS320F28388D EMIF WE 핀 (Connect to TMS320F28388D EMIF WE pin)

병렬 인터페이스는 TMS320F28388D의 EMIF에 연결되며, VDRIVE는 3.3V로 설정됩니다 (The parallel interface connects to the TMS320F28388D’s EMIF, with VDRIVE set to 3.3V).

3. 인터페이스 방식 (Interface Methods)

AD2S1210은 병렬, SPI, A-quad-B 인터페이스를 지원하며, 이 문서는 병렬 인터페이스(EMIF)에 중점을 둡니다 (The AD2S1210 supports parallel, SPI, and A-quad-B interfaces, with this document focusing on the parallel interface via EMIF).

3.1 병렬 인터페이스 (Parallel Interface)

병렬 인터페이스는 16비트 데이터를 고속으로 전송하며, TMS320F28388D의 EMIF를 활용합니다 (The parallel interface transfers 16-bit data at high speed, utilizing the TMS320F28388D’s EMIF).

  • 핀: DB0~DB15, A0, A1, RD, WR/FSYNC (Pins: DB0~DB15, A0, A1, RD, WR/FSYNC).
  • 동작: A0/A1로 레지스터 선택, RD/WR로 읽기/쓰기 (Operation: Select register with A0/A1, read/write with RD/WR).
  • 타이밍: 펄스 폭 ≥ 20 ns, EMIF 클럭 최대 100 MHz (Timing: Pulse width ≥ 20 ns, EMIF clock up to 100 MHz).
  • EMIF: 16비트 비동기 모드, 주소/데이터 멀티플렉싱 지원 (EMIF: 16-bit asynchronous mode, supports address/data multiplexing).

3.2 SPI 인터페이스 (SPI Interface)

SPI는 4선식으로 레지스터 접근에 사용되나, 이 문서에서는 사용되지 않습니다 (SPI uses a 4-wire interface for register access but is not used in this document).

3.3 A-quad-B 엔코더 출력 (A-quad-B Encoder Output)

쿼드러처 출력은 엔코더 호환성을 제공하며, TMS320F28388D의 eQEP 모듈과 연결 가능합니다 (Quadrature output provides encoder compatibility and can connect to the TMS320F28388D’s eQEP module).

  • 핀: A, B, NM (Pins: A, B, NM).
  • 동작: A/B 90° 위상 차이, NM 회전당 1펄스 (Operation: A/B 90° phase difference, NM one pulse per rotation).

4. TMS320F28388D와의 하드웨어 연결 (Hardware Connections with TMS320F28388D)

TMS320F28388D는 두 개의 EMIF를 지원하여 AD2S1210 병렬 인터페이스와 통합됩니다 (The TMS320F28388D supports two EMIFs for integration with the AD2S1210 parallel interface). 연결은 아래 표와 같습니다 (Connections are shown in the table below).

AD2S1210 핀 (Pin) TMS320F28388D 핀 (Pin) 설명 (Description)
DB0~DB15 (31~34, 37~42, 35, 43~48) EM1D0~EM1D15 16비트 데이터 버스 (16-bit data bus)
A0 (15) EM1A0 주소 선택 0 (Address select 0)
A1 (16) EM1A1 주소 선택 1 (Address select 1)
RD (17) EM1OE 읽기 제어 (Read control, active low)
WR/FSYNC (18) EM1WE 쓰기/프레임 동기 (Write/Frame sync, active low)
RESET (26) GPIO0 리셋, 20 µs 펄스 (Reset, 20 µs pulse)
SAMPLE (27) GPIO1 샘플 트리거 (Sample trigger)
LOT (28) GPIO2 추적 손실, 풀업 (Loss of tracking, pull-up)
DOS (29) GPIO3 신호 열화, 풀업 (Degradation of signal, pull-up)
LOS (30) GPIO4 신호 손실, 풀업 (Loss of signal, pull-up)
CLKIN (14) GPIO5 (ePWM) 8.192 MHz 클럭 (8.192 MHz clock)

리졸버 신호는 차폐 케이블을 사용하고, EMIF는 비동기 모드로 설정됩니다 (Resolver signals use shielded cables, and EMIF is set to asynchronous mode).

5. 병렬 드라이버 구현 (Parallel Driver Implementation)

TMS320F28388D의 EMIF를 사용한 병렬 드라이버는 16비트 데이터를 처리하며, DMA를 활용하여 효율성을 높입니다 (The parallel driver using TMS320F28388D’s EMIF handles 16-bit data, leveraging DMA for efficiency).

코드: ad2s1210_driver.h (Code: ad2s1210_driver.h)

// ad2s1210_driver.h: AD2S1210 병렬 드라이버 함수 선언
// ad2s1210_driver.h: AD2S1210 parallel driver function declarations
#ifndef AD2S1210_DRIVER_H
#define AD2S1210_DRIVER_H

#include "driverlib.h"

// AD2S1210 초기화: 리셋, 16비트 해상도, 10 kHz 여기 설정
// Initialize AD2S1210: Reset, 16-bit resolution, 10 kHz excitation
void AD2S1210_Init(void);

// 레지스터 쓰기: EMIF로 주소와 데이터 전송 (DMA 사용)
// Write register: Send address and data via EMIF (using DMA)
void AD2S1210_WriteRegister(uint8_t address, uint8_t value);

// 레지스터 읽기: EMIF로 주소에서 데이터 수신 (DMA 사용)
// Read register: Receive data from address via EMIF (using DMA)
void AD2S1210_ReadRegister(uint8_t address, uint8_t *value);

// 위치 읽기: 16비트 위치 데이터 수신
// Read position: Receive 16-bit position data
void AD2S1210_ReadPosition(uint16_t *position);

// 속도 읽기: 16비트 속도 데이터 수신
// Read velocity: Receive 16-bit velocity data
void AD2S1210_ReadVelocity(int16_t *velocity);

// 오류 읽기: Fault Register 데이터 수신
// Read fault: Receive Fault Register data
void AD2S1210_ReadFault(uint8_t *fault);

// 오류 로그: Fault Register 분석 및 UART 전송
// Log fault: Analyze Fault Register and send via UART
void AD2S1210_LogFault(uint8_t fault);

// CAN 전송: 위치/속도/오류 데이터를 CAN으로 전송
// Send CAN: Transmit position/velocity/fault data via CAN
void AD2S1210_SendCANData(void);

#endif
            

코드: ad2s1210_driver.c (Code: ad2s1210_driver.c)

// ad2s1210_driver.c: AD2S1210 병렬 드라이버 구현
// ad2s1210_driver.c: AD2S1210 parallel driver implementation
#include "ad2s1210_driver.h"
#include "driverlib.h"
#include 
#include 

// 외부 핸들: EMIF, UART, CAN, GPIO 핀 정의 (main.c에서 초기화)
// External handles: EMIF, UART, CAN, GPIO pins defined (in main.c)
extern uint32_t emif1Base;
extern uint32_t uartBase;
extern uint32_t canBase;
extern uint32_t resetPin;
extern uint32_t samplePin;
extern uint32_t lotPin;
extern uint32_t dosPin;
extern uint32_t losPin;

// 레지스터 주소 정의 (AD2S1210 데이터시트 참조)
// Register address definitions (refer to AD2S1210 datasheet)
#define REG_POSITION_MSB 0x00  // 위치 데이터 MSB (Position data MSB)
#define REG_POSITION_LSB 0x01  // 위치 데이터 LSB (Position data LSB)
#define REG_VELOCITY_MSB 0x02  // 속도 데이터 MSB (Velocity data MSB)
#define REG_VELOCITY_LSB 0x03  // 속도 데이터 LSB (Velocity data LSB)
#define REG_CONTROL 0x91       // 제어 레지스터: 여기 주파수 등 (Control register: excitation frequency, etc.)
#define REG_CONFIG 0x92        // 설정 레지스터: 해상도 등 (Configuration register: resolution, etc.)
#define REG_FAULT 0xFF         // 오류 레지스터 (Fault register)

// 오류 비트 정의 (Fault Register 비트별 오류)
// Fault bit definitions (Fault Register bit-wise errors)
#define FAULT_LOS (1 << 7)   // 신호 손실 (Loss of signal)
#define FAULT_DOS (1 << 6)   // 신호 열화 (Degradation of signal)
#define FAULT_LOT (1 << 5)   // 추적 손실 (Loss of tracking)
#define FAULT_CLIP (1 << 4)  // 신호 클리핑 (Signal clipping)

// 데이터 저장: 위치, 속도, 오류 (Stored data: position, velocity, fault)
static uint16_t position_data;
static int16_t velocity_data;
static uint8_t fault_data;
// UART 출력 버퍼 (UART output buffer)
static char uart_buffer[128];

// CAN 메시지 설정: ID 0x100, 8바이트 데이터
// CAN message configuration: ID 0x100, 8-byte data
static CAN_MsgObjHandle canTxMsg;

// EMIF 기본 주소: AD2S1210 매핑
// EMIF base address: Mapped to AD2S1210
#define AD2S1210_EMIF_BASE 0x100000

// 초기화: AD2S1210 리셋, 16비트 해상도, 10 kHz 여기 설정
// Initialize: Reset AD2S1210, set 16-bit resolution, 10 kHz excitation
void AD2S1210_Init(void) {
    // RESET 핀을 1ms 동안 Low로 설정하여 칩 리셋
    // Set RESET pin low for 1ms to reset the chip
    GPIO_writePin(resetPin, 0);
    DEVICE_DELAY_US(1000);
    GPIO_writePin(resetPin, 1);
    DEVICE_DELAY_US(10000); // 초기화 완료 대기 (Wait for initialization to complete)

    // Configuration Register: 16비트 해상도 설정 (0x0C)
    // Set Configuration Register: 16-bit resolution (0x0C)
    AD2S1210_WriteRegister(REG_CONFIG, 0x0C);
    // Control Register: 10 kHz 여기 주파수 설정 (0x40)
    // Set Control Register: 10 kHz excitation frequency (0x40)
    AD2S1210_WriteRegister(REG_CONTROL, 0x40);
}

// 레지스터 쓰기: EMIF로 주소와 데이터 전송
// Write register: Send address and data via EMIF
void AD2S1210_WriteRegister(uint8_t address, uint8_t value) {
    // 주소 선택: A0/A1 설정 (Set address: Configure A0/A1)
    EMIF_setAddress(emif1Base, (address & 0x03) | 0x80); // MSB=1 for write
    // 데이터 쓰기 (Write data)
    EMIF_writeData(emif1Base, value);
    // WR/FSYNC 펄스: 20 ns 이상 (WR/FSYNC pulse: ≥20 ns)
    EMIF_setWriteEnable(emif1Base, 0);
    DEVICE_DELAY_US(1);
    EMIF_setWriteEnable(emif1Base, 1);
}

// 레지스터 읽기: EMIF로 주소에서 데이터 수신
// Read register: Receive data from address via EMIF
void AD2S1210_ReadRegister(uint8_t address, uint8_t *value) {
    // 주소 선택: A0/A1 설정 (Set address: Configure A0/A1)
    EMIF_setAddress(emif1Base, address & 0x03);
    // RD 펄스: 20 ns 이상 (RD pulse: ≥20 ns)
    EMIF_setReadEnable(emif1Base, 0);
    DEVICE_DELAY_US(1);
    *value = EMIF_readData(emif1Base);
    EMIF_setReadEnable(emif1Base, 1);
}

// 위치 읽기: 16비트 위치 데이터 수신
// Read position: Receive 16-bit position data
void AD2S1210_ReadPosition(uint16_t *position) {
    uint8_t msb, lsb;

    // SAMPLE 핀 트리거로 데이터 갱신 (Trigger SAMPLE pin to update data)
    GPIO_writePin(samplePin, 0);
    DEVICE_DELAY_US(1);
    GPIO_writePin(samplePin, 1);

    // MSB 읽기 (Read MSB)
    AD2S1210_ReadRegister(REG_POSITION_MSB, &msb);
    // LSB 읽기 (Read LSB)
    AD2S1210_ReadRegister(REG_POSITION_LSB, &lsb);

    // 16비트 데이터 조합 (Combine 16-bit data)
    position_data = ((uint16_t)msb << 8) | lsb;
    *position = position_data;
}

// 속도 읽기: 16비트 속도 데이터 수신
// Read velocity: Receive 16-bit velocity data
void AD2S1210_ReadVelocity(int16_t *velocity) {
    uint8_t msb, lsb;

    // SAMPLE 핀 트리거 (Trigger SAMPLE pin)
    GPIO_writePin(samplePin, 0);
    DEVICE_DELAY_US(1);
    GPIO_writePin(samplePin, 1);

    // MSB 읽기 (Read MSB)
    AD2S1210_ReadRegister(REG_VELOCITY_MSB, &msb);
    // LSB 읽기 (Read LSB)
    AD2S1210_ReadRegister(REG_VELOCITY_LSB, &lsb);

    // 16비트 데이터 조합 (Combine 16-bit data)
    velocity_data = ((int16_t)msb << 8) | lsb;
    *velocity = velocity_data;
}

// 오류 읽기: Fault Register 데이터 수신
// Read fault: Receive Fault Register data
void AD2S1210_ReadFault(uint8_t *fault) {
    AD2S1210_ReadRegister(REG_FAULT, fault);
    fault_data = *fault;
}

// 오류 로그: Fault Register 비트 분석 및 UART 전송
// Log fault: Analyze Fault Register bits and send via UART
void AD2S1210_LogFault(uint8_t fault) {
    if (fault) {
        // 오류 메시지 생성 (Generate fault message)
        snprintf(uart_buffer, sizeof(uart_buffer), "Fault: 0x%02X [", fault);
        if (fault & FAULT_LOS) strcat(uart_buffer, "LOS ");
        if (fault & FAULT_DOS) strcat(uart_buffer, "DOS ");
        if (fault & FAULT_LOT) strcat(uart_buffer, "LOT ");
        if (fault & FAULT_CLIP) strcat(uart_buffer, "CLIP ");
        strcat(uart_buffer, "]\n");
        // UART 전송 (Transmit via UART)
        UART_write(uartBase, (uint8_t*)uart_buffer, strlen(uart_buffer));
    }
}

// CAN 전송: 위치/속도/오류 데이터를 CAN으로 전송
// Send CAN: Transmit position/velocity/fault data via CAN
void AD2S1210_SendCANData(void) {
    uint8_t can_data[8];
    // 데이터 패킹: 위치(2바이트), 속도(2바이트), 오류(1바이트)
    // Pack data: position (2 bytes), velocity (2 bytes), fault (1 byte)
    can_data[0] = (position_data >> 8) & 0xFF;
    can_data[1] = position_data & 0xFF;
    can_data[2] = (velocity_data >> 8) & 0xFF;
    can_data[3] = velocity_data & 0xFF;
    can_data[4] = fault_data;
    can_data[5] = 0; // 예약 (Reserved)
    can_data[6] = 0; // 예약 (Reserved)
    can_data[7] = 0; // 예약 (Reserved)

    // CAN 메시지 전송 (Transmit CAN message)
    CAN_transmitMessage(canBase, canTxMsg, can_data);
}

// GPIO 인터럽트: LOS/DOS/LOT 핀 감지 시 오류 로그 생성
// GPIO interrupt: Generate fault log on LOS/DOS/LOT pin trigger
void GPIO_IRQHandler(void) {
    uint32_t pins = GPIO_getInterruptStatus();
    if (pins & (lotPin | dosPin | losPin)) {
        uint8_t fault;
        AD2S1210_ReadFault(&fault);
        AD2S1210_LogFault(fault); // 오류 로그 전송 (Send fault log)
        GPIO_clearInterrupt(pins);
    }
}
            

코드: main.c (Code: main.c)

// main.c: TMS320F28388D에서 AD2S1210 제어 메인 프로그램
// main.c: Main program for controlling AD2S1210 with TMS320F28388D
#include "driverlib.h"
#include "device.h"
#include "ad2s1210_driver.h"
#include <stdio.h>
#include <string.h>

// 핸들 및 핀 정의: EMIF, UART, CAN, GPIO
// Handle and pin definitions: EMIF, UART, CAN, GPIO
uint32_t emif1Base = EMIF1_BASE;
uint32_t uartBase = SCIA_BASE;
uint32_t canBase = CANA_BASE;
uint32_t resetPin = 0;  // GPIO0: RESET
uint32_t samplePin = 1; // GPIO1: SAMPLE
uint32_t lotPin = 2;    // GPIO2: LOT
uint32_t dosPin = 3;    // GPIO3: DOS
uint32_t losPin = 4;    // GPIO4: LOS
CAN_MsgObjHandle canTxMsg;
CAN_MsgObjHandle canRxMsg;

// 함수 선언 (Function declarations)
void configureSystemClock(void);
void configureEMIF(void);
void configureUART(void);
void configureCAN(void);
void configureGPIO(void);
void configureTimer(void);
void checkInitialFault(void);
__interrupt void CAN_IRQHandler(void);
__interrupt void GPIO_IRQHandler(void);
__interrupt void Timer0_IRQHandler(void);

int main(void) {
    // 인터럽트 비활성화: 초기화 중 안정성 보장
    // Disable interrupts: Ensure stability during initialization
    DINT;

    // 디바이스 초기화: PLL, 플래시, RAM 설정
    // Initialize device: PLL, flash, RAM configuration
    Device_init();
    
    // 시스템 클럭 설정: 200 MHz
    // Configure system clock: 200 MHz
    configureSystemClock();

    // GPIO 초기화: EMIF 및 제어 핀
    // Initialize GPIO: EMIF and control pins
    Device_initGPIO();
    configureGPIO();

    // 인터럽트 벡터 테이블 및 PIE 모듈 초기화
    // Initialize interrupt vector table and PIE module
    Interrupt_initModule();
    Interrupt_initVectorTable();

    // 인터럽트 핸들러 등록: CAN, GPIO, 타이머
    // Register interrupt handlers: CAN, GPIO, Timer
    Interrupt_register(INT_CANA_0, &CAN_IRQHandler); // CAN 인터럽트 (CAN interrupt)
    Interrupt_register(INT_XINT1, &GPIO_IRQHandler); // GPIO 인터럽트 (GPIO interrupt)
    Interrupt_register(INT_TINT0, &Timer0_IRQHandler); // 타이머 0 인터럽트 (Timer 0 interrupt)

    // PIE 인터럽트 활성화: 명시적 그룹 설정
    // Enable PIE interrupts: Explicit group settings
    Interrupt_enableInPIE(INTERRUPT_CPU_INT9, INT_CANA_0); // CANA: PIE 그룹 9 (CANA: PIE group 9)
    Interrupt_enableInPIE(INTERRUPT_CPU_INT1, INT_XINT1);  // XINT1: PIE 그룹 1 (XINT1: PIE group 1)
    Interrupt_enableInPIE(INTERRUPT_CPU_INT1, INT_TINT0);  // TINT0: PIE 그룹 1 (TINT0: PIE group 1)

    // 인터럽트 우선순위 설정: 타이머 > CAN > GPIO
    // Set interrupt priorities: Timer > CAN > GPIO
    Interrupt_setPriority(INT_TINT0, 5);  // 타이머 우선순위 높음 (High priority for Timer)
    Interrupt_setPriority(INT_CANA_0, 4); // CAN 우선순위 중간 (Medium priority for CAN)
    Interrupt_setPriority(INT_XINT1, 3);  // GPIO 우선순위 낮음 (Lower priority for GPIO)

    // 인터럽트 활성화
    // Enable interrupts
    Interrupt_enable(INT_CANA_0);
    Interrupt_enable(INT_XINT1);
    Interrupt_enable(INT_TINT0);

    // EMIF, UART, CAN, 타이머 초기화
    // Initialize EMIF, UART, CAN, Timer
    configureEMIF();
    configureUART();
    configureCAN();
    configureTimer();

    // AD2S1210 초기화: 리셋, 16비트 해상도, 10 kHz 여기
    // Initialize AD2S1210: Reset, 16-bit resolution, 10 kHz excitation
    AD2S1210_Init();

    // 초기 오류 확인: Fault Register 점검
    // Check initial faults: Verify Fault Register
    checkInitialFault();

    // 글로벌 인터럽트 활성화
    // Enable global interrupts
    EINT;
    ERTM; // 실시간 인터럽트 활성화 (Enable real-time interrupts)

    // CAN 시작: 송수신 준비
    // Start CAN: Prepare for transmit/receive
    CAN_startModule(canBase);

    // 메인 루프: 타이머 인터럽트로 샘플링 처리
    // Main loop: Sampling handled by timer interrupt
    while (1) {
        // 유휴 상태: 필요 시 추가 작업 (Idle state: Add tasks if needed)
        __asm(" NOP"); // CPU 유휴 (CPU idle)
    }
}

// 시스템 클럭 설정: 200 MHz (HSE + PLL)
// Configure system clock: 200 MHz (HSE + PLL)
void configureSystemClock(void) {
    // PLL 설정: SYSCLK = 200 MHz (HSE=20 MHz, PLLM=2, PLLN=20)
    // Configure PLL: SYSCLK = 200 MHz (HSE=20 MHz, PLLM=2, PLLN=20)
    SysCtl_setClock(SYSCTL_OSCSRC_XTAL | SYSCTL_IMULT(20) | SYSCTL_FMULT_NONE | 
                    SYSCTL_SYSDIV(2) | SYSCTL_PLL_ENABLE);

    // EMIF 클럭 활성화 및 분주: 100 MHz
    // Enable and configure EMIF clock: 100 MHz
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EMIF1);
    SysCtl_setEMIF1ClockDivider(1); // SYSCLK/2 = 100 MHz
}

// EMIF 설정: 16비트 비동기 모드, CS2, AD2S1210 매핑
// Configure EMIF: 16-bit asynchronous mode, CS2, mapped to AD2S1210
void configureEMIF(void) {
    // EMIF 핀 멀티플렉싱: DB0~DB15, A0, A1, RD, WR
    // EMIF pin multiplexing: DB0~DB15, A0, A1, RD, WR
    GPIO_setPinConfig(GPIO_32_EM1D0);   // DB0
    GPIO_setPinConfig(GPIO_33_EM1D1);   // DB1
    GPIO_setPinConfig(GPIO_34_EM1D2);   // DB2
    GPIO_setPinConfig(GPIO_35_EM1D3);   // DB3
    GPIO_setPinConfig(GPIO_36_EM1D4);   // DB4
    GPIO_setPinConfig(GPIO_37_EM1D5);   // DB5
    GPIO_setPinConfig(GPIO_38_EM1D6);   // DB6
    GPIO_setPinConfig(GPIO_39_EM1D7);   // DB7
    GPIO_setPinConfig(GPIO_40_EM1D8);   // DB8
    GPIO_setPinConfig(GPIO_41_EM1D9);   // DB9
    GPIO_setPinConfig(GPIO_42_EM1D10);  // DB10
    GPIO_setPinConfig(GPIO_43_EM1D11);  // DB11
    GPIO_setPinConfig(GPIO_44_EM1D12);  // DB12
    GPIO_setPinConfig(GPIO_45_EM1D13);  // DB13
    GPIO_setPinConfig(GPIO_46_EM1D14);  // DB14
    GPIO_setPinConfig(GPIO_47_EM1D15);  // DB15
    GPIO_setPinConfig(GPIO_48_EM1A0);   // A0
    GPIO_setPinConfig(GPIO_49_EM1A1);   // A1
    GPIO_setPinConfig(GPIO_50_EM1OE);   // RD
    GPIO_setPinConfig(GPIO_51_EM1WE);   // WR/FSYNC

    // EMIF 비동기 타이밍 설정: AD2S1210 타이밍 요구사항 충족
    // Configure EMIF async timing: Meet AD2S1210 timing requirements
    EMIF_AsyncTimingParams timingParams = {
        .rSetup = 2,    // 읽기 설정 시간: 20 ns (Read setup time: 20 ns)
        .rStrobe = 3,   // 읽기 스트로브: 30 ns (Read strobe: 30 ns)
        .rHold = 2,     // 읽기 홀드: 20 ns (Read hold: 20 ns)
        .wSetup = 2,    // 쓰기 설정 시간: 20 ns (Write setup time: 20 ns)
        .wStrobe = 3,   // 쓰기 스트로브: 30 ns (Write strobe: 30 ns)
        .wHold = 2,     // 쓰기 홀드: 20 ns (Write hold: 20 ns)
        .turnAround = 0 // 턴어라운드: 0 (Turnaround: 0)
    };
    
    // EMIF 설정: CS2, 16비트, AD2S1210 메모리 매핑
    // Configure EMIF: CS2, 16-bit, AD2S1210 memory mapping
    EMIF_configureAsyncMemory(emif1Base, EMIF_CS2_SPACE, EMIF_16_BIT, &timingParams);
    SysCtl_selectEMIF1CS(EMIF_CS2_SPACE, 0x100000); // AD2S1210 메모리 시작 주소 (AD2S1210 memory start address)
}

// UART 설정: 115200 baud
// Configure UART: 115200 baud
void configureUART(void) {
    // SCIA 핀 설정: GPIO28(TX), GPIO29(RX)
    // Configure SCIA pins: GPIO28(TX), GPIO29(RX)
    GPIO_setPinConfig(GPIO_28_SCIA_TX);
    GPIO_setPinConfig(GPIO_29_SCIA_RX);
    
    // UART 설정: 115200 baud, 8-N-1
    // Configure UART: 115200 baud, 8-N-1
    UART_setConfig(uartBase, DEVICE_LSPCLK_FREQ, 115200, 
                   (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
    UART_enableModule(uartBase);
}

// CAN 설정: 500 kbps, ID 0x100
// Configure CAN: 500 kbps, ID 0x100
void configureCAN(void) {
    // CANA 핀 설정: GPIO8(TX), GPIO10(RX)
    // Configure CANA pins: GPIO8(TX), GPIO10(RX)
    GPIO_setPinConfig(GPIO_8_CANA_TX);
    GPIO_setPinConfig(GPIO_10_CANA_RX);
    
    // CAN 초기화: 500 kbps
    // Initialize CAN: 500 kbps
    CAN_initModule(canBase, DEVICE_SYSCLK_FREQ, 500000);
    
    // 송신 메시지 객체: ID 0x100, 8바이트
    // Transmit message object: ID 0x100, 8 bytes
    canTxMsg = CAN_setupMessageObject(canBase, 1, 0x100, CAN_MSG_OBJ_TYPE_TX, 0x7FF, 8, NULL);
    
    // 수신 메시지 객체: ID 0x200, 인터럽트 활성화
    // Receive message object: ID 0x200, interrupt enabled
    canRxMsg = CAN_setupMessageObject(canBase, 2, 0x200, CAN_MSG_OBJ_TYPE_RX, 0x7FF, 8, NULL);
    
    // CAN 인터럽트 활성화
    // Enable CAN interrupts
    CAN_enableInterrupt(canBase, CAN_INT_IE0 | CAN_INT_IE1);
}

// GPIO 설정: RESET, SAMPLE, LOS/DOS/LOT
// Configure GPIO: RESET, SAMPLE, LOS/DOS/LOT
void configureGPIO(void) {
    // RESET, SAMPLE: 출력, 초기 High (Output, initial high)
    GPIO_setPadConfig(resetPin, GPIO_PIN_TYPE_STD);
    GPIO_setDirectionMode(resetPin, GPIO_DIR_MODE_OUT);
    GPIO_writePin(resetPin, 1);
    GPIO_setPadConfig(samplePin, GPIO_PIN_TYPE_STD);
    GPIO_setDirectionMode(samplePin, GPIO_DIR_MODE_OUT);
    GPIO_writePin(samplePin, 1);

    // LOS, DOS, LOT: 입력, 풀업, 인터럽트 (Input, pull-up, interrupt)
    GPIO_setPadConfig(lotPin, GPIO_PIN_TYPE_PULLUP);
    GPIO_setDirectionMode(lotPin, GPIO_DIR_MODE_IN);
    GPIO_setInterruptType(lotPin, GPIO_INT_TYPE_FALLING);
    GPIO_enableInterrupt(lotPin);
    GPIO_setPadConfig(dosPin, GPIO_PIN_TYPE_PULLUP);
    GPIO_setDirectionMode(dosPin, GPIO_DIR_MODE_IN);
    GPIO_setInterruptType(dosPin, GPIO_INT_TYPE_FALLING);
    GPIO_enableInterrupt(dosPin);
    GPIO_setPadConfig(losPin, GPIO_PIN_TYPE_PULLUP);
    GPIO_setDirectionMode(losPin, GPIO_DIR_MODE_IN);
    GPIO_setInterruptType(losPin, GPIO_INT_TYPE_FALLING);
    GPIO_enableInterrupt(losPin);

    // XINT1에 LOS/DOS/LOT 핀 매핑
    // Map LOS/DOS/LOT pins to XINT1
    GPIO_setInterruptPin(lotPin, GPIO_INT_XINT1);
    GPIO_setInterruptPin(dosPin, GPIO_INT_XINT1);
    GPIO_setInterruptPin(losPin, GPIO_INT_XINT1);
}

// 타이머 설정: CPU 타이머 0, 100ms 주기
// Configure timer: CPU Timer 0, 100ms period
void configureTimer(void) {
    // 타이머 0 초기화: 200 MHz SYSCLK 기준
    // Initialize Timer 0: Based on 200 MHz SYSCLK
    CPUTimer_setPeriod(CPUTIMER0_BASE, 20000000); // 100ms = 20M cycles at 200 MHz
    CPUTimer_setPreScaler(CPUTIMER0_BASE, 0);    // 분주 없음 (No prescaler)
    CPUTimer_enableInterrupt(CPUTIMER0_BASE);
    CPUTimer_startTimer(CPUTIMER0_BASE);
}

// 초기 오류 확인: AD2S1210 초기화 후 Fault Register 점검
// Check initial faults: Verify Fault Register after AD2S1210 initialization
void checkInitialFault(void) {
    uint8_t fault;
    AD2S1210_ReadFault(&fault);
    if (fault) {
        // 초기 오류 감지 시 UART로 로그 전송
        // Send log via UART if initial fault detected
        AD2S1210_LogFault(fault);
        // 디버깅용 정지 (Halt for debugging)
        // while(1); // 필요 시 주석 해제 (Uncomment if needed)
    }
}

// CAN 인터럽트 핸들러
// CAN interrupt handler
__interrupt void CAN_IRQHandler(void) {
    uint32_t interruptCause = CAN_getInterruptCause(canBase);
    if (interruptCause == CAN_INT_INT0ID) {
        // 수신 메시지 처리 (Handle received message)
        uint8_t rxData[8];
        CAN_readMessage(canBase, 2, rxData);
        // 필요 시 수신 데이터 처리 로직 추가 (Add received data processing if needed)
    }
    CAN_clearInterruptStatus(canBase, interruptCause);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9); // PIE 그룹 9 ACK (Acknowledge PIE group 9)
}

// GPIO 인터럽트 핸들러: LOS/DOS/LOT
// GPIO interrupt handler: LOS/DOS/LOT
__interrupt void GPIO_IRQHandler(void) {
    uint32_t pins = GPIO_getInterruptStatus();
    if (pins & (lotPin | dosPin | losPin)) {
        uint8_t fault;
        AD2S1210_ReadFault(&fault);
        AD2S1210_LogFault(fault); // 오류 로그 전송 (Send fault log)
        GPIO_clearInterrupt(pins);
    }
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1); // PIE 그룹 1 ACK (Acknowledge PIE group 1)
}

// 타이머 0 인터럽트 핸들러: 100ms 주기 샘플링
// Timer 0 interrupt handler: 100ms periodic sampling
__interrupt void Timer0_IRQHandler(void) {
    uint16_t position;
    int16_t velocity;
    uint8_t fault;

    // 위치 읽기 및 UART 전송 (Read position and send via UART)
    AD2S1210_ReadPosition(&position);
    char buffer[64];
    snprintf(buffer, sizeof(buffer), "Position: %u\n", position);
    UART_write(uartBase, (uint8_t*)buffer, strlen(buffer));

    // 속도 읽기 및 UART 전송 (Read velocity and send via UART)
    AD2S1210_ReadVelocity(&velocity);
    snprintf(buffer, sizeof(buffer), "Velocity: %d\n", velocity);
    UART_write(uartBase, (uint8_t*)buffer, strlen(buffer));

    // 오류 확인 및 로그 전송 (Check faults and send log)
    AD2S1210_ReadFault(&fault);
    if (fault) {
        AD2S1210_LogFault(fault);
    }

    // CAN으로 데이터 전송 (Send data via CAN)
    AD2S1210_SendCANData();

    // 타이머 인터럽트 플래그 클리어
    // Clear timer interrupt flag
    CPUTimer_clearOverflowFlag(CPUTIMER0_BASE);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1); // PIE 그룹 1 ACK (Acknowledge PIE group 1)
}

6. UART/CAN 통신 (UART/CAN Communication)

AD2S1210 데이터를 외부로 전송하기 위해 UART와 CAN을 사용합니다 (UART and CAN are used to transmit AD2S1210 data externally).

  • UART: SCIA, 115200 baud, 위치/속도/오류 로그 전송 (UART: SCIA, 115200 baud, sends position/velocity/fault logs).
  • CAN: CANA, 500 kbps, ID 0x100, 8바이트 프레임 (위치 2바이트, 속도 2바이트, 오류 1바이트) (CAN: CANA, 500 kbps, ID 0x100, 8-byte frame: position 2 bytes, velocity 2 bytes, fault 1 byte).

7. 오류 처리 (Error Handling)

Fault Register(0xFF)를 통해 오류를 감지합니다 (The Fault Register (0xFF) detects errors).

비트 (Bit) 오류 (Error) 설명 (Description) 대응 (Action)
7 LOS 신호 손실 (Loss of signal) 리졸버 연결 확인 (Check resolver connections)
6 DOS 신호 열화 (Degradation of signal) 신호 품질 점검 (Check signal quality)
5 LOT 추적 손실 (Loss of tracking) CLKIN 안정성 확인 (Check CLKIN stability)
4 클리핑 (Clipping) 입력 신호 클리핑 (Input signal clipping) 입력 진폭 조정 (Adjust input amplitude)

8. 설정 옵션 (Configuration Options)

AD2S1210은 레지스터를 통해 사용자 맞춤 설정이 가능합니다 (The AD2S1210 can be customized via registers).

  • Configuration Register (0x92): 해상도, 엔코더 펄스 수 (Resolution, encoder pulse count).
  • Control Register (0x91): 여기 주파수 2~20 kHz (Excitation frequency 2~20 kHz).
  • Fault Threshold Registers (0x80~0x8F): LOS/DOS/LOT 임계값 (LOS/DOS/LOT thresholds).

9. 응용 예시 (Application Examples)

  • 전기 파워 스티어링 (EPS): 조향 각도 측정, ASIL B 인증 (EPS: Steering angle measurement, ASIL B certified).
  • 산업 서보: 로봇 팔 정밀 제어 (Industrial servo: Precise robot arm control).
  • 항공우주: 비행 제어 표면, -55°C~+125°C (Aerospace: Flight control surfaces, -55°C~+125°C).

10. 사용 방법 (Usage Instructions)

  1. CCS 설정: EMIF(16비트, 비동기), UART, CAN, GPIO 구성 (Configure CCS: EMIF 16-bit asynchronous, UART, CAN, GPIO).
  2. 코드 통합: 위 파일을 Code Composer Studio 프로젝트에 추가 (Integrate code: Add files to Code Composer Studio project).
  3. 컴파일 및 업로드: TMS320F28388D에 플래시 (Compile and flash to TMS320F28388D).
  4. 테스트: UART (115200 baud), CAN (ID 0x100)으로 데이터 확인 (Test: Verify data via UART (115200 baud) and CAN (ID 0x100)).

11. 문제 해결 (Troubleshooting)

  • EMIF: 비동기 모드 확인, 타이밍 설정 (rSetup/wSetup ≥ 10 ns) (EMIF: Verify asynchronous mode, timing settings rSetup/wSetup ≥ 10 ns).
  • 리졸버: SIN/COS 차폐 케이블, EXC 전류 ≤ 28 mA (Resolver: Shielded SIN/COS cables, EXC current ≤ 28 mA).
  • 오류: Fault Register 디버깅, GPIO 풀업 확인 (Faults: Debug Fault Register, verify GPIO pull-ups).
  • 전원: VDRIVE=3.3V, AVDD/DVDD=5V (Power: VDRIVE=3.3V, AVDD/DVDD=5V).

12. 추가 자료 (Additional Resources)

  • 데이터시트: AD2S1210 Rev. B, TMS320F28388D Rev. E (Datasheets: AD2S1210 Rev. B, TMS320F28388D Rev. E).
반응형