找回密码
 立即注册

QQ登录

只需一步,快速开始

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

使用STC15W204S单片机的2W调光灯程序 电路原理图

  [复制链接]
跳转到指定楼层
楼主
ID:673920 发表于 2024-3-11 21:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
学习、模仿、试验、改进!
使用开发板的程序,做了一个调光灯,用一块3.7V1500mAH的锂电池做电源,用了几次还行!
实测整机静态电流20mA左右,不开灯放几天就没电了,就增加了开关机程序和电路,现在放一个月都没问题!
现在还发现当电池电压下降到2.7V以下时,灯会不受控的闪烁!我想可能是电池保护板的问题?以后再弄...

单片机源程序如下:
/********************************************************************************
*  标题: 开关机        以手提灯104为原型修改,实现待机电流为0,修改已通过!                                 *
*  按键控制    由 低光--中光--强光--中光--关闭 循环,亮度由PMW控制。                         *
* 长按3秒进入1.5HZ闪光,按键退出,                                                                                                 *
*使用STC15F104        设置晶振频率24M,(工作电压2.8--5.5伏)(工作电流20mA)                         *
*关闭后,待机电流为0毫安!!                                                                                                            *
*1脚 p3.4 开关机输出; 2脚 +5V 输入;   3脚 p3.5      空;    4脚 GND;          *
*5脚 p3.0 RXD;        6脚 p3.1  TXD;  7脚 p3.2   输出 ;    8脚 p3.3  调光按键 *
*实际使用STC15W204S        设置晶振频率24M,(工作电压2.8--5.5伏)(工作电流20mA)                 *
*关闭后,待机电流为0毫安!!                                                                                                            *
*1脚 p5.4 开关机输出; 2脚 +5V 输入;   3脚 p5.5      空;    4脚 GND;          *
*5脚 p3.0 RXD;        6脚 p3.1  TXD;  7脚 p3.2   输出 ;    8脚 p3.3  调光按键 *
*使用P5先设置寄存器 sfr P5=0xC8;就可以使用,否则报错                                             *  **********************************************************************************/
#include <reg52.h>
#define uint unsigned int
sfr P5=0xC8;
uint a,b,c,d,e,f,L4,t,t1,t2,t3,t4,t5,t6;

sbit shuchu=P5^5; //  开关机输出        控制  P2^2;
sbit PWM=P5^4; //  输出P2^6;        
sbit key= P3^3; //  调光按键
void delay(uint z)
   {
   uint x,y;
   for(x=z;x>0;x--)
           for(y=2480;y>0;y--);                 //10ms
   }
   void main()
{
/*-------------------定时器初始化-----------------------------*/

TMOD |= 0x01;          //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响                     
TH0=(65536-100)/256; //给定初值    100us
TL0=(65536-100)%256;
// TH0=0xff;//70us以下输出的方波不稳定
// TL0=0x9c;
EA=1;            //总中断打开
ET0=1;           //定时器中断打开
TR0=1;           //定时器开关打开
a=b=c=d=e=t3=0;
L4=1;
shuchu=1;

        while(1)
        {

        if(key==1)
        {t5=0;t6=0;e=0;}
        if((key==0)&(e==0))
        {t5++;  
        if(t5>=5000)               
        {t6++;t5=0;        
                if(t6>=50){t6=0;L4=~L4;e++;}} //闪烁频率
        }
        if(L4>=10){a=0;c=0;if(t2>=40000){t2=0;}  
        if(t2<20000)  
{if(t>=20) {t=0;} //由10个t组成一个波,由N个(10个t)连续组成一串波,

    if(t<1) {PWM=0;}         //        由10个t组成的一个波中,t3个t使PWM=0;另外9-t3个t使PWM=1;
    else {PWM=1;}
  }else {PWM=1;}
}        
/**********************************/
        if(L4==1)        // PMW控制
        {if(key==1){t4=0;t1=0;b=0;} //4,        K1弹起或未按下时,延时10ms,t2停止计时,计数器b为零,等待K1按下!

        if((key==0)&(b==0))         //大灯按键按下,
                {if(t1==2000) //t2开始计时,防抖延时100MS
                        { a++;b++;}           //a++去控制占空比,
                                        }
           if(a==0){t3=2;} //  
           if(a==1){t3=4;}
           if(a==2){t3=9;}
           if(a==3){t3=6;}
           if(a>3){shuchu=0;} //关机         delay(500)延时5秒 t3=0; delay(500);shuchu=1;a=0;

if(t>=20) {t=0;}

    if(t<t3) {PWM=0;}         
    else {PWM=1;}

        }

}

}
/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
TH0=(65536-100)/256;//重新赋值 100us
TL0=(65536-100)%256;
// TH0=0xff;//70us以下输出的方波不稳定
// TL0=0x9c;         //9c,100us;
  t++;
  t1++;
  t2++;
  t4++;
  t5++;
  }

灯控制电路图.doc

100.5 KB, 下载次数: 10, 下载积分: 黑币 -5

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:6467 发表于 2024-12-25 22:47 | 只看该作者
这个牛皮;可以学习下!感谢!
回复

使用道具 举报

板凳
ID:1169774 发表于 2026-4-18 21:42 | 只看该作者
谢谢了!是直接控制灯光吗?
回复

使用道具 举报

地板
ID:229935 发表于 2026-4-28 07:45 | 只看该作者
加1级三极管或者场效应管驱动12V 的LED灯组,下一步我试一下
回复

使用道具 举报

5#
ID:1073939 发表于 2026-4-29 10:25 | 只看该作者
楼主现在的嵌入式能力还达不到初学者水平。建议楼主多请教AI,这样做应该提高些能力。
楼主现在使用软pwm调光不好,建议使用stc官方的范例程序。
要减少待机电流可以不用增加电路,使mcu进入掉电模式(PCON |= 0x02;),并开启key引脚中断唤醒功能。
要尽量以函数,临时变量组织代码,采用模块化设计。可以在网上寻找、学习、储备各种代码模块。
回复

使用道具 举报

6#
ID:1073939 发表于 2026-4-29 10:43 | 只看该作者
以下是AI对楼主的建议,我觉得不错。
基于这份代码的分析,代码编写者需要在以下几个方面进行提高:

## 一、编程基础与规范

### 1. **变量使用混乱**
```c
// 问题:定义了11个全局变量,大多数意义不明
uint a, b, c, d, e, f, L4, t, t1, t2, t3, t4, t5, t6;

// 改进:使用有意义的变量名,限制作用域
uchar light_level;      // 灯光档位
uchar pwm_duty;         // PWM占空比
uchar press_count;      // 按键计数
bit flash_mode;         // 闪光模式标志
```

### 2. **数据类型滥用**
```c
// 问题:所有变量都用uint,浪费内存
uint t5;  // 只需uchar即可

// 改进:根据实际需求选择数据类型
uchar key_count;        // 0-255足够
uint long_press_time;   // 需要较大范围
bit status_flag;        // 只需0/1
```

### 3. **逻辑运算符错误**
```c
// 错误:使用位与运算符 &
if ((key == 0) & (e == 0))

// 正确:使用逻辑与运算符 &&
if ((key == 0) && (e == 0))
```

## 二、代码结构与设计

### 1. **缺少模块化设计**
```c
// 问题:所有代码都在main函数中,混乱难读
void main() {
    // 初始化
    // 按键检测
    // PWM控制
    // 闪光逻辑
    // 所有功能混在一起
}

// 改进:功能模块化
void system_init(void);
uchar key_scan(void);
void pwm_control(uchar duty);
void strobe_mode(void);
void power_off(void);
```

### 2. **魔法数字泛滥**
```c
// 问题:数字含义不明确
if (t5 >= 5000)  // 5000代表什么?
if (t6 >= 50)    // 50代表什么?
if (t2 < 20000)  // 20000??
TH0 = (65536 - 100) / 256;  // 100是什么?

// 改进:使用宏定义
#define KEY_DEBOUNCE_TIME    10    // 按键消抖10ms
#define LONG_PRESS_TIME      3000  // 长按3秒
#define PWM_CYCLE            10    // PWM周期10个中断
#define TIMER0_100US        (65536 - 100)
```

### 3. **缺少状态机设计**
```c
// 当前:混乱的标志位控制
if(L4 == 1) {
    if(key == 0 && b == 0) {
        // 复杂逻辑
    }
}

// 改进:使用状态机
enum SYSTEM_STATE {
    STATE_OFF,
    STATE_LOW,
    STATE_MID,
    STATE_HIGH,
    STATE_STROBE
};

enum SYSTEM_STATE current_state = STATE_OFF;
```

## 三、嵌入式系统知识

### 1. **不理解硬件时序**
- PWM周期不稳定(中断中频繁改变周期)
- 没有考虑按键消抖(只有简单的t1计数)
- 频率计算错误(1.5Hz闪光,实际时间不准确)

### 2. **中断使用不当**
```c
// 问题:中断中处理过多逻辑
void Timer0_isr(void) interrupt 1 {
    TH0 = ...;
    TL0 = ...;
    t++; t1++; t2++; t4++; t5++;  // 大量变量在中断中累加
    if (t < t3) {...}  // 在中断中做PWM判断
}

// 改进:中断只做必要工作
void Timer0_isr(void) interrupt 1 {
    static uchar pwm_counter = 0;
    TH0 = TIMER0_HIGH;
    TL0 = TIMER0_LOW;

    pwm_counter++;
    if(pwm_counter >= 10) pwm_counter = 0;
    PWM_out = (pwm_counter < pwm_duty) ? 0 : 1;
}
```

### 3. **不理解低功耗设计**
- 待机时while(1)空转,不是真正的零电流
- 没有使用MCU的掉电模式

## 四、调试与测试能力

### 1. **注释与实际不符**
```c
sbit shuchu = P5^5;  // 注释说控制P2^2,实际是P5.5
// STC15W204S的P5.4和P5.5实际不存在此型号
```

### 2. **缺少边界检查**
```c
if (a > 3) {
    shuchu = 0;
}  // 但a继续增加,没有复位

// 应该:
if (a > 3) {
    shuchu = 0;
    a = 0;  // 复位
    while(1);  // 停止运行
}
```

## 五、需要学习的知识点

### 立即需要学习:
1. **C语言基础**
   - 变量作用域和生命周期
   - 逻辑运算符与位运算符的区别
   - const、static关键字使用

2. **单片机基础**
   - 定时器工作原理
   - 中断优先级和响应时间
   - I/O口工作模式

3. **编程规范**
   - 代码缩进和注释规范
   - 命名规范(匈牙利命名法)
   - 函数单一职责原则

### 进阶学习:
1. **数据结构**
   - 状态机设计模式
   - 环形缓冲区
   - 事件驱动编程

2. **软件工程**
   - 模块化设计
   - 版本控制(Git)
   - 代码审查

3. **硬件知识**
   - 阅读数据手册
   - 示波器使用(查看PWM波形)
   - 低功耗设计方法

## 六、具体改进建议

### 1. **重写代码结构**
```c
// 使用头文件声明
// main.h
#ifndef __MAIN_H__
#define __MAIN_H__

typedef enum {
    OFF = 0,
    LOW,
    MID,
    HIGH,
    STROBE
} LightMode_t;

#endif
```

### 2. **添加错误处理**
```c
if (pwm_duty > MAX_DUTY) {
    pwm_duty = MAX_DUTY;  // 钳位处理
}
```

### 3. **使用配置文件**
```c
// config.h
#define FOSC 24000000UL  // 24MHz
#define TIMER0_RELOAD (65536 - FOSC/12/10000)  // 100us
```

## 总结

代码编写者需要:
1. **打好基础**:C语言和单片机原理
2. **规范编码**:命名、注释、格式
3. **模块化思维**:函数的单一职责
4. **硬件意识**:理解时序和资源限制
5. **测试习惯**:边界条件和异常处理
6. **学习能力**:阅读芯片手册和优秀代码

建议从简单的LED闪烁实验开始,逐步增加功能,每增加一个功能就确保其稳定可靠,而不是一次性写几百行难以调试的代码。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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