当前位置: 首页 > news >正文

LKS32MC08x MCPWM 寄存器级控制:实现电机 P/N 安全互锁与速度控制

目录

寄存器使用实战

需求与硬件连接

官方驱动的局限性

子功能实现

PN互锁

写保护

MCPWM配置的实现方式

波形模式和比较寄存器

刹车函数及速度与方向函数

初始化

官方MCPWM驱动模块


寄存器使用实战

需求与硬件连接

有一直流电机连着一个电机驱动模块的P端和N端。

当电驱模块的P端输入PWM,N端为低电平时,电机正转且跟随PWM的占空比变换速度;当电模块的N端输入PWM,P端为低电平时,电机反转且跟随PWM的占空比变换速度。

现电驱模块的P端与 LKS32MC08x 的MCPWM的CH0P相连,电驱模块的N端与 LKS32MC08x 的MCPWM的CH0N相连。

需要写一个函数,实现对该电机的速度方向进行控制。函数输入输出和名字设计如下:

void SetMotorDirectionAndSpeed(uint8_t channel, int16_t speed);
// speed > 0: 正转,占空比 = speed
// speed < 0: 反转,占空比 = -speed
// speed == 0: 停止

官方驱动的局限性

LKS32 的 MCPWM 模块提供MCPWM_Init()函数来配置模块。然而它采用的是整体配置,一次性设置所有的寄存器,包括工作模式、周期、所有通道的比较值、死区时间、故障保护、中断使能等。即使我们只是想改CH0P/CH0N的输出方向,调用它也是如此。另外,如果软件没有P/N互锁的设计,P和N或许会短暂同时为正,烧毁电驱的MOSFET。

因此笔者自己写模块~

子功能实现

PN互锁

为了实现 P 和 N 端的绝对互锁,我们必须确保:当其中一方输出 PWM 信号时,另一方必须被强制设定为低电平(0)。
MCPWM 的 IO 控制寄存器 (MCPWM_IO01 / MCPWM_IO23) 中,控制互锁的关键宏定义是:
CHx_PS / CHx_NS:PWM 信号来源选择(1:强制模式;0:PWM 模式)。

CHxP_SCTRLP / CHxN_SCTRLN:在强制模式下(CHx_PS/CHx_NS=1)的输出值(1:高电平;0:低电平)。
要实现 “强制低电平”,需设置:CHx_PS (或 CHx_NS) = 1 CHxP_SCTRLP (或 CHxN_SCTRLN) = 0。

这一步将融合进一个叫MCPWM_SetChannelForceOutput()的函数,用于SetMotorDirectionAndSpeed()中调用,在后续“MCPWM配置的实现方式”一节中有它的实现。

    uint8_t CH0_PS;                  /* CH0_P信号来源,1:来自CH0_SCTRLP;0:来自MCPWM实际运行计数器*/uint8_t CH0_NS;                  /* CH0_N信号来源,1:来自CH0_SCTRLN;0:来自MCPWM实际运行计数器*/uint8_t CH0P_SCTRLP;             /* 当CH0_PS = 1时,输出到CH0_P通道的值*/uint8_t CH0N_SCTRLN;             /* 当CH0_NS = 1时,输出到CH0_N通道的值*/

写保护

所以,只需   MCPWM_PRT = 0xDEAD;  就能解除写保护;

写入其他值, 如    MCPWM_PRT = 0xCAFE; 就能重新加保护。

/* ---------------------- MCPWM 保护操作宏 --------------------------------- */
#define MCPWM_UNLOCK()   do { MCPWM_PRT = 0xDEAD; } while(0)
#define MCPWM_LOCK()     do { MCPWM_PRT = 0xCAFE; } while(0)

MCPWM配置的实现方式

采用宏+直接修改MCPWM_IO01控制寄存器位的方式来实现MCPWM配置。

MCPWM_SetChannelForceOutput用于设置某通道P/N的强制输出状态,MCPWM_IO01控制寄存器位定义如下图。

代码扩展了0~3共4个PWM通道。

这里的BITx定义在basic.h里,是LKS的一个pack。是一u32,第x位(低到高编号递增)为1,其它位为0。

// 内部辅助函数:设置某通道 P/N 的强制输出状态
static void MCPWM_SetChannelForceOutput(uint8_t channel, uint8_t p_pwm, uint8_t n_pwm)
{if (channel > 3) return; // 通道大于3,无效值if((p_pwm & 1u) && (n_pwm & 1u)) return; // 最低位为1为真即非0判断,不允许p_pwm和n_pwm同时输出MCPWM_UNLOCK();switch (channel){case 0:if (p_pwm) {MCPWM_IO01 |= BIT2; // CH0_NS = 1 → CH0_SCTRLNMCPWM_IO01 &= ~BIT4; // CH0_SCTRLN,当 CH0_NS = 1 时, CH0 N通道输出值MCPWM_IO01 &= ~BIT3; // CH0_PS = 0 → PWM}if (n_pwm){MCPWM_IO01 |= BIT3; // CH0_PS = 1 → CH0_SCTRLPMCPWM_IO01 &= ~BIT5; // CH0_SCTRLP,当 CH0_PS = 1 时, CH0 P通道输出值MCPWM_IO01 &= ~BIT2; // CH0_NS = 0 → PWM}break;case 1:if (p_pwm) {MCPWM_IO01 |= BIT10; // CH1_NS = 1 → CH1_SCTRLNMCPWM_IO01 &= ~BIT12; // CH1_SCTRLN,当 CH1_NS = 1 时, CH1 N通道输出值MCPWM_IO01 &= ~BIT11; // CH1_PS = 0 → PWM}if (n_pwm) {MCPWM_IO01 |= BIT11; // CH1_PS = 1 → CH1_SCTRLPMCPWM_IO01 &= ~BIT13; // CH1_SCTRLP,当 CH1_PS = 1 时, CH1 P通道输出值MCPWM_IO01 &= ~BIT10; // CH1_NS = 0 → PWM}break;case 2:if (p_pwm) {MCPWM_IO23 |= BIT2; // CH2_NS = 1 → CHI2_SCTRLNMCPWM_IO23 &= ~BIT4; // CH2_SCTRLN,当 CH2_NS = 1 时, CH2 N通道输出值MCPWM_IO23 &= ~BIT3; // CH2_PS = 0 → PWM}if (n_pwm){MCPWM_IO23 |= BIT3; // CH2_PS = 1 → CH2_SCTRLPMCPWM_IO23 &= ~BIT5; // CH2_SCTRLP,当 CH2_PS = 1 时, CH2 P通道输出值MCPWM_IO23 &= ~BIT2; // CH2_NS = 0 → PWM}break;case 3:if (p_pwm) {MCPWM_IO23 |= BIT10; // CH3_NS = 1 → CH3_SCTRLNMCPWM_IO23 &= ~BIT12; // CH3_SCTRLN,当 CH3_NS = 1 时, CH3 N通道输出值MCPWM_IO23 &= ~BIT11; // CH3_PS = 0 → PWM}if (n_pwm) {MCPWM_IO23 |= BIT11; // CH3_PS = 1 → CHI3_SCTRLPMCPWM_IO23 &= ~BIT13; // CH3_SCTRLP,当 CH3_PS = 1 时, CH3 P通道输出值MCPWM_IO23 &= ~BIT10; // CH3_NS = 0 → PWM}break;}MCPWM_LOCK();
}

波形模式和比较寄存器

使用边沿对齐模式。由于 MCPWM_THxx 是 16 位有符号数,我们使用 int16_t 作为比较值的数据类型。

// 设置 PWM 比较值(内部调用)
static void MCPWM_SetCompareValue(uint8_t channel, int16_t cmp_p, int16_t cmp_n)
{switch (channel){case 0:MCPWM_TH00 = cmp_p;MCPWM_TH01 = cmp_n;break;case 1:MCPWM_TH10 = cmp_p;MCPWM_TH11 = cmp_n;break;case 2:MCPWM_TH20 = cmp_p;MCPWM_TH21 = cmp_n;break;case 3:MCPWM_TH30 = cmp_p;MCPWM_TH31 = cmp_n;break;default:break;}
}

刹车函数及速度与方向函数

8路PWM,4个通道共用同一个MCPWM_TH计数器。把刹车的逻辑也提取成一个函数了。

// 内部辅助函数:强制通道输出安全停止状态 (P/N 都强制为低电平)
static void MCPWM_ForceStop(uint8_t channel)
{if (channel > 3) return;// 强制输出低电平:// 1. CHx_PS = 1, CHx_NS = 1 (选择强制输出模式)// 2. CHx_SCTRLP = 0, CHx_SCTRLN = 0 (强制输出的值为低电平)MCPWM_UNLOCK();switch (channel) {case 0:MCPWM_IO01 |= (BIT3 | BIT2);    // CH0_PS=1, CH0_NS=1 (选择强制模式)MCPWM_IO01 &= ~(BIT5 | BIT4);   // CH0_SCTRLP=0, CH0_SCTRLN=0 (强制输出低电平)break;case 1:MCPWM_IO01 |= (BIT11 | BIT10);  // CH1_PS=1, CH1_NS=1MCPWM_IO01 &= ~(BIT13 | BIT12); // CH1_SCTRLP=0, CH1_SCTRLN=0break;case 2:MCPWM_IO23 |= (BIT3 | BIT2);    // CH2_PS=1, CH2_NS=1MCPWM_IO23 &= ~(BIT5 | BIT4);   // CH2_SCTRLP=0, CH2_SCTRLN=0break;case 3:MCPWM_IO23 |= (BIT11 | BIT10);  // CH3_PS=1, CH3_NS=1MCPWM_IO23 &= ~(BIT13 | BIT12); // CH3_SCTRLP=0, CH3_SCTRLN=0break;}// 同时清零比较值,确保计数器不会意外触发MCPWM_SetCompareValue(channel, 0, 0); MCPWM_LOCK();
}/*** @brief 设置指定通道的电机方向和速度 (占空比)* @param channel MCPWM 通道 (0-3)* @param speed 速度值,范围 -1000 到 +1000 (代表 -100% 到 +100% 占空比)*/
void SetMotorDirectionAndSpeed(uint8_t channel, int16_t speed)
{if (channel > 3) return;// 假设 MCPWM_TH 已定义为全局周期值,或通过函数获取uint32_t period = MCPWM_TH; if (period == 0) return; // 1. 处理停止/刹车逻辑if (speed == 0) {MCPWM_ForceStop(channel);return;}// 2. 计算占空比比较值// abs_speed 的最大值是 1000uint16_t abs_speed = (speed >= 0) ? (uint16_t)speed : (uint16_t)(-speed);if (abs_speed > 1000) {abs_speed = 1000;}// 中间乘法使用 uint32_t 防止溢出int16_t cmp = (int16_t)(((uint32_t)abs_speed * period) / 1000); // 3. 设置方向和比较值if (speed > 0) {// 正转:P=PWM, N=强制低// 设置比较值 (P侧=cmp, N侧=0)MCPWM_SetCompareValue(channel, cmp, 0); // P侧切回 PWM 模式 (p_pwm=1), N侧强制低 (n_pwm=0)// 注意:这里的 1, 0 参数只用于切换 P/N 的控制源 (PWM vs Force Low)MCPWM_SetChannelForceOutput(channel, 1, 0); } else {// 反转:P=强制低, N=PWM// 设置比较值 (P侧=0, N侧=cmp)MCPWM_SetCompareValue(channel, 0, cmp); // P侧强制低 (p_pwm=0), N侧切回 PWM 模式 (n_pwm=1)MCPWM_SetChannelForceOutput(channel, 0, 1); }
}

初始化

MCPWM使用FCLK3作为外设时钟,FLK[3]的频率与系统时钟(MCLK)一致,是 96/8 MHz = 12MHz。

官方MCPWM驱动模块

void PWMOutputs(FuncState t_state);
void MCPWM_Init(MCPWM_InitTypeDef *MCPWM_InitStruct);
void MCPWM_StructInit(MCPWM_InitTypeDef *MCPWM_InitStruct);
u16 MCPWM_GetIRQFlag(uint32_t INT_flag);
void MCPWM_ClearIRQFlag(uint32_t INT_flag);

在lks32mc08x_MCPWM.c文件里,这些函数注释写得清楚,要实现某个功能,可以参考“ *@brief @b 功能描述: ”后的内容,就能知道该选择啥函数;参考 “@par 示例代码:”后的内容,就能知道该怎么使用它了。

附上配置LKS新工程教程链接:

http://bbs.sunsili.com/thread-275893-1-1.html

吐槽一下:15年的LKS32MC08x_DevDriver_v2.22 凌鸥外设库的bug有些多了,比如以下ADC触发点,tm uint16_t,来来你告诉我负数怎么用0~65535表示。

http://www.dtcms.com/a/607275.html

相关文章:

  • 软件开发网站策划方案wordpress图片上传接口
  • 今日内容总结
  • 除了PubMed,还有哪些稳定好用的查找医学文献的平台?
  • 网站登记模板网站免费建设
  • 网站建设在电子商务中的作用的看法外贸网站开发营销
  • bug【celery】
  • 常用个人网站襄县网站建设
  • MiniGPT-4:解锁 LLM 驱动的高级视觉语言能力
  • 网站设计常用软件都有哪些台州超值营销型网站建设地址
  • Rust入门:基础语法应用
  • 中国建设银行广西分行网站首页肥西县建设局网站
  • 遥感论文学习
  • 镇江市住房城乡建设局网站qq免费的推广引流软件
  • github下载repo中的单独文件
  • 营销网页wordpress数据库优化
  • 网站轮播图居中代码怎么写工作室建设规划
  • 青岛市建设安全监督站网站外贸网站建设原则
  • 大作设计网站官网登录微赞直播平台
  • 宿州网站建设公司哪家好html电子商务网站模板下载
  • 做搜狗手机网站排名软2345官网
  • 烟台网站排名seowordpress主题字体
  • 深圳提供网站建设制作wordpress收费会员
  • [科普] 卫星共视授时原理
  • 个人建设网站流程图温州市微网站制作电话
  • 做直播小视频在线观看网站龙岩个人小程序开发
  • Spring Boot 从 2.7.x 升级到 3.3注意事项
  • YOLO11-MSAM:印尼传统蜡染图案智能识别系统实现
  • 台州千寻网站建设公司好看网电影网站模板免费下载
  • 百度收录什么网站吗网页设计ppt模板
  • Mac怎么搭建网站开发环境jsp网站开发制作