器件型号:LAUNCHXL-F28377S
工具/软件:Code Composer Studio
您好!
我对“2837x_rfft_adc_RT”有疑问:
我需要将我的模数采样率从100ksps 提高到 500ksps、
在"example_setup.h"中更改以下参数就足够了?
#define ADC_SAMPLING_FREQ 100000.0L
或项目中的其他更改是必要的。
感谢你的帮助。
此致、
Amin
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.
器件型号:LAUNCHXL-F28377S
工具/软件:Code Composer Studio
您好!
我对“2837x_rfft_adc_RT”有疑问:
我需要将我的模数采样率从100ksps 提高到 500ksps、
在"example_setup.h"中更改以下参数就足够了?
#define ADC_SAMPLING_FREQ 100000.0L
或项目中的其他更改是必要的。
感谢你的帮助。
此致、
Amin
尊敬的惠特尼:
在此项目(2837x_rfft_adc_RT)中、有一个方波发生器、我想控制每个脉冲的起始点和停止点、并同时在其他 ADC 通道中对模拟信号进行采样。
如何生成一定数量的方波、例如1个方波? 我需要在项目中具有每个方波的“开始”和“结束”点,并从每个方波的起点到终点运行 ADC PIN_A0。
换句话说,如果我们假定“A”是每个脉冲周期的起始点,每个周期的结束点是“B”点, 那么:
ADC 的起点=方波开始处(A 点)
ADC 的终点=方波的终点(B 点)
如何同步 ADC 通道和方波发生器?
谢谢、此致、
Amin
在 examples_setup.h 中:
|
1
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
|
#define CPU_FRQ_200MHZ 1 #define ADC_SAMPLING_FREQ 100000.0L #define EPWM_CLK 100000000UL // EPWM_CLK starts off SYSCLK/2 #define EPWM_CLKDIV 1 // TBCLK = SYSCLK/(2*2) #define EPWM_HSPCLKDIV 4 // = SYSCLK/(2*2*8) or EPWM_CLK/(2*8) // desired freq 100KHz #define EPWM1_PERIOD EPWM_CLK/(2*8*100000UL) #define EPWM1_DUTY_CYCLE EPWM1_PERIOD/2UL // desired freq 10KHz #define EPWM2_PERIOD (EPWM_CLK)/(2*8*10000UL) #define EPWM2_DUTY_CYCLE EPWM2_PERIOD/2UL |
以下代码:结果(500kSPS ADC 和200Hz PWM)
#define CPU_FRQ_200MHz 1 #define ADC_SAMPLING_FREQ 500000.0L #define ePWM_CLK 100000000UL // ePWM_CLK 启动 SYSCLK/2 #define ePWM_CLKDIV 1 // TBCLK = SYSCLK/(2*2) #define ePWM_HSPCLK/2 #define ePWM_CLK/2 = SYSCLQ/ RELEV/ SYSCLQ2 / RELEVN 2 = SYSCLQ2 / SYSCLQ2 / SYSCLQ2 / RELEVN 2 = SYSCLQ/ SYSCLQ2 / SYSCLQ/ RELEVN ePWM_CLK/(2*8*500000UL) #define EPWM1_DUTY 周期 EPWM1_PERIODE/2UL //所需频率10kHz #define EPWM2_PERIOD (ePWM_CLK)/(2*8*200UL) #define EPWM2_Duty_cycle EPWM2_PERIODE/2UL
Amin
尊敬的惠特尼:
在该项目中、脉冲占空比发生了变化、但我不需要这种变化。 我将代码减少为脉冲发生器(ePWM2)。
e2e.ti.com/.../2017_2D00_05_2D00_23_5F00_18_2D00_33_2D00_40.mp4
//###################################################################################################################### // ////文件:ePWM_UP_AQ_cpu01.c // 标题:操作限定器模块-使用向上计数。 // //! addtogroup cpu01_example_list //!ePWM 操作限定符(ePWM_UP_AQ)
//! //! 此示例将 ePWM1、ePWM2、ePWM3配置为生成 //! EPWMxA 和 //!上具有独立调制的波形 EPWMxB。 //! //! 比较值 CMPA 和 CMPB 在 ePWM 的 ISR 内进行修改。 //! //! 在本示例中、TB 计数器处于向上计数模式。 //! //! 查看 EPWM1A/B (PA0_GPIO0和 PA1_GPIO1)、EPWM2A/B (PA2_GPIO2和 PA3_GPIO3) //! 和 EPWM3A/B (PA4_GPIO4和 PA5_GPIO5)波形。 //! // //########################################################################################################################## //$TI 发行版:F2837xS 支持库 V210 $// $发行 日期:星期二11月1日15:35:23 CDT 2016 $// 版权所有:版权所有(C) 2014-2016德州仪器(TI)公司-// http://www.ti.com/ 保留所有权利$ //############################################################################################################ // //包含的文件 // #include "F28x_Project.h" // 定义 // #define EPWM2_TIMER_TBPRD 2000 //周期寄存器//////////////////// 2000 #define EPWM2_MAX_CMPA 1950 //1950 #define EPWM2_MIN_CMPA 50 #define EPWM2_MAX_CMPB 1950 //1950 #define EPWM2_MIN_CMPB 50 #define ePWM_CMP_UP 1 #define ePWM_CMP_DOWN 0 // // Globals // typedef struct { volatile struct ePWM_regs * EPwmRegHandle; uint16 ePWM_CMPA_DIRECTION; uint16 ePWM_CMPB_DIRECTION; UINT16 EPwmTimerIntCount; uint16 EPwmMaxCMPA; uint16 EPwmMinCMPA; UINT16 EPwmMaxCMPB; uint16 EPwmMinCMPB; }ePWM_INFO; ePWM_INFO epwm2_INFO; // 函数原型 // 空 InitEPwm2Example (void); __interrupt void epwm2_ISR (void); void update_compare (ePWM_info*); // Main // Main //(void)/步骤1 / void (void)。 初始化系统控制: // PLL、看门狗、启用外设时钟 //此示例函数位于 F2837xS_SYSCTRL.c 文件中。 // InitSysCtrl(); // //步骤2。 初始化 GPIO: //此示例函数位于 F2837xS_GPIO.c 文件中, //说明了如何将 GPIO 设置为其默认状态。 // // InitGpio (); // //启用 PWM2 // CpuSysRegs.PCLKCR2.bit.EPWM2=1; // 对于这种情况、只需初始化 ePWM1、ePWM2、ePWM3的 GPIO 引脚 //这些函数位于 F2837xS_ePWM.c 文件 // InitEPwm2Gpio(); //// 步骤3。 清除所有中断并初始化 PIE 矢量表: //禁用 CPU 中断 // Dint; // //将 PIE 控制寄存器初始化为默认状态。 //默认状态是禁用所有 PIE 中断并 清除标志//。 //此函数位于 F2837xS_PIECTRL.c 文件中。 // InitPieCtrl(); // 禁用 CPU 中断并清除所有 CPU 中断标志: // IER = 0x0000; IFR = 0x0000; // //初始化 PIE 矢量表,其中包含指向 shell 中断 //服务例程(service routines,ISR)的指针。 //这将填充整个表,即使在 本示例中未使用中断//也是如此。 这对于调试很有用。 //可以在 F2837xS_DefaultIsr.c 中找到 shell ISR 例程 //此函数可在 F2837xS_PieVect.c 中找到 // InitPieVectTable(); // //此示例中使用的中断被重新映射到 这个文件中的// ISR 函数。 // EALLOW;//这是写入 EALLOW 受保护寄存器所必需的 PieVectTable.EPWM2_INT =&epwm2_ISR; EDIS;//这是禁止写入 EALLOW 受保护寄存器所必需 的// //对于这个示例,只初始化 ePWM // EALLOW; CpuSysRegs.PCLKCR0.bit.TBCLKSYNC=0; EDIS; InitEPwm2Examples(); EALLOW; CpuSysRegs.PCLKCR0.bit.TBCLKSYNC=1; EDIS; //// 步骤4。 用户特定代码、启用中断: // 启用连接到 EPWM1-3 INT 的 CPU INT3: // IER |= M_INT3; // //在 PIE 中启用 ePWM INTn:组3中断1-3 // PieCtrlRegs.PIEIER3.bit.INTx2 = 1; // 启用全局中断和更高优先级的实时调试事件: // EINT;//启用全局中断 INTM ERTM;//启用全局实时中断 DBGM // //步骤5。 空闲循环。 只需坐下来循环(可选): // for (;;) { ASM (" NOP"); } } // // epwm2_ISR -用于更新比较值的 EPWM2 ISR // __interrupt void epwm2_ISR (void) { // //更新 CMPA 和 CMPB 值 // 更新比较(epwm2_info); // //清除此计时器的 INT 标志 // EPwm2Regs.ETCLR.bit.INT = 1; // //确认此中断以接收来自组3的更多中断 // PieCtrlRegs.PIEACK.all = PIEACK_Group3; } // InitEPwm2Example -初始化 EPWM2值 // 空 InitEPwm2Examples() { // //设置 TBCLK // EPwm2Regs.TBCTL.bit.CTRMODE = TB_EPWDMD 计数;//设置 TBPRD_EPwM2RPM2计数; //设置定时器周期 EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;//禁用相位加载 EPwm2Regs.TBPHS.bit.TBPHS = 0x0000; //相位为0 EPwm2Regs.TBCTR = 0x0000; //清除计数 器 EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2;//时钟与 SYSCLKOUT EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV2; // 设置影子寄存器加载为零 // EPwm2Regs.TBCMDR.BIT.AMPC2.TL.BIT.AMCMDR.BIT.RC.TL.TL.RCMTL.RCMTL.RCMTL.TL.RCMTL.RCMTL.TL.RCMTL.TL.RCMTL.RCMTL.RCMTL.TL.RCMTL.RCMTL.RBIT.RCMTL.RCMTL.RCMTL.RBIT.RBIT.RCMTL.TL.RCMTL.TL.RCMTL.TL.TL.TL.TL.RBIT.RBIT.RCMTL.TL.TL.RBIT_RCMTL.RCMTL.RBIT.RCMTL.TL.TL.RBIT.RBIT. //设置比较 A 值 EPwm2Regs.CMPB.bit.CMPB = EPWM2_MAX_CMPB; //设置比较 B 值 // 设置操作 // EPwm2Regs.AQCTLA.bit.PRD = AQ_CLEAR; //在周期 EPwm2Regs.AQCTLA.bit.CAU = AQ_SET 时清除 PWM2A; //在事件 A 上设置 PWM2A、 //向上计数 EPwm2Regs.AQCTLB.bit.PRD = AQ_CLEAR; //在周期 EPwm2Regs.AQCTLB.bit.CBU = AQ_SET 时清除 PWM2B; //在事件 B 上设置 PWM2B、 //向上计数 // //中断,其中我们将更改比较值 // EPwm2Regs.ETSEL.bit.INTSEL = et_CTR_ZERO; //选择零事件 EPwm2Regs.ETSEL.bit.INTEN 上的 INT = 1; //启用 INT EPwm2Regs.ETPS.bit.INTPRD = et_3rd; //生成第3个事件的 INT // 信息此示例用于跟踪 // CMPA/CMPB 值 移动的方向,允许的最小值和最大值以及 //指向正确 ePWM 寄存器的指针 // epwm2_info.epwm_cmpa_direction = ePWM_cmp_up; //首先增大 CMPA epwm2_info.ePWM_CMPB_Direction = ePWM_CMP_DOWN;//并减小 CMPB epwm2_info.EPwmTimerIntCount = 0; //将中断置零 //计数 器 epwm2_info.EPwmRegHandle =&EPwm2Regs; //将指针设置为 // ePWM 模块 epwm2_info.EPwmMaxCMPA = EPWM2_MAX_CMPA; //设置最小值/最大值 // CMPA/CMPB 值 epwm2_info.EPwmMinCMPA = EPWM2_min_CMPA; epwm2_info.EPwmMaxCMPB = EPWM2_MAX_CMPB; epwCount_info.EPwmMinCMPB = EPWM2_MIN_CMPB; } // 将 每个值进行比较/ePWM/更新/?/ePWM//einfo/ePWM//ePWM//ePWM=/ePWM//ePWM/ e/ePWM//ePWM//ePWM/ e/ePWM/ e/ePWM/ ePWM/ e/ePWM/ ePWM//ePWM/ eCO/eCO/eCO/eCO/eCO/eCO/eCO/eCO/eCO/eCO/ePWM/ eCO/eCO/eCO/e 10 { ePWM_INFO->EPwmTimerIntCount = 0; // //如果我们增加 CMPA,请检查是否 //我们达到了最大值。 如果不是、请增大 CMPA //否则、更改方向并减小 CMPA // if (ePWM_INFO->ePWM_CMPA_DIRECTION == ePWM_CMP_UP) { if (ePWM_INFO->EPwmRegHandle->CMPA.bit.CMPA < ePWM_INFO->EPwmMaxCMPA) { ePWM_INFO->EPwmRegHandle->CMPA.bit.CMPA++; } 其他 { ePWM_INFO->ePWM_CMPA_DIRECTION = ePWM_CMP_DOWN; ePWM_INFO->EPwmRegHandle->CMPA.bit.CMPA--; } } // //如果我们降低了 CMPA,请检查是否 //我们达到最小值。 如果不是、请减小 CMPA //否则,更改方向并增加 CMPA // 其他 { if (ePWM_INFO->EPwmRegHandle->CMPA.bit.CMPA =ePWM_INFO->EPwmMinCMPA) { ePWM_INFO->ePWM_CMPA_DIRECTION = ePWM_CMP_UP; ePWM_INFO->EPwmRegHandle->CMPA.bit.CMPA++; } 其他 { ePWM_INFO->EPwmRegHandle->CMPA.bit.CMPA--; } } // //如果我们增加 CMPB,请检查是否 //我们达到了最大值。 如果不是、则增加 CMPB //否则、更改方向并减小 CMPB // if (ePWM_INFO->ePWM_CMPB_DIRECTION == ePWM_CMP_UP) { if (ePWM_INFO->EPwmRegHandle->CMPB.bit.CMPB < ePWM_INFO->EPwmMaxCMPB) { ePWM_INFO->EPwmRegHandle->CMPB.bit.CMPB++; } 其他 { ePWM_INFO->ePWM_CMPB_DIRECTION = ePWM_CMP_DOWN; ePWM_INFO->EPwmRegHandle->CMPB.bit.CMPB--; } } // //如果我们降低 CMPB,请检查是否 //我们达到最小值。 如果不是、减小 CMPB //否则、更改方向并增加 CMPB // 其他 { if (ePWM_INFO->EPwmRegHandle->CMPB.bit.CMPB =>= ePWM_INFO->EPwmMinCMPB) { ePWM_INFO->ePWM_CMPB_DIRECTION = ePWM_CMP_UP; ePWM_INFO->EPwmRegHandle->CMPB.bit.CMPB++; } 其他 { ePWM_INFO->EPwmRegHandle->CMPB.bit.CMPB--; } } 否则 { ePWM_INFO->EPwmTimerIntCount++; } return; } // ////文件结束 //
谢谢你。
此致、
Amin
尊敬的惠特尼:
根据您的建议、信号不会在特定的边沿生成、而是可变的。
说明示例:
假设我们有两个通道同步 ADC、
ADC1连接到具有固定频率和占空比的脉冲发生器(连接到设备以生成信号的 PWM 通道)。
ADC2连接到任意信号的。
然后我们有两个矢量、我们需要找到以下索引(i、j、k、l、…) 来分离第二个通道上的信号(这种方法很复杂)。
现在、我有一个 PWM 发生器(ePWM2)和一个 ADC 通道(ePWM1)、而不是两个通道同步 ADC。
如果我知道脉冲是在上升沿生成的、并且 ADC 同时开始采样、
由于脉冲频率是固定的、因此我可以用固定的索引来分隔样本。
我需要始终以特殊的方式(上升沿或下降沿)生成脉冲、并在此时开始采样。
谢谢、此致、
Amin
尊敬的惠特尼:
主要功能如下:
放置在 while (1)循环中的断点、
请参阅此函数: __interrupt void adcaIsr()
//######################################################################################################################## //! \file /2837x_RFFT_ADC/main.c //! //! \brief 显示具有来自 ADC 输入的512 pt 实时 RFFT 的演示代码 //! \Author Vishal Coelho (修改原始版本) //! \date 2015年3月26日 //! //! 该程序展示了如何使用12位实时 ADC //! 和相关的频谱幅度、相位。 EPWM1和2已设置 //! 这样 EPWM2输出的方波的频率比 之慢10倍//! EEPWM1;EEPWM1用作 ADC 的采样时钟、它将 //! 通过通道 A0 (引脚09)对 EPWM2A (引脚53)进行采样、然后运行 FFT。 //! 实时 FFT 是逐帧计算的。 一旦整帧为 //! 在 ADC ISR 中填充、它会设置一个标志来启动 FFT。 //! 计算完成后将重置标志 //! //! 注意此示例使用 F2837xD controlCARD Rev1.1 //! 注意输入缓冲区必须与2N 字边界对齐、N 为 //! 实际 FFT 的大小。 用户可以选择使用替代例程 、//! RFFT_ADC_f32u ()、如果无法(或不需要)对齐。 在这里 //! 情况下、可以对段 alignment #pragma 进行注释。 但是、使用此 //! 函数将降低算法的周期性能。 //! //组: C2000 //目标系列: F2837x // //////################################################################################################################ //$TI 发布:C28x 浮点单元库 V1.50.00.00 $ //$发布 日期:2017年5月22日$ //$版权:版权所有(C) 2017 Texas Instruments Incorporated - // http://www.ti.com/ 保留所有权利$ //############################################################################################################## // //包括 //********* #include "fpu_rfft.h" //主 include 文件 #include "math.h" #include "examples_setup.h" //! //! \addtogroup RFFT_examples ADC 输入(实时)的实数 FFT //@{ //********* //定义 //********* #define RFFT_STACages 9 #define RFFT_SIZE (1 << RFFT_STages) #define F_PER_SAMPLE (ADC_SAMPLING_FREQ/(float) RFFT_SIZE )#define USE_TEST_INPUT 1 //如果不在测试模式中、请务必排除 SIGNAL。asm //从构建 #define Epsilon 0.1 //********* //全局 //********* #ifdef __cplusplus #pragma DATA_SECTION ("RFFTdata1") #else #pragma DATA_SECTION (RFFTin1Buff、"RFFTdata1") #endif //_cplusplus //! 简要 FFT 计算缓冲器 //! 注意:输入缓冲区需要与2N 字边界对齐 //! 注意如果 FFT 级数为奇数、FFT 的结果将 //! 写入该缓冲器 //! 请注意、此缓冲器采用 N 个12位 ADC 输入、因此它定义为 //! 无符号 int 数组、但输入//之间的 FFT 算法 ping 通! 每个级的输出缓冲器、因此该缓冲器需要能够 //! 容纳 N 个浮点值、且大小应为2 * RFFT_SIZE uint16_t RFFTin1Buff[2 * RFFT_SIZE]; #ifdef __cplusplus #pragma DATA_SECTION ("RFFTdata2") #else #pragma DATA_SECTION (RFFTBuff、"RFFTdata2")/#magendif/ ! 简要幅度计算缓冲器 //! float RFFTmagBuff[RFFT_SIZE/2+1]; #ifdef __cplusplus #pragma DATA_SECTION ("RFFTdata2") #else #pragma DATA_SECTION (RFFTmagBuff、"RFFTdata2") #endif //_cplusplus //! \brief 相位计算缓冲器 //! float RFFTphaseBuff[RFFT_SIZE /2]; #ifdef __cplusplus #pragma DATA_SECTION ("RFFTdata3") #else #pragma DATA_SECTION (RFFToutBuff、"RFFTdata3") #endif //_cplusplus //! 简要 FFT 计算缓冲器 //! 注意如果 FFT 级数是偶数、FFT 的结果将 //! 写入该缓冲器 //! float RFFToutBuff[RFFT_SIZE]; #ifdef __cplusplus #pragma DATA_SECTION ("RFFTdata4") #else #pragma DATA_SECTION (RFFTF32Coef、"RFFTdata4") #endif //_cplusplus //! \brief Twiddle Factors //! float RFFTF32Coef[RFFT_SIZE]; //! 简要 RFFT_ADC_F32_struct 对象 //! RFFT_ADC_F32_struct rfft_ADC; //! 针对 RFFT_ADC_F32_struct 对象的\brief 句柄 //! RFFT_ADC_F32_struct_Handle HND_rfft_ADC =&rfft_ADC; //! 简要 RFFT_F32_struct 对象 //! RFFT_F32_struct rfft; //! 针对 RFFT_F32_struct 对象的\brief 句柄 //! RFFT_F32_struct_Handle HND_rfft =&rfft; //! \brief 标志、用于指示 ADC 已完成采样和存储、 //! FFT 输入缓冲器中的 N 个点 //! volatile uint16_t flagInputReady = 0; //! \brief 进入 FFT 输入缓冲器的索引 //! volatile uint16_t sampleIndex = 0; //********* //函数原型 //********* _interrupt void adcaIsr (); //********* //函数定义 //********* //! //! \brief 针对512样本 RFFT ADC 示例的主例程 //! 返回1 //! //! 该程序展示了如何计算 //的实际 FFT、幅度和相位! 来自12位 ADC 输入的数据。 输入缓冲器必须与 A //!对齐 如果使用 RFFT_F32、则为2N 字边界。 //! 数据段对齐(#pragma ...) RFFT_ADC_f32u // ! 但在运行 RFFT_ADC_F32时需要。 但是、使用未对齐 的//! 版本将降低算法的周期性能。 //! //! 最小级数为3。 当级数更多 时//! 大于9时、量化误差会很大、不建议这么做。 //! 此示例将通过 ADC 通道对 ePWM 通道进行采样、并运行 //! RFFT 对实信号的影响。 //! //! RFFT_F32_struct 是一个定义为: //! //! typedef 结构{ //! float * InBuf; //! float * OutBuf; //! float * CosSinBuf; //! float * MagBuf; //! float * PhaseBuf; //! uint16_t FFTize; //! uint16_t FFTStage; //!} RFFT_F32_struct; //! //! RFFT_ADC_F32_struct 定义为: //! typedef 结构{ //! uint16_t * InBuf; //! 无效 *尾线; //!} RFFT_ADC_F32_struct; //! //! 假设: //! //! -# RFFT_F32_struct 的 OutBuf 必须传递到 //的尾端! RFFT_ADC_F32_struct //! -#输入信号存储在 Signal.asm //! -# FFTize 必须是2的幂(32、64、128等) //! -# FFTize 必须大于或等于32 //! -# FFTStages 必须为 log2 (FFTize) //! -# InBuf、OutBuf、CosSinBuf 在长度上 FFTize //! -#幅度缓冲器的长度为 FFTSize/2+1 //! -#相位缓冲器的长度为 FFTSize/2 //! //! 观察变量: //! //! -# InBuf (RFFT_ADC_F32_struct)输入缓冲 器//! -# BUF (RFFT_F32_STRURT) 未使用 //! -#尾灯 存储了 OutBuf 的地址 //! -# OutBuf 输出缓冲器 //! -# CosSinBuf Twiddle 因子缓冲 器//! -# MagBuf 幅度缓冲 器//! -# PhaseBuf 相位缓冲器 //! -# j 标准化数字频率分量的索引 //! -#频率 原始信号的实际模拟频率 //! //! 外部连接: //! 将 A0 (引脚9)连接到 F2837x controlCARD 上的 EPWM2A (引脚53)。 请参阅 //! 用于引脚定位的电路板原理图。 //! 请注意、ADC 将以100KHz 对50%占空比1KHz 波形(EPWM2A)进行采样 //! 并在其上运行 FFT。 由于输入是方波、因此您将 //! 请参见第5个 bin 处的基频1KHz //! (5*FS/N = 5*100K/512 = 976.5)及其所有奇次谐波。 因为采样 的//! 波形不是 FFT_SIZE 的整数倍、您将看到一些 //! 频谱泄漏时、基频的一部分将泄漏到第6个容器中。 //! 克服这一问题的一种方法是在//运行 FFT 之前窗口输入! 它。 //! int16_t main (void) { //本地 uint16_t i、j; float freq = 0.0; #ifdef 闪存 EALLOW; Flash0EccRegs.ecc_enable.bit.enable = 0; memcpy (((uint32_t *)&RamfuncsRunStart、(uint32_t *)&RamfuncsLoadStart、 (uint32_t)&RamfuncsLoadSize); FPU_initFlash(); #endif //flash FPU_initSystemClocks(); FPU_initEPIE(); //设置 ADC-A FPU_initADCA(); //将 EPWM1A 设置为采样时钟、将 EPWM2A 设置为信号 //采样 FPU_initEPWM(); //映射 ISR 函数 EALLOW; PieVectTable.ADCA1_INT =&adcaIsr;// ADCA 中断1的函数 EDIS; //启用全局中断和更高优先级的实时调试事件: PieCtrlRegs.PIEIER1.bit.INTx1 = 1;//启用 ADC1INT IER |= M_INT1;//启用组1中断 EINT; //启用全局中断 INTM ERTM; //启用全局实时中断 DBGM //启动 ePWM FPU_startEPWM (); //将 RFFT_ADC_F32_struct 链接到 RFFT_F32_struct。 尾指针 RFFT_ADC_F32_struct 的//被传递到的 OutBuf 指针 //RFFT_F32_struct hnd_rfft_adc->Tail =&(hnd_rfft->OutBuf); hnd_rfft->FFTize = RFFT_SIZE; //FFT 大小 hnd_rfft->FFTStage = RFFT_STOPENAINTS; //FFT 级 hnd_rfft_adc->InBuf =&RFFTin1Buff[0];//输入缓冲器(12位 ADC 输入) hnd_rfft->OutBuf =&RFFToutBuff[0];//输出缓冲区 hnd_rfft->CosSinBuf =&RFFTF32Coef[0];//Twiddle 因子 hnd_rfft->MagBuf =&RFFTmagBuff[0];//幅度输出缓冲区 hnd_rfft->PhaseBuf =&RFFTphaseBuff[0];//相位输出缓冲器 RFFT_F32_SINCOSTable (HND_RFFT); //Calculate Twiddle Factor 对于(i=0;i < RFFT_SIZE;i++){ RFFToutBuff[i]= 0; //清理输出缓冲 器} 对于(i=0;i <= RFFT_SIZE/2;i++){ RFFTmagBuff[i]= 0; //清理幅度缓冲 器} 对于(i=0;i < RFFT_SIZ/2;i++){ RFFTphaseBuff[i]= 0; //清理相位缓冲 器} while (1){ while (flagInputReady = 0){};//等待 ADC ISR 设置该标志 //然后再继续 RFFT_ADC_F32 (HND_rfft_ADC);//计算实数 FFT (12位 ADC 输入)<--- 断点 flagInputReady = 0; //重置标志 在项目中--tmu_support=tmu0时,#ifdef __TMS320C28XX_tmu__//定义 //属性 RFFT_F32_MAG_TMU0 (HND_RFFT); //计算幅度 RFFT_F32_PHASE_TMU0 (HND_RFFT); //计算相 位#else RFFT_F32_MAG (HND_RFFT); //计算幅度 RFFT_F32_PHASE (HND_RFFT); //计算相 位#endif //__TMS320C28XX_TMU__ //找出信号频率的最大频率分量 //分量信号。 该算法仅用于查找频率 一个分量频率信号的//;在本例中、它给出了 采样方波的//基频 J = 1; FREQ = RFFTmagBuff[1]; for (i=2;i 频率){ J = I; FREQ = RFFTmagBuff[i]; } } //将标准化数字频率转换为实际模拟频率 //f = m * FS/N //其中 m 是最大值的二进制数、即采样 fs //频率和 N FFT 中的点数 FREQ = F_PER_SAMPLE *(float) j; } //执行永远不会达到此点 返回1; } // main 的末尾 //! \brief ADC 中断服务例程 //! ISR 会将每个采样值存储在 FFT 缓冲区中、和 //! 一旦缓冲区已满、升起标志 //! _interrupt void adcaIsr () { RFFTin1Buff[sampleIndex++]= AdcaResultRegs.ADCRESULT0; if (sampleIndex ==(RFFT_SIZE - 1))){ sampleIndex = 0; flagInputReady = 1; EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;//<--- 新 EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;//<--- 新 EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET;//<--- 新 EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;//<--- 新 } AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;//清除 INT1标志 PieCtrlRegs.PIEACK.all = PIEACK_Group1; } //@}//addtogroup //文件末尾
运行程序(使用 Resume (F8))几次的结果并显示在示波器上:
谢谢你。
此致、
Amin
我更改了代码、
void FPU_initEPWM (void) { CpuSysRegs.PCLKCR2.bit.EPWM1 =1;//启用 EPWM1时钟 CpuSysRegs.PCLKCR2.bit.EPWM2 =1;//启用 EPWM1时钟 //启用 ePWM GPIO InitEPwm1Gpio(); InitEPwm2Gpio(); EALLOW; // ePWM 时钟分频器设置为/2 ClkCfgRegs.PERCLKDIVSEL.bit.EPWMCLKDIV=1; //关闭 ePWM 时钟 CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0; //禁用组上的 SOC EPwm1Regs.ETSEL.bit.SOCAEN = 0; //在向上计数时选择 SOC EPwm1Regs.ETSEL.bit.SOCASEL = 4; //在发生第一个事件时生成脉冲 EPwm1Regs.ETPS.bit.SOCAPRD = 1; //将比较 A 值设置为2000次计数 EPwm1Regs.CMPA.bit.CMPA = EPWM1_DUTY; //将周期设置为4000个计数 EPwm1Regs.TBPRD = EPWM1_PERIOD; //冻结计数器 EPwm1Regs.TBCTL.bit.CTRMODE = 3; //启用 SOCA EPwm1Regs.ETSEL.bit.SOCAEN = 1; EPwm1Regs.TBCTL.bit.HSPCLKDIV = ePWM_HSPCLKDIV; //禁用组上的 SOC EPwm2Regs.ETSEL.bit.SOCAEN = 0; //将比较 A 值设置为10000次计数 EPwm2Regs.CMPA.bit.CMPA = EPWM2_Duty_cycle; //将周期设置为20000个计数 EPwm2Regs.TBPRD = EPWM2_PERIOD; //冻结计数器 EPwm2Regs.TBCTL.bit.CTRMODE = 3; EPwm2Regs.TBCTL.bit.HSPCLKDIV = ePWM_HSPCLKDIV; //清除零上的 PWM1A // EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; EPwm1Regs.AQCTLA.bit.PRD = AQ_CLEAR; //清零 PWM2A EPwm2Regs.AQCTLA.bit.CAU = AQ_SET; EPwm2Regs.AQCTLA.bit.PRD = AQ_CLEAR;*/ EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET; EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; EDIS; }
问题是 RFFTin1Buff 上存储的值 是时间中的一个变量
我需要启动脉冲始终相同。
此致、
Amin
好的、你是否尝试了我关于减小 ePWM 时钟上的分频器的其他建议以使 ePWM 保持同步?
[引用]此外、即使它们开始同步、它们也将不同步。 您目前正在将 ePWM1周期设置为12、将 ePWM2周期设置为31250、不能被12除。 因此、您可以重新配置 ePWM 分频器、直到您能够获得两个可保持同步的 PRD 值、或者您必须通过清除 TBCLKSYNC、清除 TBCTR 和设置 TBCLKSYNC 来重新同步它们。[/QUERP]
例如、在 examples_setup.h 中
// //定义 //********* #define CPU_FRQ_200MHz 1 #define ADC_SAMPLING_FREQ 100000.0L #define ePWM_CLK 100000000 //ePWM_CLOCK 是 SYSCLK/2 #define ePWM_CLKDIV 1 //ePWM_CLOCK 是 SYSCLK/(2*2) #define ePWM_HSPCLKDIV 2. //ePWM_CLOCK 是 SYSCLK/(4*2*2) #define EPWM1_PERIOD ePWM_CLK/(4*2*500000U) #define EPWM1_DUTY EPWM1_PERIODE/2 #define EPWM2_PERIOD ePWM_CLK/(4*2*200U) #define EPWM2_Duty_cycle EPWM2_PERIODE/2
谢谢、
惠特尼