恶补DSP:3.F28335的ePWM模块
在“微机世界”中,PWM(脉宽调制)为城市交通信号灯调度系统。
ePWM模块就是交通信号灯调度中心总控室,它制订全城某一路口(IO口)红灯亮多久、绿灯亮多久,节奏如何切换,是否联动等规则;并把信号准确无误地传递到每个城门(IO接口),指导市民(电流/信号/外设)怎样有序地进出城市。
(ePWM生成周期性高低电平波形,调节占空比,实现能量/亮度/速度等的线性可控)
ePWM各部门详细分工
城市交通信号调度由四大部门组成:
(1)时基模块TB——“城市交通节拍局”
城市交通信号调度的每一步都要跟着固定的节奏走,节奏局负责规定节奏的起止、节拍周期、计数模式:
- 计数方式:像是交通信号灯按顺序放行,先红后绿(向上计数)。
- 初始节奏:所有交通信号灯最开始“从0秒开始计数”。
- 周期长度:节奏局每次给信号灯的指令周期性重复,比如红绿灯每隔一段时间重新开始(TBPRD)。
- 同步功能:本次设置为“自管自控”,不同路口的信号灯可以互不联动(不启用相位同步)。
- 节奏频率:跟着城市主发电厂的节拍(系统时钟),不做再分频减速。
- 节拍发生器开关:所有信号灯总开关,全部调度中心同时开启。
(设置TBCTL寄存器的CTRMODE、SYNCOSEL、PHSEN等,TBPRD设置周期,TBCTR清零,HSPCLKDIV/CLKDIV设置为1)
(2)比较模块CC——“交通路口事件对比处”
具体到每个路口,调度中心要决定“几秒时红灯变绿灯,几秒时绿灯变红灯”——这就是比较中心的职责。
- 影子寄存器模式:先悄悄在后台设好新规则,下个周期再生效,保证切换平滑(SHADOW)。
- 切换时机:每次从0秒重新计数时加载新规则(LOADAMODE/LOADBMDOE=CTR_ZERO)。
- 初始切换点:一开始规则都设为0,后续由主控程序动态调整(CMPA/CMPB)。
(设置CMPCTL寄存器,SHDWAMODE/SHDWBMODE为SHADOW,LOADAMODE/LOADBMODE为CTR_ZERO,CMPA/CMPB赋值)
(3)动作限定AQ——“信号灯变化指令组”
每个路口还要精确规定“什么时候亮红灯、什么时候变绿灯”——这由动作限定小组决定:
- A路口(ePWMA):计数到0秒时(即新一轮红绿灯周期开始)就全体亮红灯(清低电平),等数到CMPA规定的那一秒时变绿灯(置高电平)。
- B路口(ePWMB):同理,计数到0时亮红灯(清低电平),到CMPB时变绿灯(置高电平)。
这样就形成了“红绿灯”的周期性亮灭模式,占空比就是“绿灯与总周期的比例”。
(AQCTLA/AQCTLB的ZRO、CAU、CBU等位设置CLEAR/SET)
(4)事件触发ET——“路口信号广播台”
每逢红绿灯周期归零或者达到某些条件时,交通局要通过广播台通知中央政府(CPU):“该处理新一轮信号了!”
- 触发条件:本次设为周期归零时(即每次红绿灯刚亮红时)。
- 使能事件:广播台“开麦”,允许信号传递。
- 事件频率:每次周期都报告一次。
(ETSEL.INTSEL=CTR_ZERO, ETSEL.INTEN=1, ETPS.INTPRD=ET_1ST)
整体流程
信号规则设定
调度中心(时基TB、比较CC、动作AQ、触发ET四大部门)设好红绿灯一轮的总周期、何时变灯、何时广播、是否联动等全部规则。总闸放行
打开总节奏同步闸,所有城门(IO口)开始按新交通规则亮灭红绿灯。主控动态调度占空比
交通总控台持续微调每个路口放行时长,于是信号灯逐渐变亮/变暗,实现了“呼吸灯”般的流动美感。信号广播反馈
每逢规则关键点(如周期归零),系统广播一次,主控台可据此设计更复杂的反馈与管理机制。
代码分析:
1.EPWM1_Init函数
void EPWM1_Init(Uint16 tbprd)
{EALLOW;SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Disable TBCLK within the ePWMSysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1; // ePWM1EDIS;// Interrupts that are used in this example are re-mapped to// ISR functions found within this file.EALLOW; // This is needed to write to EALLOW protected registersPieVectTable.EPWM1_INT = &epwm1_timer_isr;EDIS; // This is needed to disable write to EALLOW protected registersEALLOW;SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Stop all the TB clocksEDIS;// Setup SyncEPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // Pass through// Allow each timer to be sync'edEPwm1Regs.TBCTL.bit.PHSEN = TB_ENABLE;EPwm1Regs.TBPHS.half.TBPHS = 0;EPwm1Regs.TBPRD = tbprd;EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count upEPwm1Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;EPwm1Regs.TBCTL.bit.CLKDIV=TB_DIV1;EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero eventEPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INTEPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st eventEALLOW;SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Start all the timers syncedEDIS;// Enable CPU INT3 which is connected to EPWM1-6 INT:IER |= M_INT3;// Enable EPWM INTn in the PIE: Group 3 interrupt 1-6PieCtrlRegs.PIEIER3.bit.INTx1 = 1;// Enable global Interrupts and higher priority real-time debug events:EINT; // Enable Global interrupt INTMERTM; // Enable Global realtime interrupt DBGM
}
代码详解如下:
1. 基本时钟与模块使能
EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Disable TBCLK within the ePWM SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1; // ePWM1 EDIS;
分析:
EALLOW/EDIS
用于允许/禁止对受保护寄存器的写操作。SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1
:TBCLK同步使能,允许ePWM模块的时钟。你注释为“Disable TBCLK”,但实际上1
表示使能(即同步所有ePWM的时钟),通常初始化前后要做开关切换。SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1
:使能ePWM1模块时钟,为“总控室”供电。
2. 中断向量重映射
EALLOW; PieVectTable.EPWM1_INT = &epwm1_timer_isr; EDIS;
分析:
- 把ePWM1的中断向量表入口指向
epwm1_timer_isr
,即当“广播台”通知CPU时,实际执行你编写的ISR(中断服务函数)。
3. 停止所有ePWM定时器(准备配置)
EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Stop all the TB clocks EDIS;
分析:
- 初始化设置前,关闭所有ePWM时基时钟,防止在配置期间产生错误信号,相当于“暂停城市所有红绿灯节奏发生器”。
4. 同步与相位
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // Pass through EPwm1Regs.TBCTL.bit.PHSEN = TB_ENABLE; EPwm1Regs.TBPHS.half.TBPHS = 0;
分析:
SYNCOSEL
(同步信号选择)为TB_SYNC_IN
,即允许外部或主控输入同步。本城市交通信号灯同步由外部决定。PHSEN = TB_ENABLE
:使能相位同步,即允许“路口”根据同步信号统一步调。TBPHS = 0
:初始相位为0,即从0开始“计时”,所有灯都从头开始算。
5. 时基与计数方式设置
EPwm1Regs.TBPRD = tbprd; EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up EPwm1Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1; EPwm1Regs.TBCTL.bit.CLKDIV=TB_DIV1;
分析:
TBPRD = tbprd
:设定红绿灯节奏周期,比如一个红绿灯多少“秒”一轮。CTRMODE = TB_COUNT_UP
:向上计数,如红绿灯从0到最大,周期性递增。HSPCLKDIV/CLKDIV = 1
:无分频,最大节奏,即“主发电厂”时钟直通。
6. 事件触发设置(中断广播)
EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event
分析:
INTSEL = ET_CTR_ZERO
:当周期计数归零时触发中断,即每逢“红灯刚亮”就广播一次。INTEN = 1
:使能中断广播功能。INTPRD = ET_1ST
:每次归零都广播,而不是每几次广播一次。
7. 启动所有时基时钟
EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Start all the timers synced EDIS;
分析:
- 所有ePWM的时钟同步开关打开,所有红绿灯节奏器一起启动,全市交通信号灯从同一起点开始有序运行。
8. CPU和PIE中断使能
IER |= M_INT3; // 使能CPU的第3组中断 PieCtrlRegs.PIEIER3.bit.INTx1 = 1; // PIE控制器第3组第1路(EPWM1_INT)使能
分析:
M_INT3
:CPU中断组3,ePWM1~6中断专属信道。PIEIER3.bit.INTx1 = 1
:PIE中断分发器对应ePWM1中断使能。保证当ePWM1周期事件发生时,CPU能响应。
9. 全局中断和实时调试使能
EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM
分析:
EINT
:总中断开关,允许中断响应。ERTM
:实时调试中断开关,允许高级调试用中断。
10.调用方式
例如:EPWM1_Init(15000);
即设置
参数:tbprd = 15000
,设置时基周期寄存器(TBPRD
),表示红绿灯的一个完整周期为 15000 个系统时钟节拍,且无分频(HSPCLKDIV = 1, CLKDIV = 1
)。
周期时间 = TBPRD / 系统时钟频率 = 15000 / 150x10^6 = 0.1ms = 100us