历史上的今天
今天是:2025年01月04日(星期六)
2021年01月04日 | 基于51单片机的多功能时钟温度计 DS1302+LCD1602
2021-01-04 来源:51hei
本设计是由STC89C52单片机为控制核心,具有在线编程功能,低功耗;时钟电路由DS1302提供,它是一种高性能、低功耗的时钟电路,工作电压为3V~5V;所以采用DS1302作为本设计的日历芯片;显示部份使用LCD1602B液晶模块进行数字显示,1602B液晶模块可以显示2行16个字符,有8位数据总线D0—D7,和RS、R/W、EN三个控制端口,工作电压为5V,并且带有字符对比度调节和背光。该模块也可以只用D4-D7作为四位数据分两次传送,这样就可以节省MCU的I/O口资源,系统主要由晶振电路、复位电路、时钟电路部分、中央处理单元、晶显示部分组成。
电路原理图如下:
制作出来的实物图如下:

Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
单片机源程序如下:
#include #include #define uchar unsigned char #define uint unsigned int #define LCDIO P0 sbit rs=P2^0; sbit rd=P2^1; sbit lcden=P2^2; sbit acc0=ACC^0; //移位时的第0位 sbit acc7=ACC^7; //移位时用的第7位 sbit ct=P2^3; sbit speaker=P3^5; sbit DQ=P2^5;//ds18b20与单片机连接口 int djs11=0,js,dsmin=0,dshour=0; uchar second,minute,hour,day,month,year,week,count=0; uchar ReadValue,num,time; uint tvalue;//温度值 uchar tflag; uchar code table[]={" 2000-00-00 FRI"}; uchar code table1[]={" 00:00:00 "}; uchar code table2[]= "THUFRISATSUNMONTUEWES"; char szdata[8]; char szdata1[8]; uchar data disdata[5]; sbit DATA=P3^3; //时钟数据接口 sbit RST=P3^4; sbit SCLK=P3^2; sbit menu=P2^7; //菜单 sbit add=P2^6; //加一 sbit dec=P2^4; sbit set=P2^3 ; //减一 sbit djs=P3^6; void miaobiao(); void yx(); void delayms(int x) { char i; while(x--) { for(i=150;i>0;i--); } } void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void delay1(uint z) { for(;z>0;z--); } void write_com(uchar com) { rs=0; rd=0; lcden=0; LCDIO=com; delay(5); lcden=1; delay(5); lcden=0; } void write_date(uchar date) { rs=1; rd=0; lcden=0; LCDIO=date; delay(5); lcden=1; delay(5); lcden=0; } void init() { uchar num; lcden=0; write_com(0x38); write_com(0x0c); write_com(0x06); write_com(0x01); write_com(0x80); delay(5); write_com(0x80); for(num=0;num<15;num++) { write_date(table[num]); delay(5); } write_com(0x80+0x40); for(num=0;num<15;num++) { write_date(table1[num]); delay(5); } } void Write1302(uchar dat) { uchar i; SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备 delay1(2); //稍微等待,使硬件做好准备 for(i=0;i<8;i++) //连续写8个二进制位数据 { DATA=dat&0x01; //取出dat的第0位数据写入1302 delay(2); //稍微等待,使硬件做好准备 SCLK=1; //上升沿写入数据 delay1(2); //稍微等待,使硬件做好准备 SCLK=0; //重新拉低SCLK,形成脉冲 dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位 } } void WriteSet1302(uchar Cmd,uchar dat) { RST=0; //禁止数据传递 SCLK=0; //确保写数居前SCLK被拉低 RST=1; //启动数据传输 delay1(2); //稍微等待,使硬件做好准备 Write1302(Cmd); //写入命令字 Write1302(dat); //写数据 SCLK=1; //将时钟电平置于已知状态 RST=0; //禁止数据传递 } uchar Read1302(void) { uchar i,dat; delay(2); //稍微等待,使硬件做好准备 for(i=0;i<8;i++) //连续读8个二进制位数据 { dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位 if(DATA==1) //如果读出的数据是1 dat|=0x80; //将1取出,写在dat的最高位 SCLK=1; //将SCLK置于高电平,为下降沿读出 delay1(2); //稍微等待 SCLK=0; //拉低SCLK,形成脉冲下降沿 delay1(2); //稍微等待 } return dat; //将读出的数据返回 } uchar ReadSet1302(uchar Cmd) { uchar dat; RST=0; //拉低RST SCLK=0; //确保写数居前SCLK被拉低 RST=1; //启动数据传输 Write1302(Cmd); //写入命令字 dat=Read1302(); //读出数据 SCLK=1; //将时钟电平置于已知状态 RST=0; //禁止数据传递 return dat; //将读出的数据返回 } void Init_DS1302(void) { WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令 WriteSet1302(0x80,((0/10)<<4|(0%10))); //根据写秒寄存器命令字,写入秒的初始值 WriteSet1302(0x82,((12/10)<<4|(12%10))); //根据写分寄存器命令字,写入分的初始值 WriteSet1302(0x84,((11/10)<<4|(11%10))); //根据写小时寄存器命令字,写入小时的初始值 WriteSet1302(0x86,((25/10)<<4|(25%10))); //根据写日寄存器命令字,写入日的初始值 WriteSet1302(0x88,((1/10)<<4|(1%10))); //根据写月寄存器命令字,写入月的初始值 WriteSet1302(0x8c,((13/10)<<4|(13%10))); //nian WriteSet1302(0x8a,((1/10)<<4|(1%10))); } void DisplaySecond(uchar x) { uchar i,j; i=x/10; j=x%10; write_com(0xc7); write_date(0x30+i); write_date(0x30+j); } void DisplayMinute(uchar x) { uchar i,j; i=x/10; j=x%10; write_com(0xc4); write_date(0x30+i); write_date(0x30+j); } void DisplayHour(uchar x) { uchar i,j; i=x/10; j=x%10; write_com(0xc1); write_date(0x30+i); write_date(0x30+j); } void DisplayDay(uchar x) { uchar i,j; i=x/10; j=x%10; write_com(0x89); write_date(0x30+i); write_date(0x30+j); } void DisplayMonth(uchar x) { uchar i,j; i=x/10; j=x%10; write_com(0x86); write_date(0x30+i); write_date(0x30+j); } void DisplayYear(uchar x) { uchar i,j; i=x/10; j=x%10; write_com(0x83); write_date(0x30+i); write_date(0x30+j); } void DisplayWeek(uchar x) { uchar i; x=x*3; write_com(0x8c); for(i=0;i<3;i++) { write_date(table2[x]); x++; } } void read_date(void) { ReadValue = ReadSet1302(0x81); second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = ReadSet1302(0x83); minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = ReadSet1302(0x85); hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = ReadSet1302(0x87); day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = ReadSet1302(0x89); month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = ReadSet1302(0x8d); year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue=ReadSet1302(0x8b); //读星期 week=ReadValue&0x07; if((year==szdata[1])&&(month==szdata[2])&&(day==szdata[3])&&(week==szdata[4])&&(hour==szdata[5])&&(minute==szdata[6])&&(second==szdata[7])) speaker=0; DisplaySecond(second); DisplayMinute(minute); DisplayHour(hour); DisplayDay(day); DisplayMonth(month); DisplayYear(year);
上一篇:单片机可调数字钟闹钟整点报时功能
下一篇:51单片机汇编语言数字时钟
史海拾趣
|
由于编程的需要,采用Double型存储数据,可是,在调试的时候,Memory观察窗中发现Double型会自动将后面几位截取,进而用指数来表示,不知道这只是显示的问题,还是它存储的数据就是截掉末尾几位的了?… 查看全部问答> |
|
用串口转usb接口的模块 数据接收存储技术革新是信号采集处理领域内的一个重要课题。利用这种技术,可以把信号的实时采集和精确处理在时间上分为两个阶段,有利于获得令人更满意的处理结果。在无线数传接收设备中应用数据接收存储方法时,除了要 ...… 查看全部问答> |
|
写了一个字符设备的驱动,但用的是驱动模型框架,用的是platform_driver_register接口注册的,然后在probe里注册一个字符设备驱动,现在驱动已经加载上了,用lsmod |grep xxx, cat /procmodules | grep xxx, ls /sys/modules/xxx都已经有相关信息, ...… 查看全部问答> |
|
产品信息: STM103V100是英蓓特公司新推出的一款基于ST意法半导体STM32系列处理器(Cortex-M3内核)的全功能评估板。该评估板采用主板与子板组合的工作方式,只需通过换插不同的CPU(现配STM32F103VBT6处理器)子板,即 ...… 查看全部问答> |
|
Altium 对于 Atmel Touch Controls 的支持 (中) 使用 SmallQTouchSlider 器件来实现一个小型slider传感器。这是一个自电容,一维,立体内插式传感器。它有三个独立通道直接连接到Atmel QTouch 感应控制器。相应的sensor模板在PCB中是由简单的矩形电极组成。这个模板包含2个完 ...… 查看全部问答> |




