Thread 中讨论的其他器件:SysConfig、 C2000WARE
您好!
是否可以在单个 ADC 的单个 DMA 设置中即时更改乒乓缓冲器的 PWM 频率?
假设我们要在同一 ADC 通道上设置两个不同的采样周期(不同的频率和不同的长度)。 您建议如何执行此操作?

此时、我们有一个长块、然后抽取其中一个、但现在我们需要对2个 ADC 通道执行相同的操作、并且器件上没有足够的存储器。 在硬件上,我们还将 ADC 连接了两个...所以这是可能的。 但我不确定如何实现它。
此致
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.
您好!
是否可以在单个 ADC 的单个 DMA 设置中即时更改乒乓缓冲器的 PWM 频率?
假设我们要在同一 ADC 通道上设置两个不同的采样周期(不同的频率和不同的长度)。 您建议如何执行此操作?

此时、我们有一个长块、然后抽取其中一个、但现在我们需要对2个 ADC 通道执行相同的操作、并且器件上没有足够的存储器。 在硬件上,我们还将 ADC 连接了两个...所以这是可能的。 但我不确定如何实现它。
此致
您有没有关于 PRD 影子模式和 TBPRD 的示例?
谢谢 Joseph Casuga。
是的、信号采样频率始终是确定性的。
例如、我们要设置一个完整的6k 采样块、其中5k 使用一个采样频率、其余1k 采样使用更高频率(第一个频率的 x4因子)。
您是否愿意为此提供一个示例?
此致
这是我的实际 PWM 代码:
void ConfigureEPWM(void)
{
//
// Make the timer count up
//
EPwm2Regs.TBCTL.all = 0x0000;
EPwm2Regs.TZCTL.all = 0x0000;
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;
EPwm2Regs.TBPRD = 199; // 500khz
//
// Set the A output on zero and reset on CMPA
//
EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET;
EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;
EPwm2Regs.AQCTLA.bit.PRD = AQ_TOGGLE; // Toggle on PRD
//
// Set CMPA to 20us to get a 50% duty
//
EPwm2Regs.CMPA.bit.CMPA = 100; //80;//1200;//2000
//
// Start ADC when timer equals zero (note: don't enable yet)
//
EPwm2Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO;
EPwm2Regs.ETPS.bit.SOCAPRD = ET_1ST;
//
// Enable initialization of the SOCA event counter. Since we are
// disabling the ETSEL.SOCAEN bit, we need a way to reset the SOCACNT.
// Hence, enable the counter initialize control.
//
EPwm2Regs.ETCNTINITCTL.bit.SOCAINITEN = 1;
}谢谢你 Nima。
我能否举个例子说明如何实现这一点?
we would like to set a full 6k samples block for example, 5k of them using 100kHz and the rest 1k sampling using 500kHz. Then we would go back to the first block
你好 Nima。
我对执行情况有一些疑问。 我已经为 ADC 和计时器实现了 DMACH1和 CH2。 如何在 DMACH5上添加此功能?
下面是一个示例。
PieVectTable.DMA_CH5_INT =&dmach5_isr_timer;
//INTERRUPT for TIMER
PieVectTable.DMA_CH5_INT = &dmach5_isr_TIMER;
void ConfigureEPWM(void)
{
//
// Make the timer count up
//
EPwm2Regs.TBCTL.all = 0x0000;
EPwm2Regs.TZCTL.all = 0x0000;
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;
EPwm2Regs.TBPRD = 199; // 500khz
//
// Set the A output on zero and reset on CMPA
//
EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET;
EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;
EPwm2Regs.AQCTLA.bit.PRD = AQ_TOGGLE; // Toggle on PRD
//
// Set CMPA to 20us to get a 50% duty
//
EPwm2Regs.CMPA.bit.CMPA = 100; //80;//1200;//2000
//
// Start ADC when timer equals zero (note: don't enable yet)
//
EPwm2Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO;
EPwm2Regs.ETPS.bit.SOCAPRD = ET_1ST;
//
// Enable initialization of the SOCA event counter. Since we are
// disabling the ETSEL.SOCAEN bit, we need a way to reset the SOCACNT.
// Hence, enable the counter initialize control.
//
EPwm2Regs.ETCNTINITCTL.bit.SOCAINITEN = 1;
}
//
// DMA setup channels.
//
void DMA_for_ADCS()
{
//
// Initialize DMA
//
DMAInitialize();
//
// DMA set up for first ADC
//
DMACH1AddrConfig(adcData_compuesto, &AdccResultRegs.ADCRESULT0);
DmaRegs.CH1.BURST_SIZE.bit.BURSTSIZE = 0;
DMACH1TransferConfig(RESULTS_BUFFER_SIZE_TOTAL - 1, 0, 2);
DMACH1ModeConfig(
DMA_ADCCINT1,
PERINT_ENABLE,
ONESHOT_DISABLE,
CONT_ENABLE,
SYNC_DISABLE,
SYNC_SRC,
OVRFLOW_DISABLE,
SIXTEEN_BIT,
CHINT_END,
CHINT_ENABLE);
//
// DMA set up for second ADC
//
DMACH2AddrConfig(&adcData_compuesto[1], &AdcaResultRegs.ADCRESULT0);
DmaRegs.CH2.BURST_SIZE.bit.BURSTSIZE = 0;
DMACH2TransferConfig(RESULTS_BUFFER_SIZE_TOTAL- 1, 0, 2);
DMACH2ModeConfig(
DMA_ADCAINT2,
PERINT_ENABLE,
ONESHOT_DISABLE,
CONT_ENABLE,
SYNC_DISABLE,
SYNC_SRC,
OVRFLOW_DISABLE,
SIXTEEN_BIT,
CHINT_END,
CHINT_DISABLE);
}
void initDMA()
{
//
// Initialize DMA
//
DMA_initController();
//.
//.......................
DMA_for_ADCS();
//........................
////////////////////////////////////////////////////
//my doubt!!!!
////////////////////////////////////////////////////
//
// DMA CH5
//
DMA_configAddresses(DMA_CH5_BASE, (uint16_t *)(EPwm2Regs + EPWM_O_CMPA),
compareConfigs);
//no burst now
//DMA_configBurst(DMA_CH5_BASE, BURST, 1, 1);
//DMA_configTransfer(DMA_CH5_BASE, TRANSFER, 1, 1-BURST);
//samller buffer to generate interrupt and change FREQ
DMACH5TransferConfig(RESULTS_BUFFER_SIZE_SMALLER - 1, 0, 2);
//What is this setup??????
DMA_configMode(DMA_CH5_BASE, DMA_TRIGGER_EPWM2SOCA, DMA_CFG_ONESHOT_DISABLE |
DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
DMACH5ModeConfig(
//DMA_ADCAINT1,
DMA_TRIGGER_EPWM2SOCA, //IS it ok?
PERINT_ENABLE,
ONESHOT_DISABLE,
CONT_ENABLE,
SYNC_DISABLE,
SYNC_SRC,
OVRFLOW_DISABLE,
SIXTEEN_BIT,
CHINT_END,
CHINT_DISABLE);
//
// Configure DMA Ch5 interrupts
//
DMA_setInterruptMode(DMA_CH5_BASE, DMA_INT_AT_END);
DMA_enableInterrupt(DMA_CH5_BASE);
DMA_enableTrigger(DMA_CH5_BASE);
}朴世利
我无法与您在论坛上的共享特定于应用的代码。 我可以帮助您在使用我们的 SDK 实施时朝着正确的方向进行指导。
例如、
如果您为 DMA 的 CH5实施了代码、但代码无法正常工作、我可以为您提供有关代码需要如何更改或代码行为方式为何的指导。
但是、我无法编写代码并通过论坛与您共享。 它不会让我通过点击授权来提供完整的应用示例。
我建议您实施 ePWM 中断计数器代码、然后实施 DMA5通道、当您达到阈值时、立即启动该 DMA 通道。 如果您的代码不起作用、您可以共享 DMA5 CH 配置代码和 ePWM 事件计数代码、我本人和我们的 DMA 专家将非常乐意为您提供有关器件运行方式的原因的指导。
NIMA
哇、很有趣的是、我一直在找一个示例、您"无法分享示例代码。 您必须使用 C2000Ware/driverlib 文件夹中的现有软件并实现此功能。" 然后我可以重写 TI 的一段代码、然后您可以进行检查。
不在论坛上公开,以便每个人都能进入论坛。 有时、我在 e2e 上找到了一些答案、其中有一些私有文件共享、需要检查。 然后、我向 TI 要求他们、并被告知负责该公司的人员不再在该公司工作。 浪费时间。
根据您的竞争对手的经验、在高级情况下、我提出了相同的请求、一些专家编写了代码并与我们分享进行测试。
这只是一个事实、我在解释我们选择其他供应商的原因(我不是唯一具有相同经验的供应商)。 只是反馈。
祝你度过美好的一天!
你好 Nima。
很多帖子都是毫无结果的...例如:
其他问题在内部得到解决、这使得具有相同问题的其他工程师难以找到快速解决方案。
例如、在这个线程中、我只是要求一个简单的示例、说明如何在同一 ADC DMA 块内的两个不同频率下动态更改 ePWM 的频率、从而对 ADC 进行采样。 我共享了一些代码。 我共享了一个图。
最后、我在我的代码中执行了权变措施(仍然对该解决方案感兴趣)、但我们的工程资源需要专注于我们的应用、而不是通过 TI DSP 芯片实现功能...而 IMHO TI 似乎不分享这一愿景。
朴世利
一般而言、TI 会跟踪工程师的响应时间和效率。 我们有很多有关 E2E 支持的规则。 对于新的 C2000线程、没有回答的问题非常少见、但我看到的是您共享的问题。
对于那个、
if (PingPongState == 0) {
// Set DMA address to start at ping buffer.
DMA_configAddresses(DMA_CH1_BASE,
(const void *)AdcBufRaw,
(const void *)(ADCARESULT_BASE + ADC_O_RESULT0));
// Fill AdcBuf with contents of the pong buffer.
AdcBufRawPtr = AdcBufRaw + ADC_BUF_LEN;
for (i = 0; i < ADC_BUF_LEN; i++) {
*(AdcBufPtr++) = *(AdcBufRawPtr++);
}
} else {
// Set DMA address to start at pong buffer.
DMA_configAddresses(DMA_CH1_BASE,
(const void *)(AdcBufRaw + ADC_BUF_LEN),
(const void *)(ADCARESULT_BASE + ADC_O_RESULT0));
// Fill AdcBuf with contents on the ping buffer.
AdcBufRawPtr = AdcBufRaw;
for (i = 0; i < ADC_BUF_LEN; i++) {
*(AdcBufPtr++) = *(AdcBufRawPtr++);
}
}
// Toggle PingPongState.
PingPongState ^= 1;
逻辑看起来正确。 是的、这是第一次执行空缓冲区复制、但从第二次开始按预期工作。
首次:
为 ADC 尚未接收的下一组采样设置 DMA。
您将在 AdcBufRaw[0..ADC_BUF_LEN-1]中填充这些值。 尚未收到任何资料。 DMA 将执行此操作。
然后将上次接收到的内容 AdcBufRaw[ADC_BUF_LEN 复制到 ADC_BUF_LEN*2-1]到 AdcBufRawPtr 中。
是的,由于 AdcBufRawPtr 的 AdcBufRaw[ADC_BUF_LEN 至 ADC_BUF_LEN*2-1]为空,因此第一次将用空值填充 AdcBufRawPtr。
例如、我们要设置一个完整的6k 采样块、其中5k 采样使用100kHz、其余1k 采样使用500kHz。
更改 EPWM 频率后、您应该能够自动更改 ADC 采样率、因为它连接到 DMA 以接收样本。
这是我要做的、
1.将 EPWM PRD 设置为100KHz。
2.设置 ADC + DMA 以传输6K 样本
3.运行 ePWM。
4、DMA 传输完成后、产生中断、更改 EPWM PRD (500kHz)、保留相同的 DMA 设置、但传输大小设置为1K 除外。
等待下一个 ISR 完成 DMA
6.返回第1步重复。