主题中讨论的其他器件:C2000WARE
工具/软件:Code Composer Studio
我已将 c2000ware 示例 ADC_SoC_Continuous_DMA 扩展到四个 ADC (原始示例仅使用其中的两个 ADC)。 我将新代码粘贴到这里以供参考
//
//包含的文件
//
#include "F28x_Project.h"
//
函数原型
//
__interrupt void adca1_ISR (void);
__interrupt void dmach1_ISR (void);
void ConfigureEPWM (void);
void ConfigureADC (void);
void SetupADCContinuex (void struct adcadc_isr)
;void Configureadc (void anc (void);void adc (void)
//
//定义
//
#define results_buffer_size 512 //用于存储转换结果的缓冲
区//(大小必须是16的倍数)
//
Globals
//
#pragma DATA_SECTION (adcData0、"ramgs0");
#pragma DATA_SECTION (adcData1、"ramgs0");#pragma
DATA_SECTION (adcData2、"ram_SECTION) "ramgs0");
#pragma DATA_SECTION (adcData3、"ramgs0");
uint16 adcData0[results_buffer_size];
uint16 adcData1[results_buffer_size];
uint16 adcData2[results_buffer_size];
uint16 adcData3[results_buffer_size];
volatile Uint16 done;
void main (void)
{
uint16 resultsIndex;
//
//步骤1。 初始化系统控制:
// PLL、看门狗、启用外设时钟
//此示例函数位于 F2837xD_sysctrl.c 文件中。
//
InitSysCtrl();
//
//步骤2。 初始化 GPIO:
//此示例函数位于 F2837xD_GPIO.c 文件中,
//说明了如何将 GPIO 设置为其默认状态。
//
InitGpio();
////
步骤3. 清除所有中断并初始化 PIE 矢量表:
//禁用 CPU 中断
//
Dint;
//
//将 PIE 控制寄存器初始化为默认状态。
//默认状态是禁用所有 PIE 中断并
清除标志//。
//此函数位于 F2837xD_PIECTRL.c 文件中。
//
InitPieCtrl();
//
禁用 CPU 中断并清除所有 CPU 中断标志:
//
IER = 0x0000;
IFR = 0x0000;
//
//初始化 PIE 矢量表,其中包含指向 shell 中断
//服务例程(service routines,ISR)的指针。
//这将填充整个表,即使在
本示例中未使用中断//也是如此。 这对于调试很有用。
//可以在 F2837xD_DefaultIsr.c 中找到 shell ISR 例程
//此函数可在 F2837xD_PieVect.c 中找到
//
InitPieVectTable ();
//
//设置本示例使用的 ISR
//
针对 ADCA INT1的 ISR -发生在第一次转换之后
//针对 DMA CH1的 ISR -发生在 DMA 传输完成时
//
EALLOW;
PieVectTable.ADCA1_INT =&adca1_ISR;
PieVectTable.DMA_CH1_INT =&dmach1_ISR;
EDIS;
//
//启用特定的 CPU 中断:用于 ADC 的 INT1和用于 DMA
的 INT7 //
IER |= M_INT1;
IER |= M_INT7;
//
启用特定 PIE 中断
//
// ADCA INT1 -组1,中断1
// DMA 中断-组7,中断1
//
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
PieCtrlRegs.PIEIER7.bit.INTx1 = 1;
//
//停止 ePWM 时钟
//
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC=0;
EDIS;
//
//调用 ePWM 2的设置功能
//
ConfigureEPWM ();
//
//启动 ePWM 时钟
//
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC=1;
EDIS;
//
//配置 ADC 并为其加电
//
ConfigureADC();
//
//将 ADC 设置为通道 A3和 B3上的连续转换
//
SetupADCContinuimal(&AdcRegs, 3);
SetupADCContinuimal(&AdcbRegs, 3);
SetupADCContinuimal(&AdcRegs, 3);
SetupADCContinuimal(&AdcdRegs、3);
//
初始化 DMA
//
DMAInit();
//
启用全局中断和更高优先级的实时调试事件:
//
EINT;
//启用全局中断 INTM
ERTM;
//启用全局实时中断 DBGM
//
初始化结果缓冲
区//
对于(resultsIndex = 0;resultsIndex < results_buffer_size;resultsIndex++)
{
adcData0[resultsIndex]= 0;
adcData1[resultsIndex]= 0;
adcData2[resultsIndex]= 0;
adcData3[resultsIndex]= 0;
}
//
//清除所有挂起的中断标志
//
EALLOW;
DmaRegs.ch1.control.bit.PERINTCLR = 1;
DmaRegs.ch2.control.bit.PERINTCLR = 1;
DmaRegs.ch3.control.bit.PERINTCLR = 1;
DmaRegs.Ch4.control.bit.PERINTCLR = 1;
AdcaRegs.ADCINTFLGCLR.ALL = 0x3;
AdcbRegs.ADCINTFLGCLR.ALL = 0x3;
AdccRegs.ADCINTFLGCLR.ALL = 0x3;
AdcdRegs.ADCINTFLGCLR.ALL = 0x3;
EPwm2Regs.ETCNTINITCTL.bit.SOCAINITFRC= 1;
EPwm2Regs.ETCLR.bit.SOCA = 1;
//
//通过设置最后一个 SOC 来重新触发第一个//来启用连续操作
AdcaRegs.ADCINTSOCSEL1.bit.SOC0 = 2;
AdcbRegs.ADCINTSOCSEL1.bit.SOC0 = 2;
AdccRegs.ADCINTSOCSEL.bit.SOC0 = 2;
AdcdRegs.ADCINTSOCSEL.bit.SOC0 = 2;
EDIS;
//
//启动 DMA
//
完成= 0;
StartDMACH1();
StartDMACH2();
StartDMACH3();
StartDMACH4 ();
//
//最后,从 ePWM 启用 SOCA 触发。 这将在
下一个 ePWM 事件时启动//转换。
//
EPwm2Regs.ETSEL.bit.SOCAEN = 1;
//
/循环、直到 ISR 发出传输完成信号
//
while (done = 0)
{
_asm (" NOP");
}
ESTOP0;
}
////
adca1_ISR -这在第一次转换后调用并将禁用
// 以避免重新触发问题。
//
#pragma CODE_SECTION (adca1_ISR、".TI.ramfunc");
__interrupt void adca1_ISR (void)
{
//
//删除 ePWM 触发器
//
EPwm2Regs.ETSEL.bit.SOCAEN = 0;
//
//禁止再次发生此中断
//
PieCtrlRegs.PIEIER1.bit.INTx1 = 0;
//
//确认
//
PieCtrlRegs.PIEACK.all = PIEACK_Group1;
}
//
dmach1_ISR -这在 DMA 传输结束时调用,转换
// 通过从
//中删除第一个 SOC 的触发器来停止 最后一个。
//
#pragma CODE_SECTION (dmach1_ISR、".TI.ramfunc");
__interrupt void dmach1_ISR (void)
{
//
//通过移除 SOC0的触发器来停止 ADC
//
EALLOW;
AdcaRegs.ADCINTSOCSEL1.bit.SOC0 = 0;
AdcbRegs.ADCINTSOCSEL1.bit.SOC0 = 0;
AdccRegs.ADCINTSOCSEL.bit.SOC0 = 0;
AdcdRegs.ADCINTSOCSEL.bit.SOC0 = 0;
EDIS;
DONE = 1;
//
//确认
//
PieCtrlRegs.PIEACK.all = PIEACK_group7;
}
//
ConfigureEPWM -设置 ePWM2模块,以便 A 输出具有一个周期
// 占空比为50%。 SOCA 信号与
//保持一致 它的上升沿。
//
void ConfigureEPWM (void)
{
//
//使计时器计数的周期为40us
//
EPwm2Regs.TBCTL.ALL = 0x0000;
EPwm2Regs.TBPRD = 4000;
//
//将 A 输出设置为零并在 CMPA 上复位
//
EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET;
EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;
//
//将 CMPA 设置为20us 以获得50%的占空比
//
EPwm2Regs.CMPA.bit.CMPA = 2000;
//
//在计时器等于零时启动 ADC (注:尚未启用)
//
EPwm2Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO;
EPwm2Regs.ETPS.bit.SOCAPRD = ET_1ST;
//
//启用 SOCA 事件计数器的初始化。 因为我们是这样
//禁用 ETSEL.SOCAEN 位,我们需要一种复位 SOCACNT 的方法。
// Hence、启用计数器初始化控制。
//
EPwm2Regs.ETCNTINITCTL.bit.SOCAINITEN = 1;
}
//
// ConfigureADC -写入 ADC 配置并为这两个
//都加电 ADC ADC A 和 ADC B
//
void ConfigureADC (void)
{
EALLOW;
//
//写入预分频配置
//
AdcaRegs.ADCCTL2.bit.prescale = 6;//将 ADCCLK 分频器设置为/4
AdcbRegs.ADCCTL2.bit.prescale = 6;
AdccRegs.ADCCTL2.bit.prescale = 6;
AdcdRegs.ADCCTL2.bit.prescale = 6;
//
//设置模式
//
AdcSetMode (ADC_ADCA、ADC_resolution_12位、ADC_SIGNALMODE_SINGLE);
AdcSetMode (ADC_ADCB、ADC_Resolution、12位、ADC_SIGNALMODE_SINGLE);
AdcSetMode (ADC_ADCC、ADC_Resolution、12位、ADC_SIGNALMODE_SINGLE);
AdcSetMode (ADC_ADCD、ADC_Resolution、12位、ADC_SIGNALMODE_SINGLE);
//
//将脉冲位置设置为晚期
//
AdcaRegs.ADCCTL1.bit.INTPULSEPOS=1;
AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;
AdccRegs.ADCCTL1.bit.INTPULSEPOS = 1;
AdcdRegs.ADCCTL1.bit.INTPULSEPOS = 1;
//
//为 ADC 加电
//
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;
AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1;
AdccRegs.ADCCTL1.bit.ADCPWDNZ = 1;
AdcdRegs.ADCCTL1.bit.ADCPWDNZ = 1;
//
//延迟1ms 以允许 ADC 有时间上电
//
DELAY_US (1000);
EDIS;
}
//
SetupADCContinuous-设置 ADC 以在一个通道上持续转换
//
void SetupADCContinuous(volatile struct adc_regs * adcRegs、uint16 channel)
{
uint16 acqps;
//
//根据分辨率确定最小采集窗口(在 SYSCLKS 中)
//
IF (ADC_RESolution_12bit =adcRegs->ADCCTL2.bit.resolution)
{
acqps = 14;// 75ns
}
否则//分辨率为16位
{
acqps = 63;// 320ns
}
EALLOW;
//
// SOC 将在同一指定通道上转换
//
adcRegs->ADCSOC0CTL.bit.CHSEL =通道;
adcRegs->ADCSOC1CTL.bit.CHSEL =通道;
adcRegs->ADCSOC2CTL.bit.CHSEL =通道;
adcRegs->ADCSOC3CTL.bit.CHSEL =通道;
adcRegs->ADCSOC4CTL.bit.CHSEL =通道;
adcRegs->ADCSOC5CTL.bit.CHSEL =通道;
adcRegs->ADCSOC6CTL.bit.CHSEL =通道;
adcRegs->ADCSOC7CTL.bit.CHSEL =通道;
adcRegs->ADCSOC8CTL.bit.CHSEL =通道;
adcRegs->ADCSOC9CTL.bit.CHSEL =通道;
adcRegs->ADCSOC10CTL.bit.CHSEL =通道;
adcRegs->ADCSOC11CTL.bit.CHSEL =通道;
adcRegs->ADCSOC12CTL.bit.CHSEL =通道;
adcRegs->ADCSOC13CTL.bit.CHSEL =通道;
adcRegs->ADCSOC14CTL.bit.CHSEL =通道;
adcRegs->ADCSOC15CTL.bit.CHSEL =通道;
//
//采样窗口为 acqps + 1个 SYSCLK 周期
//
adcRegs->ADCSOC0CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC1CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC2CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC3CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC4CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC5CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC6CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC7CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC8CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC9CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC10CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC11CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC12CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC13CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC14CTL.bit.ACQPS = acqps;
adcRegs->ADCSOC15CTL.bit.ACQPS = acqps;
//
//从 EPWM2SOCA 触发 SCO0
//
adcRegs->ADCSOC0CTL.bit.TRIGSEL = 7;
//
//从 INT1触发所有其他 SOC (SOC0上的 EOC)
//
adcRegs->ADCINTSOCSEL1.bit.SOC1 = 1;
adcRegs->ADCINTSOCSEL1.bit.SOC2 = 1;
adcRegs->ADCINTSOCSEL1.bit.SOC3 = 1;
adcRegs->ADCINTSOCSEL1.bit.SOC4 = 1;
adcRegs->ADCINTSOCSEL1.bit.SOC5 = 1;
adcRegs->ADCINTSOCSEL1.bit.SOC6 = 1;
adcRegs->ADCINTSOCSEL1.bit.SOC7 = 1;
adcRegs->ADCINTSOCSEL2.bit.SOC8 = 1;
adcRegs->ADCINTSOCSEL2.bit.SOC9 = 1;
adcRegs->ADCINTSOCSEL2.bit.SOC10 = 1;
adcRegs->ADCINTSOCSEL2.bit.SOC11 = 1;
adcRegs->ADCINTSOCSEL2.bit.SOC12=1;
adcRegs->ADCINTSOCSEL2.bit.SOC13 = 1;
adcRegs->ADCINTSOCSEL2.bit.SOC14 = 1;
adcRegs->ADCINTSOCSEL2.bit.SOC15 = 1;
adcRegs->ADCINTSEL1N2.bit.INT1E = 1;//启用 INT1标志
adcRegs->ADCINTSEL1N2.bit.INT2E = 1;//启用 INT2标志
adcRegs->ADCINTSEL3N4.bit.INT3E = 0;//禁用 INT3标志
adcRegs->ADCINTSEL3N4.bit.INT4E = 0;//禁用 INT4标志
adcRegs->ADCINTSEL1N2.bit.INT1CONT = 1;
adcRegs->ADCINTSEL1N2.bit.INT2CONT = 1;
adcRegs->ADCINTSEL1N2.bit.INT1SEL = 0;// SOC0结束
adcRegs->ADCINTSEL1N2.bit.INT2SEL = 15;// SOC15结束
EDIS;
}
//
// DMAInit -初始化 DMA 通道1以将 ADCA 结果和 DMA 通道2传输到
// 传输 ADCB 结果
//
void DMAInit (void)
{
//
//初始化 DMA
//
DMAInitialize();
//
//为第一个 ADC 设置 DMA
//
DMACH1AddrConfig (adcData0、&AdcResultRegs.ADCRESULT0);
//
//执行足够的16字突发来填充结果缓冲区。 数据将是
//一次传输32位,因此地址步进如下。
//
//启用 DMA 通道1中断
//
DMACH1BurstConfig (15、2、2);
DMACH1TransferConfig ((results_buffer_size >> 4)- 1、-14、2);
DMACH1ModeConfig (
DMA_ADCAINT2、
PERINT_ENABLE、
OneShot_disable、
CONT_DISABLE、
SYNC_DISABLE、
SYNC_SRC、
OVRFLOW_DISABLE、
三十二位、
Chint_end、
Chint_enable);
//
//为第二个 ADC 设置 DMA
//
DMACH2AddrConfig (adcData1、&AdcbResultRegs.ADCRESULT0);
//
//执行足够的16字突发来填充结果缓冲区。 数据将是
//一次传输32位,因此地址步进如下。
//
DMACH2BurstConfig (15、2、2);
DMACH2TransferConfig (((results_buffer_size >> 4)- 1、-14、2);
DMACH2ModeConfig (
DMA_ADCAINT2、
PERINT_ENABLE、
OneShot_disable、
CONT_DISABLE、
SYNC_DISABLE、
SYNC_SRC、
OVRFLOW_DISABLE、
三十二位、
Chint_end、
Chint_disable);
//
//为第三个 ADC 设置 DMA
//
DMACH3AddrConfig (adcData2、&AdccResultRegs.ADCRESULT0);
//
//执行足够的16字突发来填充结果缓冲区。 数据将是
//一次传输32位,因此地址步进如下。
//
DMACH3BurstConfig (15、2、2);
DMACH3TransferConfig ((results_buffer_size >> 4)- 1、-14、2);
DMACH3ModeConfig (
DMA_ADCAINT2、
PERINT_ENABLE、
OneShot_disable、
CONT_DISABLE、
SYNC_DISABLE、
SYNC_SRC、
OVRFLOW_DISABLE、
三十二位、
Chint_end、
Chint_disable);
//
//为第四个 ADC 设置 DMA
//
DMACH4AddrConfig (adcData3、&AdcdResultRegs.ADCRESULT0);
//
//执行足够的16字突发来填充结果缓冲区。 数据将是
//一次传输32位,因此地址步进如下。
//
DMACH4BurstConfig (15、2、2);
DMACH4TransferConfig ((results_buffer_size >> 4)- 1、-14、2);
DMACH4ModeConfig (
DMA_ADCAINT2、
PERINT_ENABLE、
OneShot_disable、
CONT_DISABLE、
SYNC_DISABLE、
SYNC_SRC、
OVRFLOW_DISABLE、
三十二位、
Chint_end、
Chint_disable);
}
//
//文件结束
//
它可以毫无问题地运行、并且由 ADC a、b 和 c 获取的数据是正确的。 但在这里、当我使用 ADC d 获取正弦波时、我看到的是:
每16个样本就会出现一次毛刺脉冲、即 SOC 的数量。 我只有在同时使用四个 ADC 时才会遇到这个问题。 例如、如果我排除 ADC c、则只需注释启动 DMA CH3的代码
// //启动 DMA // 完成= 0; StartDMACH1(); StartDMACH2(); //StartDMACH3(); StartDMACH4();
然后、我在 ADC d 上获得非常干净的结果。这怎么可能呢?
此致
弗朗西斯科