请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
器件型号:TMS320F28379D 主题中讨论的其他器件:C2000WARE
工具/软件:Code Composer Studio
您好!
我是 C2000程序员的新手。 我的任务是使用 DMA 实现 ADC 测量(连续)。
我安装了 C2000Ware、下面显示了一个示例:
//###################################################################################################################### // ////文件:adc_soc _continuous_dma_cpu01.c // 标题:ADC 连续转换由 DMA 读取、用于 F2837xD。 // //! addtogroup cpu01_example_list //!DMA 读取的 ADC 连续转换(ADC_SoC_Continuous_DMA)
//! //! 此示例设置两个 ADC 通道以同时转换。 //! 结果将由 DMA 传输到 RAM 中的缓冲区中。 //! //! 程序运行后、存储器将包含: //! //! -\b adcData0 \b:引脚 A3上电压的数字表示\n //! -\b adcData1 \b:引脚 B3上电压的数字表示\n// ! // //########################################################################################################################## //$TI 发布:F2837xD 支持库 v3.01.00.00 $ //$发布 日期:星期一5月22日15:43:40 CDT 2017 $ //版权所有: //版权所有(C) 2013-2017 Texas Instruments Incorporated - http://www.ti.com/ // 只要 满足以下条件,就允许以源代码和二进制形式重新分发和使用//修改或不修改//: // //重新分发源代码必须保留上述版权 //声明、此条件列表和以下免责声明。 // //二进制形式的再发行必须复制上述版权 //声明、此条件列表和// 分发随附的//文档和/或其他材料中的以下免责声明。 //// 未经 事先书面许可,不能使用德州仪器公司的名称或//其贡献者的名称来认可或推广源自此软件的产品//。 //// 本软件由版权所有者和贡献者提供 //“按原样”,不 承认任何明示或暗示的保证,包括但不限于//适销性和对//特定用途适用性的暗示保证。 在任何情况下、版权 //所有者或贡献者都不对任何直接、间接、偶然、 //特殊、模范、 或相应的损害(包括但不 限于采购替代产品或服务;丧失使用、 //数据或利润; 或业务中断)、无论 出于何种原因使用 本软件(即使被告知可能会造成此类损坏)、还是出于任何原因而产生的任何//责任理论(无论是合同、严格责任还是侵权行为)//(包括疏忽或其他)。 //$ //######################################################################################################################## // //包含的文件 // #include "F28x_Project.h" // 函数原型 // __interrupt void adcA1x_ISR (void); __interrupt void dmach1_ISR (void); void ConfigureEPWM (void); void ConfigureADC (void);void SetupADCContinuex (void struct adc_isr);//为 空位转换结果定义 void /nategtran/ void 大小/intranc (void)//定义空位数转换结果//空位转换结果//空位转换结果//空位转换结果 //(大小必须是16的倍数) // Globals // #pragma DATA_SECTION (adcData0、"ramgs0"); #pragma DATA_SECTION (adcData1、"ramgs0"); uint16 adcData0[results_buffer_size]; uint16 adcData1[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 =&adca1x_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); // 初始化 DMA // DMAInit(); // 启用全局中断和更高优先级的实时调试事件: // EINT;//启用全局中断 INTM ERTM;//启用全局实时中断 DBGM // 初始化结果缓冲 区// for (resultsIndex = 0;resultsIndex < results_buffer_size;resultsIndex++) { adcData0[resultsIndex]= 0; adcData1[resultsIndex]= 0; } // //清除所有挂起的中断标志 // EALLOW; DmaRegs.ch1.control.bit.PERINTCLR = 1; DmaRegs.ch2.control.bit.PERINTCLR = 1; AdcaRegs.ADCINTFLGCLR.ALL = 0x3; AdcbRegs.ADCINTFLGCLR.ALL = 0x3; EPwm2Regs.ETCNTINITCTL.bit.SOCAINITFRC= 1; EPwm2Regs.ETCLR.bit.SOCA = 1; // //通过设置最后一个 SOC 来重新触发第一个//来启用连续操作 AdcaRegs.ADCINTSOCSEL1.bit.SOC0 = 2; AdcbRegs.ADCINTSOCSEL1.bit.SOC0 = 2; EDIS; // //启动 DMA // 完成= 0; StartDMACH1(); StartDMACH2 (); // //最后,从 ePWM 启用 SOCA 触发。 这将在 下一个 ePWM 事件时启动//转换。 // EPwm2Regs.ETSEL.bit.SOCAEN = 1; // /循环、直到 ISR 发出传输完成信号 // while (done = 0) { _asm (" NOP"); } ESTOP0; } //// adca1_ISR -这在第一次转换后调用并将禁用 // 以避免重新触发问题。 // #pragma CODE_SECTION (adca1x_ISR、".TI.ramfunc"); __interrupt void adca1x_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; 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; // //设置模式 // AdcSetMode (ADC_ADCA、ADC_resolution_12位、ADC_SIGNALMODE_SINGLE); AdcSetMode (ADC_ADCB、ADC_Resolution、12位、ADC_SIGNALMODE_SINGLE); // //将脉冲位置设置为晚期 // AdcaRegs.ADCCTL1.bit.INTPULSEPOS=1; AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1; // //为 ADC 加电 // AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; AdcbRegs.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 = AdcaRegs.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->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 ); } // ////文件结束 //
问题是、当我使用这个原始示例(未更改)时、当我开始调试然后运行时、它以 ILLEGAL_ISR 结束。
//
//##########################################################################################################################
//
////文件:F2837xD_DefaultISR.c
//
//标题:F2837xD 设备默认中断服务例程
//
////####################################################################################
//$TI 发行版:F2837xD 支持库 V210 $//
$发行 日期:星期二11月1日14:46:15 CDT 2016 $//
版权所有:版权所有(C) 2013-2016德州仪器(TI)公司-//
http://www.ti.com/ 保留所有权利$
//############################################################################################################
。
(删除了行)
..
//
//非法操作陷阱
//
中断 void ILLEGAL_ISR (void)
{
//
//在此处插入 ISR 代码
//
//
//接下来的两行仅用于调试,以在此处停止处理器
//插入 ISR 代码后删除
//
ASM (" ESTOP0");
for (;;);
}
。
(删除了行)
作为一个新手、我迷路了。
谢谢、米兰