给大家分享一个基于51单片机的多功能万年历12864液晶显示,温度补偿,同时更新时间温度,与电脑同步。可以设置闹钟
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
#include "value.h"
#include "nongli.h"
uchar n_nian,n_yue,n_ri;
bit flag_200ms = 1;
uchar menu_1;
uchar flag_clock_en; //闹钟标志位
uchar flag_clock_kai; //闹钟开标志位
uchar flag_c_en;
bit flag_100ms;
sbit beep=P2^7; //蜂鸣器IO口
sbit dq=P3^2; //18b20 IO口的定义
uint temperature ; //温度变量
/************ 延时函数 *****************/
void delay_uint(uint z)
{
while(z--);
}
/********************************************************************
* 名称 : delay_1ms()
* 功能 : 延时1ms函数
* 输入 : q
* 输出 : 无
***********************************************************************/
void delay_1ms(uint q)
{
uint i,j;
for(i=0;i<q;i++)
for(j=0;j<115;j++);
}
uchar dis_lcd[10];
#include "lcd12864bu.h"
/******************显示时间函数***************************/
void dis_shijian() //显示时间
{
write_shu16(3*2,1*8,shi,0);
write_shuzi(1,3*2,3*8,fuhao[1],0);
write_shu16(3*2,4*8,fen,0);
write_shuzi(1,3*2,6*8,fuhao[1],0);
write_shu16(3*2,7*8,miao,0);
write_shu16(1*2,6*8,nian,0);
write_shu16(1*2,10*8,yue,0);
write_shu16(1*2,14*8,ri,0);
write_shu16(2*2,4*8,n_yue,0);
write_shuzi(1,2*2,6*8,fuhao[0],0);
write_shu16(2*2,7*8,n_ri,0);
if(week==0)
{
write_yhanzi(1,4,7*16,xingqi[0]);
}
if(week==1)
{
write_yhanzi(1,4,7*16,xingqi[1]);
}
if(week==2)
{
write_yhanzi(1,4,7*16,xingqi[2]);
}
if(week==3)
{
write_yhanzi(1,4,7*16,xingqi[3]);
}
if(week==4)
{
write_yhanzi(1,4,7*16,xingqi[4]);
}
if(week==5)
{
write_yhanzi(1,4,7*16,xingqi[5]);
}
if(week==6)
{
write_yhanzi(1,4,7*16,xingqi[6]);
}
if(week==7)
{
week=0;
write_yhanzi(1,4,7*16,xingqi[0]);
}
write_shu18b20(3*2,10*8,temperature,0);
write_shuzi(1,3*2,12*8,dian,0);
}
/************初始化显示*****************/
void init_12864_dis() //初始化显示
{
cs1=1; //左屏开显示
cs2=0;
write_yhanzi(7,0,16,dzrl); //多功能电子日历
write_yhanzi(2,2,0,yangli); //阳(0) 历(1)
write_yhanzi(2,4,0,nongli); //农(0) 历(1)
// write_yhanzi(2,6,0,0x00); //时间
// write_yhanzi(2,6,0,shijian); //时间
write_shu16(1*2,4*8,0x20,0);
write_yhanzi(1,2,4*16,qita[0]); //年
write_yhanzi(1,2,6*16,qita[1]); //月
write_yhanzi(2,4,5*16,qita[6]); //星期
dis_shijian(); //显示时间
write_yhanzi(1,6,7*16,wendu_fuhao); //℃
}
/***********************18b20初始化函数*****************************/
void init_18b20()
{
bit q;
dq = 1; //把总线拿高
delay_uint(1); //15us
dq = 0; //给复位脉冲
delay_uint(80); //750us
dq = 1; //把总线拿高 等待
delay_uint(10); //110us
q = dq; //读取18b20初始化信号
delay_uint(20); //200us
dq = 1; //把总线拿高 释放总线
}
/*************写18b20内的数据***************/
void write_18b20(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{ //写数据是低位开始
dq = 0; //把总线拿低写时间隙开始
dq = dat & 0x01; //向18b20总线写数据了
delay_uint(5); // 60us
dq = 1; //释放总线
dat >>= 1;
}
}
/*************读取18b20内的数据***************/
uchar read_18b20()
{
uchar i,value;
for(i=0;i<8;i++)
{
dq = 0; //把总线拿低读时间隙开始
value >>= 1; //读数据是低位开始
dq = 1; //释放总线
if(dq == 1) //开始读写数据
value |= 0x80;
delay_uint(5); //60us 读一个时间隙最少要保持60us的时间
}
return value; //返回数据
}
/*************读取温度的值 读出来的是小数***************/
uint read_temp()
{
uint value;
uchar low; //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
init_18b20(); //初始化18b20
write_18b20(0xcc); //跳过64位ROM
write_18b20(0x44); //启动一次温度转换命令
delay_uint(50); //500us
init_18b20(); //初始化18b20
write_18b20(0xcc); //跳过64位ROM
write_18b20(0xbe); //发出读取暂存器命令
EA = 0;
low = read_18b20(); //读温度低字节
value = read_18b20(); //读温度高字节
EA = 1;
value <<= 8; //把温度的高位左移8位
value |= low; //把读出的温度低位放到value的低八位中
value *= 0.625; //转换到温度值 小数
return value; //返回读出的温度 带小数
}
全部资料51hei下载地址:
单片机多功能万年历温度(12864液晶显示).zip
(275.64 KB, 下载次数: 112)
|