This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

遇到f28m35中AD转换器通道以及触发源设置问题的

Other Parts Discussed in Thread: CONTROLSUITE

现在用F28M35做应用程序,需要采集8路模拟信息,现在使用ADC1部分,ADC2部分没有使用。

AD转换的设置按手册上讲是三个方面:SOC触发源,通道号,采样宽度。

如果要一个触发源来触发,完成8个通道的AD采集,该怎么来初始化AD转换器?

下面两条语句的区别是什么?

AdclogSysCtrlRegs.TRIG1SEL.all = 5;

Adc1Regs.ADCSOC0CTL.bit.TRIGSEL =5;        //选用EPWM1A 作为触发源。

 

看了好久还是整不好,能读出AD转换值,但是采集的三相电压信号不正常,请高手给予指点,谢谢!

 

 

 

  • 程序中首先AD初始化:

    void A_Config(void)
    {
      //Adc1Regs.ADCSOC0CTL.bit.
         EALLOW;
         Adc1Regs.ADCCTL2.bit.ADCNONOVERLAP = 1;     // Enable non-overlap mode i.e.
                                                                                                      // conversion and future sampling
                                                                                                       // events dont overlap
         Adc1Regs.ADCCTL1.bit.INTPULSEPOS   = 1;     // ADCINT1 trips after AdcResults latch

         Adc1Regs.INTSEL1N2.bit.INT1E       = 0;     // Enabled ADCINT1
         Adc1Regs.INTSEL1N2.bit.INT1CONT    = 0;     // Disable ADCINT1 Continuous mode
         Adc1Regs.INTSEL1N2.bit.INT1SEL     = 8;     // setup EOC0 to trigger ADCINT1 to fire
         Adc1Regs.ADCSOC0CTL.bit.CHSEL      = 15;    // set SOC0 channel select to
                                                     // ADC1B7
         Adc1Regs.ADCSOC1CTL.bit.CHSEL      = 15;    // set SOC0 channel select to
                                                     // ADC1B7
         Adc1Regs.ADCSOC2CTL.bit.CHSEL      = 12;    // set SOC1 channel select to
                                                     // ADC1B4
         Adc1Regs.ADCSOC3CTL.bit.CHSEL      = 11;     // set SOC0 channel select to
                                                     // ADC1B3
         Adc1Regs.ADCSOC4CTL.bit.CHSEL      = 8;     // set SOC1 channel select to
                                                     // ADC1B0
         Adc1Regs.ADCSOC5CTL.bit.CHSEL      = 0;     // set SOC0 channel select to
                                                     // ADC1A0
         Adc1Regs.ADCSOC6CTL.bit.CHSEL      = 2;     // set SOC1 channel select to
                                                     // ADC1A2
         Adc1Regs.ADCSOC7CTL.bit.CHSEL      = 3;     // set SOC0 channel select to
                                                     // ADC1A3
         Adc1Regs.ADCSOC8CTL.bit.CHSEL      = 4;     // set SOC1 channel select to
                                                     // ADC1A4
         AnalogSysctrlRegs.TRIG1SEL.all     = 5;     // Assigning EPWM1SOCA to
                                                     // ADC TRIGGER 1 of the ADC module
         Adc1Regs.ADCSOC0CTL.bit.TRIGSEL    = 5;     // Set SOC0 start trigger to
                                                     // ADC Trigger 1(EPWM1 SOCA) of the
                                                     // adc
         Adc1Regs.ADCSOC1CTL.bit.TRIGSEL    = 5;     // set SOC1 start trigger to
                                                     // ADC Trigger 1(EPWM1 SOCA) of the
                                                     // adc
         Adc1Regs.ADCSOC2CTL.bit.TRIGSEL    = 5;     // Set SOC0 start trigger to
                                                     // ADC Trigger 1(EPWM1 SOCA) of the
                                                     // adc
         Adc1Regs.ADCSOC3CTL.bit.TRIGSEL    = 5;     // set SOC1 start trigger to
                                                     // ADC Trigger 1(EPWM1 SOCA) of the
                                                     // adc
         Adc1Regs.ADCSOC4CTL.bit.TRIGSEL    = 5;     // Set SOC0 start trigger to
                                                     // ADC Trigger 1(EPWM1 SOCA) of the
                                                     // adc
         Adc1Regs.ADCSOC5CTL.bit.TRIGSEL    = 5;     // set SOC1 start trigger to
                                                     // ADC Trigger 1(EPWM1 SOCA) of the
                                                     // adc
         Adc1Regs.ADCSOC6CTL.bit.TRIGSEL    = 5;     // Set SOC0 start trigger to
                                                     // ADC Trigger 1(EPWM1 SOCA) of the
                                                     // adc
         Adc1Regs.ADCSOC7CTL.bit.TRIGSEL    = 5;     // set SOC1 start trigger to
                                                     // ADC Trigger 1(EPWM1 SOCA) of the
                                                     // adc
         Adc1Regs.ADCSOC8CTL.bit.TRIGSEL    = 5;     // set SOC1 start trigger to
                                                     // ADC Trigger 1(EPWM1 SOCA) of the
                                                     // adc
         Adc1Regs.ADCSOC0CTL.bit.ACQPS      = 6;     // set SOC0 S/H Window to 7 ADC
                                                     // Clock Cycles, (6 ACQPS plus
                                                     // 1)
         Adc1Regs.ADCSOC1CTL.bit.ACQPS      = 6;     // set SOC1 S/H Window to 7 ADC
                                                     // Clock Cycles, (6 ACQPS plus
                                                     // 1)
         Adc1Regs.ADCSOC2CTL.bit.ACQPS      = 6;     // set SOC0 S/H Window to 7 ADC
                                                     // Clock Cycles, (6 ACQPS plus
                                                     // 1)
         Adc1Regs.ADCSOC3CTL.bit.ACQPS      = 6;     // set SOC1 S/H Window to 7 ADC
                                                     // Clock Cycles, (6 ACQPS plus
                                                     // 1)
         Adc1Regs.ADCSOC4CTL.bit.ACQPS      = 6;     // set SOC0 S/H Window to 7 ADC
                                                     // Clock Cycles, (6 ACQPS plus
                                                     // 1)
         Adc1Regs.ADCSOC5CTL.bit.ACQPS      = 6;     // set SOC1 S/H Window to 7 ADC
                                                     // Clock Cycles, (6 ACQPS plus
                                                     // 1)
         Adc1Regs.ADCSOC6CTL.bit.ACQPS      = 6;     // set SOC0 S/H Window to 7 ADC
                                                     // Clock Cycles, (6 ACQPS plus
                                                     // 1)
         Adc1Regs.ADCSOC7CTL.bit.ACQPS      = 6;     // set SOC1 S/H Window to 7 ADC
                                                     // Clock Cycles, (6 ACQPS plus
                                                     // 1)
         Adc1Regs.ADCSOC8CTL.bit.ACQPS      = 6;     // set SOC1 S/H Window to 7 ADC
                                                     // Clock Cycles, (6 ACQPS plus
                                                     // 1)
         EDIS;

    }

     然后配置EPW1A来出发ADC

    //--------------------------------------------------------------------------------
        EPwm1Regs.ETSEL.bit.INTEN  = 1;     // Enable EPWM1INT generation
        EPwm1Regs.ETSEL.bit.INTSEL  = 1;    // Enable interrupt CNT_zero event
        EPwm1Regs.ETPS.bit.INTPRD  = 1;     // Generate interrupt on the 1st event
     EPwm1Regs.ETCLR.bit.INT  = 1;      // Enable more interrupts

        /* Set up Event Trigger with CNT_zero enable for Time-base of EPWM1 */      \
        EPwm1Regs.ETSEL.bit.SOCAEN  = 1;      /* Enable SOCA */          \
        EPwm1Regs.ETSEL.bit.SOCASEL = 2;     /* Enable period event for SOCA */      \
        EPwm1Regs.ETPS.bit.SOCAPRD  = 1;      /* Generate SOCA on the 1st event */     \
     EPwm1Regs.ETCLR.bit.SOCA  = 1;        /* Clear SOCA flag */
    //----------------------------------------------------------------------------------

     然后读取AD中断数据:


    interrupt void adc1_isr(void)
    {
     LoopCount++;
     m_voltage_ab = Adc1Result.ADCRESULT1;   //phase AB voltage
     m_voltage_bc = Adc1Result.ADCRESULT2;   //phase BC voltage
     m_voltage_ca = Adc1Result.ADCRESULT3;   //phase CA voltage
     m_current_ab = Adc1Result.ADCRESULT5;   //phase AB current
     m_current_bc = Adc1Result.ADCRESULT7;   //phase BC current
     m_current_ca = Adc1Result.ADCRESULT8;   //phase CA current
     m_voltage_mx = Adc1Result.ADCRESULT4;   //DC voltage
     m_current_mx = Adc1Result.ADCRESULT8;   //DC current

     m_voltage_output_add+=m_voltage_ca;

     if(LoopCount > 499)
      LoopCount = 0;
     //
    // uab_array[LoopCount] = m_voltage_ca;
    // ubc_array[LoopCount] = m_voltage_bc;
    // uca_array[LoopCount] = m_voltage_ca;

    // if(ConversionCount == 9)
    // {
    //  ConversionCount = 0;
    //  m_voltage_output_avg=(m_voltage_output_add*36)>>9;
    //  m_voltage_output_add = 0;
    // }
    // else
    //  ConversionCount ++;

     //m_vol_mx    = Adc1Result.ADCRESULT0;  //A0-DC line voltage
     //m_tempurature_pfc  = Adc1Result.ADCRESULT1;  //A1-PFC module temperature
     //m_output_cur_setting = Adc1Result.ADCRESULT2;  //A2-setting maxim DC output current
     //m_output_vol_setting = Adc1Result.ADCRESULT3;     //A3- setting the maxim output voltage
     //m_temperature_ext  = Adc1Result.ADCRESULT4;  //B0-temperature of exit point
     //m_current_xz   = Adc1Result.ADCRESULT5;  //B1-current of resonant
     //m_voltage_output  = Adc1Result.ADCRESULT6;  //B2-current of the output
     //m_current_output  = Adc1Result.ADCRESULT7;  //B3-current of DC output

        Adc1Regs.ADCINTFLGCLR.bit.ADCINT1 = 1;  //Clear ADCINT1 flag reinitialize
                                                // for next SOC
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE
    }

    发现读出的三相电压数据矢量和不等于零,

    TI示例程序中是两通道ADC1A0和ADC1A2的信号采集,我把通道都选择B7(15通道),读出的AD值也不一样

    main()
    {
        unsigned short analoginit;

    // Step 1. Initialize System Control for Control and Analog Subsytems
    // Enable Peripheral Clocks
    // This example function is found in the F28M35x_SysCtrl.c file.
        InitSysCtrl();
       
    // If project is linked into flash, copy critical code sections to RAM.   
    #ifdef _FLASH
       memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
    #endif   

    // Step 2. Initialize GPIO:
    // This example function is found in the F28M35x_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    // InitGpio();  // Skipped for this example
        EALLOW;
        GpioG1CtrlRegs.GPADIR.bit.GPIO0      = 1;       //Set as output
        GpioG1CtrlRegs.GPADIR.bit.GPIO8      = 1;       //Set as output
        GpioG1CtrlRegs.GPAMUX1.bit.GPIO0     = 1;      //Set mux to EPWM1A
        GpioG1CtrlRegs.GPAMUX1.bit.GPIO8     = 3;      //Set mux to ADCSOCAn
        EDIS;

        EALLOW;
        GpioG1CtrlRegs.GPCDIR.bit.GPIO69 = 1;
        GpioG1CtrlRegs.GPCDIR.bit.GPIO70 = 1;
        GpioG1CtrlRegs.GPCDIR.bit.GPIO71 = 1;
        EDIS;
        GpioG1DataRegs.GPCDAT.bit.GPIO69 = 1;
        GpioG1DataRegs.GPCDAT.bit.GPIO70 = 1;
        GpioG1DataRegs.GPCDAT.bit.GPIO71 = 0;

    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
        DINT;

    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the F28M35x_PieCtrl.c file.
        InitPieCtrl();

    // Disable CPU interrupts and clear all CPU interrupt flags:
        IER = 0x0000;
        IFR = 0x0000;

    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in F28M35x_DefaultIsr.c.
    // This function is found in F28M35x_PieVect.c.
        InitPieVectTable();

    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
        EALLOW; // This is needed to write to EALLOW protected register
        PieVectTable.ADCINT1 = &adc1_isr;
        EDIS;   // This is needed to disable write to EALLOW protected registers

    // Step 4. Initialize all the Device Peripherals:
    // This function is found in F28M35x_InitPeripherals.c
    // InitPeripherals(); // Not required for this example
        InitAdc1(); // For this example, init the ADC

    // Step 5. User specific code, enable interrupts:

    // Enable ADCINT1 in PIE
        PieCtrlRegs.PIEIER1.bit.INTx1 = 1;  // Enable INT 1.1 in the PIE
        IER |= M_INT1;                      // Enable CPU Interrupt 1
        EINT;                               // Enable Global interrupt INTM
        ERTM;                               // Enable Global realtime interrupt DBGM

        LoopCount = 0;
        ConversionCount = 0;
        delay = 0;

    // Configure ADC
        EALLOW;
        Adc1Regs.ADCCTL2.bit.ADCNONOVERLAP = 1;     // Enable non-overlap mode i.e.
                                                    // conversion and future
                                                    // sampling
                                                    // events dont overlap
        Adc1Regs.ADCCTL1.bit.INTPULSEPOS   = 1;     // ADCINT1 trips after
                                                    // AdcResults latch
        Adc1Regs.INTSEL1N2.bit.INT2E       = 1;     // Enabled ADCINT1
        Adc1Regs.INTSEL1N2.bit.INT1CONT    = 0;     // Disable ADCINT1 Continuous
                                                    // mode
        Adc1Regs.INTSEL1N2.bit.INT2SEL     = 0;     // setup EOC0 to trigger ADCINT1
                                                    // to fire
        Adc1Regs.ADCSOC0CTL.bit.CHSEL      = 15;     // set SOC0 channel select to
                                                    // ADC1A0
        Adc1Regs.ADCSOC1CTL.bit.CHSEL      = 15;     // set SOC1 channel select to
                                                    // ADC1A2
        AnalogSysctrlRegs.TRIG1SEL.all     = 5;     // Assigning EPWM1SOCA to
                                                    // ADC TRIGGER 1 of the ADC module
        Adc1Regs.ADCSOC0CTL.bit.TRIGSEL    = 5;     // Set SOC0 start trigger to
                                                    // ADC Trigger 1(EPWM1 SOCA) of the
                                                    // adc
        Adc1Regs.ADCSOC1CTL.bit.TRIGSEL    = 5;     // set SOC1 start trigger to
                                                    // ADC Trigger 1(EPWM1 SOCA) of the
                                                    // adc
        Adc1Regs.ADCSOC0CTL.bit.ACQPS      = 6;     // set SOC0 S/H Window to 7 ADC
                                                    // Clock Cycles, (6 ACQPS plus
                                                    // 1)
        Adc1Regs.ADCSOC1CTL.bit.ACQPS      = 6;     // set SOC1 S/H Window to 7 ADC
                                                    // Clock Cycles, (6 ACQPS plus
                                                    // 1)

        EDIS;

    //// Assumes ePWM1 clock is already enabled in InitSysCtrl();

        //Set event triggers (SOCA) for ADC SOC1
        EPwm1Regs.ETSEL.bit.SOCAEN         = 1;      // Enable SOC on A group
        EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTRU_CMPA;  // Select SOC from CMPA on
                                                     // upcount
        EPwm1Regs.ETPS.bit.SOCAPRD         = 3;      // Generate pulse on every 3rd
                                                     // event

        // Time-base registers
        EPwm1Regs.TBPRD = 2000;//PERIOD;                   // Set timer period, PWM
                                                    // frequency = 1 / period
        EPwm1Regs.TBPHS.all = 0;                    // Time-Base Phase Register
        EPwm1Regs.TBCTR = 0;                        // Time-Base Counter Register
        EPwm1Regs.TBCTL.bit.PRDLD = TB_IMMEDIATE;   // Set Immediate load
        EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;//TB_COUNT_UP;  // Count-up mode: used for
                                                    // asymmetric PWM
        EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;     // Disable phase loading
        EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
        EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
        EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

        // Setup shadow register load on ZERO

        EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
        EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
        EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR=Zero
        EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // load on CTR=Zero

        // Set Compare values

        EPwm1Regs.CMPA.half.CMPA = DUTY_CYCLE_A;     // Set duty 50% initially
        EPwm1Regs.CMPB = DUTY_CYCLE_B;               // Set duty 50% initially

        // Set actions

        EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;           // Set PWM2A on Zero
        EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;         // Clear PWM2A on event A, up
                                                     // count

        EPwm1Regs.AQCTLB.bit.ZRO = AQ_CLEAR;         // Set PWM2B on Zero
        EPwm1Regs.AQCTLB.bit.CBU = AQ_SET;           // Clear PWM2B on event B, up
                                                     // count

    // Wait for ADC interrupt
        for(;;)
        {
            LoopCount++;
         GpioG1DataRegs.GPCDAT.bit.GPIO69 = 0;
         GpioG1DataRegs.GPCDAT.bit.GPIO70 = 0;
         GpioG1DataRegs.GPCDAT.bit.GPIO71 = 1;
         for(delay =0 ;delay< 200000;delay++)
         {
         }
         GpioG1DataRegs.GPCDAT.bit.GPIO69 = 1;
         GpioG1DataRegs.GPCDAT.bit.GPIO70 = 1;
         GpioG1DataRegs.GPCDAT.bit.GPIO71 = 0;
         for(delay =0 ;delay< 200000;delay++)
         {
         }
        }

    }

    interrupt void  adc1_isr(void)
    {
        Voltage1[ConversionCount] = Adc1Result.ADCRESULT0;
        Voltage2[ConversionCount] = Adc1Result.ADCRESULT1;
        Voltage3[ConversionCount] = Adc1Result.ADCRESULT2;
        Voltage4[ConversionCount] = Adc1Result.ADCRESULT3;
        Voltage5[ConversionCount] = Adc1Result.ADCRESULT4;
        Voltage6[ConversionCount] = Adc1Result.ADCRESULT5;
        Voltage7[ConversionCount] = Adc1Result.ADCRESULT6;
        Voltage8[ConversionCount] = Adc1Result.ADCRESULT7;
        Voltage9[ConversionCount] = Adc1Result.ADCRESULT8;

        // If 20 conversions have been logged, start over
        if(ConversionCount == 9)
        {
            ConversionCount = 0;
        }
        else ConversionCount++;

        Adc1Regs.ADCINTFLGCLR.bit.ADCINT1 = 1;  //Clear ADCINT1 flag reinitialize
                                                // for next SOC
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE

        return;
    }

    不知道该怎么配置初始化程序,求高手指点,谢谢!
     

     

     

  • Wang,

    可以参考例程C:\ti\controlSUITE\device_support\f28m35x\v200\F28M35x_examples_Control\adc_soc

    如果要使用一个触发源触发8 个通道的话,

    只要设置8个SOC,然后使用相同的TRIGSEL,再给个输入通道,配置采样窗,采样窗有些值不能设,要看user guide关于采样窗的说明。当然也可以按照例程来写。

    Eric

  • 另外关于语句:

    AdclogSysCtrlRegs.TRIG1SEL.all = 5;

    Adc1Regs.ADCSOC0CTL.bit.TRIGSEL =5;        //选用EPWM1A 作为触发源。

    我认为第二条语句更属于TI的编程习惯。

    第二条语句是对SOC触发源的配置。至于第一条语句,从字面上看是相同意思,但看似不符合TI的编程命名规范,需要查看文件中关于这个结构体的具体定义,看是对应哪个寄存器。

    Eric

  • 谢谢Eric Ma先生的回答!

      我用C:\ti\controlSUITE\device_support\f28m35x\v200\F28M35x_examples_Control\adc_soc示例程序来运行,仅仅改变通道号从A0,A2改为B7,B7,输入一个正弦波,按道理来说,采集出来的结果应该是很接近的,但实际上差别太大,AdcResult0为2800,,AdcResult1甚至是700,就是这点感觉太离谱,相邻转换应该是一个触发源到来之后,每个通道挨个转换,其间的时间差也就570ns左右,怎么也不会得到那么悬殊的结果;

    还有一个问题,ADC中断有在PIE-vector中有1.1-Adc1、1.2-Adc2两个中断,同时还有pie10中的ADC1到ADC8中断,我没看到手册中介绍这部分怎么区分的,示例程序中也是用的1.1-Adc1中断。

  • 谢谢Eric!

         我自己搞错了,我始终盯着Watch上的变量在看,相同通道在Watch里显示的确实数值悬殊,但是这可能是一个假象。

         我用RUN->STOP,停下来去观察AdcResult的数值,发现数据只相差一点点,符合要求。

         总结一下,就是盯着Watch看到的参数并不是同一时间采样的,也就是Watch刷新不是每个变量都实时的。

     

  • Wang,

    可以使用realtime的模式debug,然后点击watchwindow右上角的continuous refresh。

    就可以观察到实时数据。

    Eric

  • 可否跟您请教一下 ADC的一些问题  我用的也是F28M35   在查看采集的电压信号时, 电压数组中的数据不正常。不知道具体原因

  • 这是什么意思? result0中赋值到数组一个数组中  难道这个数组中的数值不是相邻采样得到的?

  • Rufeng,

    你可以新开一个帖子,然后把问题描述的更具体一点。

    也可以把ADC的初始化配置贴出来。

    Eric

  • 如果是三相电压采集,你用clarke变换看一看三个结果相加是否为零,如果不为零,应该采集的有问题了。

    AD的设置就是例子ADConvert中的一样的。

  • 谢谢 大侠的关注, 我已经调试出来了~  设置没看仔细 哈哈哈……

  • 谢谢 大侠的解答……我已经调试出……哈哈哈