STC8 简单 PWM 输出使用指南

STC8 简单 PWM 输出使用指南

  • 更新时间:20250213

本指南以 STC8H1K16 为例,介绍 PWM(脉宽调制)功能的基本使用方法,适合新手快速上手 PWM 配置。


1. STC8 的 PWM 基本概念

STC8 系列单片机内部集成了 8 通道 16 位高级 PWM 定时器,分成两组周期不同的 PWM:

  • PWMA
  • PWMB

每组 PWM 都可以独立配置不同的周期和占空比。


2. PWM 基本代码示例

以下示例展示了如何配置 PWMA 进行 PWM 输出,PWM 频率基于 11.0592MHz 主频。

#include "stc8h.h"
#include "intrins.h"

void main()
{
    P_SW2 |= 0x80; // 使能访问 XFR

    // 设置所有 GPIO 口为准双向模式(避免引脚受限)
    P0M0 = P0M1 = 0x00;
    P1M0 = P1M1 = 0x00;
    P2M0 = P2M1 = 0x00;
    P3M0 = P3M1 = 0x00;
    P4M0 = P4M1 = 0x00;
    P5M0 = P5M1 = 0x00;

    PWMA_CCER1 = 0x00;  // 关闭通道,写 CCMRx 前必须清零 CCERx
    PWMA_CCMR1 = 0x60;  // 设置 CC1 为 PWMA 输出模式
    PWMA_CCER1 = 0x01;  // 使能 CC1 通道
    PWMA_CCR1 = 100;    // 设置占空比时间
    PWMA_ARR = 500;     // 设置 PWM 周期时间
    PWMA_ENO = 0x01;    // 使能 PWM1P 端口输出
    PWMA_BKR = 0x80;    // 使能主输出
    PWMA_CR1 = 0x01;    // 启动 PWM 计时

    while (1);
}

关键说明

  1. P_SW2 |= 0x80; —— 必须使能 XFR 访问,否则 PWM 配置无效,且程序不会报错。
  2. CCR/ARR = 有效电平的占空比
    • ARR(自动重装寄存器) 是两个 8 位寄存器合成的 16 位寄存器,设置时需避免溢出。

3. PWM 频率计算公式

PWM 计数器的频率计算如下:

[
f_{CK_CNT} = \frac{f_{CK_PSC}}{PSCR[15:0] + 1}
]

其中:

  • fCK_PSC:预分频时钟
  • PSCR[15:0]:预分频系数

可选时钟源

  • 内部时钟(fMASTER)
  • 外部时钟模式 1(TIx 作为输入)
  • 外部时钟模式 2(外部触发输入 ETR)
  • 内部触发输入(ITRx)(使用一个 PWM 的 TRGO 作为另一个 PWM 的预分频时钟)

一般情况下,使用 内部时钟,若不进行预分频,则 PWM 频率同步于内部时钟。
在这里插入图片描述


4. PWM 极性调整

PWMB_CCER2 寄存器可调整 PWM 输出极性

  • CCxP = 0:高电平有效
  • CCxP = 1:低电平有效

计算有效占空比

[
\text{有效电平占空比} = \frac{CCR}{ARR}
]

例如:

  • 计算结果为 20%
    • CCxP = 0,则 高电平占空比 = 20%
    • CCxP = 1,则 低电平占空比 = 20%

5. 实时更改 PWM 占空比

在 PWM 输出过程中,可以直接修改 CCR 寄存器的值来 实时调整 PWM 占空比,无需其他额外操作。


6. PWM 端口复用

PWMA_PS 寄存器用于 PWM 输出端口选择,请参考芯片手册对应的复用表。
在这里插入图片描述

7. 实战示例:按键控制 PWM 占空比和极性

  • 该示例通过按键控制 PWM 占空比,并可切换 PWM 极性
  • 运行在20MHz频率。

代码

#include "STC8H.h"

// PWM 相关配置
#define PWM_MIN_DUTY 20   // 最小占空比 20%
#define PWM_MAX_DUTY 100  // 最大占空比 100%
#define PWM_INIT_DUTY 100 // 初始占空比 100%
#define PWM_ARR 10000     // PWM 频率相关参数

int pwm_duty = PWM_INIT_DUTY; // 当前 PWM 占空比
bit pwm_inverted = 0;         // PWM 反相标志

// 延时函数
void Delay_ms(unsigned int ms)
{
    unsigned int i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 120; j++);
}

// 初始化 PWM
void PWM_Init()
{
    PWMB_CCER2 = 0x00;          // 关闭通道
    PWMB_CCMR3 = 0x68;          // 设置 PWM 输出模式
    PWMB_CCER2 = 0x01;          // 使能 CC7 通道
    PWMB_CCR7 = PWM_ARR;        // 设置占空比时间
    PWMB_ARR = PWM_ARR;         // 设置周期时间
    PWMB_ENO = 0x10;            // 使能 PWM 输出
    PWMB_PS = 0x20;             // PWM 通道7输出到 P0.2
    PWMB_BKR = 0x80;            // 使能主输出
    PWMB_CR1 = 0x01;            // 允许计数器
}

// 更新 PWM 占空比
void Update_PWM()
{
    unsigned long temp = (unsigned long)pwm_duty * PWM_ARR; // 防止计算时溢出
    PWMB_CCR7 = temp / 100;     // 更新 PWM 输出
    PWMB_CCER2 = pwm_inverted ? 0x03 : 0x01; // 设置 PWM 反相
}

// 主循环
void main()
{
    PWM_Init(); // 初始化 PWM

    while (1)
    {
        if (P10 == 0) // 占空比增加
        {
            while (P10 == 0);
            if (pwm_duty < PWM_MAX_DUTY)
            {
                pwm_duty += 10;
                if (pwm_duty > PWM_MAX_DUTY) pwm_duty = PWM_MAX_DUTY;
                Update_PWM();
            }
        }

        if (P11 == 0) // 占空比减少
        {
            while (P11 == 0);
            if (pwm_duty > PWM_MIN_DUTY)
            {
                pwm_duty -= 10;
                if (pwm_duty < PWM_MIN_DUTY) pwm_duty = PWM_MIN_DUTY;
                Update_PWM();
            }
        }

        if (P12 == 0) // 反相 PWM
        {
            while (P12 == 0);
            pwm_inverted = !pwm_inverted;
            Update_PWM();
        }

        Delay_ms(20); // 按键去抖
    }
}
if (P12 == 0) // 反相 PWM
    {
        while (P12 == 0);
        pwm_inverted = !pwm_inverted;
        Update_PWM();
    }

    Delay_ms(20); // 按键去抖
}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__Witheart__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值