程序说明

  • 文件名:main.c
  • 描 述:DSP-28027ADC实验
  • 版本号:v1.0.0
  • 型 号:DSP-28027

实验内容

  1. 根据模拟量与数字量的关系求出A4引脚实际的电压值(模拟量)。注意:要求100次ADC的均值!(均值的求解在main 中进行!设置一个标志位,用于标示数据采集是否完成)
  2. 将上述试验1中ADC由PWM触发改为利用定时器0触发(1ms触发一次,即定时器周期为1ms),其他不做变动。

实验笔记

寄存器ADCSOCxCTL中的TRIGSEL位、寄存器ADCINTSOCSEL1或者ADCINTSOCSEL2中的相应位写入合适的值,可以完成SOCx的触发源设置(后2个寄存器用于连续ADC);也可以通过寄存器ADCSOCFRC1的SOC事件来软件强迫触发ADC。

通过寄存器ADCSOCxCTL的位CHSEL和位ACQPS的配置可以选择ADC的通道和采样窗口长度。

ADCSOCxCTL寄存器都有一个6位的域ACQPS, 此位域决定了S/H窗的长度(需要注意:采样窗长度=ACQPS值+1个ADC时钟周期),最小采样窗长度为7(ACQPS=6)。将模拟信号转换为数字信号的总长度为AD转换时间+采样窗长度,例如当系统时钟为60MHz时,采样窗长度为7时对应的采样时间为116.67ns,ADC时间为216.67ns,所以总的模拟信号转换时间为333.34ns。---(3MHz)

中断源的选择受寄存器ADCSOCxCTL位TRIGSEL的控制,多个SOC可以配置为相同的触发源。

寄存器ADCSOCxCTL中的域CHSEL决定了要转换的通道,当SOC配置为同步采样模式(simultaneous sampling mode)时,CHSEL的最高位被舍弃,剩下的低三位决定了同步采样的两个通道。

程序演示

悬空状态
接3.3v引脚
接地

程序代码

#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
interrupt void adc_isr(void);//ADC中断服务程序
interrupt void cpu_timer0_isr(void);//定时器0的中断服务程序
void Adc_Config(void);//ADC配置程序
// 用到的变量:
Uint16 ConversionCount=0;
Uint16 Voltage1[100];
Uint16 Voltage2[100];

int flag = 0;    //计算完成标志位
Uint32 Vcctage = 0;   //采集值求和
Uint16 Vcc_ave = 0;   //采集值取平均
float Vcc = 0;       //输出转换后的结果值

void main()
{
    // 初始化系统控制:PLL,看门狗,使能外围时钟,见DSP281x_SysCtrl.c
    InitSysCtrl();
    DINT; //关闭总中断
    InitPieCtrl();//初始化PIE控制寄存器,缺省状态为PIE中断禁止,标志位清除。见DSP2802x_PieCtrl.c
    IER = 0x0000;//关闭外设中断:Disable CPU interrupts
    IFR = 0x0000;//清除中断标志:clear all CPU interrupt flags
    InitPieVectTable();//初始化PIE向量表,使得指针指向各自中断服务子程序,在本例中未用到的中断也会//被初始化
    //默认ISR 子程序见 DSP2802x_DefaultIsr.c.
    //InitPieVectTable()见 DSP2802x_PieVect.c.
    // 设置中断服务程序入口
    InitCpuTimers(); //in DSP2802x_CpuTimers.c
    ConfigCpuTimer(&CpuTimer0, 60, 1000);//设置周期为10us 1毫秒
    CpuTimer0Regs.TCR.all = 0x4001; // Use write-only instruction to set TSS bit = 0
    StopCpuTimer0();//暂停Timer0// #define StopCpuTimer0()   CpuTimer0Regs.TCR.bit.TSS = 1
    StartCpuTimer0();//启动Timer0//#define StartCpuTimer0()   CpuTimer0Regs.TCR.bit.TSS = 0

    EALLOW;    // 允许写入受EALLOW保护的寄存器
    PieVectTable.TINT0 = &cpu_timer0_isr;//设置中断服务程序入口
    PieVectTable.ADCINT1 = &adc_isr;
    EDIS;    // 禁止写入受EALLOW保护的寄存器
    InitAdc();  // 初始化ADC,见文件“DSP2802x_Adc.c”
    IER |= M_INT1;                      // 使能CPU中断 1
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1;    // 使能中断,ADC的中断在PIE Group 1.1
    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;  //允许 TINT0 ,在 PIE的 Group 1 ,interrupt 7

    EINT;    //使能全局中断INTM
    ERTM;   // 开启全局实时中断 DBGM

    ConversionCount = 0;
    Adc_Config();//配置ADC
    // 以下一直循环运行,等待ADC中断
     for(;;)
     {
         if(flag == 1)
         {
             Vcc_ave = Vcctage / 100;
             Vcctage = 0;
             Vcc = (float)Vcc_ave / 4095 * 3.3;
             flag = 0;
         }
     }
}//main

interrupt void  adc_isr(void)
{
    if(flag == 0)
    {
        Voltage1[ConversionCount] = AdcResult.ADCRESULT1;  //A4引脚取第2次的采样值
        Voltage2[ConversionCount] = AdcResult.ADCRESULT2;

        Vcctage +=  Voltage1[ConversionCount];

        if (ConversionCount >= 99)
        {
            flag = 1;
            ConversionCount = -1;
        }

        ConversionCount++;
    }
    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;        //清除ADCINT1标志位以允许后续中断
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // PIE的中断应答
}
void Adc_Config(void)//配置ADC
{//注意: 通道ADCINA4 被采样2次 
    EALLOW;
    AdcRegs.ADCCTL1.bit.INTPULSEPOS    = 1;    //ADCINT1 中断信号在Adc结果锁存时产生
    AdcRegs.INTSEL1N2.bit.INT1E     = 1;    //开启ADCINT1
    AdcRegs.INTSEL1N2.bit.INT1CONT  = 0;    //禁止ADCINT1 连续模式
    AdcRegs.INTSEL1N2.bit.INT1SEL    = 2;    //设置 EOC2 去触发  ADCINT1,即SOC2转换完后再产生中断 ADCINT1
    AdcRegs.ADCSOC0CTL.bit.CHSEL     = 4;    //通道 SOC0 连接 ADCINA4
    AdcRegs.ADCSOC1CTL.bit.CHSEL     = 4;    //通道 SOC1 连接 ADCINA4
    AdcRegs.ADCSOC2CTL.bit.CHSEL     = 2;    //通道 SOC1 连接 ADCINA2

//    AdcRegs.ADCSOC0CTL.bit.TRIGSEL     = 5;    //SOC0 的启动触发信号源为EPWM1A, 转换先后顺序为SOC0、SOC1、SOC2

    AdcRegs.ADCSOC0CTL.bit.TRIGSEL  = 1;    //SOC0 的启动触发信号源为定时器0, 转换先后顺序为SOC0、SOC1、SOC2

    AdcRegs.ADCSOC1CTL.bit.TRIGSEL     = 5;    //SOC1的启动触发信号源为EPWM1A
    AdcRegs.ADCSOC2CTL.bit.TRIGSEL     = 5;    //SOC2的启动触发信号源为EPWM1A 
    AdcRegs.ADCSOC0CTL.bit.ACQPS     = 6;    //设置SOC0的 采样保持窗长度为 7个 ADC Clock Cycles, (6 ACQPS+ 1)
    AdcRegs.ADCSOC1CTL.bit.ACQPS     = 6;    //设置SOC0的 采样保持窗长度为 7个 ADC Clock Cycles, (6 ACQPS+ 1)
    AdcRegs.ADCSOC2CTL.bit.ACQPS     = 6;    //设置SOC0的 采样保持窗长度为 7个 ADC Clock Cycles, (6 ACQPS+ 1)
    EDIS;
    //注意:第一个ADC的数据被舍弃。以防止有错,见device errata
// 假设 ePWM1 clock 已在 InitSysCtrl()中开启;
   EPwm1Regs.ETSEL.bit.SOCAEN    = 1;        // 开启EPwm1A中的SOC
   EPwm1Regs.ETSEL.bit.SOCASEL    = 4;        // TBC增加到CPMA时产生SOC信号
   EPwm1Regs.ETPS.bit.SOCAPRD     = 1;        // 一次PWM比较事件产生一次触发信号
   EPwm1Regs.CMPA.half.CMPA     = 0x0080;    //  A 的比较值
   EPwm1Regs.TBPRD                 = 0xFFFF;    // ePWM1周期
   EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2;         // TBCLK = SYSCLK, TB_DIV1=0
   EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV2;            // TB
   EPwm1Regs.TBCTL.bit.CTRMODE     = 0;        // 递增模式并启动
}
 
interrupt void cpu_timer0_isr(void)//定时器0的中断服务程序
{
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
End

本文标题:DSP-28027ADC转换实验

本文链接:http://www.kitteno.com/archives/adc.html

除非另有说明,本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

声明:转载请注明文章来源。

最后修改:2022 年 04 月 28 日
如果觉得我的文章对你有用,请随意赞赏