|
PWM输出: 将TMS320F28027的 EPWM1A (GPIO0) 和 EPWM1B (GPIO1) 引脚连接到L298的两个逻辑输入端 IN1 和 IN2。通过配置ePWM1模块,可以产生一对带死区的互补PWM波,同时控制电机的方向和速度。 电机连接: 将L298的 OUT1 和 OUT2 输出端连接到直流电机的两端。 按键输入: 将4个按键的一端分别连接到TMS320F28027的任意4个GPIO引脚(例如 GPIO12, GPIO13, GPIO14, GPIO15),另一端接地。在代码中将这些GPIO配置为带上拉电阻的输入模式。 LED指示: 将2个LED的正极通过限流电阻连接到TMS320F28027的任意2个GPIO引脚(例如 GPIO16, GPIO17),负极接地。 LCD显示: 将LCD的 RS, E, D4, D5, D6, D7 引脚连接到TMS320F28027的6个GPIO引脚(例如 GPIO18 到 GPIO23),用于4位数据模式通信。RW 引脚接地(只写模式)。 电源: 为TMS320F28027和L298的逻辑部分提供3.3V电源,为L298的电机驱动部分和电机提供合适的直流电压(如12V)。 程序使用C语言在Code Composer Studio (CCS)中编写,基于TI的C2000Ware库。 代码如下: #include "DSP28x_Project.h" // 设备头文件#include "F2802x_EPwm.h" // ePWM寄存器定义#include "F2802x_Gpio.h" // GPIO寄存器定义// 自定义头文件 (可选,用于模块化)// #include "key_scan.h"// #include "lcd_display.h"// 全局变量Uint16 duty_cycle = 0; // 占空比 (0-1000)Uint16 motor_direction = 0; // 0: 停止, 1: 正转, 2: 反转char speed_str[16]; // 用于LCD显示的字符串// 函数声明void InitSystem(void);void InitEPwm1(void);void InitGpioForUser(void);void Key_Scan(void);void Update_Motor_Control(void);void Display_Speed(void);void DelayUs(Uint32 count);void main(void){ InitSystem(); // 1. 系统初始化 InitEPwm1(); // 2. ePWM模块初始化 InitGpioForUser(); // 3. 用户GPIO初始化 (按键, LED, LCD) EINT; // 使能全局中断 ERTM; // 使能实时中断 // 初始状态 duty_cycle = 0; motor_direction = 0; Update_Motor_Control(); sprintf(speed_str, "Speed: %3d%%", 0); // Lcd_Init(); // 假设的LCD初始化函数 // Lcd_ShowString(0, 0, speed_str); // 假设的LCD显示函数 while(1) { Key_Scan(); // 4. 扫描按键 Update_Motor_Control(); // 5. 根据按键结果更新PWM Display_Speed(); // 6. 更新LCD显示 DELAY_US(10000); // 延时,降低CPU占用,实现简单的按键消抖 }}// 系统初始化void InitSystem(void){ InitSysCtrl(); // 初始化系统时钟、看门狗等 DINT; // 禁用全局中断 InitPieCtrl(); // 初始化PIE控制寄存器 IER = 0x0000; // 禁用所有CPU中断 IFR = 0x0000; // 清除所有CPU中断标志 InitPieVectTable(); // 初始化PIE向量表}// ePWM1模块初始化void InitEPwm1(void){ EALLOW; GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0; // 使能GPIO0 (EPWM1A) 上拉 GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0; // 使能GPIO1 (EPWM1B) 上拉 GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // 配置GPIO0为EPWM1A GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // 配置GPIO1为EPWM1B EDIS; // 时基 submodule EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // 向上计数模式 EPwm1Regs.TBPRD = 1000; // 周期 = 1000, PWM频率 = SYSCLKOUT / (2 * TBPRD) EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // 比较 submodule EPwm1Regs.CMPA.half.CMPA = 0; // 初始占空比为0 // 动作限定 submodule (关键:实现正反转控制) // 当计数器等于0时,将EPWM1A和EPWM1B都置为高电平 EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET; // 当计数器等于CMPA时,根据方向控制电平翻转 // 正转: EPWM1A在CMPA处变低,EPWM1B保持高 -> 电流从A流向B EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // 反转: EPWM1B在CMPA处变低,EPWM1A保持高 -> 电流从B流向A EPwm1Regs.AQCTLB.bit.CAU = AQ_CLEAR; // 死区 submodule (防止H桥直通) EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL; EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; EPwm1Regs.DBRED = 10; // 上升沿延时 EPwm1Regs.DBFED = 10; // 下降沿延时}// 用户GPIO初始化 (按键, LED, LCD)void InitGpioForUser(void){ EALLOW; // 按键输入 (以GPIO12-15为例) GpioCtrlRegs.GPAPUD.bit.GPIO12 = 0; // 上拉 GpioCtrlRegs.GPADIR.bit.GPIO12 = 0; // 输入 // ... 对GPIO13, 14, 15做同样配置 // LED输出 (以GPIO16-17为例) GpioCtrlRegs.GPAPUD.bit.GPIO16 = 0; GpioCtrlRegs.GPADIR.bit.GPIO16 = 1; // 输出 GpioDataRegs.GPACLEAR.bit.GPIO16 = 1; // 初始熄灭 // ... 对GPIO17做同样配置 // LCD输出 (以GPIO18-23为例) // ... 配置为输出 EDIS; // Lcd_Init(); // 调用LCD初始化函数}// 按键扫描与处理 (满足要求2, 3)void Key_Scan(void){ // 正转按键 (GPIO12) if (GpioDataRegs.GPADAT.bit.GPIO12 == 0) { DELAY_US(20000); // 消抖延时 if (GpioDataRegs.GPADAT.bit.GPIO12 == 0) { motor_direction = 1; GpioDataRegs.GPASET.bit.GPIO16 = 1; // 点亮正转LED GpioDataRegs.GPACLEAR.bit.GPIO17 = 1; // 熄灭反转LED while(GpioDataRegs.GPADAT.bit.GPIO12 == 0); // 等待按键释放 } } // 反转按键 (GPIO13) else if (GpioDataRegs.GPADAT.bit.GPIO13 == 0) { DELAY_US(20000); if (GpioDataRegs.GPADAT.bit.GPIO13 == 0) { motor_direction = 2; GpioDataRegs.GPACLEAR.bit.GPIO16 = 1; GpioDataRegs.GPASET.bit.GPIO17 = 1; while(GpioDataRegs.GPADAT.bit.GPIO13 == 0); } } // 加速按键 (GPIO14) if (GpioDataRegs.GPADAT.bit.GPIO14 == 0) { DELAY_US(20000); if (GpioDataRegs.GPADAT.bit.GPIO14 == 0) { if (duty_cycle < 1000) duty_cycle += 50; // 增加占空比 while(GpioDataRegs.GPADAT.bit.GPIO14 == 0); } } // 减速按键 (GPIO15) if (GpioDataRegs.GPADAT.bit.GPIO15 == 0) { DELAY_US(20000); if (GpioDataRegs.GPADAT.bit.GPIO15 == 0) { if (duty_cycle > 0) duty_cycle -= 50; // 减小占空比 while(GpioDataRegs.GPADAT.bit.GPIO15 == 0); } }}// 更新电机控制 (满足要求1, 2, 3, 4)void Update_Motor_Control(void){ if (motor_direction == 0) // 停止 { EPwm1Regs.AQCTLA.bit.CAU = AQ_NO_ACTION; EPwm1Regs.AQCTLB.bit.CAU = AQ_NO_ACTION; EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR; EPwm1Regs.AQCTLB.bit.ZRO = AQ_CLEAR; EPwm1Regs.CMPA.half.CMPA = 0; } else if (motor_direction == 1) // 正转 { EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET; EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; EPwm1Regs.AQCTLB.bit.CAU = AQ_NO_ACTION; EPwm1Regs.CMPA.half.CMPA = duty_cycle; } else if (motor_direction == 2) // 反转 { EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET; EPwm1Regs.AQCTLA.bit.CAU = AQ_NO_ACTION; EPwm1Regs.AQCTLB.bit.CAU = AQ_CLEAR; EPwm1Regs.CMPA.half.CMPA = duty_cycle; }}// 显示转速 (满足要求4)void Display_Speed(void){ Uint16 speed_percent = (duty_cycle * 100) / 1000; sprintf(speed_str, "Speed: %3d%%", speed_percent); // Lcd_ShowString(0, 0, speed_str); // 在LCD第一行显示} |