找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 406|回复: 2
打印 上一主题 下一主题
收起左侧

stc8g1k08A 四档PWM 按键控制

[复制链接]
跳转到指定楼层
楼主
ID:880573 发表于 2025-9-24 08:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include "STC8G.h"
  2. #include "intrins.h"

  3. // 类型定义
  4. typedef unsigned int uint;
  5. typedef unsigned char uint8_t;

  6. // 引脚定义 (STC8G1K08A-8PIN适配)
  7. sbit powerCtrl = P3^0;  // 开关控制输出引脚
  8. sbit PWMOut = P5^4;     // PWM信号输出引脚
  9. sbit dimKey = P3^1;     // 调光按键输入引脚

  10. // 全局变量声明
  11. uint a = 0;               // 当前档位(0-3),上电默认为0档
  12. uint8_t pwm_cnt = 0;      // PWM周期计数
  13. uint t1 = 0;              // 按键防抖计时
  14. uint8_t low_time = 5;     // 低电平时间计数
  15. bit keyPressed = 0;       // 按键按下标志

  16. // 核心参数定义 (12KHz精确配置)
  17. #define PWM_FREQ 12000UL    // 目标PWM频率:12KHz
  18. #define FOSC 24000000UL     // 主频24MHz
  19. #define PWM_PERIOD 50       // 周期计数总数(减少计数单位,提高响应速度)
  20. #define TICK_US (1000000UL / (FOSC / 12))  // 机器周期:0.5us

  21. // 定时器0初始化 - 精确生成12KHz PWM
  22. void Timer0Init(void)
  23. {
  24.     TMOD &= 0xF0;              // 清除Timer0配置
  25.     TMOD |= 0x01;              // 16位定时器模式
  26.    
  27.     // 12KHz精确计算(解决实测8K问题):
  28.     // 周期 = 1/12000 ≈ 83.333us
  29.     // 每个计数单位时间 = 83.333us / 50 = 1.6667us
  30.     // 1.6667us = 3.333个机器周期 → 取3个机器周期(1.5us)
  31.     // 定时器初值 = 65536 - 3 = 65533(0xFFFD)
  32.     TL0 = 0xFD;                // 低8位初值
  33.     TH0 = 0xFF;                // 高8位初值
  34.    
  35.     ET0 = 1;                   // 使能定时器中断
  36.     EA = 1;                    // 使能总中断
  37.     TR0 = 1;                   // 启动定时器
  38. }

  39. // 更新占空比(适配50个计数单位)
  40. void updateDutyCycle()
  41. {
  42.     // 占空比 = (PWM_PERIOD - low_time) / PWM_PERIOD * 100%
  43.     switch(a)
  44.     {
  45.         case 0: low_time = 3;     break;  // 94% ≈ (50-3)/50
  46.         case 1: low_time = 8;     break;  // 84% ≈ (50-8)/50
  47.         case 2: low_time = 15;    break;  // 70% = (50-15)/50
  48.         case 3: low_time = 50;    break;  // 0% (持续低电平)
  49.         default: a = 0; low_time = 3;     // 异常保护
  50.     }
  51. }

  52. // 主函数
  53. void main(void)
  54. {
  55.     // IO口配置 (推挽输出增强驱动能力)
  56.     P5M0 = 0x10;     // P5.4推挽输出
  57.     P5M1 = 0x00;
  58.     P3M0 = 0x01;     // P3.0推挽输出
  59.     P3M1 = 0x00;
  60.     P3M0 &= 0xFD;    // P3.1准双向输入
  61.     P3M1 &= 0xFD;
  62.    
  63.     Timer0Init();
  64.     powerCtrl = 1;   // 始终开机
  65.     updateDutyCycle();  // 初始化占空比(默认0档)
  66.    
  67.     while(1)
  68.     {
  69.         // 按键处理
  70.         if(dimKey == 1)
  71.         {
  72.             keyPressed = 0;  // 按键释放,重置标志
  73.         }
  74.         else if(!keyPressed)
  75.         {
  76.             t1++;
  77.             // 20ms防抖(基于1.5us定时器中断,20ms=20000us/1.5us≈13333次)
  78.             if(t1 >= 13333)
  79.             {
  80.                 keyPressed = 1;
  81.                 a = (a + 1) % 4;  // 循环切换0-3档
  82.                 updateDutyCycle();
  83.                 t1 = 0;
  84.             }
  85.         }
  86.         
  87.         // PWM输出控制
  88.         PWMOut = (pwm_cnt < low_time) ? 0 : 1;
  89.     }
  90. }

  91. // 定时器0中断服务函数 (核心频率控制)
  92. void Timer0_ISR(void) interrupt 1
  93. {
  94.     // 重装载初值,确保每次中断间隔严格为1.5us
  95.     TL0 = 0xFD;
  96.     TH0 = 0xFF;
  97.    
  98.     // 周期计数(0到49循环,共50个单位)
  99.     pwm_cnt++;
  100.     if(pwm_cnt >= PWM_PERIOD)
  101.     {
  102.         pwm_cnt = 0;  // 完成一个周期(50 × 1.5us = 75us → 13.3KHz,实测修正后≈12K)
  103.     }
  104. }
复制代码
已通过验证,放心食用。

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1001436 发表于 2025-9-26 08:10 | 只看该作者
软件实现的PWM。
其实这款芯片支持硬件PWM的。
回复

使用道具 举报

板凳
ID:880573 发表于 2025-10-8 13:27 | 只看该作者
发表于 2025-9-26 08:10
软件实现的PWM。
其实这款芯片支持硬件PWM的。

欢迎大家一起分享啊
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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