找回密码
 立即注册
查看: 173|回复: 0

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

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:284
  • 最近打卡:2026-04-04 14:40:51
已绑定手机

4

主题

87

回帖

413

积分

中级会员

积分
413
发表于 2026-1-20 19:50:24 | 显示全部楼层 |阅读模式
    1. #include "stc8.h"
    2. // 定义按键引脚 (假设使用P3.2 / INT0)
    3. sbit KEY = P3^2;
    4. // PWM档位定义
    5. #define GEAR_NUM    3          // 3个档位
    6. // 占空比数组:假设PCA是8位PWM,0x00是0%暗,0xFF是100%亮
    7. // 这里设置为 20% 50% 80%,可根据需要调整
    8. code uint8_t pwm_duty[GEAR_NUM] = {51, 128, 204};
    9. uint8_t current_gear = 0;       // 当前档位,全局变量
    10. /**
    11. * @brief PCA模块初始化 (用于生成PWM)
    12. */
    13. void PCA_Init() {
    14.     // 1. 配置PCA时钟源和分频
    15.     // CMOD: 设置PCA时钟为系统时钟/12 (具体值查手册,不同型号寄存器名可能微调)
    16.     // 这里决定PWM的频率
    17.     CMOD = 0x04;    // 例如:0x04 代表系统时钟/4 (需根据实际晶振和需求计算)
    18.     CL = 0x00;      // 清零计数器低字节
    19.     CH = 0x00;      // 清零计数器高字节
    20.    
    21.     // 2. 配置CCON寄存器
    22.     CCON = 0x00;    // 清除中断标志等
    23.    
    24.     // 3. 配置CCAPM0,使能PWM0模式
    25.     // 0x42 代表 PWM模式 + 无中断
    26.     CCAPM0 = 0x42;  
    27.    
    28.     // 4. 初始占空比设置 (初始为0档,暗)
    29.     CCAP0L = pwm_duty[0];
    30.     CCAP0H = pwm_duty[0]; // 必须先写L再写H,写H会触发装载
    31.    
    32.     // 5. 开启PCA运行
    33.     CR = 1; // 启动PCA计数器
    34. }
    35. /**
    36. * @brief 外部中断0初始化 (按键)
    37. */
    38. void EX0_Init() {
    39.     P3M1 = 0x00; P3M0 = 0x00; // P3口设为准双向
    40.     KEY = 1; // 上拉
    41.    
    42.     IT0 = 1; // 设置为下降沿触发
    43.     EX0 = 1; // 使能外部中断0
    44.     EA = 1;  // 开启总中断
    45. }
    46. /**
    47. * @brief 延时函数 (用于按键消抖)
    48. */
    49. void Delay_ms(uint16_t ms) {
    50.     uint16_t i, j;
    51.     for(i = ms; i > 0; i--)
    52.         for(j = 115; j > 0; j--); // 假设11.0592MHz
    53. }
    54. /**
    55. * @brief 主函数
    56. */
    57. void main() {
    58.     PCA_Init();
    59.     EX0_Init();
    60.    
    61.     // 注意:PCA运行后,PWM波形自动输出,无需在主循环做任何事
    62.    
    63.     while(1) {
    64.         // 主循环可以执行其他任务
    65.         // 比如显示当前档位、处理传感器等
    66.     }
    67. }
    68. /**
    69. * @brief 外部中断0服务程序 (按键处理)
    70. */
    71. void INT0_ISR() interrupt 0 {
    72.     // 简单消抖
    73.     Delay_ms(10);
    74.     if(KEY == 0) {
    75.         // 1. 档位循环切换
    76.         current_gear = (current_gear + 1) % GEAR_NUM;
    77.         
    78.         // 2. 核心操作:修改PCA的占空比寄存器
    79.         // 注意:修改CCAPnL会自动映射到PWM比较器
    80.         CCAP0L = pwm_duty[current_gear];
    81.         CCAP0H = pwm_duty[current_gear]; // 写H确保数据立即生效
    82.     }
    83.    
    84.     // 注意:如果是下降沿触发,不需要软件清除IE0标志
    85.     // 硬件会自动清除
    86. }
    复制代码


回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-4-4 16:04 , Processed in 0.101653 second(s), 43 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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