51单片机毕业论文

# include & ltreg 51 . h & gt;

#include"DS18B20_3。h "

#定义uint无符号整数

#定义uchar无符号字符

uchar a,苗,石,分,日,月,年,周,旗,key1n,temp

//flag用于读取头文件中的温度值并显示温度值。

#定义YH 0x 80//LCD第一行的初始位置,因为LCD1602字符地址的第一位D7恒定为1 (10000000 = 80)。

# definer 0x 80+0x40//LCD第二行的初始位置(因为第二行的第一个字符位置地址是0x 40)

LCD与C51引脚连接定义(显示数据线接C51的P0口)

sbit rs=p1^0;

sbit en=p1^2;

sbit rw=p1^1;//如果rw在硬件上是接地的,就不需要写这句话和rw=0。

sbit led=p3^7;//LCD背光开关

//DS1302时钟芯片与C51引脚连接定义

sbit io=p2^2;

sbit sclk=p2^1;

sbit rst=p2^2;

sbit acc0=acc^0;

sbit acc7=acc^7;

/************************************************************

ACC累加器=A

加速0=E0H

ACC.0是ACC的第0位。Acc可以是位寻址的。

累加器ACC是一个8位存储单元,用来放数据。然而,这个存储单元有其特殊的位置。

它是单片机中非常关键的单元,很多操作都要通过ACC来进行。以后学指令的时候,

通常用来表示累加器。但是也有一些例外,比如在PUSH指令中,必须使用ACC这个名字。

一般来说,A代表累加器的内容,ACC代表累加器的地址。

***************************************************************/

//时间校准键与C51引脚连接定义

sbit key1=p2^4;//设置密钥

sbit key2=p2^5;//键控

sbit key3=p2^6;//键还原

sbit buzzer=p2^0;//蜂鸣器,晶体管9012驱动,低电平端口响应。

/**************************************************************/

uchar代码tab 1[]= { " 20--" };//固定显示年份的字符

uchar代码tab 2[]= { "::" };//时间显示的固定字符

//延迟函数,后面经常调用。

void delay(uin TMS)//延迟函数,参数函数

{

uint x,y;

for(x = xms;x & gt0;x -)

for(y = 120;y & gt0;y-);

}

/* * * * * * * * LCD写指令功能和写数据功能,可以叫* * * * * * * * * */

/*在这个程序中,与液晶写入相关的函数会在DS1302的函数中调用,所以液晶程序要放在前面*/

write _ 1602 com(uchircom)/* * * * LCD写命令功能* * * *

{

RS = 0;//数据/指令选择设置为指令。

rw = 0;//读写选择设置为写。

P0 = com//发送数据

延时(1);

en = 1;//拉高enable引脚,为有效下降沿做准备。

延时(1);

en = 0;//en由高变低,产生下降沿,液晶执行命令。

}

write _ 1602 dat(uchardat)/* * * LCD写入数据功能* * * *

{

RS = 1;//数据/命令选择设置为数据

rw = 0;//读写选择设置为写。

P0 = dat//发送数据

延时(1);

en = 1;//en设为高电平,为下降沿做准备。

延时(1);

en = 0;//en由高变低,产生下降沿,液晶执行命令。

}

LCD _ init ()/* * * LCD初始化函数* * * *

{

write _ 1602 com(0x 38);//设置LCD工作模式,含义:16*2行显示,5*7点阵,8位数据。

write _ 1602 com(0x0c);//打开显示,但不显示光标

write _ 1602 com(0x 06);//整个屏幕不动,光标自动向右移动。

write _ 1602 com(0x 01);//清除显示

write _ 1602 com(yh+1);//日历显示固定符号在第一行第1位后开始显示。

for(a = 0;a & lt14;a++)

{

write _ 1602 dat(tab 1[a]);//将日历显示的固定符号部分写入液晶屏。

//delay(3);

}

write _ 1602 com(er+2);//时间显示固定的符号书写位置,从第二个位置开始。

for(a = 0;a & lt8;a++)

{

write _ 1602 dat(tab 2[a]);//写一个固定显示时间的符号,两个冒号。

//delay(3);

}

}

/********************超过******************/

/* * * * * * * * * * * * DS1302相关子功能* * * * * * * * * * * * * *

Void write_byte(uchar dat)//写入一个字节。

{

ACC = dat

RST = 1;

for(a = 8;a & gt0;答-)

{

IO = ACC0

SCLK = 0;

SCLK = 1;

ACC = ACC & gt& gt1;

}

}

Uchar read_byte()//读取一个字节。

{

RST = 1;

for(a = 8;a & gt0;答-)

{

ACC7 = IO

SCLK = 1;

SCLK = 0;

ACC = ACC & gt& gt1;

}

返回(ACC);

}

// -

Voidwrite _ 1302 (uchar add,uchar dat)//向1302芯片写一个函数,指定写地址和数据。

{

RST = 0;

SCLK = 0;

RST = 1;

write_byte(添加);

写入字节(dat);

SCLK = 1;

RST = 0;

}

uchar Read _ 1302(uchar add)//从1302读取数据函数,指定读取数据的源地址。

{

uchar温度;

RST = 0;

SCLK = 0;

RST = 1;

write_byte(添加);

temp=read_byte()。

SCLK = 1;

RST = 0;

返回(临时);

}

uchar BCD _ decimal(uchar BCD)//BCD码到decimal函数,输入BCD,返回decimal。

{

uchar十进制;

Decimal = bcd & gt& gt4;

return(Decimal = Decimal * 10+(BCD & amp;= 0x0F));

}

// -

void DS 1302 _ init()//1302芯片初始化子函数(2010-01-07,12: 00: 00,第4周)

{

RST = 0;

SCLK = 0;

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x80,0x 00);//将初始第二数据00写入DS1302中的写第二寄存器80H。

write_1302(0x82,0x 00);//将初始子数据00写入DS1302中的写子寄存器82H。

write_1302(0x84,0x 12);//将初始小时数据12写入DS1302中的写小时寄存器84H。

write_1302(0x8a,0x 04);//将初始周数据4写入DS1302中的写周寄存器8aH。

write_1302(0x86,0x 07);//将初始日期数据07写入DS1302中的写日期寄存器86H。

write_1302(0x88,0x 01);//将初始月份数据01写入DS1302中的写月份寄存器88H。

write_1302(0x8c,0x 10);//将初始年份数据10写入DS1302中的写年份寄存器8cH。

write_1302(0x8e,0x 80);//打开写保护

}

// -

//温度显示子功能

Voidwrite _ temp (uchar add,uchar dat)//将温度数据写入LCD并指定显示位置。

{

uchar gw,SW;

GW = dat % 10;//获取个位数。

SW = dat/10;//获取十位数

write _ 1602 com(er+add);//er是头文件中指定的值0x80+0x40。

write _ 1602 dat(0x 30+SW);//Number +30得到该号码的LCD1602显示码。

write _ 1602 dat(0x 30+GW);//Number +30得到该号码的LCD1602显示码。

write _ 1602 dat(0x df);//显示温度的小圆圈符号,0xdf是该符号在LCD字符库中的地址码。

write _ 1602 dat(0x 43);//显示符号“C”,0x43是LCD字符库中大写C的地址码。

}

// -

//以分、秒显示子功能。

Voidwrite _ SFM (UCHAR ADD,UCHAR DAT)//写入LCD时,有两个参数:显示位置加当前数据。

{

uchar gw,SW;

GW = dat % 10;//获取个位数。

SW = dat/10;//获取十位数

write _ 1602 com(er+add);//er是头文件中指定的值0x80+0x40。

write _ 1602 dat(0x 30+SW);//Number +30得到该号码的LCD1602显示码。

write _ 1602 dat(0x 30+GW);//Number +30得到该号码的LCD1602显示码。

}

// -

//年、月、日显示子功能。

Voidwrite _ nyr (uchar add,uchar dat)//将年月日写入LCD,有两个参数:显示位置加数和显示数据。

{

uchar gw,SW;

GW = dat % 10;//获取个位数。

SW = dat/10;//获取十位数

write _ 1602 com(yh+add);//将显示位置设置为第一个位置+add

write _ 1602 dat(0x 30+SW);//Number +30得到该号码的LCD1602显示码。

write _ 1602 dat(0x 30+GW);//Number +30得到该号码的LCD1602显示码。

}

// -

Void write_week(uchar week)//写周函数

{

write _ 1602 com(yh+0x0c);//显示星期几字符的位置

切换(周)

{

case 1:write _ 1602 dat(' M ');//当周数为1时,显示。

write _ 1602 dat(' O ');

write _ 1602 dat(' N ');

打破;

情况二:write _ 1602 dat(' T ');//当周数据为2时显示。

write _ 1602 dat(' U ');

write _ 1602 dat(' E ');

打破;

案例三:write _ 1602 dat(' W ');//当周数据为3时显示。

write _ 1602 dat(' E ');

write _ 1602 dat(' D ');

打破;

案例四:write _ 1602 dat(' T ');//显示4的周数据。

write _ 1602 dat(' H ');

write _ 1602 dat(' U ');

打破;

情况5:write _ 1602 dat(' F ');//当周数据为5时显示。

write _ 1602 dat(' R ');

write _ 1602 dat(' I ');

打破;

案例6:write _ 1602 dat(' S ');//当周数据为6时显示。

write _ 1602 dat(' T ');

write _ 1602 dat(' A ');

打破;

案例7:write _ 1602 dat(' S ');//当周数据为7时显示。

write _ 1602 dat(' U ');

write _ 1602 dat(' N ');

打破;

}

}

//* * * * * * * * * * * * * *键盘扫描相关功能* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *。

void键扫描()

{

如果(key1 = = 0)/ - key1是功能键(设置键)-。

{

延迟(9);//延迟,用于消除抖动

If(key1==0)//延迟一段时间后,确认再次按键。

{

蜂鸣器= 0;//蜂鸣器响一次。

延迟(20);

蜂鸣器= 1;

而(!key 1);

key 1n++;

if(key1n==9)

key 1n = 1;//设置按钮* * *有八个功能循环:秒、分、小时、周、日、月、年、返回。

开关(钥匙1n)

{

案例1:TR0 = 0;//关闭计时器

//tr 1 = 0;

write _ 1602 com(er+0x 09);//按一次设置键,光标以秒为单位显示。

write _ 1602 com(0x0f);//将光标设置为闪烁。

temp=(苗)/10*16+(苗)% 10;//sec数据写入DS1302。

write_1302(0x8e,0x 00);

write_1302(0x80,0x 80 | temp);//苗

write_1302(0x8e,0x 80);

打破;

案例二:write _ 1602 com(er+6);//按两下fen位置显示光标。

//write _ 1602 com(0x0f);

打破;

案例三:write _ 1602 com(er+3);//按三下,石

//write _ 1602 com(0x0f);

打破;

情况四:write _ 1602 com(yh+0x0e);//每周按4次

//write _ 1602 com(0x0f);

打破;

案例五:write _ 1602 com(yh+0);//按5次,ri

//write _ 1602 com(0x0f);

打破;

案例六:write _ 1602 com(yh+0x 07);//按6次,曰

//write _ 1602 com(0x0f);

打破;

情况7:write _ 1602 com(yh+0x 04);//按7次,年

//write _ 1602 com(0x0f);

打破;

案例8:

write _ 1602 com(0x0c);//第八次按,设置光标不闪烁。

TR0 = 1;//打开计时器

temp=(苗)/10*16+(苗)% 10;

write_1302(0x8e,0x 00);

write_1302(0x80,0x 00 | temp);//苗数据写入DS1302。

write_1302(0x8e,0x 80);

打破;

}

}

}

// -按下按键键2。

if(key1n!=0)//当按键1被按下时。按以下键有效(击键次数不等于零)

{

If(key2==0) //向上键

{

延时(10);

if(key2==0)

{

蜂鸣器= 0;//蜂鸣器响一次。

延迟(20);

蜂鸣器= 1;

而(!key 2);

开关(钥匙1n)

{

案例1:苗++;//按设置键1次调整秒。

如果(苗==60)

苗= 0;//如果秒超过59,则将1加零。

write_sfm(0x08,苗);//使LCD在正确的位置显示“加号”设定的秒数。

temp=(苗)/10*16+(苗)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x80,temp);//将调整后的第二数据BCD码写入DS1302中的写第二寄存器80H。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(er+0x 09);//因为LCD模式设置为写入数据后自动向右移动光标,所以需要指定return。

//write _ 1602 com(0x0b);

打破;

案例二:fen++;

如果(fen==60)

fen = 0;

write_sfm(0x05,fen);//让LCD在正确的位置显示“加号”设定子数据。

temp=(分)/10*16+(分)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x82,temp);//将调整后的子数据BCD码写入DS1302的子写寄存器82H。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(er+6);//因为LCD模式设置为写数据,指针会自动加一,这种情况下会写回原来的位置。

打破;

案例三:石++;

if(shi==24)

Shi = 0;

write_sfm(2,Shi);//使LCD在正确的位置显示“加号”设定小时数据。

temp=(石)/10*16+(石)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x84,temp);//将调整后的小时数据BCD码写入DS1302中的写小时寄存器84H。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(er+3);//因为LCD模式设置为写数据,指针会自动加一,所以光标需要返回。

打破;

案例四:周++;

if(week==8)

周= 1;

write _ 1602 com(yh+0x0C);//在“加号”后指定周数据的显示位置

write_week(周);//指定每周数据显示内容。

temp=(周)/10*16+(周)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x8a,temp);//将调整后的周数据BCD码写入DS1302中的周寄存器8aH。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(yh+0x0e);//因为LCD模式设置为写数据,指针会自动加一,所以光标需要返回。

打破;

案例五:ri++;

如果(ri==32)

ri = 1;

write_nyr(9,ri);//使LCD在正确的位置显示“加号”设定日期数据。

temp =(ri)/10 * 16+(ri)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x86,temp);//将调整后的日期数据BCD码写入DS1302中的写日期寄存器86H。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(yh+10);//因为LCD模式设置为写数据,指针会自动加一,所以光标需要返回。

打破;

案例六:岳++;

if(岳==13)

岳= 1;

write_nyr(6,岳);//使LCD在正确的位置显示“加号”设定的月份数据。

temp=(岳)/10*16+(岳)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x88,temp);//将调整后的月份数据BCD码写入DS1302中的月份写入寄存器88H。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(yh+7);//因为LCD模式设置为写数据,指针会自动加一,所以光标需要返回。

打破;

案例7:年++;

if(年==100)

年= 0;

write_nyr(3,年);//使LCD在正确的位置显示“加号”的设定年份数据。

temp=(年)/10*16+(年)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x8c,temp);//将调整后的年份数据BCD码写入DS1302中的年份寄存器8cH。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(yh+4);//因为LCD模式设置为写数据,指针会自动加一,所以光标需要返回。

打破;

}

}

}

// - key3。有关每个句子的功能,请参考“Keying”注释。

if(key3==0)

{

延时(10);//延迟调整和抖动消除

if(key3==0)

{

蜂鸣器= 0;//蜂鸣器响一次。

延迟(20);

蜂鸣器= 1;

而(!key 3);

开关(钥匙1n)

{

案例1:苗-;

if(苗==-1)

苗= 59;//秒数据还原为-1时自动变成59。

write_sfm(0x08,苗);//在LCD的正确位置显示更改后的新秒数。

temp=(苗)/10*16+(苗)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x80,temp);//将调整后的第二数据BCD码写入DS1302中的写第二寄存器80H。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(er+0x 09);//因为LCD模式设置为写数据,指针会自动加一,这种情况下会写回原来的位置。

//write _ 1602 com(0x0b);

打破;

案例2:fen-;

if(fen==-1)

fen = 59

write_sfm(5,fen);

temp=(分)/10*16+(分)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x82,temp);//将调整后的子数据BCD码写入DS1302的子写寄存器82H。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(er+6);//因为LCD模式设置为写数据,指针会自动加一,这种情况下会写回原来的位置。

打破;

案例三:石-;

if(shi==-1)

石= 23;

write_sfm(2,Shi);

temp=(石)/10*16+(石)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x84,temp);//将调整后的小时数据BCD码写入DS1302中的写小时寄存器84H。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(er+3);//因为LCD模式设置为写数据,指针会自动加一,所以光标需要返回。

打破;

案例四:周-;

if(week==0)

周= 7;

write _ 1602 com(yh+0x0C);//在“加号”后指定周数据的显示位置

write_week(周);//指定每周数据显示内容。

temp=(周)/10*16+(周)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x8a,temp);//将调整后的周数据BCD码写入DS1302中的周寄存器8aH。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(yh+0x0e);//因为LCD模式设置为写数据,指针会自动加一,所以光标需要返回。

打破;

案例5:ri-;

如果(ri==0)

ri = 31;

write_nyr(9,ri);

temp =(ri)/10 * 16+(ri)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x86,temp);//将调整后的日期数据BCD码写入DS1302中的写日期寄存器86H。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(yh+10);//因为LCD模式设置为写数据,指针会自动加一,所以光标需要返回。

打破;

案例6:岳-;

如果(岳==0)

岳= 12;

write_nyr(6,岳);

temp=(岳)/10*16+(岳)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x88,temp);//将调整后的月份数据BCD码写入DS1302中的月份写入寄存器88H。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(yh+7);//因为LCD模式设置为写数据,指针会自动加一,所以光标需要返回。

打破;

案例7:年-;

if(年==-1)

年= 99;

write_nyr(3,年);

temp=(年)/10*16+(年)% 10;//ds 1302要求的十进制转换成DCB码。

write_1302(0x8e,0x 00);//允许写入,禁止写保护。

write_1302(0x8c,temp);//将调整后的年份数据BCD码写入DS1302中的年份寄存器8cH。

write_1302(0x8e,0x 80);//打开写保护

write _ 1602 com(yh+4);//因为LCD模式设置为写数据,指针会自动加一,所以光标需要返回。

打破;

}

}

}

}

}

// -

Void init() //定时器,计数器设置函数

{

TMOD = 0x 11;//指定定时器/计数器的工作模式为3。

TH0 = 0;//定时器T0 =0的高四位

TL0 = 0;//定时器T0 =0的低四位

EA = 1;//系统允许打开中断。

ET0 = 1;//允许T0中断

TR0 = 1;//打开中断,启动定时器。

}

//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

//***************************************************

void main()

{

LCD _ init();//调用LCD初始化子函数。

ds 1302 _ init();//调用DS1302时钟的初始化子函数。

init();//调用定时器计数器的设置子函数。

led = 0;//打开LCD的背光电源。

蜂鸣器= 0;//蜂鸣器响一次。

延迟(80);

蜂鸣器= 1;

While(1) //无限循环下面的语句:

{

key scan();//调用键盘扫描子函数。

}

}

Void timer0()中断1 //获取并显示日历和时间。

{

//Init _ ds 18b 20();//温度传感器DS18b2的初始化子函数在头文件中。

flag = read temperature();//将运行18b2头文件返回的函数结果发送到变量FLAG显示。

//以秒为单位读取周、月、年、年七个数据(DS1302的读寄存器与写寄存器不同):

Miao = BCD _ Decimal(read _ 1302(0x 81));

fen = BCD _ Decimal(read _ 1302(0x 83));

Shi = BCD _ Decimal(read _ 1302(0x 85));

ri = BCD _ Decimal(read _ 1302(0x 87));

岳= BCD _ Decimal(read _ 1302(0x 89));

nian = BCD _ Decimal(read _ 1302(0x8d));

week = BCD _ Decimal(read _ 1302(0x8b));

//显示温度、秒、小时和分钟数据:

write_temp(12,flag);//显示温度,从第二行第12个字符开始。

write_sfm(8,苗);//秒,从第二行的第八个字开始(调用时每秒显示一次子函数)

write_sfm(5,fen);//分钟,从第二行第五个字符开始。

write_sfm(2,Shi);//小时,从第二行第二个字符开始。

//显示日期、月份和年份数据:

write_nyr(9,ri);//日期,显示在第二行第九个字符之后。

write_nyr(6,岳);//月份,显示在第二行第六个字符之后。

write_nyr(3,年);//年份,从第二行第三个字符开始。

write_week(周);

}