Microprocessor/DSP (TMS320F28x) TR28335 개발 KIT Potentiometer 가변저항 ADC 로 Control
  • 728x90
    반응형

     

     

    Potentiometer 가변저항 ADC로 전압값 읽어오기

    SOURCE TR28335_P2200.h

    /*==============================================================
     *
     * FILE   : TR28335_P2200.h .2017
     * TITLE  : TR28335 Potentiometer ADC Interrupt Service Routine
     * SENSOR : Potentiometer(P2200)
     *
     *==============================================================*/ 
    #ifndef __TR28335_P2200_H__
    #define __TR28335_P2200_H__
    #ifdef _cplusplus
    extern "C" {
    #endif
    #include <main.h>
    
    #define ADC_CORE_12_BIT                 4095
    
    #define SINGLE_16_STATE_SEQ(ADC_DATA)   ((ADC_DATA) >> 4)
    #define VOLTAGE(ADC_DATA)               ((ADC_DATA) * (3.3f / ADC_CORE_12_BIT))
    
    void initP2200Adc(void);
    
    #ifdef _cplusplus
    }
    #endif  /* extern "C"          */
    #endif  /* __TR28335_P2200_H__ */

     

    SOURCE TR28335_P2200.c

    /*==============================================================
     *
     * FILE   : TR28335_P2200.c .2017
     * TITLE  : TR28335 Potentiometer ADC Interrupt Service Routine
     * SENSOR : Potentiometer(P2200)
     *
     *==============================================================*/ 
    #include <TR28335_P2200.h>
    
    interrupt void p2200_adc_isr(void);
    
    float32 gVoltage;
    /*=======================================
    *
    * Name        : initP2200Adc
    * Type        : Fucntion
    * Description : P2200 ADC Initialization
    *
    =========================================*/
    void initP2200Adc(void)
    {
        gVoltage= 0.0f;
        
        EALLOW;
        PieVectTable.ADCINT = &p2200_adc_isr;
        EDIS;
        
        /* ADC 초기화 */
        InitAdc();
        
        /* ADC 설정   */
        AdcRegs.ADCTRL3.bit.ADCCLKPS = 3;       /* ADCCLK = HSPCLK/(ADCCLKPS*2)/(CPS+1)                         */
        AdcRegs.ADCTRL1.bit.CPS      = 1;       /* ADCCLK = 75MHz/(3*2)/(1+1) = 6.2MHz                          */
        AdcRegs.ADCTRL1.bit.ACQ_PS   = 3;       /* 샘플/홀드 사이클 = ADQ_PS + 1 = 4 (ADCCLK 기준)                */
        AdcRegs.ADCTRL1.bit.SEQ_CASC = 1;       /* 시퀀스 모드 설정 : 직렬 시퀀스 모드 (0: 병렬 모드, 1: 직렬 모드) */
        AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0;   /* ADC 채널수 설정 : 1개 (=MAX_CONV+1) 채널을 ADC                 */
        AdcRegs.ADCCHSELSEQ1.bit.CONV00  = 0;   /* ADC 순서 설정 : 첫번째로 ADCINA0 채널을 ADC                    */
    
        AdcRegs.ADCTRL2.bit.EPWM_SOCB_SEQ = 1;  /* ePWM_SOCB로 ADC 시퀀스 시동                                   */
        AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1  = 1;  /* ADC 시퀀스 완료시 인터럽트 발생 설정                           */
    
        /* ePWM_SOCB 이벤트 트리거 설정 */
        EPwm3Regs.ETSEL.bit.SOCBEN  = 1;        /* SOCB 이벤트 트리거 Enable                                    */
        EPwm3Regs.ETSEL.bit.SOCBSEL = 2;        /* SCCB 트리거 조건 : 카운터 주기 일치 시                         */
        EPwm3Regs.ETPS.bit.SOCBPRD  = 1;        /* SOCB 이벤트 분주 설정 : 트리거 조건 한번 마다                   */
        EPwm3Regs.TBCTL.bit.CTRMODE = 0;        /* 카운트 모드 설정 : UP-count 모드                               */
        EPwm3Regs.TBCTL.bit.HSPCLKDIV = 1;      /* TBCLK = [SYSCLKOUT / ((HSPCLKDIV * 2) * 2^(CLKDIV))]         */
        EPwm3Regs.TBCTL.bit.CLKDIV    = 1;      /* TBCLK = [150MHz / (2*2)] = 37.5MHz                           */
        EPwm3Regs.TBPRD = 1874;                 /* TB주기 = (TBPRD + 1)/TBCLK = 1875/37.5MHz = 50us(20KHz)      */
        EPwm3Regs.TBCTR = 0x0000;               /* TB 카운터 초기화                                              */
    
        PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
        IER |= M_INT1; 
      
        return;
    }
    
    /*==================================================
    *
    * Name        : p2200_adc_isr
    * Type        : Interrupt
    * Description : P2200 ADC Interrupt Service Routine 
    *
    ====================================================*/
    interrupt void p2200_adc_isr(void)
    {
        gVoltage= VOLTAGE(SINGLE_16_STATE_SEQ(AdcRegs.ADCRESULT0));
    
        /* Reinitialize for next ADC sequence */
        AdcRegs.ADCTRL2.bit.RST_SEQ1   = 1;
        AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    }

     

    코드 분석

     

    📌 Step .1 ADCINT : PIE Group 1 Vectors Table 에 Interrupt Service Routine 등록한다.

     

     

    📌 Step .2 InitAdc : 이 함수는 TI에서 기술하여 제공하는 DSP2833x_Adc.c 라는 파일에서 찾을 수 있다. 사용자가 ADC 회로를 이용하여 어떠한 데이터를 변환할 수 있도록 ADC 회로를 초기화 하는 과정을 담고있다. 이 과정에서는 ADC 회로의 정상적인 기동을 위한 Power-up Sequence 가 포함된다.

     

     

    📌 Step .3 : ADC 구동에 필요한 클럭 공급 과정 

    • 오실레이터에서 30MHz클럭 발생
    • PLL 분주 : 오실레이터에서 발생한 클럭이 PLL 분주 회로를 거치게 된다. PLLCR[3~0]비트 상태에 따라 오실레이터 클럭을 15MHz~150MHz 까지 분주할 수 있다. 
    • 코어를 거친 클럭은 SYSCLKOUT(150MHz) 로 High-speed preacaler라는 회로로 들어간다.

     

     

    • 여기에 들어온 클럭은 HISPCP[2~0]의 비트 상태에 따라 SYSCLKOUT을 다시 분주한다.

     

     

     

    • 다시 분주된 HSPCLK 가 ADCCLK 까지 가는데 필요한 2번의 분주 과정중 첫번쨰는 ADCTRL3[4~1]의 비트상태에 따라 분주하게 된다.
    • ADCTRL1[7](CPS) 상태에 따른 분주한 결과 까지 포함하여 최종 목적지인 ADCCLK에 도달하게 된다.

     

     

     

    📌 Step .4 ADCTRL1 - ACQ_PS : ADC Sample & Hold 회로의 Acquisition window size 를 설정하는 항목이다. TM320F28X에 탑재된 ADC 회로는 일종의 비교형의 형태를 띠고 있으므로 취득한 외부 신호를 비교가 완료될 때까지 유지할 필요성이 있다. S/H 회로가 값을 취듯해 가지고 있는 시간이 결정 된다.

     

     

    📌 Step.5 ADCTRL1 - SEQ_CASC : 시퀀서의 운용방법을 결정하는 비트다. 두 개의 시퀀서를 직렬로 연결하여 마치 하나의 시퀀서인 것 처럼 사용할 수 있는 직렬시퀀서모드(Cascaded mode)와 독립된 두 개로 운용하는 독립시퀀서모드(Dual-sequencer mode)로 구분된다.

     

     

    📌 Step .6 ADCMAXCONV - MAX_CONV1 : ADC 채널수를 설정 한다.

     

     

    📌 Step .7 ADCCHSELSEQ - CONV00 : P2200 은 ADCINA0 에 연결되어 있으므로 ADC 순서 설정 CONV00 비트에 ADCINA0 를 설정한다.

     

     

    📌 Step .8 ADCTRL2 - EPWM_SOCB_SEQ : 직렬 시퀀스에서만 유효 하며 ePWM_SOCB 신호를 변환시작.

     

     

    📌 Step .9 ADCTRL2 - INT_ENA_SEQ1 : 시퀀스 1에 의한 인터럽트를 활성화.

     

     

    📌 Step .10 ETSEL - SOCBEN : EPWMxSOCB 는 ADC 인터럽트를 위해 제작되었다는 것을 알 수 있다.

     

     

    📌 Step .11 ETSEL - SOCBSEL : 주기에 대한 트리거(인터럽트) 발생 옵션 부분이다. Enable event time-base counter equal to period(TBCTR = TBPRD) 는 초기값으로 설정하는 TBPRD 비트와 카운팅되서 증가하는 TBCTR비트값이 동일할 경우에 트리거가 발생하게 해준다. PRD 값이 고정되고 증가 클럭 속도를 설정을 통해서 정할 수 있으므로 원하는 시간을 계산할 수 있다.

     

     

    📌 Step .12 ETPS - SOCBPRD : 이벤트 주기에서의 변환시작 선택 설정.

     

     

    📌 Step .13 TBCTL - CTRMODE : 카운터 모드 설정.

     

    📌 Step .14 TBCTL - HSPCLKDIV, CLKDIV : TBLCK 는 Time Base clock를 의미하며 pwm의 clock으로 사용된다. 이는 SYSCLK에서 분배하여 그 값을 정하며 수식적으로는 위에 표시해 놓았듯이 TBCLK = SYSCLK / (HSPCLKDIV * CLKDIV) 이다.

     

    관련 그림은 아래와 같다.

     

     

    📌 Step .15 TBPRD : ePWM 주기를 설정하는 카운터로 카운팅되는 TBCTR 이 TBPRD와 같으면 인터럽트가 발생된다.

     

     

    📌 Step .16 ADCRESULT0 : ADCRESULT0 으로 ADC 결과를 받을때 주의할점은 첫 0~3bit 가 Reserved 이므로 4bit 만큼 시프트하여 사용하여야 한다.

     

    결과

     

    gVoltage 변수를 그래프로 관찰하면 아래와같이 0V~32V로 가변하는 그래프 결과를 확인할 수 있다.

     

    ADC Clock 클럭 계산 Excel

    ADC Clock 계산.xlsx
    다운로드

     

     

    728x90
    반응형
상단으로