找回密码
 立即注册
查看: 267|回复: 3

STC8H2K32U 移相全桥驱动的例子

[复制链接]
已绑定手机

872

主题

1万

回帖

2万

积分

管理员

积分
25432
发表于 2026-9-18 08:52:56 | 显示全部楼层 |阅读模式

STC8H2K32U 移相全桥驱动的例子

截图202609180852494622.jpg
回复

使用道具 举报 送花

已绑定手机

872

主题

1万

回帖

2万

积分

管理员

积分
25432
 楼主| 发表于 2026-9-18 08:53:37 | 显示全部楼层

我已获取到足够的手册依据。需要先向您说明一个重要提示:

关于手册原文的适用范围:在"高级PWM-硬件移相"章节的"PWM硬件移相端口说明"原文中,明确指出"STC8H2K12U系列支持PWM硬件移相的端口为 P1.3(PWMAPS5)和 P1.5(PWMAPS6)"。手册中未单独列出 STC8H2K32U 的移相端口编号,但两者同属 2K 系列、封装管脚定义基本一致(P1.3、P1.5 均标注为 PWMAPS5/PWMAPS6),因此下面示例按 P1.3/P1.5 这两个移相端口来配置,请您在实测时以实际芯片验证为准。


STC8H2K32U 移相全桥驱动示例

一、方案依据(手册原文)

1. 芯片支持情况(来源:"16位高级PWM定时器,支持正交编码器"产品支持表)

  • STC8H2K32U:高级PWM ●、高级PWM新增硬件移相功能 ●、高速高级PWM ●
  • 特性表明确标注:"144MHz 16位高级PWM定时器 互补对称死区控制 硬件移相"

2. 移相原理(来源:"高级PWM-硬件移相" → "移相PWM输出模式" → "不对称PWM模式")

"在不对称模式下,生成的两个中心对齐PWM信号间允许存在可编程相移。频率由 PWMA_ARR 寄存器的值确定,而占空比和相移则由一对 PWMA_CCRx 寄存器确定……向 PWMA_CCMRx 寄存器的 OCxM 位写入'1110'(不对称PWM模式1)或'1111'(不对称PWM模式2)。"
"与死区发生器配合使用时,这可控制相移全桥直流到直流转换器。"

这就是移相全桥驱动的官方实现路径:不对称PWM模式(OCxM=1110)+ 死区发生器。

3. 输出脚(来源:"16位高级PWM定时器" → "高级PWM功能脚切换",PWMA_PS 寄存器)

  • C1PS[1:0]=00 → PWM1P=P1.0,PWM1N=P1.1
  • C2PS[1:0]=00 → PWM2P=P1.2,PWM2N=P1.3

4. I/O口模式(来源:"I/O口" → "配置I/O口")

  • 推挽输出:PnM1.x=0,PnM0.x=1

二、移相全桥信号结构

移相全桥需要 4 个开关管(Q1~Q4),两组互补桥臂:

  • 超前桥臂:Q1(PWM1P)、Q2(PWM1N)—— 固定 50% 占空比
  • 滞后桥臂:Q3(PWM2P)、Q4(PWM2N)—— 固定 50% 占空比,但相对超前桥臂移相

而 OC1REFC 由 PWMA_CCR1 与 PWMA_CCR2 共同决定,OC2REFC 由 PWMA_CCR3 与 PWMA_CCR4 共同决定。因此本示例用通道1/通道2这一对,通过 CCR1 与 CCR2 的差值设定相移量。

说明:手册给出的通道-CCR 对应关系为"OC1REFC 由 PWMA_CCR1 和 PWMA_CCR2 控制",其中递增计数用 CCR1、递减计数用 CCR2。二者设置相同的 50% 值时输出即为标准中心对齐;两者之和偏离满量程时即产生相移。为便于工程调试,示例中将相移量参数化,您可通过串口在线调整。


三、示例代码(Keil C51,单文件可编译)

/* ============================================================
 *  STC8H2K32U 移相全桥驱动示例
 * ------------------------------------------------------------
 *  功能说明:
 *    1. 使用 PWMA 的"不对称PWM模式1"输出一组相移PWM波
 *    2. 通道1(PWM1P=P1.0 / PWM1N=P1.1) 作为超前桥臂,50%固定占空比
 *    3. 通道2(PWM2P=P1.2 / PWM2N=P1.3) 作为滞后桥臂,相对超前臂移相
 *    4. 开启死区发生器,防止上下管直通
 *    5. 通过串口1可在线修改相移量(0~ARR),观察移相效果
 *
 *  硬件接线(以 LQFP32 为例):
 *    P1.0 -> 驱动芯片(超前桥臂上管)
 *    P1.1 -> 驱动芯片(超前桥臂下管)
 *    P1.2 -> 驱动芯片(滞后桥臂上管)
 *    P1.3 -> 驱动芯片(滞后桥臂下管)
 *    P3.0/P3.1 -> 串口1,连接PC,用于在线调相移量(115200,8,N,1)
 *
 *  操作说明:
 *    编译下载后,串口发送形如 "PS:100" 的指令即可设置相移量,
 *    单片机回传 "OK:100",相移量越大,滞后桥臂滞后越多。
 * ============================================================ */

#include "stc8h.h"
#include "stdio.h"
#include "string.h"

/* ---------------- PWM 参数定义 ---------------- */
#define PWM_PERIOD   2400    /* PWMA_ARR 值,决定PWM频率 */
                             /* f_PWM = F_MASTER / (2 * PWM_PERIOD)   */
                             /* 中心对齐模式下,一个完整周期 = 2*ARR 个计数 */

/* 相移量:0 ~ PWM_PERIOD,数值越大滞后桥臂相移越大 */
#define PHASE_DEFAULT 300

unsigned int g_Phase = PHASE_DEFAULT;   /* 当前相移量 */

/* ---------------- 串口接收缓冲 ---------------- */
#define RX_BUF_LEN   32
unsigned char xdata g_RxBuf[RX_BUF_LEN];
unsigned char g_RxCnt = 0;              /* 已接收字符数 */
bit g_RxFinish = 0;                     /* 一帧接收完成标志 */
unsigned char g_TxBuf[64];              /* 发送缓冲 */

/* ------------------------------------------------------------
 * 函数:PWM_Init
 * 说明:初始化PWMA,配置为不对称PWM模式1,输出4路互补信号
 * ------------------------------------------------------------ */
void PWM_Init(void)
{
    unsigned int cmp_lead;      /* 超前桥臂比较值 */
    unsigned int cmp_lag;       /* 滞后桥臂比较值 */

    P_SW2 |= 0x80;              /* 使能访问XFR扩展寄存器 */

    /* --- 1. 初始化PWM输出引脚为推挽输出 --- */
    P1M1 &= ~0x0F;              /* P1.0~P1.3 的M1位清0 */
    P1M0 |=  0x0F;              /* P1.0~P1.3 的M0位置1 -> 推挽输出 */

    /* --- 2. 配置PWM时钟源与输出脚切换 --- */
    PWMA_PS = 0x00;             /* C1PS=00 -> PWM1P=P1.0,PWM1N=P1.1 */
                                /* C2PS=00 -> PWM2P=P1.2,PWM2N=P1.3 */

    /* --- 3. 设置自动重装载值与预分频 --- */
    PWMA_PSCRH = 0x00;          /* 预分频高字节 */
    PWMA_PSCRL = 0x00;          /* 预分频=0,即不分频 */
    PWMA_ARRH  = (unsigned char)(PWM_PERIOD >> 8);
    PWMA_ARRL  = (unsigned char)(PWM_PERIOD & 0xFF);

    /* --- 4. 配置通道1为不对称PWM模式1 --- */
    /* OC1M[3:0] = 1110,其中OC1M[2:0]在CCMR1的B6~B4,
       最高位OC1M[3]在CCMR1X的B0 */
    PWMA_CCMR1 = (0x06 << 4);   /* OC1M[2:0]=110 */
    PWMA_CCMR1X = 0x01;         /* OC1M[3]=1 -> 合起来OC1M[3:0]=1110 */
    PWMA_CCMR1 |= 0x08;         /* OC1PE=1,允许CCR1预装载 */

    /* --- 5. 配置通道2为不对称PWM模式1 --- */
    PWMA_CCMR2 = (0x06 << 4);   /* OC2M[2:0]=110 */
    PWMA_CCMR2X = 0x01;         /* OC2M[3]=1 -> OC2M[3:0]=1110 */
    PWMA_CCMR2 |= 0x08;         /* OC2PE=1,允许CCR2预装载 */

    /* --- 6. 设置比较值,决定占空比与相移 --- */
    /* 不对称模式:UP计数到CCR1,DOWN计数到CCR2 */
    /* 50%占空比中心对齐:CCR1+CCR2 = 2*ARR 时对称 */
    cmp_lead = PWM_PERIOD;              /* 超前臂50% */
    cmp_lag  = PWM_PERIOD - g_Phase;    /* 滞后臂:相移 g_Phase */

    PWMA_CCR1H = (unsigned char)(cmp_lead >> 8);
    PWMA_CCR1L = (unsigned char)(cmp_lead & 0xFF);
    PWMA_CCR2H = (unsigned char)(cmp_lag >> 8);
    PWMA_CCR2L = (unsigned char)(cmp_lag & 0xFF);

    /* --- 7. 使能输出通道及互补输出 --- */
    PWMA_CCER1 = 0x55;          /* CC1E=1,CC1NE=1,CC2E=1,CC2NE=1 */
                                /* 极性和死区由死区发生器配合 */

    /* --- 8. 设置死区时间 --- */
    /* 死区时间 = DTGA[7:0] x T_Master,单位视死区分频而定 */
    PWMA_DTR = 0x10;            /* 适当死区,需按驱动芯片调整 */

    /* --- 9. 使能主输出 MOEA=1 --- */
    PWMA_BKR = 0x80;            /* MOEA=1使能PWM输出,OSSR/OSSI按需配置 */

    /* --- 10. 使能PWM计数器,中心对齐模式 --- */
    /* CMSA[1:0]=01 -> 中心对齐模式1,ARRPE=1自动重装载 */
    PWMA_CR1 = 0x81;            /* ARPEA=1, CMSA=01 -> 0b1000_0001 */
                                /* CENA=1启动计数 */

    P_SW2 &= ~0x80;             /* 关闭XFR访问(可选) */
}

/* ------------------------------------------------------------
 * 函数:Uart_Init
 * 说明:串口1初始化,115200,8,N,1
 * ------------------------------------------------------------ */
void Uart_Init(void)
{
    SCON = 0x50;                /* 8位数据,可变波特率 */

    /* 使用定时器2作为波特率发生器 */
    AUXR |= 0x01;               /* S1ST2=1,串口1用定时器2 */
    AUXR |= 0x04;               /* T2x12=1,定时器2 1T模式 */

    /* 系统时钟24MHz时,115200对应的重载值约为 (65536-13) */
    T2L = 0xF3;
    T2H = 0xFF;

    AUXR |= 0x10;               /* T2R=1,启动定时器2 */

    ES = 1;                     /* 使能串口1中断 */
    EA = 1;                     /* 打开总中断 */
}

/* ------------------------------------------------------------
 * 函数:Uart_SendString
 * 说明:发送一个字符串
 * ------------------------------------------------------------ */
void Uart_SendString(unsigned char *p)
{
    while (*p)
    {
        SBUF = *p++;
        while (!TI);
        TI = 0;
    }
}

/* ------------------------------------------------------------
 * 函数:Uart1_Isr
 * 说明:串口1接收中断,按'\n'或'\r'结束一帧
 * ------------------------------------------------------------ */
void Uart1_Isr(void) interrupt 4
{
    unsigned char c;

    if (RI)
    {
        RI = 0;
        c = SBUF;
        if (c == '\n' || c == '\r')
        {
            g_RxBuf[g_RxCnt] = '\0';
            g_RxFinish = 1;     /* 通知主循环处理 */
        }
        else
        {
            if (g_RxCnt < RX_BUF_LEN - 1)
            {
                g_RxBuf[g_RxCnt++] = c;
            }
        }
    }
}

/* ------------------------------------------------------------
 * 函数:main
 * ------------------------------------------------------------ */
void main(void)
{
    unsigned int new_phase;
    unsigned int cmp_lag;

    PWM_Init();
    Uart_Init();

    Uart_SendString("STC8H2K32U Phase-Shift Full-Bridge Demo\r\n");
    Uart_SendString("Send PS:xxx to set phase (0-2400)\r\n");

    while (1)
    {
        if (g_RxFinish)
        {
            g_RxFinish = 0;

            /* 解析 "PS:xxx" 格式指令 */
            if (strncmp((char *)g_RxBuf, "PS:", 3) == 0)
            {
                if (sscanf((char *)g_RxBuf, "PS:%u", &new_phase) == 1)
                {
                    if (new_phase > PWM_PERIOD)
                    {
                        new_phase = PWM_PERIOD;
                    }
                    g_Phase = new_phase;

                    /* 更新滞后桥臂比较值 */
                    cmp_lag = PWM_PERIOD - g_Phase;

                    P_SW2 |= 0x80;      /* 使能XFR访问 */

                    /* 通过CCR2更新相移,ARRPE与OC2PE保证在更新事件生效 */
                    PWMA_CCR2H = (unsigned char)(cmp_lag >> 8);
                    PWMA_CCR2L = (unsigned char)(cmp_lag & 0xFF);

                    /* 产生更新事件,使CCR2立即生效 */
                    PWMA_EGR = 0x01;    /* UGA=1,产生更新事件 */

                    P_SW2 &= ~0x80;

                    /* 回传结果 */
                    sprintf((char *)g_TxBuf, "OK:%u\r\n", g_Phase);
                    Uart_SendString(g_TxBuf);
                }
            }
            else
            {
                Uart_SendString("ERR\r\n");
            }

            g_RxCnt = 0;    /* 清接收计数,准备下一帧 */
        }
    }
}

四、关键配置说明与注意事项

项目 手册依据 说明
OC1M[3:0]=1110 "高级PWM-硬件移相"章节 不对称PWM模式1,最高位OC1M[3]在CCMR1X,低3位在CCMR1
OC1M 位域分两部分 章节注释:"出于兼容性原因,OCxM[3:0]位域分为两部分,最高有效位与最低有效的3位不相邻" 所以必须分别写 CCMR1 和 CCMR1X
MOEA=1 "刹车寄存器(PWMx_BKR)" MOEA(B7)=1 才允许输出
死区 "死区寄存器(PWMx_DTR)" DTGA[7:0]
推挽输出 "配置I/O口" PnM1.x=0, PnM0.x=1

⚠️ 需要您注意/确认的点:

  1. 系统时钟:示例按 24MHz 估算波特率重载值。若您使用 45MHz 或其他 IRC 频率,请相应修改 T2L/T2H。PWM 频率由 PWM_PERIOD 和主频共同决定,请按实际需求重新计算。
  2. 相移与占空比的耦合:在不对称PWM模式1中,CCR1、CCR2 共同决定占空比和相移。本示例将超前臂固定在 50%,仅调 CCR2 实现相移。实际移相全桥通常需要两臂都保持 50% 占空比、仅相位不同,若您追求严格的双50%相移,建议采用组合PWM模式(OCxM=1100/1101),手册原文说明该模式"生成的两个边沿或中心对齐PWM信号的各个脉冲间允许存在可编程延时和相移",更适合精确移相。是否需要我按组合PWM模式再给一版?
  3. 死区时间:PWMA_DTR=0x10 仅为示例值,必须根据您选用的栅极驱动芯片和 MOS 管开关时间实际计算。
  4. 移相端口 P1.3/P1.5:手册明确写的是 STC8H2K12U 的移相端口,本型号请以实测为准。

需要我进一步为您提供以下哪一项?

  • 按组合PWM模式重写一版(更贴合严格50%移相全桥)
  • 增加刹车/过流保护(PWMFLT 外部异常检测)配置
  • 帮您计算具体主频下的 PWM 频率、死区时间参数

请告诉我您的系统主频和目标 PWM 频率,我可给出精确的寄存器取值。


🔍 搜索 "STC8H2K32U 移相全桥驱动的例子"

📌 相关论坛讨论

  1. 求推荐一款合适的单片机,需要驱动一个移相全桥的转换器工作
  2. 关于8H12系列移相功能PWM芯片问题
  3. 请教各位大师 AI8H2K32U硬件PWM移相问题

⏱️ 查找用时 10.5s | 总回答用时 28.6s

回复

使用道具 举报 送花

已绑定手机

18

主题

80

回帖

1310

积分

金牌会员

积分
1310
发表于 2026-9-18 11:44:57 | 显示全部楼层
神*** 发表于 2026-9-18 08:53
我已获取到足够的手册依据。需要先向您说明一个重要提示:
关于手册原文的适用范围:在&quot;高级PWM-硬件移相&quot; ...

正需要这个做 电源。原来一直用TI的现成芯片 太贵
你先做了,再说话。
回复

使用道具 举报 送花

已绑定手机

11

主题

484

回帖

1362

积分

金牌会员

积分
1362
发表于 2026-9-18 16:07:12 | 显示全部楼层
学习了
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-11-8 03:09 , Processed in 0.073149 second(s), 58 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表