春节4天做的电子钟(用AMCNC-01雕刻机做的外壳)
春节4天做的电子钟:具有时钟、温度、定时报警功能。
电路比较简单,程序是在中断里做的扫描,处理了显示、按键、读时间、温度,可以给初学者参考。
外壳用AMCNC-01雕刻机制造。
http://cache.amobbs.com/bbs_upload782111/files_36/ourdev_615509T2MAB9.jpg
(原文件名:IMG_8210.jpg)
http://cache.amobbs.com/bbs_upload782111/files_36/ourdev_615510AK1Q2I.jpg
(原文件名:IMG_8211.jpg)
http://cache.amobbs.com/bbs_upload782111/files_36/ourdev_615511AHKUQW.jpg
(原文件名:IMG_8213.jpg)
http://cache.amobbs.com/bbs_upload782111/files_36/ourdev_615512WZ2FR1.jpg
(原文件名:IMG_8216.jpg)
http://cache.amobbs.com/bbs_upload782111/files_36/ourdev_615513RWK50K.jpg
(原文件名:pcb.jpg)
原理图很简单, 没有画. 就是 P0口接段选, P2口接位选. P3.6接DS18B20P3.7接蜂鸣器P1.0 P1.1 P1.2 接到 DS1302时钟控制线
PCB是CAD画的. /*******************************************************************
* *
* 数码管时钟 *
* *
* 工作芯片:AT89S52 晶振频率:11.0592MHz *
* 其他芯片:时钟:DS1302 温度:DS18B20 *
* 显示:8位数码管 4位8段带: 和 4位普通8段 *
* 功能:4位显示 小时:分钟 4位置显示温度/定时 *
* *
* *
* 作者:阿晖QQ13819989 最后更新:2011.02.04 *
* *
*******************************************************************/
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define bit70x80
#define bit60x40
#define bit50x20
#define bit40x10
#define bit30x08
#define bit20x04
#define bit10x02
#define bit00x01
//开发板
/*
sbit DQ = P3^3; //定义DS18B20端口DQ
sbit BEEP = P3^7; //蜂鸣器
sbit reset = P1^2;
sbit sclk= P1^0;
sbit io = P1^1;
sbitK1 = P1^4; //温度
sbitK2 = P1^5; //定时
*/
//实际电路
sbit DQ = P3^6; //定义DS18B20端口DQ
sbit BEEP = P3^7; //蜂鸣器
sbit sclk= P1^2; //DS1302时钟控制线
sbit io = P1^1; //DS1302时钟控制线
sbit reset = P1^0; //DS1302时钟控制线
sbitK1 = P1^3; //温度
sbitK2 = P1^4; //定时
unsigned char presence ;
unsigned char datatemp_data = {0x00,0x00};
//unsigned char datadisplay = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char codeditab = {0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,
0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
bitbDS18B20OK=0; //温度正常开关标记 0正常 1出错
unsigned char h = 0; //整数
unsigned char l = 0; //小数
bit flag = 1;
uint timecount = 0;
uint count = 0;
uchar data init [] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00};//
//秒, 分, 时, 日, 月,星期,年
uchar display_pos = 0;
//uchar code display[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
uchar code pos_data[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
//开发板 - 共阳
//uchar code led_display[]=
//{
//0xc0,/*0*/
//0xf9,/*1*/
//0xa4,/*2*/
//0xb0,/*3*/
//0x99,/*4*/
//0x92,/*5*/
//0x82,/*6*/
//0xf8,/*7*/
//0x80,/*8*/
//0x90 /*9*/
//};
//实际电路 - 共阴
uchar code led_display[]=
{
0x3F,/*0*/
0x06,/*1*/
0x5B,/*2*/
0x4F,/*3*/
0x66,/*4*/
0x6D,/*5*/
0x7D,/*6*/
0x07,/*7*/
0x7F,/*8*/
0x6F/*9*/
};
//uchar shift;
//按键处理
#define MAX_KEY_TIMES 80 //每次1ms 10次为10ms
uchar key_times = 0;
uchar old_key = 0; //0无按键 1上次按K1 2上次按K2
bit play_temperature = 1; //显示温度开关
uint alarmMinute = 0; //定时分钟
uint left_alarmMinute = 0;//定时剩余分钟
uint now_minute, old_minute;
bit alarm_beep = 0; //定时到:响铃开关
/**********************************************************/
void delay(unsigned int num)//延时函数
{
while( --num );
}
/********************************************************
延时子函数
/********************************************************/
void delayms(unsigned char ms)
{
unsigned char i;
while(ms--)
{
for(i = 0; i < 125; i++); //old 120
}
}
void play_hour()
{
BEEP = 0;
delayms(255);
BEEP = 1;
delayms(255);
delayms(255);
BEEP = 0;
delayms(255);
BEEP = 1;
delayms(255);
delayms(255);
BEEP = 0;
delayms(255);
BEEP = 1;
delayms(255);
delayms(255);
BEEP = 0;
delayms(255);
BEEP = 1;
delayms(255);
delayms(255);
BEEP = 0;
delayms(255);
delayms(255);
delayms(255);
delayms(255);
BEEP = 1;
}
/**********************************************************/
Init_DS18B20(void)//初始化ds1820
{
DQ = 1; //DQ复位
delay(8); //稍做延时
DQ = 0; //单片机将DQ拉低
delay(90); //精确延时 大于 480us
DQ = 1; //拉高总线
delay(8);
presence = DQ; //如果=0则初始化成功 =1则初始化失败
delay(100);
DQ = 1;
return(presence); //返回信号,0=presence,1= no presence
}
/**********************************************************/
ReadOneChar(void)//读一个字节
{
unsigned char i = 0;
unsigned char dat = 0;
for (i = 8; i > 0; i--)
{
DQ = 0; // 给脉冲信号
dat >>= 1;
DQ = 1; // 给脉冲信号
if(DQ)
dat |= 0x80;
delay(4);
}
return (dat);
}
/**********************************************************/
WriteOneChar(unsigned char dat)//写一个字节
{
unsigned char i = 0;
for (i = 8; i > 0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay(5);
DQ = 1;
dat>>=1;
}
}
/*********************************************************/
Read_Temperature(void)//读取温度
{
Init_DS18B20();
if(presence==1)
{ bDS18B20OK = 1;} //DS18B20不正常,蜂鸣器报警
else
{
bDS18B20OK=0;
WriteOneChar(0xCC);// 跳过读序号列号的操作
WriteOneChar(0x44);// 启动温度转换
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0xBE);//读取温度寄存器
temp_data = ReadOneChar(); //温度低8位
temp_data = ReadOneChar(); //温度高8位
}
}
/*********************************************************/
Disp_Temperature()//显示温度
{
/*
l = ditab&0x0f]; //查表得小数位的值
display = l + 0x30;
display = '.';
h = ((temp_data&0xf0)>>4)|((temp_data&0x0f)<<4);
display = (h / 100) + 0x30;
if (display == '0')
display = ' ';
display = ((h%100) / 10) + 0x30;
display = (h % 10) + 0x30;
write_str(1,1,display);
*/
// lcd_wdat(0x00); //显示自定义字符
// lcd_wdat('C'); //显示C
}
/**********************************************************/
void write_byte(uchar inbyte)
{
uchar i;
for(i=0;i<8;i++)
{
sclk=0; //写的时候低电平改变数据
if(inbyte&0x01)
io=1;
else
io=0;
sclk=1; //写的时候高电平,把数据写入ds1302
_nop_();
inbyte=inbyte>>1;
}
}
/**********************************************************/
uchar read_byte() //sclk的下跳沿读数据
{
uchar i,temp=0;
io=1; //设置为输入口
for(i=0;i<7;i++)
{
sclk=0;
if(io==1)
temp=temp|0x80;
else
temp=temp&0x7f;
sclk=1; //产生下跳沿
temp=temp>>1;
}
return (temp);
}
/**********************************************************/
// 往ds1302的某个地址写入数据
/**********************************************************/
void write_ds1302(uchar cmd,uchar indata)
{
sclk=0;
reset=1;
write_byte(cmd);
write_byte(indata);
sclk=0;
reset=0;
}
/**********************************************************/
// 读ds1302某地址的的数据
/**********************************************************/
uchar read_ds1302(uchar addr)
{
uchar backdata;
sclk=0;
reset=1;
write_byte(addr); //先写地址
backdata=read_byte();//然后读数据
sclk=0;
reset=0;
return (backdata);
}
/**********************************************************/
// 设置初始时间
/**********************************************************/
void set_ds1302(uchar addr,uchar *p,uchar n) //写入n个数据
{
write_ds1302(0x8e,0x00); //写控制字,允许写操作
for(;n>0;n--)
{
write_ds1302(addr,*p);
p++;
addr=addr+2;
}
write_ds1302(0x8e,0x80); //写保护,不允许写
}
/**********************************************************/
// 读取当前时间
/**********************************************************/
void read_nowtime(uchar addr,uchar *p,uchar n)
{
for(;n>0;n--)
{
*p=read_ds1302(addr);
p++;
addr=addr+2;
}
}
/**********************************************************/
// 初始化DS1302
/**********************************************************/
void init_ds1302()
{
reset=0;
sclk=0;
write_ds1302(0x80,0x00);
// write_ds1302(0x90,0xa6); //一个二极管+4K电阻充电
write_ds1302(0x90,0x00); //禁止涓流充电
write_ds1302(0x8e,0x80); //写保护控制字,禁止写
}
/**********************************************************/
// Time0中断函数
/**********************************************************/
void Time0(void) interrupt 1 using 0
{
uchar disp;//8位数码管
EA = 0;
//按键处理
if (K2 == 0) //定时 按下K2
{
if (old_key == 2)
{
key_times ++;
if (key_times >= MAX_KEY_TIMES) //确认按下键
{
if (play_temperature) //目前显示温度模式
play_temperature = 0; //切换为定时模式
if (alarmMinute < left_alarmMinute + 1) //说明定时已经执行了不到二分钟,还可以改
{
if (alarmMinute < 999)//最大999分钟
{
alarmMinute ++;
left_alarmMinute ++;
key_times = 0;
now_minute = ((init&0xf0)>>4) * 10 + init&0x0f;
old_minute = now_minute;
}
}
alarm_beep = 0; //取消报警
BEEP = 1; //关蜂鸣器
}
}
else
{
old_key = 2;
key_times = 1;
}
}
else if (K1 == 0) //温度 按下K1
{
if (old_key == 1)
{
key_times ++;
if (key_times >= MAX_KEY_TIMES) //确认按下键
{
if (!play_temperature) //目前显示定时模式
play_temperature = 1; //切换为温度模式
alarmMinute = 0;
left_alarmMinute = 0;
key_times = 0;
alarm_beep = 0; //取消报警
BEEP = 1; //关蜂鸣器
}
}
else
{
old_key = 1;
key_times = 1;
}
}
else
key_times = 0;
//半秒标志
timecount ++;
if(timecount > 499) //500ms
{
timecount = 0;
flag = ~flag;
}
count ++;
count ++;
if (count > 60000)
count = 0;
//温度处理
if (count % 10000 == 0) // 10秒
{
if (play_temperature) //处理温度
{
Read_Temperature();
if (bDS18B20OK == 1) //18B20 err
{
h = 0x00;
l = 0x00;
}
else
{
h = ((temp_data&0xf0)>>4)|((temp_data&0x0f)<<4);
l = ditab&0x0f]; //查表得小数位的值
}
}
}
//时间处理 定时处理
if (count % 10000 == 0) // 10秒
{
read_nowtime(0x81,init,7);//读出当前时间,读出7个字节
if (!play_temperature)//处理定时
{
now_minute = ((init&0xf0)>>4) * 10 + init&0x0f;
if (now_minute != old_minute) //分钟发生变化,说明过了一分钟了
{
if (left_alarmMinute > 0)
left_alarmMinute --;
old_minute = now_minute;
}
if (left_alarmMinute == 0)//定时到!!! 持续响铃
alarm_beep = 1;
}
}
//响铃控制
if (alarm_beep)
{
if (flag)
BEEP = 0;
else
BEEP = 1;
}
//数码管 段选
if (display_pos == 0)
P0 = led_display[(init&0xf0)>>4]; //小时高位
else if (display_pos == 1)
P0 = led_display&0x0f]; //小时低位
else if (display_pos == 2)
{
P0 = led_display[(init&0xf0)>>4]; //分钟高位
if (flag)
P0 |= 0x80; // add point
// P0 &= 0x7f; // add point
}
else if (display_pos == 3)
{
P0 = led_display&0x0f]; //分钟低位
if (flag)
P0 |= 0x80; // add point
// P0 &= 0x7f; // add point
}
else if (display_pos == 4)
{
// if ((h/100) > 0)
// P0 = led_display;
// else
P0 = 0x00;
// P0 = 0xff;
}
else if (display_pos == 5)
{
if (play_temperature)
P0 = led_display[(h%100)/10];
else
{
if ((left_alarmMinute == alarmMinute) || (flag && left_alarmMinute != alarmMinute))
{
if (left_alarmMinute >= 100)
P0 = led_display;
else
P0 = 0x00;
// P0 = 0xff;
}
else
P0 = 0x00;
// P0 = 0xff;
}
}
else if (display_pos == 6)
{
if (play_temperature)
{
P0 = led_display;
P0 |= 0x80; // add point
// P0 &= 0x7f; // add point
}
else
{
if ((left_alarmMinute == alarmMinute) || (flag && left_alarmMinute != alarmMinute))
P0 = led_display[(left_alarmMinute%100)/10];
else
P0 = 0x00;
// P0 = 0xff;
}
}
else if (display_pos == 7)
{
if (play_temperature)
P0 = led_display;//查表得小数位的值
else
{
if ((left_alarmMinute == alarmMinute) || (flag && left_alarmMinute != alarmMinute))
P0 = led_display;
else
P0 = 0x00;
// P0 = 0xff;
}
}
//数码管 位选
P2 = pos_data;
// delayms(1);
//换位 每1ms中断只显示一位
display_pos ++;
if (display_pos == 4) //第4位不显示,直接跳过,这样可以提高亮度
display_pos ++;
if (display_pos > 7)
display_pos = 0;
// TH0 = 0x4c; //50ms定时
// TL0 = 0x00;
TH0 = 0xfc; //1ms定时
TL0 = 0x66;
EA = 1;
}
/*********************************************************/
void beep()
{
unsigned char i;
for (i=0;i<100;i++)
{
delay(60);
BEEP=!BEEP; //BEEP取反
}
BEEP=1; //关闭蜂鸣器
}
main()
{
uint i;
// uchar date_init[] = {0x00,0x41,0x14,0x03,0x02,0x04,0x11}; //用于设置初始时间
//秒, 分, 时, 日, 月,星期,年
P0 = 0xff;
P2 = 0xff;
// EA = 0;
TMOD = 0x01;
// TH0 = 0x4c; //50ms定时
// TL0 = 0x00;
TH0 = 0xfc; //1ms定时
TL0 = 0x66;
ET0 = 1;
TR0 = 1;
beep();
delayms(200);
beep();
delayms(200);
init_ds1302(); //初始化ds1302
// set_ds1302(0x80,date_init,7);//设置初始时间,日期,年月第一次设置过后屏蔽掉 DS1302用备用电继续走
read_nowtime(0x81,init,7);//读出当前时间,读出7个字节
//18B20刚开始会读出很高的值,不知为什么?所以先读几次就正常了
i = 0;
while (i < 5)
{
Read_Temperature();
if (bDS18B20OK == 1) //18B20 err
{
h = 0;
l = 0;
BEEP = 0;
delayms(100);
BEEP = 1;
}
else
{
h = ((temp_data&0xf0)>>4)|((temp_data&0x0f)<<4);
l = ditab&0x0f]; //查表得小数位的值
}
delayms(200);
i ++;
}
delayms(200);
// play_hour();
EA = 1;
while (1)
{
;
/*
read_nowtime(0x81,init,7);//读出当前时间,读出7个字节
Read_Temperature();
if (bDS18B20OK == 0) //18B20 err
{
h = 0x00;
l = 0x00;
}
else
{
h = ((temp_data&0xf0)>>4)|((temp_data&0x0f)<<4);
l = ditab&0x0f]; //查表得小数位的值
}
procFlag = 0;
for (i = 0; i < 50; i ++)
delayms(200);
*/
}
} 顶 ku a cool a 这个面板 开的不错啊 又得裤子了, 以后一定再做好的 请问电路板是雕的吗? 这要顶! 顶 不错,前面板的四个螺丝没有的话看上去更好. 回复【9楼】gtnr
-----------------------------------------------------------------------
“前面板的四个螺丝没有的话看上去更好”
你有什么办法解决? 回复【10楼】suncq
回复【9楼】gtnr
-----------------------------------------------------------------------
“前面板的四个螺丝没有的话看上去更好”
你有什么办法解决?
-----------------------------------------------------------------------
热熔胶
楼主的板子上怎么那么多飞线? 飞线的原因是不是断了铜皮?不过看起来板子象万能板+最小系统板。 电路板是用热转印做的. 本来想用 8550做位选, 结果不知什么原因没试出来. 就改成段选接上拉电阻后, 位选直接接P2口了. 实际上没有用一个三级管, 但是多了8根飞线
本来做的单面板, 计划只有位选的8根飞线. 不错。
不过在程序中看到不少delayms()函数……程序忙的过来吗? 回复【11楼】fsclub 绿林好汉
回复【10楼】suncq
回复【9楼】gtnr
-----------------------------------------------------------------------
“前面板的四个螺丝没有的话看上去更好”
你有什么办法解决?
-----------------------------------------------------------------------
热熔胶
-----------------------------------------------------------------------
热熔胶恐怕不够结实. 螺丝用成内六角的应该更好看 做的很好看啊,有机会也做个,争取胜过你,哈哈 就做了这么个外壳呀,块得了吧你,别给阿莫雕刻机丢人了 飞线好多
面板既然是雕的,加点装饰花纹不是更好 在数码管上加一个黑色带透明的那种玻璃,从前面看就可以以假乱真了 只能算个面板吧,壳算不上。。。 回复【17楼】zzy9903 9903
就做了这么个外壳呀,块得了吧你,别给阿莫雕刻机丢人了
-----------------------------------------------------------------------
你也做个出来晒晒啊 jh 做的非常不错,顶./emotion/em004.gif 不错 回复【8楼】tangwei039
顶
-----------------------------------------------------------------------
你的头像有点儿那个,像**妇女,- -!! 面板上的4颗螺丝很掉价。。。 面板可以用双层,一层拧螺丝,外边粘一层整体的!盖住螺钉 不错 个人认为面板设计得很漂亮。同时发表些个人建议:
1、4个螺丝如果用那种内六角的,就让他凸出来,可能还有质感些。
2、蜂鸣器不要整个露出来,而只把发声孔打个洞。面板可能更简洁。
3、羡慕有雕刻机。 相当好......................................................... 回复【17楼】zzy9903 9903
就做了这么个外壳呀,块得了吧你,别给阿莫雕刻机丢人了
-----------------------------------------------------------------------
新手制作出这个外壳,已经不错了。 不知道能给个原理图不,自己也想做一个! mark 楼主面板是不是装饰用的铝塑板刻的? 回楼上: 面板用铝塑板做的, 40元买了很大一块,算下来这块1元不到.
原理图很简单,我没有画. 用的 AT89S52 就是 P0口接段选, P2口接位选. P3.6接DS18B20P3.7接蜂鸣器P1.0 P1.1 P1.2 接到 DS1302时钟控制线 总体说来这个外壳雕的很好 mark 回复【36楼】aahui 阿晖
回楼上: 面板用铝塑板做的, 40元买了很大一块,算下来这块1元不到.
原理图很简单,我没有画. 用的 at89s52 就是 p0口接段选, p2口接位选. p3.6接ds18b20p3.7接蜂鸣器p1.0 p1.1 p1.2 接到 ds1302时钟控制线
-----------------------------------------------------------------------
我也曾经打过铝塑板的主意,它能弯折吗?用v刀在背面刻槽后,能否像硬纸板一样折成盒子? 为什么不用雕刻机直接出双面PCB?而去用热转印? 雕刻机用的不熟啊!
面板可以刻几个字么
面板的4个螺丝,如果是内六角,就会有点缀作用了 回复【10楼】suncq
回复【9楼】gtnr
-----------------------------------------------------------------------
“前面板的四个螺丝没有的话看上去更好”
你有什么办法解决?
-----------------------------------------------------------------------
回复【15楼】aahui 阿晖
回复【11楼】fsclub 绿林好汉
回复【10楼】suncq
回复【9楼】gtnr
-----------------------------------------------------------------------
“前面板的四个螺丝没有的话看上去更好”
你有什么办法解决?
-----------------------------------------------------------------------
热熔胶
-----------------------------------------------------------------------
热熔胶恐怕不够结实. 螺丝用成内六角的应该更好看
-----------------------------------------------------------------------
不要小看了伟大的热熔胶 ~~中国的山寨产业少不了这个
回复【19楼】yu_wen
在数码管上加一个黑色带透明的那种玻璃,从前面看就可以以假乱真了
-----------------------------------------------------------------------
对~~~~
回复【39楼】leolink
回复【36楼】aahui 阿晖
回楼上: 面板用铝塑板做的, 40元买了很大一块,算下来这块1元不到.
原理图很简单,我没有画. 用的 at89s52 就是 p0口接段选, p2口接位选. p3.6接ds18b20p3.7接蜂鸣器p1.0 p1.1 p1.2 接到 ds1302时钟控制线
-----------------------------------------------------------------------
我也曾经打过铝塑板的主意,它能弯折吗?用v刀在背面刻槽后,能否像硬纸板一样折成盒子?
-----------------------------------------------------------------------
可以折但不能反复折 参考下程序 回复【14楼】XA144F
-----------------------------------------------------------------------
不要那么排斥delayms,单片机没那么任务就不要用那么复杂的算法。
简单、易用远比“高科技”重要,特别是在做产品的时候。
回复【30楼】ytangy
-----------------------------------------------------------------------
想说的都让你给说了,在面板上玩点花样就更漂亮了。 这雕刻机? 本来是主要想show单片机做的程序的, 结果大家对面板更有兴趣... 美工不行啊,LED 管前面不盖一半透明板很难看,既然一定要LED可以选高档点的,感觉好很多 标记 mark 非常不错,顶一个 留下足迹。有空学习一下楼主的程序。 xuexi学习 那个蜂鸣器乍一看还以为摄像头呢. MARK!!! 不错谢谢分享 面板上四个锣丝改用平头的会好一些 分享快乐, 回复【1楼】aahui阿晖
-----------------------------------------------------------------------
做的非常不错,值得学习,顶! mark 回复【1楼】aahui 阿晖
-----------------------------------------------------------------------
相当不错!!有时间了,好好看一下,有点困了。
页:
[1]