ADC란
: Analog to Digital Converter, 말 그대로 아날로그 신호를 디지털 신호로 변환해 주는 역할을 하는 IC입니다.
간단한 예시로 마이크에서 들은 소리나 카메라에서 촬영한 빛을 디지털 데이터로 전환시키기 위한 부품을 칭합니다.
사실상 현대의 센서라고 부를만한 제품엔 모두 달려있는 필수요소입니다.
기본적으로 외부의 신호는 아날로그 신호이기 때문에 ADC가 없으면 읽어낼 수가 없다고 볼 수 있습니다.
Part 1. 예제 실습의 목적
: Delfino EVM의 Potentiometer의 DC 출력 신호를 ADC하고, 결과를 CCS의 Expressions 창에서 확인하는 예제입니다. ePWM 모듈의 타이머를 사용해서 정확한 주기로 ADC-B 모듈의 SOC0 을 트리거 하여 ADC를 진행하고, ADC 변환 종료 후에 인터럽트를 발생시켜서 ADC 결과를 저장하는 예제입니다.
*EVM이란 평가 모듈을 뜻하는 것으로 엔지니어와 개발자가 특정 마이크로컨트롤러의 기능을 실험하고 테스트할 수 있는 개발 및 평가 보드입니다.
위 사진의 보드가 실습에서 요구하는 준비물로, 레버를 돌려 DC 조절을 해야합니다.
하지만 저희 연구실에 해당 연습용 보드가 없어 위에 보이는 Digilent Analog Discovery 2™를 사용하였습니다. WaveForm 프로그램과 함께 사용하여 DC인가(Supplies)를 해주었습니다.
Part 2. 실습 진행 순서
- WaveForm 실행 후 DC인가(Supplies) 준비
- CCS 실행 후 실행 작업(Launch→Build→Load) 후 Realtime으로 실행
- 변수 값 변화 확인
Part 3. TEST(Code)
아래 코드는 싱크웍스의 Delfino 개발보드 F28377D 예제 2번의 CCS 코드입니다.
// 선행처리 지시
#include "F28x_Project.h" // Device Headerfile and Examples Include File
// 함수 선언
interrupt void adcb1_isr(void);
// 시스템에서 사용할 전역 변수 선언
Uint16 ADC_value;
Uint16 Loop_cnt, ADC_cnt;
// 메인 함수 - 시작
void main(void)
{
// Step 1. 전역 인터럽트 해제
DINT;
// Step 2. 시스템 클럭 초기화:
InitSysCtrl();
EALLOW; // PWM 모듈에 공급되는 시스템 클럭 분주
ClkCfgRegs.PERCLKDIVSEL.bit.EPWMCLKDIV = 0; // 0: 1분주, 1: 1/2분주
EDIS;
// Step 3. 인터럽트 초기화:
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
// Vector Remapping
EALLOW;
PieVectTable.ADCB1_INT = &adcb1_isr;
EDIS;
// 외부 인터터트 포합된 백터 활성화
PieCtrlRegs.PIEIER1.bit.INTx2 = 1; // PIE 인터럽트(ADCA1INT) 활성화
IER |= M_INT1; // CPU 인터럽트(INT1) 활성화
// Step 4. ADC 초기화
// ADC 모드 설정 및 Power-up
EALLOW;
AdcbRegs.ADCCTL2.bit.PRESCALE = 6; // ADCCLK = SYSCLK / 4, SYSCLK = 200MHz
AdcSetMode(ADC_ADCB, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1; // ADC Interrupt Pulse Position: 변환종료 후 발생
AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1; // ADC 시동(Power-up)
DELAY_US(1000); // ADC가 시동되는 동안 1ms 지연
EDIS;
// ADC SOC(채널, S/H시간, 트리거소스) 및 인터럽트 설정
EALLOW;
AdcbRegs.ADCSOC0CTL.bit.CHSEL = 0; // SOC0 : ADCINB0 채널 변환
AdcbRegs.ADCSOC0CTL.bit.ACQPS = 14; // (S/H 시간) 설정 75ns = (ACQPS+1)/SYSCLK
AdcbRegs.ADCSOC0CTL.bit.TRIGSEL = 7; // SOC0: ePWM2 SOCA/C로 트리거
AdcbRegs.ADCINTSEL1N2.bit.INT1SEL = 0; // EOC0가 ADCINT1를 발생
AdcbRegs.ADCINTSEL1N2.bit.INT1E = 1; // ADCINT1 활성화
AdcbRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // ADCINT1 flag 클리어 확인
EDIS;
//ADC SOC 트리거를 위한 ePWM2 설정
EALLOW;
EPwm2Regs.ETSEL.bit.SOCAEN = 1; // SOCA 이벤트 트리거 Enable
EPwm2Regs.ETSEL.bit.SOCASEL = 2; // SCCA 트리거 조건 : 카운터 주기 일치 시
EPwm2Regs.ETPS.bit.SOCAPRD = 1; // SOCA 이벤트 분주 설정 : 트리거 조건 한번 마다
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // count up and start
EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0; // TBCLK = [SYSCLKOUT / ((HSPCLKDIV*2) * 2^(CLKDIV))]
EPwm2Regs.TBCTL.bit.CLKDIV = 0; // TBCLK = [200MHz / (1*1)] = 200MHz
EPwm2Regs.TBPRD = 10000 - 1; // TBCLK/(TBPRD+1) = 200MHz/10,000 = 20KHz
EPwm2Regs.TBCTR = 0x0000; // TB 카운터 초기화
EDIS;
// Step 6. 변수 초기화
ADC_value = 0;
Loop_cnt = 0;
// 전역 인터럽트 활성화 및 and 리얼타임 디버깅 이벤트 활성화
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
// IDLE loop. Just sit and loop forever :
for(;;)
{
Loop_cnt++;
}
}
// 메인 함수 - 끝
// ADC 인터럽트 서비스 루틴
interrupt void adcb1_isr(void)
{
ADC_value= AdcbResultRegs.ADCRESULT0;
AdcbRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
Part 4. 코드 간략 설명
SOC(Start of Conversion) : ADC를 시작하는 신호(트리거)
0~15 중 하나를 선택하여 아래 동작을 조작한다.
TRIGSEL(트리거 선택), CHSEL(입력 채널 선택), ACQPS(샘플 시간 결정)
→ ADCRESULTx 에 저장한다.
AdcxRegs :
ADC x핀의 결과값이 가상의 포트인
AdcResultREGs.ADCRESULTx에 저장된다.
Part 5. 실습 결과
DC값을 0~3V까지 바꿔주면서 ADC_value값이 변화하는 것을 관찰할 수 있습니다.
DataSheet에 기반하여 작성한 글이며 해당 파일이 용량이 큰 관계로 필요하신 분은 댓글로 이메일 남겨주시면 보내드리겠습니다.
이상으로 글을 마치겠습니다. 감사합니다.