liuxingyu 发表于 2026-1-20 19:50:24

按键中断控制PWM循环切换亮度


[*]#include "stc8.h"

// 定义按键引脚 (假设使用P3.2 / INT0)
sbit KEY = P3^2;

// PWM档位定义
#define GEAR_NUM    3          // 3个档位
// 占空比数组:假设PCA是8位PWM,0x00是0%暗,0xFF是100%亮
// 这里设置为 20% 50% 80%,可根据需要调整
code uint8_t pwm_duty = {51, 128, 204};

uint8_t current_gear = 0;       // 当前档位,全局变量

/**
* @brief PCA模块初始化 (用于生成PWM)
*/
void PCA_Init() {
    // 1. 配置PCA时钟源和分频
    // CMOD: 设置PCA时钟为系统时钟/12 (具体值查手册,不同型号寄存器名可能微调)
    // 这里决定PWM的频率
    CMOD = 0x04;    // 例如:0x04 代表系统时钟/4 (需根据实际晶振和需求计算)
    CL = 0x00;      // 清零计数器低字节
    CH = 0x00;      // 清零计数器高字节
   
    // 2. 配置CCON寄存器
    CCON = 0x00;    // 清除中断标志等
   
    // 3. 配置CCAPM0,使能PWM0模式
    // 0x42 代表 PWM模式 + 无中断
    CCAPM0 = 0x42;
   
    // 4. 初始占空比设置 (初始为0档,暗)
    CCAP0L = pwm_duty;
    CCAP0H = pwm_duty; // 必须先写L再写H,写H会触发装载
   
    // 5. 开启PCA运行
    CR = 1; // 启动PCA计数器
}

/**
* @brief 外部中断0初始化 (按键)
*/
void EX0_Init() {
    P3M1 = 0x00; P3M0 = 0x00; // P3口设为准双向
    KEY = 1; // 上拉
   
    IT0 = 1; // 设置为下降沿触发
    EX0 = 1; // 使能外部中断0
    EA = 1;// 开启总中断
}

/**
* @brief 延时函数 (用于按键消抖)
*/
void Delay_ms(uint16_t ms) {
    uint16_t i, j;
    for(i = ms; i > 0; i--)
      for(j = 115; j > 0; j--); // 假设11.0592MHz
}

/**
* @brief 主函数
*/
void main() {
    PCA_Init();
    EX0_Init();
   
    // 注意:PCA运行后,PWM波形自动输出,无需在主循环做任何事
   
    while(1) {
      // 主循环可以执行其他任务
      // 比如显示当前档位、处理传感器等
    }
}

/**
* @brief 外部中断0服务程序 (按键处理)
*/
void INT0_ISR() interrupt 0 {
    // 简单消抖
    Delay_ms(10);
    if(KEY == 0) {
      // 1. 档位循环切换
      current_gear = (current_gear + 1) % GEAR_NUM;
      
      // 2. 核心操作:修改PCA的占空比寄存器
      // 注意:修改CCAPnL会自动映射到PWM比较器
      CCAP0L = pwm_duty;
      CCAP0H = pwm_duty; // 写H确保数据立即生效
    }
   
    // 注意:如果是下降沿触发,不需要软件清除IE0标志
    // 硬件会自动清除
}

页: [1]
查看完整版本: 按键中断控制PWM循环切换亮度