f28027 ADC详细学习过程

  • Post author:
  • Post category:其他




adc简介

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述




SOC



TMS320F28027的ADC为3型,是基于SOC的而不是基于序列的。SOC是一种配置设置,它定义的是单通道单转换。包含3个配置:启动转换的触发源、转换通道、采样保持窗口。每个SOC都是单独配置,即触发源、通道、采样保持窗口可任意组合,可实现从“使用不同触发器、不同通道的单独采样”到“使用单个触发器、相同通道的过采样”。



在这里插入图片描述

  1. ADCSOCxCTL: SOCx控制寄存器 (x =0~15)
  2. ADCSOCFLG: SOC标志寄存器



触发源 4个

在这里插入图片描述



通道 A/B 8个

在这里插入图片描述




采样保持窗口:

	**外部驱动能力的不同影响推动模拟信号速度和有效性。有一些电路需要更长的时间,使电荷正确地转移到ADC的采样电容。为了满足需求,ADC可以在SOC中独立地控制采样窗口的宽度。每个ADCSOCxCTL寄存器都有6位域,ACQPS,用来决定采样保持窗口的大小。写到这个位域的值要比期望的采样保持窗口的包括的周期要少1。例如:位域的值为15,那就需要16个周期来采样。允许最少的采样周期是7(ACQPS=6)。完成一次转换的时间由采样时间加转换时间(13个ADC时钟)组成**
	![在这里插入图片描述](https://img-blog.csdnimg.cn/20190713123849733.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMDMzNTQ3,size_16,color_FFFFFF,t_70)



受EALLOW保护



在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

adc的连接

在这里插入图片描述

在这里插入图片描述

例如,要确保通道ADCINA1上的单个转换在ePWM3计时器达到其周期匹配时发生,必须首先设置ePWM3,以便在周期匹配上输出SOCA或SOCB信号。参见TMS320x2802x Piccolo增强脉冲宽度调制器模块用户指南(SPRUGE9),了解如何做到这一点。在本例中,我们将使用SOCA。然后,使用它的ADCSOCxCTL寄存器设置SOC中的一个。我们选择哪个soc无关紧要,所以我们将使用SOCO。ADC最快的采样窗口为7个循环。为示例窗口选择最快的时间,通道ADCINA1用于通道转换,ePWM3用于SOCO触发器,我们将设置ACQPS字段到6,CHSEL字段到1和TRIGSEL字段到9。写入寄存器的结果值为:

当这样配置时,将在ePWM3 SOCA事件上启动一次ADCINA1的转换,其结果值存储在ADCRESULTO寄存器中。如果ADCINA1需要3倍的过采样。可以给soc1 soc2 SoC3赋予与SOco相同的构型

外部驱动程序能够快速有效地驱动模拟信号。有些电路需要更长的时间才能正确地将电荷转移到ADC的采样电容中。为了解决这个问题,ADC支持控制样本窗口长度为每个单独的SOC实现方式。每个ADCSOCxCTL reaister都有一个6位字段ACQPS。这决定了采样和保持(S/H)窗口大小写入该字段的值比该SOC的采样窗口所需的周期数少一个。因此,该字段中的值15将给出16个时钟周期的采样时间。允许的最小采样周期数为7 (ACQPS-6)。总采样时间是通过将采样窗口大小添加到ADC的转换时间中得到的。13 ADC的时钟。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

ADC编程步骤

在这里插入图片描述

初始化程序 123固定

void InitAdc(void)
{
    extern void DSP28x_usDelay(Uint32 Count);

    // *IMPORTANT*
    // The Device_cal function, which copies the ADC calibration values from TI reserved
    // OTP into the ADCREFSEL and ADCOFFTRIM registers, occurs automatically in the
    // Boot ROM. If the boot ROM code is bypassed during the debug process, the
    // following function MUST be called for the ADC to function according
    // to specification. The clocks to the ADC MUST be enabled before calling this
    // function.
    // See the device data manual and/or the ADC Reference
    // Manual for more information.

        EALLOW;
        SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;//使能ADC模块时钟
        (*Device_cal)();
        EDIS;

    // To powerup the ADC the ADCENCLK bit should be set first to enable
    // clocks, followed by powering up the bandgap, reference circuitry, and ADC core.
    // Before the first conversion is performed a 5ms delay must be observed
    // after power up to give all analog circuits time to power up and settle

    // Please note that for the delay function below to operate correctly the
    // CPU_RATE define statement in the DSP2802x_Examples.h file must
    // contain the correct CPU clock period in nanoseconds.
    EALLOW;
    AdcRegs.ADCCTL1.bit.ADCBGPWD  = 1;      // Power ADC BG  带隙
    AdcRegs.ADCCTL1.bit.ADCREFPWD = 1;      // Power reference 参考源
    AdcRegs.ADCCTL1.bit.ADCPWDN   = 1;      // Power ADC 启动模拟电路
    AdcRegs.ADCCTL1.bit.ADCENABLE = 1;      // Enable ADC  使能ADC
    AdcRegs.ADCCTL1.bit.ADCREFSEL = 0;      // Select interal BG 选择内部带隙
    EDIS;

    DELAY_US(ADC_usDELAY);         // Delay before converting ADC channels
}
初始化函数已经把我们的前三步都做完了,也就是使能时钟、上电、使能ADC模块;
 
那我们现在来进行SOC相关设置,也就是:触发源、采样时隙、通道选择。 
*触发源*我们选择定时器0,因为我们做测试肯定输入一个稳定的直流电压,那用定时器最方便。 
AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 1; 

采样时隙就用最短时隙,也就是AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; 	

由于TI那个实验板只引出了几个ADC引脚而已,我们就用ADCINA1,也就是 AdcRegs.ADCSOC0CTL.bit.CHSEL = 1;

另外,我们说了,我们本次的实验是顺序采样,迟中断,那就是:

AdcRegs.ADCSAMPLEMODE.bit.SIMULEN0 = 1;

AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1;

到这里SOC相关设置就完成了

 AdcRegs.ADCSOC0CTL.bit.CHSEL         = 1;        //set SOC0 channel select to ADCINA0              选择AD通道  1
 AdcRegs.ADCSOC0CTL.bit.TRIGSEL         = 1;        //set SOC0 start trigger on timer 0 only          选择AD触发方式
 AdcRegs.ADCSOC0CTL.bit.ACQPS         = 6;        //set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)  配置转换时间
 AdcRegs.ADCSAMPLEMODE.bit.SIMULEN0 = 1;  //顺序采样
 AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; 
 EDIS;

在这里插入图片描述

在这里插入图片描述

最后还要再PIE组里面打开ADCINT1开关:PieCtrlRegs.PIEIER1.bit.INTx1 = 1;

ADC中断函数就一个置位:

interrupt void ADCINT1_ISR(void)   // ADC  (Can also be ISR for INT10.1 when enabled)
{
  // Insert ISR Code here

  // To receive more interrupts from this PIE group, acknowledge this interrupt
   PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

  // Next two lines for debug only to halt the processor here
  // Remove after inserting ISR Code

  //asm ("      ESTOP0");
  //for(;;);

}

定时器

void InitCpuTimers(void)
{
    // CPU Timer 0
    // Initialize address pointers to respective timer registers:
    CpuTimer0.RegsAddr = &CpuTimer0Regs;
    // Initialize timer period to maximum:
    CpuTimer0Regs.PRD.all  = 1000;
    // Initialize pre-scale counter to divide by 1 (SYSCLKOUT):
    CpuTimer0Regs.TPR.bit.TDDR  = 59;
    CpuTimer0Regs.TPRH.bit.TDDRH = 0;
    // Make sure timer is stopped:
    CpuTimer0Regs.TCR.bit.TSS = 1;
    // Reload all counter register with period value:
    CpuTimer0Regs.TCR.bit.TRB = 1;
    // Reset interrupt counters:
    CpuTimer0.InterruptCount = 0;

// CpuTimer 1 and CpuTimer2 are reserved for DSP BIOS & other RTOS
// Do not use these two timers if you ever plan on integrating
// DSP-BIOS or another realtime OS.
//
// Initialize address pointers to respective timer registers:
    CpuTimer1.RegsAddr = &CpuTimer1Regs;
    CpuTimer2.RegsAddr = &CpuTimer2Regs;
    // Initialize timer period to maximum:
    CpuTimer1Regs.PRD.all  = 0xFFFFFFFF;
    CpuTimer2Regs.PRD.all  = 0xFFFFFFFF;
    // Initialize pre-scale counter to divide by 1 (SYSCLKOUT):
    CpuTimer1Regs.TPR.all  = 0;
    CpuTimer1Regs.TPRH.all = 0;
    CpuTimer2Regs.TPR.all  = 0;
    CpuTimer2Regs.TPRH.all = 0;
    // Make sure timers are stopped:
    CpuTimer1Regs.TCR.bit.TSS = 1;
    CpuTimer2Regs.TCR.bit.TSS = 1;
    // Reload all counter register with period value:
    CpuTimer1Regs.TCR.bit.TRB = 1;
    CpuTimer2Regs.TCR.bit.TRB = 1;
    // Reset interrupt counters:
    CpuTimer1.InterruptCount = 0;
    CpuTimer2.InterruptCount = 0;

}

定时器中断

interrupt void  TINT0_ISR(void)      // CPU-Timer 0
{
  // Insert ISR Code here

  // To receive more interrupts from this PIE group, acknowledge this interrupt
  PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

  // Next two lines for debug only to halt the processor here
  // Remove after inserting ISR Code
//  asm ("      ESTOP0");
//  for(;;);
}

相关中断设置

   CpuTimer0Regs.TCR.bit.TIE = 1;
   StartCpuTimer0();
   EALLOW;
   PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
   PieCtrlRegs.PIECTRL.bit.ENPIE = 1;
   IER |= 0x0001;
   EINT;
   EDIS;

显示

   while(1)
   {
       if(AdcRegs.ADCSOCFLG1.bit.SOC0==1)
       {
           while(AdcRegs.ADCSOCFLG1.bit.SOC0==1);
           AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
           DELAY_US(10);
           sum+=AdcResult.ADCRESULT0;
           i++;
       }
       if(i==100)
       {
           sum/=100;
           vol=sum*3.3/4095;
           WRITECMD_LCD12864(0x01);
           DISLPLAY_LONGSTRING(2,0,sum);
           DISLPLAY_FLOATSTRING(3,0,vol);
           WRITEDATA_LCD12864('v');
           sum=0;
           i=0;
       }
   }

主要参考:

https://blog.csdn.net/BHK_SOFTWARE/article/details/52137577


寄存器讲解

https://wenku.baidu.com/view/e14aaf55d15abe23492f4d52.html?pn=51


程序代码

https://blog.csdn.net/w471176877/article/details/8049697



http://bbs.eeworld.com.cn/thread-475877-1-1.html

	 主频:60M
     描述:练习ADC,同时采样模式,ADCINA4与ADCINB4
     CPU TIM0为触发,同时采样两路电压
#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
#include "LEDs.h"

interrupt void tim0_isr(void);
interrupt void ADC_convered(void);

Uint16 ADCINA4_Voltage_sum = 0;
Uint16 ADCINB4_Voltage_sum = 0;
Uint16 ADCINA4_Voltage = 0;
Uint16 ADCINB4_Voltage = 0;
char convered_count = 0;

void main(void)
{

// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2802x_SysCtrl.c file.
   InitSysCtrl();

// Step 2. Initalize GPIO:
// This example function is found in the DSP2802x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio();  // Skipped for this example


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

// Initialize 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 DSP2802x_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 DSP2802x_DefaultIsr.c.
// This function is found in DSP2802x_PieVect.c.
   InitPieVectTable();


// Step 4. Initialize all the Device Peripherals:
// This function is found in DSP2802x_InitPeripherals.c
// InitPeripherals(); // Not required for this example

// Step 5. User specific code:

   InitAdc();

   EALLOW;

   AdcRegs.ADCSAMPLEMODE.bit.SIMULEN0 = 1; //同时采样
   AdcRegs.ADCSOC0CTL.bit.CHSEL = 4;       //soc通道选择
   AdcRegs.ADCSOC1CTL.bit.CHSEL = 12;
   AdcRegs.ADCSOC0CTL.bit.ACQPS = 6;     //采样时间
   AdcRegs.ADCSOC1CTL.bit.ACQPS = 6;
   AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 1;    //soc触发选择,TIM0
   AdcRegs.ADCCTL1.bit.INTPULSEPOS	= 1;  //结果存入寄存器才产生中断

   PieVectTable.ADCINT1 = &ADC_convered;
   AdcRegs.INTSEL1N2.bit.INT1SEL = 1;    //中断线1选择soc1
   AdcRegs.INTSEL1N2.bit.INT1CONT  = 0;
   AdcRegs.INTSEL1N2.bit.INT1E	= 1;	//中断使能

   PieCtrlRegs.PIEIER1.bit.INTx1 = 1;	//使能int1.1
   EDIS;

/****************设置定时器,用以触发ADC*****************/
   CpuTimer0Regs.TPR.bit.TDDR = 59;
   CpuTimer0Regs.TPRH.bit.TDDRH = 0; //对输入时钟60分频,60M/60=1M
   CpuTimer0Regs.PRD.all = 500000;//定时0.5s
   CpuTimer0Regs.TCR.bit.TRB = 1; //reload
   CpuTimer0Regs.TCR.bit.TIE = 1; //使能中断
   CpuTimer0Regs.TCR.bit.TSS = 0; //开始计数

   EALLOW;
   PieVectTable.TINT0 = &tim0_isr;
   PieCtrlRegs.PIECTRL.bit.ENPIE = 1;	//使能PIE
   PieCtrlRegs.PIEIER1.bit.INTx7 = 1;	//使能int1.7
   IER |= 0x0001;//使能GROUP1
   EINT;
   EDIS;

   LEDs_init();
   while(1)
   {
   };
}

interrupt void ADC_convered(void)
{

	LED_toggle(LED2);
	ADCINA4_Voltage_sum += AdcResult.ADCRESULT0;
	ADCINB4_Voltage_sum += AdcResult.ADCRESULT1;
	AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
	PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
	convered_count++;
	/*********转换16次,取平均值*********/
	if(convered_count > 15)
	{
		ADCINA4_Voltage = ADCINA4_Voltage_sum >> 4;//相当于除以16
		ADCINB4_Voltage = ADCINB4_Voltage_sum >> 4;
		ADCINA4_Voltage_sum = 0;
		ADCINB4_Voltage_sum = 0;
		convered_count = 0;
	}
}

interrupt void tim0_isr(void)
{
	LED_toggle(LED0);
	PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
--------------------- 
作者:w471176877 
来源:CSDN 
原文:https://blog.csdn.net/w471176877/article/details/8049697 
版权声明:本文为博主原创文章,转载请附上博文链接!
		配置ADC单通道软件强制转换 ,配合程序来解释ADC配置的思路。
    step 1InitSysCtrl();  // 系统初始化子程序,在DSP28_sysctrl.c中,PLL,关闭看门狗,使能外围模块
    step 2InitPieCtrl();  //初始化PIE控制寄存器,恢复默认设置
              IER = 0x0000;//CPU禁止使能
              IFR = 0x0000;//清楚CPU所有中断标志
              InitPieVectTable();//初始化PIE向量表
    step 3:
              //初始化ADC
            EALLOW;  //使能ADC模块的时钟
            SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;
             (*Device_cal)();
             EDIS;
    step 4:
            EALLOW;                            //这部分官方手册建议就按这个顺序配置
            AdcRegs.ADCCTL1.bit.ADCBGPWD  = 1;      // Power ADC BG
            AdcRegs.ADCCTL1.bit.ADCREFPWD = 1;      // Power reference
            AdcRegs.ADCCTL1.bit.ADCPWDN   = 1;      // Power ADC
            AdcRegs.ADCCTL1.bit.ADCENABLE = 1;      // Enable ADC
            AdcRegs.ADCCTL1.bit.ADCREFSEL = 0;      // Select interal BG
           EDIS;
           DELAY_US(ADC_usDELAY);         // Delay before converting ADC channels    step 5:
          EALLOW;          AdcRegs.INTSEL1N2.bit.INT1E     = 1;        //使能    ADCINT1
          //ADCSOCxCTL    x可设置0--15,CHSEL 选择AD输入通道
          AdcRegs.ADCSOC0CTL.bit.CHSEL         = 0;        //set SOC0 channel select to ADCINA0              选择AD通道
          AdcRegs.ADCSOC0CTL.bit.TRIGSEL         = 0;        //set SOC0 start trigger on software only          选择AD触发方式
          AdcRegs.ADCSOC0CTL.bit.ACQPS         = 6;        //set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)  配置转换时间
          EDIS;
   step 6:
           // 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

                for(;;)
                  {
                //Force start of conversion on SOC0 
                AdcRegs.ADCSOCFRC1.all = 0x01;
                DELAY_US(1000000);//delay 1s   在死循环里面这样写就可以每1S就会强制ADC转换一次

                  }
         //以下是中断服务函数

interrupt void  adc_isr(void)
{
  Voltage = AdcResult.ADCRESULT0;  //读取AdcResult的值要与自己相对应配置的SOCx相对应,这个程序配置的是SOC0,所以要读取ADCRESULT0。
  vol=Voltage*3.3/4096;
  AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;                //Clear ADCINT1 flag reinitialize for next SOC
  PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE
  return;
}




版权声明:本文为qq_43033547原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。