This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CCS/LAUNCHXL-F28379D:每隔一定的时间间隔出现反相 ADC 读数问题

Guru**** 2580475 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/648469/ccs-launchxl-f28379d-having-troubles-with-inverted-adc-readings-every-certain-intervals

器件型号:LAUNCHXL-F28379D

工具/软件:Code Composer Studio

大家好、

我在 ADC 读数每隔一定的时间间隔(60次采样)反转时遇到问题。 我的硬件是 Launchpad XL 28379D。 我已经在这个问题上停留了很长时间、因此我非常感谢您的帮助。

我尝试使用 ADCA2、ADCA3、ADCB2、ADCB3、ADCC2、ADCC2读取6个模拟数据、 ADCC3。 3个 ADC 模块由 ePWM7SOCA 触发、在转换结束时、它们将分别触发3个 DMA 通道1、2和3。 DMA 通道中断1是我用于主控制的中断。

在这个图表中可以清楚地看到 AdcbResultRegs.ADCRESULT0的问题。 我无法理解为什么图形的某些部分不断被反转(如下所示)。 只有当我输入正弦波时、才会发生这种情况:

我不会遇到与我为它提供直流值相同的问题:

我使用20kHz 采样频率并对 ePWM7进行向上计数

//在 CALC_PRD 上设置 ePWM7以触发 ADC 的 CONVST
EPwm7Regs.TBCTL.bit.CTRMODE = TB_FREEZE;//禁用计时器(复位时默认值)
EPwm7Regs.TBCTL.bit.PHSDIR = TB_UP;//同步后向上计数
EPwm7Regs.TBCTL.bit.CLKDIV = TB_DIV1;// TBCLK = HSPCLK/1
EPwm7Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;// HSPCLK = EPWMCLK/1
EPwm7Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;//直通
EPwm7Regs.TBCTL.bit.PRDLD = TB_SHADOW;//启用影子模式
EPwm7Regs.TBCTL.bit.PHSEN = TB_DISABLE;//禁用相位控制
EPwm7Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;//向上-向下计数
EPwm7Regs.TBPHS.bit.TBPHS = 0x0000;//设置定时器相位
EPwm7Regs.TBCTR = 0x0000;//清除计时器计数器
EPwm7Regs.TBPRD = ISR_PERIOD;//设置计时器周期
EPwm7Regs.ETSEL.bit.SOCAEN = 0x1;//启用 extsoc1a 事件
EPwm7Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO;//将事件设置为在 TBCTR = 0时发生
EPwm7Regs.ETPS.bit.SOCAPRD = et_1st;//在第一个事件发生时生成 SoC (触发器)

//启用 TZ 中断
PieCtrlRegs.PIEIER2.bit.INTx1 = 1;//启用 TZ 中断以进行保护
PieCtrlRegs.PIEIER2.bit.INTx2 = 1;//启用 TZ 中断以进行保护
PieCtrlRegs.PIEIER2.bit.INTx3=1;//启用 TZ 中断以进行保护
IER |= M_INT2;

请按如下方式查看我的外设代码:

空 InitDma (空)

asm (" EALLOW");//启用 EALLOW 受保护寄存器访问

///----------------------------------------------------------
//--总体 DMA 设置
///----------------------------------------------------------
DmaRegs.DMACTRL.bit.hardreset = 1;//重置整个 DMA 模块
asm (" NOP");//硬复位生效的1个周期延迟

DmaRegs.DEBUGCTRL.bit.FREE = 1;// 1 = DMA 不受仿真停止的影响
DmaRegs.PRIORITYCTRL1.bit.CH1PRIORITY = 0;//未使用 CH1优先级模式

///----------------------------------------------------------
//---配置 DMA 通道1、2、3以读取 ADC 结果
///----------------------------------------------------------
//设置 DMA CH3中断进行控制,ISR 函数稍后由 HW_ADC_SET_ISR 函数调用给出
DMARegs.CH1.MODE.BIT.CHINTE = CHINT_ENABLE;//启用 CPU 通道中断
//DmaRegs.ch2.mode.bit.CHINTE = CHINT_ENABLE;
//DmaRegs.ch3.mode.bit.CHINTE = CHINT_ENABLE;

DMARegs.CH1.MODE.BIT.DATASIZE = 16_BIT;//数据大小设置为16位
DMARegs.CH2.MODE.BIT.DATASIZE =十六位;
DMARegs.CH3.MODE.BIT.DATASIZE =十六位;

DMARegs.CH1.MODE.BIT.CONTINUST= CONT_ENABLE;//连续模式被启用
DmaRegs.CH2.MODE.bit.CONT_ENABLE;
DmaRegs.CH3.MODE.bit.CONT_ENABLE;

DmaRegs.CH1.MODE.bit.OneShot = OneShot_disable;//启用单次模式
DmaRegs.CH2.MODE.bit.OneShot = OneShot_disable;
DmaRegs.CH3.MODE.bit.OneShot = OneShot_disable;

DMARegs.CH1.MODE.BIT.CHINTMODE = CHINT_END;//传输结束时的中断
//DmaRegs.ch2.mode.bit.CHINTMODE = CHINT_END;
//DmaRegs.ch3.mode.bit.CHINTMODE = CHINT_END;

DMARegs.CH1.MODE.BIT.PERINTE = PERINT_ENABLE;//外设中断触发使能
DMARegs.CH2.MODE.BIT.PERINTE = PERINT_ENABLE;
DMARegs.CH3.MODE.BIT.PERINTE = PERINT_ENABLE;

DMARegs.CH1.MODE.BIT.PERINTSEL = 1;//设置为通道编号
DMARegs.CH2.MODE.BIT.PERINTSEL = 2;
DMARegs.CH3.MODE.BIT.PERINTSEL = 3;

//--为每个 DMA 通道选择 DMA 中断源//触发源(保留未列出的数字)
DmaClaSrcSelRegs.DMACHSRCSEL1.bit.CH1 = 1;// 0 =无6 = ADCBINT1 12 = ADCCINT2 18 = ADCDINT3 32 = XINT4 40 = EPWM3SOCA 46 = EPWM6SOCA 52 = EPWM9SOCA 58 = EPWM12SOTCA 72 = EPWM1SOTCA= EPWM132= EPTM98_EPTA
DmaClaSrcSelRegs.DMACHSRCSEL1.bit.CH2 = 6;// 1=ADCAINT1 7=ADCBINT2 13=ADCCINT3 19=ADCDINT4 33=XINT5 41=EPWM3SOCB 47=EPWM6SOCB 53=EPWM9SOBA 59=EPWM12SOB=EPWM73=EPXDSB=EPTX_EPTXB=EPSDB=EPTXB=EPB=EPTX_EPTXB=EPTXD
DmaClaSrcSelRegs.DMACHSRCSEL1.bit.CH3 = 11;// 2=ADCAINT2 8=ADCBINT3 14=ADCCINT4 20=ADCDEVT 36=EPWM1SOCA 42=EPWM4SOCA 48=EPWM7SOCA 54=EPWM134 SOTDA1068=ADCDEVT 42=EPWM1SOCA 42=EPWM42=EPWM4SOTSDB=EPTB=EPWM42=EPWM1SOTIRB=EPW1042=EPWTRFLTB_EPT2
DmaClaSrcSelRegs.DMACHSRCSEL1.bit.Ch4 = 0;// 3=ADCAINT3 9=ADCBINT4 15=ADCCEVT 29=XINT1 37=EPWM1SOCB 43=EPWM4SOCB 49=EPWM7SOCB 55=EPWM102SOBA 69=TINT1SOC=EP101=EPWST1=EPT1SOCB=EP101=EP101=EPWSDT1SOC=EP101=EP101=EP101=EPWMT1SOCB=X1SOC=EP101=EP101=EP101=EP101=
DmaClaSrcSelRegs.DMACHSRCSEL2.bit.CH5 = 0;// 4 = ADCAINT4 10 = ADCBEVT 16 = ADCDINT1 30 = XINT2 38 = EPWM2SOCA 44 = EPWM5SOCA 50 = EPWM8SOCA 56 = EPWM11SOT1 70 = XINT2 = EPWM1SDTX_EPT2 = EPT2
DmaClaSrcSelRegs.DMACHSRCSEL2.bit.CH6 = 0;// 5 = ADCAEVT 11 = ADCCINT1 17 = ADCDINT2 31 = XINT3 39 = EPWM2SOCB 45 = EPWM5SOCB 51 = EPWM8SOBA 57 = EPWM11SOBA 109 = EPWM1SOCB = EPTX_EPT1 = EPTX_EPT3

//-- DMA 触发源锁定
DMACHSRCSELLOCK.BIT.DMACHSRCSEL1=0;//写1来锁定(一旦置位就不能清零)
DmaClaSrcSelRegs.DMACHSRCSELLOCK.bit.DMACHSRCSEL2 = 0;//写1来锁定(一旦置1就不能清零)

// DMA 通道1
DmaRegs.CH1.SRC_BeG_ADDR_SHADDADDR =(uint32)&AdcaResultRegs.ADCRESULT0;//指向源缓冲区的开头
DmaRegs.CH1.SRC_ADDR_SHADDow =(uint32)&AdcaResultRegs.ADCRESULT0;
DmaRegs.CH1.dst_beg_ADDR_SHADDADDR =(uint32)(adc_res[0]+2);//指向目的缓冲区的开头
DmaRegs.CH1.dst_ADDR_SHADDow =(uint32)(adc_res[0]+2);

DMARegs.CH1.burst_size.bit.BURSTSIZE = 1;//每个突发 n+1个字
DMARegs.CH1.TRANSFER_SIZE = 1;//每次传输的突发数、DMA 中断在每次传输完成后发生
DmaRegs.CH1.SRC_BURST_STEP = 0;//在每个字之间步进
DmaRegs.CH1.SRC_TRANSFER_STEP = 0x0001;//每次传输之间的步长(在指针地址内)
DmaRegs.CH1.dst_burst_step = 0;//在每个字之间步进
DmaRegs.CH1.dst_transfer_step = 0x0001;//每个突发之间的步长(在指针地址内)

DmaRegs.CH1.SRC_wrap_size = 0x0002;//大于 transfer_step 以禁用换行
DmaRegs.CH1.SRC_WOP_STEP = 0x0000;//无关
DmaRegs.CH1.dst_wrap_size = 0x0002;//大于 transfer_step 以禁用换行
DmaRegs.CH1.dst_wrap_step = 0x0000;//无关

// DMA 通道2
DmaRegs.CH2.SRC_beg_ADDR_SHADDR =(uint32)&AdcbResultRegs.ADCRESULT0;//指向源缓冲区的开头
DmaRegs.CH2.SRC_ADDR_SHADDow =(uint32)&AdcbResultRegs.ADCRESULT0;
DmaRegs.ch2.dst_beg_ADDR_SHADDADDR =(uint32)(adc_res[1]+2);//指向目的缓冲区的开头
DmaRegs.CH2.dst_ADDR_SHADDow =(uint32)(adc_res[1]+2);

DMARegs.CH2.burst_size.bit.BURSTSIZE = 1;//每个突发 n+1个字
DmaRegs.CH2.transfer_size = 1;//每次传输的突发次数、DMA 中断在每次传输完成后发生
DmaRegs.CH2.SRC_BURST_STEP = 0;//在每个字之间步进
DmaRegs.CH2.SRC_TRANSFER_STEP = 0x0001;//在每个突发之间步进
DmaRegs.CH2.dst_burst_step = 0;//在每个字之间步进
DmaRegs.CH2.dst_transfer_step = 0x0001;//在每个突发之间步进

DmaRegs.CH2.SRC_wrap_size = 0x0002;//大于 transfer_step 以禁用换行
DmaRegs.CH2.SRC_WOP_STEP = 0x0000;//无关
DmaRegs.CH2.dst_wrap_size = 0x0002;//大于 transfer_step 以禁用换行
DmaRegs.CH2.dst_wrap_step = 0x0000;//无关

// DMA 通道3
DmaRegs.CH3.SRC_beg_ADDR_SHADDAD=(uint32)&AdccResultRegs.ADCRESULT0;//指向源缓冲区的开头
DmaRegs.CH3.SRC_ADDR_SHADDow =(uint32)&AdcResultRegs.ADCRESULT0;
DmaRegs.CH3.dst_beg_ADDR_SHADDADDR =(uint32)(adc_res[2]+2);//指向目的缓冲区的开头
DmaRegs.CH3.dst_ADDR_SHADDow =(uint32)(adc_res[2]+2);

DMARegs.CH3.burst_size.bit.BURSTSIZE = 1;//每个突发 n+1个字
DMARegs.CH3.TRANSFER_SIZE = 1;//每次传输的突发数、DMA 中断在每次传输完成后发生
DmaRegs.CH3.SRC_BURST_STEP = 0;//在每个字之间步进
DmaRegs.CH3.SRC_TRANSFER_STEP = 0x0001;//在每个突发之间步进
DmaRegs.CH3.dst_burst_step = 0;//在每个字之间步进
DmaRegs.CH3.dst_transfer_step = 0x0001;//在每个突发之间步进

DmaRegs.CH3.SRC_wrap_size = 0x0002;//大于 transfer_step 以禁用换行
DmaRegs.CH3.SRC_WOP_STEP = 0x0000;//无关
DmaRegs.CH3.dst_wrap_size = 0x0002;//大于 transfer_step 以禁用换行
DmaRegs.CH3.dst_wrap_step = 0x0000;//无关

//清除错误并运行 DMA 通道
DmaRegs.ch1.control.bit.ERRCLR = 1;//清除任何错误
DmaRegs.ch1.control.bit.PERINTCLR = 1;//清除任何寄生中断标志
DMARegs.CH1.control.bit.run = 1;//启动 DMA 通道

DmaRegs.ch2.control.bit.ERRCLR = 1;//清除任何错误
DmaRegs.ch2.control.bit.PERINTCLR = 1;//清除任何寄生中断标志
DmaRegs.ch2.control.bit.run = 1;//启动 DMA 通道

DmaRegs.ch3.control.bit.ERRCLR = 1;//清除任何错误
DmaRegs.ch3.control.bit.PERINTCLR = 1;//清除任何寄生中断标志
DmaRegs.ch3.control.bit.run = 1;//启动 DMA 通道

//--完成
asm (" EDIS");//禁用 EALLOW 受保护寄存器访问

//--启用 DMA 中断
PieCtrlRegs.PIEIER7.bit.INTx1 = 1;//在 PIE 组7中启用 DINTCH1
IER |= 0x0040;//在 IER 中启用 INT7以启用 PIE 组

}//结束 InitDma()

空 InitAdc (空)

asm (" EALLOW");//启用 EALLOW 受保护寄存器访问

//--复位 ADC。 这是一种良好的编程实践。
DevCfgRegs.SOFTPRES13.bit.ADC_A = 1;// ADC 复位
DevCfgRegs.SOFTPRES13.bit.ADC_A = 0;// ADC 从复位中释放

DevCfgRegs.SOFTPRES13.bit.ADC_B = 1;// ADC 复位
DevCfgRegs.SOFTPRES13.bit.ADC_B = 0;// ADC 从复位中释放

DevCfgRegs.SOFTPRES13.bit.ADC_C = 1;// ADC 复位
DevCfgRegs.SOFTPRES13.bit.ADC_C = 0;// ADC 从复位中释放

//---配置 ADC 基址寄存器
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 0;// ADCPWDNZ、ADC 断电
AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 0;
AdccRegs.ADCCTL1.bit.ADCPWDNZ = 0;

AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;// INT 脉冲生成、0=转换开始、1=转换结束
AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;
AdccRegs.ADCCTL1.bit.INTPULSEPOS = 1;

AdcaRegs.ADCCTL2.bit.prescale = 0x6;//预分频、ADC 时钟预分频器。 0110=CPUCLK/4
AdcbRegs.ADCCTL2.bit.prescale = 0x6;
AdccRegs.ADCCTL2.bit.prescale = 0x6;

AdcaRegs.ADCBURSTCTL.bit.BURSTEN = 0;// 0 =禁用突发模式,1 =启用突发模式
AdcbRegs.ADCBURSTCTL.bit.bURSTEN = 0;
AdccRegs.ADCBURSTCTL.bit.BURSTEN = 0;

//---调用 AdcSetMode()以配置分辨率和信号模式。
//这也会对配置的模式执行正确的 ADC 校准。
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);

//-- SOC 配置
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 0x11;//使用 ePWM7-ADCSOCA 触发
AdcaRegs.ADCSOC0CTL.bit.CHSEL = 2;//转换通道 ADCINA2 (通道2)
AdcaRegs.ADCSOC0CTL.bit.ACQPS = 19;//采集窗口设置为(19+1)=20个周期(200MHz SYSCLK 时为100ns)

AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 0x11;//使用 ePWM7-ADCSOCA 触发
AdcaRegs.ADCSOC1CTL.bit.CHSEL = 3;//转换通道 ADCINA3 (通道3)
AdcaRegs.ADCSOC1CTL.bit.ACQPS = 19;//采集窗口设置为(19+1)=20个周期(200MHz SYSCLK 时为100ns)

AdcbRegs.ADCSOC0CTL.bit.TRIGSEL = 0x11;//使用 ePWM7-ADCSOCA 触发
AdcbRegs.ADCSOC0CTL.bit.CHSEL = 2;//转换通道 ADCINB2 (通道2)
AdcbRegs.ADCSOC0CTL.bit.ACQPS = 19;//采集窗口设置为(19+1)= 20个周期(200MHz SYSCLK 时为100ns)

AdcbRegs.ADCSOC1CTL.bit.TRIGSEL = 0x11;//使用 ePWM7-ADCSOCA 触发
AdcbRegs.ADCSOC1CTL.bit.CHSEL = 3;//转换通道 ADCINB3 (通道3)
AdcbRegs.ADCSOC1CTL.bit.ACQPS = 19;//采集窗口设置为(19+1)= 20个周期(200MHz SYSCLK 时为100ns)

AdccRegs.ADCSOC0CTL.bit.TRIGSEL = 0x11;//使用 ePWM7-ADCSOCA 触发
AdccRegs.ADCSOC0CTL.bit.CHSEL = 2;//转换通道 ADCINC2 (通道2)
AdccRegs.ADCSOC0CTL.bit.ACQPS = 19;//采集窗口设置为(19+1)=20个周期(200MHz SYSCLK 时为100ns)

AdccRegs.ADCSOC1CTL.bit.TRIGSEL = 0x11;//使用 ePWM7-ADCSOCA 触发
AdccRegs.ADCSOC1CTL.bit.CHSEL = 3;//转换通道 ADCINC3 (通道3)
AdccRegs.ADCSOC1CTL.bit.ACQPS = 19;//采集窗口设置为(19+1)=20个周期(200MHz SYSCLK 时为100ns)

AdcaRegs.ADCSOCPRICTL.bit.SOCPRIORITY = 0;//所有 SOC 在循环模式下处理
AdcbRegs.ADCSOCPRICTL.bit.SOCPRIORITY = 0;//所有 SOC 在循环模式下处理
AdccRegs.ADCSOCPRICTL.bit.SOCPRIORITY = 0;//所有 SOC 在循环模式下处理

//-- ADC 中断配置
AdcaRegs.ADCINTSEL1N2.bit.INT1CONT = 1;//中断脉冲、与标志状态无关
AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 1;// EOC3触发中断
AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1;//启用 ADC 中的中断
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;//确保 INT1标志被清除

AdcbRegs.ADCINTSEL1N2.bit.INT1CONT = 1;//中断脉冲、与标志状态无关
AdcbRegs.ADCINTSEL1N2.bit.INT1SEL = 1;// EOC3触发中断
AdcbRegs.ADCINTSEL1N2.bit.INT1E = 1;//启用 ADC 中的中断
AdcbRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;//确保 INT1标志被清除

AdccRegs.ADCINTSEL1N2.bit.INT1CONT = 1;//中断脉冲、与标志状态无关
AdccRegs.ADCINTSEL1N2.bit.INT1SEL = 1;// EOC3触发中断
AdccRegs.ADCINTSEL1N2.bit.INT1E = 1;//启用 ADC 中的中断
AdccRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;//确保 INT1标志被清除

//--完成
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;//为 ADC 加电
AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1;//为 ADC 加电
AdccRegs.ADCCTL1.bit.ADCPWDNZ = 1;//为 ADC 加电

DelayU (1000);//加电后等待1ms、然后再使用 ADC
asm (" EDIS");//禁用 EALLOW 受保护寄存器访问

}//结束 InitAdc()

这是我第一次发布、如果我遗漏了任何关键信息、请原谅。 以前有人遇到过这个问题吗?

谢谢你

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Benjamin、

    我不认为您的信号是反相的;它们可能会被拼接错、因此转换结果的顺序是错误的。 这很可能表示存在 DMA 问题。

    您可以首先尝试对每个通道施加不同的直流电压、以确保给定通道的所有转换结果都转至正确的 RAM 位置。 如果您在同一个图中看到多个直流电平、可能不同通道的转换结果会混合在一起? 如果不是、那么给定通道的转换结果可能不会按顺序填满缓冲区?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的评论!

    您是对的、我的信号未反相。 我使用 DAC 模块实时绘制 ADC 读数、它们完全正弦。

    我的转换结果根本无法正确填充我的图缓冲器。 我已经将使用 DMA 中断填充缓冲区的过程计时为:

    中断空 DMA_CH1_ISR (空)

    (笑声)

    //获取 TI Code Composer 中的缓冲区和绘图
    ISR_COUNT++;
    如果(ISR_COUNT > 256) ISR_COUNT = 0;
    plT_SIG[ISR_COUNT]=&AdcaResultRegs.ADCRESULT0;

    该软件看起来不像这样、为我提供了您之前看到的"拼接"图形。 您能解释一下填充缓冲区和在 code composer studio 中获取正确图解的正确方法吗?

    再次感谢您的帮助、

    Benjamin