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:CCS/LAUNCHXL-F28379D:使用 SGEN 库生成100kHz 正弦波

Guru**** 2538960 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/879207/ccs-launchxl-f28379d-ccs-launchxl-f28379d-generating-100khz-sine-wave-using-sgen-library

器件型号:LAUNCHXL-F28379D

工具/软件:Code Composer Studio

尊敬的 TI 社区:

我要在项目中使用 SGEN 库创建可扫描频率发生器、这是一个障碍。 我的上限是100kHz、无法输出干净的正弦输出。 图1显示了100kHz 时正弦输出的外观。 此项目的引用是 buffdac_sine_cpu01

还有另一个使用  DMA 的正弦发生器示例 buffdac_sine_dma_cpu01。 我能够  使用 DMA 生成平滑的100kHz 正弦波、但我不使用它、因为我希望能够手动扫描频率。 我可以使用 SGEN 库在运行时修改 sgen.freq 值来实现这一点。

在 TI 的信号发生器库模块用户指南中、它逐步介绍了如何生成特定频率输出。 我在1.8MHz 的采样频率下使用 CPU Timer0 ISR。 CPU 定时器0触发的采样频率越高、输出信号就越平滑。 参数 sgen.gain 和 sgen.offset 分别设置为0x7FFF 和0。 这会将增益设置为1、不会添加偏移。 接下来、我计算 sgen.step_max 和 sgen.freq。

该步骤定义为:

其中 F_max 是程序的最大频率(100kHz)、F_ISR 是 ISR 的频率(1.8MHz)。 我计算的步进值为 238、609、294。

最后、我所需的频率为100kHz、要计算 sgen.freq、我执行以下操作:

其中 f 是所需的100kHz 频率、f_max 是100kHz。 结果为2^31或2、147、483、648

运行该代码后、输出如下面的图1所示。

我尝试通过将其增加到2MHz 来改进采样、新计算的步长值 为214、748、365。 这会导致较低输出频率(90kHz)的正弦波形、如图2所示。 我认为这是由于 DAC 输出的限制而发生的。

是否有办法改进此 SGEN 代码以获得平滑正弦输出、或者是否受到库的限制? 非常感谢您的参与。

//包含的文件
#include "F28x_Project.h"
#include "sgen.h" //信号生成头文件


volatile struct dac_regs* dac_ptr[4]={0x0、DacaRegs、DacbRegs、& DaccRegs};

SGENHP_1 sgen = SGENHP_1_num;

uint32 samplplingFreq_Hz = 1800000;
uint16 sisr sude_freedums =


0






;void voltaturedac = 0_float = 0_id_float;void voltatureid_float = 0_float 0_id_id_id_id_float = 0;uatureid_float 0_id_id_id_id_float = 0_id_id_id_float = 0_id_float 0_id_ // CPU 定时器0中断服务例程

//主
void main (void)
{
//初始化系统控制:
InitSysCtrl();

//禁用 CPU 中断
Dint;

//将 PIE 控制寄存器初始化为默认状态。
InitPieCtrl();

//清除所有中断并初始化 PIE 矢量表:
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();

//将 CPU Timer0和 ADCA1中断函数映射到 PIE 矢量表
EALLOW;
PieVectTable.TIMER0_INT =&CPU_timer0_ISR;
EDIS;

//初始化变量
cpuPeriod_us =(1.0/200);
samplingPeriod_us =(1000000.0/samplingFreq_Hz);

//配置 DAC
configureDAC (2);

//配置 SGEN
sgen.alpha = 0; //范围(16)= 0x0000 -> 0xFFFF
sgen.offset = 0x0; //范围(Q15)= 0x8000 -> 0x7FFF
Sgen.gain = 0x7FFF;//范围(Q15)= 0x0000 -> 0x7FFF
sgen.step_max = 238609294;
sgen.freq = 2147483648;

//初始化 CPU 定时器
InitCpuTimer();

//将 CPU Timer0配置为以指定的采样频率中断
ConfigCpuTimer (&CpuTimer0、200、1000000.0/samplingFreq_Hz);

//启动 CPU Timer0
CpuTimer0Regs.TCR.ALL = 0x4000;

//启用中断
IER |= M_INT1;
PieCtrlRegs.PIEIER1.bit.INTx7=1;
EINT;
ERTM;

while (1){}
//

configureDAC -启用并配置请求的 DAC 模块
void configureDAC (uint16 DAC_num)
{
EALLOW;

DAC_PTR[DAC_num]->DACCTL.bit.DACREFSEL = 1;
DAC_PTR[DAC_num]->DACOUTEN 位.DACOUTEN = 1;
DAC_PTR[DAC_num]->DACVALS.ALL = 0;

DELAY_US (10);//缓冲 DAC 加电延迟

EDIS;
}

// cpu_timer0_isr -将正弦值写入 DAC 的计时器 ISR,记录正弦
// 计算下一个正弦值、并计算中断
// 持续
时间中断 void cpu_timer0_isr (void)
{

//启动 CPU 定时器1以指示中断开始
CpuTimer1Regs.TCR.ALL = 0x0000;

//将当前正弦值写入缓冲 DAC
DAC_PTR[2]->DACVALS.all = sgen_out;

//计算下一个正弦值
sgen.calc(&sgen);

//缩放下一个正弦值
sgen_out =(sgen.out + 32768)>> 4;

//确认此中断以从组1接收更多中断
PieCtrlRegs.PIEACX.ALL = PIEACK_Group1;

//停止 CPU 定时器1以指示中断结束
CpuTimer1Regs.TCR.ALL = 0x0010;

//重新加载 CPU 定时器1
CpuTimer1Regs.TCR.ALL = 0x0030;
}

图1.

图2.


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

    我想您的 CPU 带宽即将用完。  通过在 ISR 中的第一个和最后一个汇编指令上放置断点、我可以看到它需要大约100个周期。  在1.8MHz 时、CPU 保持正常运行、但当您提高速率时:2MHz x 100 = 200MHz、这是器件时钟速度。  可能当您测量频率降低时、这是因为缺少样本。

    您可能能够减少 ISR 有效负载-我可以看到您正在操作计时器1、这可能是多余的、但这只会购买一点我怀疑的。

    要在 DAC 输出端平滑步进、您可以构建一个重建滤波器、具体取决于您的频率范围和可容忍的相移量。  否则、我认为您只能通过构建基于查找表的算法来手动编码正弦波发生器、不过如果您走这条路、您需要考虑频率分辨率。   

    此致、

    Richard

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

    Richard、

    感谢您的回复。

    请问您是如何计算100个周期的? 我执行了计数事件方法、我看到大约60个周期。  

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

    不用客气。

    我将 C 代码复制到源文件中、将其嵌入到我自己的 CCS 项目中、然后构建并运行。  我在 ISR 中的第一条汇编指令上放置了一个断点、在最后一条汇编指令(IRET)上放置了另一个断点。  我在它们之间运行、并使用 CCS 时钟测量周期计数。 我看到97个周期。

    当然、这是在优化关闭的情况下进行的。

    此致、

    Richard