ZHCA963 August   2019 TMS320F280040-Q1 , TMS320F280040C-Q1 , TMS320F280041 , TMS320F280041-Q1 , TMS320F280041C , TMS320F280041C-Q1 , TMS320F280045 , TMS320F280048-Q1 , TMS320F280048C-Q1 , TMS320F280049 , TMS320F280049-Q1 , TMS320F280049C , TMS320F280049C-Q1 , TMS320F28374D , TMS320F28375D , TMS320F28376D , TMS320F28377D , TMS320F28377D-EP , TMS320F28377D-Q1 , TMS320F28378D , TMS320F28379D , TMS320F28379D-Q1

 

  1.   使用 C2000可配置逻辑块 (CLB) 进行设计
    1.     商标
    2. 简介
    3. 补充在线信息
    4. 设计概述
    5. 对输入采样
    6. 在 FSM 子模块中部署状态机
    7. 生成 PWM 信号
    8. 修改 PWM 周期和占空比
    9. 已完成的设计
    10. 输入 X-BAR、输出 X-BAR 和 CLB X-BAR
      1. 9.1 使用 X-BAR 将信号导入到 CLB 逻辑块中
      2. 9.2 使用 X-BAR 从 CLB 逻辑块中导出信号
    11. 10 运行示例项目
      1. 10.1 设置和连接
      2. 10.2 测试状态和转换
        1. 10.2.1 步骤 1
        2. 10.2.2 步骤 2
        3. 10.2.3 步骤 3
        4. 10.2.4 步骤 4
        5. 10.2.5 步骤 5
      3. 10.3 测试 PWM 周期和占空比
    12. 11 总结
    13. 12 参考文献

修改 PWM 周期和占空比

需要更新 COUNTER1 的 load_val 和 match1_val,以修改 CLB 逻辑块生成的 PWM 的周期和占空比。C28x 内核能够访问 COUNTER1 中的这两个寄存器并根据需要对它们进行更新。不过,最好在 COUNTER1 发生 counter=ZERO 事件时更新 load_val 和 match1_val,以免发生任何不可预测的行为。在此设计中,C28x 内核提出请求之后,计数器值会在下一个 counter=ZERO 事件时被更新。为了加载计数器值,将使用 HLC 子模块和推挽接口。推挽接口是 C28x 内核和 HLC 子模块用来传输数据的 4 级深度 FIFO。C28x 内核将新的周期和占空比值写入到推挽 FIFO 中。HLC 读取这些值并在发生下一个 counter=ZERO 事件时更新 COUNTER1 寄存器。C28x 还必须向 HLC 发出信号,以表明推挽 FIFO 中提供了新值。使用 GPREG 寄存器(C28x 可以访问的寄存器)的 BIT2 (0b00000100) 创建此信号。将 GPREG 寄存器位连接到 CLB 逻辑块的 BOUNDARY 输入。HLC 在输入事件被激活时执行自己的任务。

在此设计中,使用 EVENT0 向 HLC 发出信号,以使其读取推挽 FIFO 并更新 PWM 的值。如果在 HLC 的 EVENT0 上检测到上升沿,则执行指定的指令。由于 C28x 内核必须向 HLC 发出信号以使其在发生下一个 COUNTER1 counter=ZERO 事件时开始更新 PWM 值,因此属于 HLC 的 EVENT0 输入必须是对 COUNTER1 counter=ZERO 和 BOUNDARY IN2 执行与运算之后得到的信号。使用 LUT2 对这两个信号执行逻辑与运算。随后将 LUT2 的输出连接到 HLC 的 EVENT0 输入。

Figure 12 显示了 LUT2 的 SysConfig 配置。

lut2 config.pngFigure 12. LUT2 配置

接下来,定义 HLC 的指令。C28x 内核先后使用新的周期值和新的占空比更新 FIFO。HLC 必须按同样的顺序从 FIFO 中拉取这些值。首先,HLC 必须将周期值拉到 COUNTER1 的有效计数器寄存器中(此值也会写入到将在下一步中讨论的 load_val 中)。必须将从 FIFO 拉取的下一个值写入到 COUNTER1 的 match1_val 中。不过,“拉取”指令无法将值拉到计数器子模块的 match1_val 中。唯一能够向计数器的匹配值执行写入的指令是 MOV_T1 和 MOV_T2。这两个指令分别访问 match1_val 和 match2_val。使用“拉取”指令将 FIFO 中的值拉到 HLC 的 R1 寄存器中。随后,R1 值将使用 MOV_T1 指令更新 COUNTER1 的 match1_val。

INTR 指令是 HLC 执行的最终指令。INTR 指令在 C28x 内核上生成中断,此中断向 C28x 内核表明已执行更新。FIFO 现在为空,可以再次使用。C28x 内核也会清除 GPREG BIT2,以使下一个 counter=ZERO 事件不会生成另一个 HLC 事件(导致 FIFO 为空时被读取并导致下溢)。INTR 指令需要一个被称为“中断标签”的参数。读取 C28x 内核读取此标签,以了解为何造成中断。HLC 可以在逻辑块中发生不同的事件时生成多个中断;但在此设计中,只会使用一个中断。与 INTR 指令配合使用的中断标签是“1”,C28x 内核会在处理中断服务例程时确保中断标签为“1”。

Figure 13 显示了 HLC 子模块的 SysConfig 配置。

hlc config.pngFigure 13. HLC 配置

在此设计的这一部分中尚未执行的最终一项操作是更新 COUNTER1 的 load_val。HLC 无法访问此寄存器,因此 C28x 必须更新此值才能设置 GPREG BIT2。如果不更新 load_val,将不会更新周期。如下代码片段展示了 C28x 内核如何更新 PWM 周期和占空比以及在收到中断之后清除 GPREG。

void updateClbPwm(uint32_t period, uint32_t duty) { if (canUpdate) { canUpdate = 0; CLB_writeInterface(CLB1_BASE, CLB_ADDR_COUNTER_1_LOAD, period); HWREG(CLB1_BASE + CLB_LOGICCTL + CLB_O_BUF_PTR) = 0U; HWREG(CLB1_BASE + CLB_DATAEXCH + CLB_O_PULL(0)) = period; HWREG(CLB1_BASE + CLB_DATAEXCH + CLB_O_PULL(1)) = duty; CLB_setGPREG(CLB1_BASE, 1 << TRIGGER_PWM_UPDATE_SHIFT); } } __interrupt void clb1ISR(void) { uint16_t tag = CLB_getInterruptTag(CLB1_BASE); if (tag == UPDATE_PWM_COMPLETED_TAG) { canUpdate = 1; CLB_setGPREG(CLB1_BASE, 0); } CLB_clearInterruptTag(CLB1_BASE); Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP5); }

Section 9 说明了如何使用 XBAR 模块为 CLB 逻辑块导入和导出信号。