估计下学期晚上宿舍要断电,所以我做了个很实用的东西——USB供电的PWM调光台灯。
主要功能就是通过按键实现调光,电路板上只有一个按键,按住不放就是调光,调到最亮或最暗后就调不动了,每按一次可以实现调高亮度和调低亮度的翻转,单击可以实现开、关灯(这个功能不实用,后来去掉了)。程序的代码就是基于上次发的定时器PWM做的,如果PWM频率过低,闪烁会比较明显,眼睛很累的,一般认为,pwm调光在400hz以上,人肉眼不可察觉,所以PWM的频率一定要尽可能高,而我的pwm在12MHz主频下可以达到600Hz,不过我在下载时将单片机的主频提高到24MHz,频闪更小,主频太高单片机工作不稳定。废话不多说,直接看图。
首先,翻箱倒柜找来个铝板,然后用电钻打孔,上螺丝,把边角都打磨一下,具体施工过程就不放图了。
温馨提示,打孔的钻头如果不是很锋利打孔速度慢先不说,最重要的——摩擦生热,然后铝板会很烫!!!(不要问我是怎么知道的)
弄一块大小合适的万用板,在合适的位置打孔。
电路焊接完成后的正面图,右下角的那个按键就是用来调光的,用的芯片是stc15f104e。
这是电路板的背面,最上面那四个是7135。
4颗1W的白色LED,焊接好把线穿过去。
这四颗LED共地,正极分别和7135连接。
焊接好就是这个样子
把电路板固定好就算完成了,电路板下面就是铝板,一定要做好绝缘。
用螺丝把LED固定好,记得涂上硅脂,LED最害怕的就是高温。
实际效果展示。
这是亮度最低的时候。
稍微亮一点
亮度一半
最亮
拍照时每张照片的曝光度、快门时间略有不同,与实际亮度有一定偏差。原本想拍视频展示一下,发现效果更差,大家就凑合看照片吧。
在此说明一点,不要以为我放了4张照片就认为我的台灯只有四档,我的台灯亮度是连续可调的!!!!!
最后送上源代码和部分说明,看热闹可以按Ctrl+W或Alt+F4或单击右上角的×
为了提高PWM频率,下载时可以适当提高单片机的频率。
你可以
在未经本人允许的情况下使用这些代码
在这些代码的基础上创作属于你自己的作品
把这些代码改得更高效、简洁
and so on……
但是,你不可以
声明这些代码是你自己写的
在未经本人许可的情况下在其他网站发布这些代码
这个代码可是实现多路pwm输出,需要几路自己添加。
#include <stc15f104e.h>
sbit pwm_out1 = P3^3;//在此添加多路输出
sbit key1 = P3^4;
unsigned char pwm_value1;//在此添加多路输出
unsigned char pwm_count1;//在此添加多路输出
unsigned char a = 0x01;
void timer0_init(void);
void timer1_init(void);
void timer0_inter(void);
void timer1_inter(void);
void timer(unsigned int t);
//void power_on(void);//外部中断,从掉电模式中恢复
int main()
{
P3M0 = 0x08;//pwm输出口设置为强推挽输出可避免亮度最高时的闪烁。
key1 = 1;
pwm_value1 = 30;
timer0_init();
timer1_init();
while(1)
{
if(key1 == 0)
{
timer(300);
/*这部分代码可以实现单击关灯的功能
if(key1)//单击按键令单片机进入掉电模式
{
ET0 = 0;//关闭定时器0的中断
ET1 = 0;//关闭定时器1的中断
IT0 = 1;//设置为下降沿唤醒
EX0 = 1;//允许外部中断0
PCON = 0x02;//进入掉电模式
}
timer(100);
*/
while(key1 == 0)
{
timer(100);
pwm_value1 += a;
if(pwm_value1 == 0 || pwm_value1 == 160)//pwm的上限是255,在这里将其设为160,是综合功率、发热、和亮度考虑的结果。
{
while(key1 == 0);
timer(200);//考虑按键抖动
}
}
a = a ^ 0xFE;//a的值为1(0000 0001),与0xFE(1111 1110)异或运算可变为-1(1111 1111),以此实现正负的翻转
}
}
return 0;
}
void timer0_init(void)//1536微秒,12.000MHz,16位自动重载
{
AUXR |= 0x80;//定时器时钟1T模式
TMOD &= 0xF0;//设置定时器模式
TL0 = 0x00;//设置定时初值
TH0 = 0xb8;//设置定时初值
TF0 = 0;//清除TF0标志
TR0 = 1;//启动定时器0
ET0 = 1;//开启定时器0的中断
EA = 1;//开启总中断
}
void timer1_init(void)//6微秒,12.000MHz,16位自动重载
{
AUXR |= 0x40;//定时器时钟1T模式
TMOD &= 0x0F;//设置定时器模式
TL1 = 0xb8;//设置定时初值
TH1 = 0xFF;//设置定时初值
TF1 = 0;//清除TF1标志
TR1 = 1;//启动定时器1
ET1 = 1;//开启定时器1的中断
EA = 1;//开启总中断
}
void timer0_inter(void) interrupt 1//定时器0中断服务函数
{
//TH0 = 0x00;
//TL0 = 0xF4;//若所使用的单片机不支持16位自动重装模式,请在此手动装入初值
pwm_out1 = 1;
pwm_count1 = 0;
}
void timer1_inter(void) interrupt 3//定时器1中断服务函数
{
if(pwm_count1 < pwm_value1)
pwm_count1++;
else
pwm_out1 = 0;
//仿照上面的形式在此添加多路输出的判断
}
void timer(unsigned int t)
{
unsigned int i;
unsigned char j;
for(i=0; i<t; i++)
for(j=0; j<200; j++);
}
/*这部分代码可实现单击开灯的功能
void power_on() interrupt 0//外部中断0唤醒单片机
{
PCON = 0x00;//电源寄存器,详细说明见数据手册
ET0 = 1;//开启定时器0的中断
ET1 = 1;//开启定时器1的中断
}
*/