程序说明
- 文件名:main.c
- 描 述:DSP-28027ADC实验
- 版本号:v1.0.0
- 型 号:DSP-28027
实验内容
- 根据模拟量与数字量的关系求出A4引脚实际的电压值(模拟量)。注意:要求100次ADC的均值!(均值的求解在main 中进行!设置一个标志位,用于标示数据采集是否完成)
- 将上述试验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的最高位被舍弃,剩下的低三位决定了同步采样的两个通道。
程序演示
程序代码
#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;
}
1 条评论
写得真好