您好!
我正在尝试使用 EPG 外设驱动信号输出、以控制一组 WS2812 LED。 我正在尝试发送8个数据位、该数据位使用以3倍的速度运行的图形发生器的24位来生成图形、然后使用 EPG 中断向 EPG 馈送新数据、以便针对每个数据字节发送。
我最初的方法是使用 DMA、但我不确定是否甚至可以使用 EPG。 EPG 基址表列出了 DMA 无法访问寄存器、不过 DMA 方框图(图12-1)显示 EPG 已连接到 DMA 总线。
我已切换到使用 EPG 中断、但我只能获得一次中断触发、并且无法获取要清除的 GINTSTS INT 位、以便再次触发中断。 我的更新函数应该触发信号发生器开始成功发送每次运行时的前24位图形数据、但 ISR 仅运行一次、在我必须复位 CPU 以清除标志之前。
以下是我用于设置 EPG 的代码:
EPG_selectEPGOutput(EPG1_BASE, EPG_OUT0, EPG_OUT_SEL_SIG);
EPG_selectSignalOutput(EPG1_BASE, EPG_OUT0, EPG_SIGGEN0_DATATRANOUT3);
// Bit period is 1.25us and there are three periods per bit. 120 MHz sysclk / 49 = 2.45 MHz
// which gets pretty close.
EPG_setClkGenPeriod(EPG1_BASE, EPG_CLKGEN0, 49U);
EPG_selectSigGenClkSource(EPG1_BASE, EPG_SIGGEN0, EPG_CLKGEN0_CLKOUT0_GCLK);
EPG_setClkGenOffset(EPG1_BASE, EPG_CLKGEN0, 0, 0);
EPG_setDataBitLen(EPG1_BASE, EPG_SIGGEN0, 24);
EPG_setSignalGenMode(EPG1_BASE, EPG_SIGGEN0, EPG_SIGGEN_MODE_SHIFT_LEFT_REPEAT);
EPG_enableGlobal(EPG1_BASE);
此代码每10ms 运行一次、以发送图形发生器中的第一个数据。 正在正确发送初始24位。
EPG_setData0Word(EPG1_BASE, EPG_SIGGEN0, ws2812_color);
EPG_setSignalGenMode(EPG1_BASE, EPG_SIGGEN0, EPG_SIGGEN_MODE_SHIFT_LEFT_REPEAT);
Interrupt_enable(INT_SYS_ERR);
EPG_clearInterruptFlag(EPG1_BASE, EPG_INT_SIGGEN0_FILL | EPG_INT_SIGGEN0_DONE);
SysCtl_clearInterruptStatus(SYSCTL_SYS_ERR_INT_CLR_GINT | SYSCTL_SYS_ERR_INT_CLR_EPG1_INT);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
EPG_enableInterruptFlag(EPG1_BASE, EPG_INT_SIGGEN0_FILL);
EPG_enableSignalGen(EPG1_BASE, EPG_SIGGEN0);
这是我的 ISR、它似乎只运行一次、无法清除 GINTSTS 寄存器中的 INT 状态。
__interrupt void ws2812_isr(void)
{
uint32_t epg_int_status = EPG_getInterruptStatus(EPG1_BASE);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
SysCtl_clearInterruptStatus(SYSCTL_SYS_ERR_INT_CLR_GINT | SYSCTL_SYS_ERR_INT_CLR_EPG1_INT);
EPG_clearInterruptFlag(EPG1_BASE, EPG_INT_SIGGEN0_FILL | EPG_INT_SIGGEN0_DONE);
if (epg_int_status & EPG_INT_SIGGEN0_FILL) {
uint16_t pixel = data_counter / 3;
uint16_t color = data_counter % 3;
data_counter += 1;
if (pixel < PIXEL_COUNT) {
uint32_t ws2812_color;
if (color == 0) {
ws2812_color = color_to_ws2812(led_data[pixel].green);
} else if (color == 1) {
ws2812_color = color_to_ws2812(led_data[pixel].red);
} else {
ws2812_color = color_to_ws2812(led_data[pixel].blue);
}
EPG_setData0Word(EPG1_BASE, EPG_SIGGEN0, ws2812_color);
EPG_setData1Word(EPG1_BASE, EPG_SIGGEN0, 0x00);
} else {
// EPG_setSignalGenMode(EPG1_BASE, EPG_SIGGEN0, EPG_SIGGEN_MODE_SHIFT_RIGHT_ONCE);
// EPG_disableSignalGen(EPG1_BASE, EPG_SIGGEN0);
}
}
}
我已经单步执行了 ISR 和触发函数中的代码、其中 EPG_clearInterruptFlag 被调用、而 GINTSTS INT 标志从未被清除。 有时会清除 SIGGEN0_FILL 位、但 INT 标志本身仍保持设置状态。 关于清除标志或如何向 EPG 提供连续数据、我是否遗漏了某些内容。 如果我可以让 DMA 方法有效、而不是首选的中断。
