参考文档SPRUGE5FTMS320F28027的ADC功能:1.12位双采样保持电路。2.同时采样和序列采样方式。3.全范围电压输入,0V到3.3V固定,或者VREFLO到VREFHI可调。4.系统时钟全频运行,无需分频。5.16输入通道。6.16个SOC配置,设置触发,采样窗口,通道。7.16个独立保存转换结果的结果寄存器。8.多触发源。9.9个灵活的PIE中断。SOC操作原理:与以往的ADC类型不同,TMS320F28027的ADC为3型,它是基于SOC的而不是基于序列的。SOC可以配置定义一个单独通道的独立转换。包括三种配置:开始转换的触发源,转换的通道,采样窗口的大小。每个SOC是独立配置的,可以有很多种触发源,通道,采样窗口大小的组合。如果需要,多个SOC可以配置成一样的触发源,通道,采样窗口大小。这提供了一种灵活的配置方法。可以配置转换在不同通道用不同的触发独立采样。可以用一个单独的触发过采样一个相同的通道。可以创建同一个触发不同通道的转换序列。SOCx的触发源由ADCSOCxCTL寄存器中的TRIGSEL和ADCINTSOCSEL1或 ADCINTSOCSEL2 寄存器配置。软件可以通过ADCSOCFRC1寄存器产生一个SOC事件。通道和采样窗口大小可以通过ADCSOCxCTL寄存器的CHSEL和ACQPS配置。采样保持窗口:外部驱动能力的不同影响推动模拟信号速度和有效性。有一些电路需要更长的时间,使电荷正确地转移到ADC的采样电容。为了满足需求,ADC可以在SOC中独立地控制采样窗口的宽度。每个ADCSOCxCTL寄存器都有6位域,ACQPS,用来决定采样保持窗口的大小。写到这个位域的值要比期望的采样保持窗口的包括的周期要少1。例如:位域的值为15,那就需要16个周期来采样。允许最少的采样周期是7(ACQPS=6)。完成一次转换的时间由采样时间加转换时间(13个ADC时钟)组成。ONESHOT单次转换支持:该模式将允许你在循环计划的下一个SOC触发时,执行一次循环转换。这种模式只适用于循环轮中的通道。那些没有配置在循环轮中触发的通道,将会基于ADCSOCPRIORITYCTL寄存器中的SOCPRIORITY确定优先级。 ONESHOT模式对顺序和同时采样方式作用如下:顺序模式:只有在RR模式中的下一个激活的soc才允许生成。触发其它所有的soc均会被忽略。同时模式:如果当前RR指针指向的SOC使能了同时采样方式,激活的SOC会从当前的指针增加到二个,这是因为同时采样方式会产生SOCx和SOCx+1的结果,而且SOCx+1不会被用户触发。AD转换的优先级: 当数个SOC标志同时被设置,两种形式的优先级顺序中的一种决定它们转换的顺序。默认的决定方式是轮转。在这种策略中,没有某个SOC会有比其它更高的优先级。优先级由轮转指针决定。ADCSOCPRIORITYCTL寄存器中的RRPOINTER指向最后转换的SOC。最高优先级SOC就是下一个比RRPOINTER值大的SOC,在SOC0到SOC15中轮回。复位时的值是32,因为0表示转换已经发生。当RRPOINTER值为32,最高优先级的是SOC0。当ADCCTL1.RESET被置位或者SOCPRICTL寄存器被写入,RRPOINTER被设备复位。ADCSOCPRIORITYCTL寄存器的SOCPRIORITY可用于配置所有SOC的优先级。如果一个SOC被设置成高优先级,它将会当前转换完成之后中断轮转,把自己插入到下一次转换中。当转换完成,轮转在被中断处继续。如果两个高优先级的SOC同时被触发,编号较低的SOC被优先考虑。同时采样模式:在某些应用中,保持两个采样的信号之间的最小延迟是非常重要的。ADC模块包括双采样保持电路,允许两个不同的通道同时采样。同时采样模式是通过ADCSAMPLEMODE寄存器为两个soc配置的。偶数SOC与接着的奇数SOC作为一对,使用同一个使能位。这一对的动作如下:1. 其中一个SOCx的触发将开始一对的转换。2. 一对通道的转换包括A和B对应的CHSEL的值(0-7)。3. 两个通道同时采样。4. A通道先转换。5. A通道转换结束,偶数EOCx将会产生一个脉冲。B通道转换结束,奇数EOCx将会产生一个脉冲。6. A通道的转换结果将会存放在偶数ADCRESULTx寄存器中,A通道的转换结果将会存放在偶数ADCRESULTx寄存器中。转换结束和中断操作:由于有16个独立的SOCx配置,所以有16个EOCx标志。在序列采样中,EOCx是直接与SOCx相关联的。在同时采样模式中,如上5所述。根据ADCCTL1.INTPULSEPOS的设定,EOCx脉冲将会发生在转换开始或者结束时。 ADC模块包括9个能被PIE标志或者通过PIE的中断,每个中断都可以配置接受EOCx信号作为中断源。哪个EOCx信号作为中断源是在INTSELxNy寄存器中配置的。另外,ADCINT1和ADCINT2信号可作为一个SOCx的触发。这有利于建立一个连续的转换。上电序列:ADC复位后是关闭状态。在写任意ADC寄存器之前必须置位PCLKCR0寄存器中的ADCENCLK位。启动ADC的操作序列如下:1. 如果希望使用外部参考源,在ADCCTL1寄存器的ADCREFSEL中使能这种模式。2. 在ADCCTL1寄存器(5-7位ADCPWDN,ADCBGPWD,ADCREFPWD)中一起启动参考源,带隙和模拟电路。3. 通过设置ADCCTL1寄存器的ADCENABLE使能ADC。4. 在首次转换之前延时1毫秒。ADC校准:任何转换器都固有一个零偏移误差和满量程的增益误差。该ADC出厂校时在25摄氏度校正两者,同时允许用户修改任何偏移量的校正应对应用程序环境的影响,如环境温度。除非处在某些仿真环境下,或者需要修改出厂设置,用户不需要执行任何特定的操作。ADC将会在设备引导过程中得到合适的校正。厂家设定与校准功能:在制造和测试过程中,德州仪器伴随着一对内部晶振的设置,校正一些ADC设置。这些设置内嵌在保留的OTP memory中,作为一个C语言可调用函数Device_cal(),在Boot ROM启动引导过程中,程序调用这个函数写出厂设置到各个有效寄存器。在这种情况发生时,ADC和内部振荡器不会保留他们的指定参数。如果引导程序在仿真过程中被跳过,用户必须确保校准设置能被写入各寄存器,以确保ADC和内部振荡器满足在数据手册中的要求。这可以手动调用Device_cal(),或者在应用程序中设定。ADC零点偏移校准:零点偏移误差被定义为,当转换一个在VREFLO电压时得到的结果。这个基本误差会影响ADC的所有转换,包括满刻度的增益和线性度指标,决定了转换器的直流精度。零点偏移误差可能是正的,或者是负的,正的意味着转换VREFLO时得到一个正的结果。负的意味着转换一个高于VREFLO的电压结果仍会是0。为了更正这种错误,两种误差的补码都会被写入ADCOFFTRIM寄存器。这个寄存器的值在AD转换结果保存到ADC结果寄存器之前会被用到。此操作被完全包含在ADC内核,所以结果的定时将不会受到影响,ADC能够保持全动态范围通过修改微调值。调用Device_cal()把厂家校正的零点偏移写到ADCOFFTRIM寄存器,用户能够修改ADCOFFTRIM的值以减少环境造成偏移误差。这个可以通过设置ADCCTRL1的VREFLOCONV位实现,不需要任何一个ADC通道。如下步骤重新校准ADC偏移:1. Set ADCOFFTRIM to80 (50h)2. SetADCCTL1.VREFLOCONV to 13. Perform multiple conversions on B5 (i.e. sampleVREFLO) and take an average to account for board noise4. Set ADCOFFTRIM to 80 (50h) minus the averageobtained in step 35. SetADCCTL1.VREFLOCONV to 0.文件DSP2802x(3x)_Adc.c中的AdcOffsetSelfCal()函数实现了以上操作。ADC满量程增益校准:增益错误是一个增量,随着输入电压的增加。满量程增益错误发生在输入电压最大值的时候。如同偏移误差一样,增益误差可能是正的也可能是负的。一个正的满量程增益误差,意味着输入未来最大值之前转换结果就已经到达最大值。一个负的满量程增益误差,意味着转换结果永远达不到最大值。校正函数Device_cal()会写一个厂家调整值到ADCREFTRIM寄存器以矫正ADC的满量程增益误差。这个寄存器在调用Device_cal()之后不应该被改动。ADC偏移电流校正:为了增加ADC的精度,Device_cal()函数同样会向ADC的一个寄存器写入厂家调整值矫正偏移电流,这个寄存器在调用Device_cal()之后不应该被修改。程序设计: 以CPU TIM0为触发,同时采样两路电压。
程序:/*********************************************
标题:ADC_test.c
软件平台:CCS v5.2
硬件平台:C2000 LaunchPad
主频:60M
描述:练习ADC,同时采样模式,ADCINA4与ADCINB4
基于2802x C/C++ Header Files V1.26
author:小船
data:2012-10-08
As supplied, this project is configured for "boot to SARAM"
operation. The 2802x Boot Mode table is shown below.
$Boot_Table
While an emulator is connected to your device, the TRSTn pin = 1,
which sets the device into EMU_BOOT boot mode. In this mode, the
peripheral boot modes are as follows:
Boot Mode: EMU_KEY EMU_BMODE
(0xD00) (0xD01)
---------------------------------------
Wait !=0x55AA X
I/O 0x55AA 0x0000
SCI 0x55AA 0x0001
Wait 0x55AA 0x0002
Get_Mode 0x55AA 0x0003
SPI 0x55AA 0x0004
I2C 0x55AA 0x0005
OTP 0x55AA 0x0006
Wait 0x55AA 0x0007
Wait 0x55AA 0x0008
SARAM 0x55AA 0x000A <-- "Boot to SARAM"
Flash 0x55AA 0x000B
Wait 0x55AA Other
Write EMU_KEY to 0xD00 and EMU_BMODE to 0xD01 via the debugger
according to the Boot Mode Table above. Build/Load project,
Reset the device, and Run example
$End_Boot_Table
**********************************************/
#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;
}
//===========================================================================
// No more.
//===========================================================================
程序运行结果: