推荐
1.每次上电,必须把秒寄存器高位(第7位)设置为0,时钟才能走时。
2.如果需要写入数据和时钟日历信息,必须把“写保护”寄存器设置成为0
内存数据定义
BitCnt data 3Ch 数据位计数器
ByteCnt data 3Dh 数据字节计数器
Command data 3Eh 命令字节地址
RcvDat DATA 40H 接收数据缓冲区
XmtDat DATA 50H 发送数据缓差弊冲区
端口位定义
IO_DATA bit P1.6 数据传送总线
SCLK bit P1.5时钟控制总线
RST bit P1.7 复位总线
RS BIT P3.5
RW BIT P3.6
EN BIT P3.7
ORG 0000H
ORG 0013H
LCALL JKS
AJMP KS
**************************** main program
ORG0030H
KS: CLR RST
MOV SP,#2AH
----LCD初始化----
CLR EN 使能端为0,液晶执行命令
INIT_LCD:
MOV A,#38H 双列显示,字形5*7点阵
ACALL WCOM
ACALL DELAY1
MOV A,#38H 双列显示,字形5*7点阵
ACALL WCOM
ACALL DELAY1
MOV A,#38H 双列显示,字形返庆游5*7点阵
ACALL WCOM
ACALL DELAY1
MOV A,#0CH 开显示,关光标
ACALL WCOM
ACALL DELAY1
MOV A,#01H 清除 LCD 显示屏
ACALL WCOM
ACALL DELAY1
MOV A,#06H 地址加1
ACALL WCOM
ACALL DELAY1
------------------------------------初始化1302-------------------------
SET1302:
LCALL Write_Enable写允许
LCALL Osc_Disable
LCALL Write_Multiplebyte初始化1302,将我们要设定的数据写入
LCALL Read_Multiplebyte将我们设定的漏销数据读出来
LCALL Osc_Enable
START:
ACALL LCD
LCALL Read_Multiplebyte
AJMP START
---------------------LCD显示-------------------------
LCD:
MOV A,#11001000B
LCALL WCOM
MOV A,#0显示时间
MOV A,42H
LCALL SSH2
MOV A,#00111010B
LCALL WDATA
MOV A,41H
LCALL SSH2
MOV A,#00111010B
LCALL WDATA
MOV A,40H
LCALL SSH2
MOV A,#11000000B
LCALL WCOM
MOV A,#0显示日期字符
MOV A,46H
LCALL SSH2
MOV A,#00101101B
LCALL WDATA
MOV A,44H
LCALL SSH2
MOV A,#00101101B
LCALL WDATA
MOV A,43H
LCALL SSH2
RET
SSH2:
MOV B,#16
DIV AB
MOV 58H,B
MOV 59H,A
MOV A,59H
MOV DPTR,#TAB
MOVC A,@A+DPTR
ACALL WDATA
MOV A,58H
MOV DPTR,#TAB
MOVC A,@A+DPTR
ACALL WDATA
RET
-----------------------------------------------------
写指令、数据使能子程序
-----------------------------------------------------
WCOM: 写指令使能
ACALL DELAY0
MOV P0,A
CLR RS
CLR RW
CLR EN
CLR EN
CLR EN
SETB EN
RET
WDATA: 写数据使能
ACALL DELAY0
MOV P0,A
SETB RS RS=H,RW=L,D0-D7=数据,E=高脉冲
CLR RW
CLR EN
CLR EN
CLR EN
SETB EN
RET
****判忙音****
DELAY0:
MOV P0,#0FFH
CLR RS
SETB RW
CLR EN
NOP
SETB EN
JB P0.7,DELAY0
RET
TAB:DB 00110000B,00110001B,00110010B,00110011B
DB 00110100B,00110101B,00110110B,00110111B
DB 00111000B,00111001B
********************************************************************************************
发送数据程序
名称:Send_Byte
描述:发送ByteCnt 个字节给被控器DS1302
命令字节地址在Command 中
所发送数据的字节数在ByteCnt 中发送的数据在XmtDat 缓冲区中
********************************************************************************************
Send_Byte:
CLR RST 复位引脚为低电平所有数据传送终止
NOP
CLR SCLK清时钟总线
NOP
SETB RST 复位引脚为高电平逻辑控制有效
NOP
MOV A,Command准备发送命令字节
MOV BitCnt,#08h 传送位数为8
S_Byte0:
RRC A 将最低位传送给进位位C
MOV IO_DATA,C 位传送至数据总线
NOP
SETB SCLK 时钟上升沿发送数据有效
NOP
CLR SCLK 清时钟总线
DJNZ BitCnt,S_Byte0 位传送未完毕则继续
NOP
S_Byte1: 准备发送数据
MOV A,@R0 传送数据过程与传送命令相同
MOV BitCnt,#08h
S_Byte2:
RRC A
MOV IO_DATA,C
NOP
SETB SCLK
NOP
CLR SCLK
DJNZ BitCnt,S_Byte2
INC R0 发送数据的内存地址加1
DJNZ ByteCnt,S_Byte1 字节传送未完毕则继续
NOP
CLR RST 逻辑 *** 作完毕清RST
RET
***************************************************************************************
接收数据程序
名称:Receive_Byte
描述:从被控器DS1302 接收ByteCnt 个字节数据
命令字节地址在Command 中
所接收数据的字节数在ByteCnt 中接收的数据在RcvDat 缓冲区中
***********************************************************************************
Receive_Byte:
CLR RST 复位引脚为低电平所有数据传送终止
NOP
CLR SCLK 清时钟总线
NOP
SETB RST 复位引脚为高电平逻辑控制有效
MOV A,Command 准备发送命令字节
MOV BitCnt,#08h 传送位数为8
R_Byte0:
RRC A 将最低位传送给进位位C
MOV IO_DATA,C 位传送至数据总线
NOP
SETB SCLK 时钟上升沿发送数据有效
NOP
CLR SCLK 清时钟总线
DJNZ BitCnt,R_Byte0 位传送未完毕则继续
NOP
R_Byte1: 准备接收数据
CLR A 清类加器
CLR C 清进位位C
MOV BitCnt,#08h 接收位数为8
R_Byte2:
NOP
MOV C,IO_DATA 数据总线上的数据传送给C
RRC A 从最低位接收数据
SETB SCLK 时钟总线置高
NOP
CLR SCLK 时钟下降沿接收数据有效
DJNZ BitCnt,R_Byte2 位接收未完毕则继续
MOV @R1,A 接收到的完整数据字节放入接收内存缓冲区
INC R1 接收数据的内存地址加1
DJNZ ByteCnt,R_Byte1 字节接收未完毕则继续
NOP
CLR RST 逻辑 *** 作完毕清RST
RET
--写保护寄存器 *** 作------------------------------------------
Write_Enable:
MOV Command,#8Eh 命令字节为8E
MOV ByteCnt,#1 单字节传送模式
MOV R0,#XmtDat 数据地址覆给R0
MOV XmtDat,#00h 数据内容为0 写入允许
ACALL Send_Byte 调用写入数据子程序
RET
当写保护寄存器的最高位为1 时禁止数据写入寄存器---------------
Write_Disable:
MOV Command,#8Eh 命令字节为8E
MOV ByteCnt,#1 单字节传送模式
MOV R0,#XmtDat 数据地址覆给R0
MOV XmtDat,#80h 数据内容为80h 禁止写入
ACALL Send_Byte 调用写入数据子程序
RET 返回调用本子程序处
当把秒寄存器的第7 位时钟停止位设置为0 时起动时钟开始---------
Osc_Enable:
MOV Command,#80h 命令字节为80
MOV ByteCnt,#1 单字节传送模式
MOV R0,#XmtDat 数据地址覆给R0
MOV XmtDat,#00h 数据内容为0 振荡器工作允许
ACALL Send_Byte 调用写入数据子程序
RET 返回调用本子程序处
当把秒寄存器的第7 位时钟停止位设置为1 时时钟振荡器停止HT1380 进入低功耗方式---------------
Osc_Disable:
MOV Command,#80h 命令字节为80
MOV ByteCnt,#1 单字节传送模式
MOV R0,#XmtDat 数据地址覆给R0
MOV XmtDat,#80h 数据内容为80h 振荡器停止
ACALL Send_Byte 调用写入数据子程序
RET 返回调用本子程序处
写入00 年6 月21 日星期三13 时59 分59---------------------
Write_Multiplebyte:
MOV Command,#0BEh 命令字节为BEh
MOV ByteCnt,#8 多字节写入模式此模块为8 个
MOV R0,#XmtDat 数据地址覆给R0
MOV XmtDat,#59h 秒单元内容为59h
MOV XmtDat+1,#59h 分单元内容为59h
MOV XmtDat+2,#13h 时单元内容为13h
MOV XmtDat+3,#21h 日期单元内容为21h
MOV XmtDat+4,#06h 月单元内容为06h
MOV XmtDat+5,#03h 星期单元内容为03h
MOV XmtDat+6,#0 年单元内容为00h
MOV XmtDat+7,#0 写保护单元内容为00h
ACALL Send_Byte 调用写入数据子程序
RET 返回调用本子程序处
读出寄存器0-7 的内容程序设置如下
Read_Multiplebyte:
MOV Command,#0BFh 命令字节为BFh
MOV ByteCnt,#8 多字节读出模式此模块为8 个
MOV R1,#RcvDat 数据地址覆给R1
ACALL Receive_Byte调用读出数据子程序
RET返回调用本子程序处
DELAY1: 延时10MS
MOV 21H,#75
D2:MOV 22H,#100
DJNZ 22H,$
DJNZ 21H,D2
RET
=============================================================================================
END
#include<reg51.h>#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit sda=P2^7
sbit scl=P3^6
sbit wp=P3^7
sbit lcden=P3^5
sbit lcdrs=P3^0
sbit lcdrw=P3^1
sbit modekey=P3^3
sbit setkey=P3^4
sbit DQ =P2^0 //定义通信端口销友带
//延时函数
static unsigned char HT,LT,beng //定义用告橡于存放温度值的高位
sbit second_ge=P2^6
sbit second_shi=P2^5
sbit min_ge=P2^4
sbit min_shi=P2^3
sbit hour_ge=P2^2
sbit hour_shi=P2^1
uchar num,num1,num2,num3,num4,num5,num6,num7,numtemp,tt,tempbuf,a,x,dis1,dis2,dis3,dat
uchar sbuf,mbuf,hbuf,wbuf,dbuf,mobuf,ybuf,keyV,key1buf,key2buf,miao,shi,fen,xin,ri,yue,nian
uchar code table[]={0x28,0x7e,0xa2,0x62,0x74,0x61,0x21,0x7a,0x20,0x60}//0123456789
uchar code table1[]="2010-01-13 WED"
uchar code table2[]="00:00:00 00.0 C"
uchar code table3[]="SUNMONTUEWEDTHUFRISAT"
uchar code month_day[]={0,32,30,32,31,32,31,32,32,31,32,31,32,30}
uchar code tempdottab[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9}
void delay()
{ }
void delay1(uint x)
{
uchar a,b
for(a=xa>0a--)
for(b=100b>0b--)
}
//以下为LCD显示程序
void write_com(uchar com)
{
lcdrs=0
P1=com
delay1(5)
lcden=1
delay1(5)
lcden=0
}
void write_data(uchar date)
{
lcdrs=1
P1=date
delay1(5)
lcden=1
delay1(5)
lcden=0
}
void write_sfm(uchar add,uchar date)
{
uchar shi,ge
shi=date/10
ge=date%10
write_com(0x80+0x40+add)
write_data(0x30+shi)//地址自动加1
write_data(0x30+ge)
}
void write_nyr(uchar add,uchar date)
{
uchar shi,ge
shi=date/10
ge=date%10
write_com(0x80+add)
write_data(0x30+shi)//地址自动加1
write_data(0x30+ge)
}
void write_week(uchar add,uchar date)
{ uchar bai,shi,ge
bai=table3[date*3]
shi=table3[date*3+1]
ge=table3[date*3+2]
write_com(0x80+add)
write_data(bai)//地址自动加1
write_data(shi)
write_data(ge)
}
lcd_display()
{
miao=dis1
fen=dis2
shi=dis3
/亏芦/lcdrw=0
write_sfm(4,shi)
write_sfm(7,fen)
write_sfm(10,miao)
write_week(12,num4)
write_nyr(9,num5)
write_nyr(6,num6)
write_nyr(3,num7)
//lcdrw=1//必须置位,否则会与按键程序冲突
}
//DB18B20子程序
void delay2(unsigned int i) //
{
while(i--)
}
void delayms(unsigned int i) //延时 1MS
{ unsigned char j=0
for (i>0i--)
{ for (j=0j<125j++)
{}
}
}
//DB18B20初始化函数
Init_DS18B20(void)
{
unsigned char x=0
DQ = 1 //DQ复位
delay2(8) //稍做延时
DQ = 0 //单片机将DQ拉低
delay2(80)//精确延时 大于 480us
DQ = 1 //拉高总线
delay2(14)
x=DQ //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay2(20)
}
//读一个字节
ReadOneChar(void)
{
unsigned char i=0
unsigned char dat = 0
for (i=8i>0i--)
{
DQ = 0// 给脉冲信号
dat>>=1 // 逐位右移
DQ = 1// 给脉冲信号
if(DQ) //DQ为1 时,表示收到高电平1
dat|=0x80 // 把收到的高电平置给DAT的最高位
delay2(4)
}
return(dat) //
}
//写一个字节
WriteOneChar(unsigned char dat)
{
unsigned char i=0
for (i=8i>0i--)
{
DQ = 0
DQ = dat&0x01 //把要发送的高电平或者低电平给DQ 发送出去
delay2(5)
DQ = 1
dat>>=1 //逐位右移
}
delay2(4)
}
//读取温度
void ReadTemperature()
{
unsigned char a=0
unsigned char b=0
Init_DS18B20() //调用初始化函数
WriteOneChar(0xCC)// 跳过读序号列号的 *** 作
//不需要验证序列号。
WriteOneChar(0x44)// 发送温度转换命令 启动温度转换
Init_DS18B20()
WriteOneChar(0xCC)//跳过读序号列号的 *** 作
WriteOneChar(0xBE)//
a=ReadOneChar() //读取温度值低位
b=ReadOneChar() //读取温度值高位
LT=tempdottab[a&0x0f]
//LT=(a&0xF0)?5:0 //这句话的意思如果问号前的语句为真(判断小数位的高位是否为1111),是的话,置小数位位5 则LT=5 如果假 LT=0
/*如果a是从18B20里读来的低8位值
xiaoshu1 = (a&0x0f)*10/16//小数第一位
xiaoshu2 = (a&0x0f)*100/16%10//小数第二位
xiaoshu=xiaoshu1*10+xiaoshu2//小数两位*/
HT=b<<4 //
HT+=(a&0xF0)>>4 //
}
void lcd_display_tempmain( )
{
//uchar k
if (HT>99) //
{
write_com(0x80+0x40+8)//数码管百显示"1",表示100度
write_data(1)
}
if (HT<1) // 如果温度低于1度
{
write_com(0x80+0x40+8)//数码管百显示"-",表示零下温度
write_data(0x2d)
}
write_com(0x80+0x40+12)// 显示小数位温度值
write_data(0x30+LT)
write_com(0x80+0x40+9)// 显示十位温度值
write_data(0x30+HT%100/10)
write_com(0x80+0x40+10)// 显示个位温度值
write_data(0x30+HT%10)
}
//以下为初始化程序
void init()
{
P2=0xff
delay()
scl=1
delay()
num=0
num4=xin=3
num5=ri=13
num6=mobuf=yue=1
num7=nian=10
tt=0
wp=0
modekey=1
setkey=1
TMOD=0x01//设置定时器0为工作方式1
TH0=(65536-10000)/256
TL0=(65536-10000)%256
//TH1=(65536-20000)/256
//TL1=(65536-20000)%256
EA=1//开总中断
ET0=1//开定时器0中断
//ET1=1
lcdrw=0
lcden=0
write_com(0x38)//显示模式设置
write_com(0x0c)//显示开关及光标设置
write_com(0x06)//光标书写设置
write_com(0x01)//清屏
write_com(0x80+0x00)//首行显示地址设置
for(num=0num<15num++)
{
write_data(table1[num])
delay1(5)
}
write_com(0x80+0x40)
for(num=0num<15num++)
{
write_data(table2[num])
delay1(5)
}
write_com(0x80+0x40+13)
write_data(0xdf)
ReadTemperature() //读取温度值
lcd_display_tempmain( ) //对读到的温度值进行处理
TR0=1//启动定时器0
//TR1=1
}
//以下为按键管理程序
uchar key()
{
if(modekey==1)
return(0)
delay1(10)
if(modekey==1)
return(0)
while(!modekey)
keyV++
if(keyV==9)
keyV=0
return(keyV)
}
void key1()
{
key1buf=key()
switch(key1buf)
{
case 1:
{
TR0=0
key2buf=1
write_com(0x80+0x40+6)
write_com(0x0f)
break
}
case 2:
{
TR0=0
key2buf=2
write_com(0x80+0x40+3)
write_com(0x0f)
break
}
case 3:
{
TR0=0
key2buf=3
write_com(0x80+0x40+0)
write_com(0x0f)
break
}
case 4:
{
TR0=0
key2buf=4
write_com(0x80+12)
write_com(0x0f)
break
}
case 5:
{
TR0=0
key2buf=5
write_com(0x80+8)
write_com(0x0f)
break
}
case 6:
{
TR0=0
key2buf=6
write_com(0x80+5)
write_com(0x0f)
break
}
case 7:
{
TR0=0
key2buf=7
write_com(0x80+0)
write_com(0x0f)
break
}
case 8:
{
key2buf=0
keyV=0
write_com(0x0c)
TR0=1
}
}
if(key2buf!=0)
{
if(setkey==0)
{
delay1(5)
if(setkey==0)
{
while(!setkey)
switch(key2buf)
{
case 1:
{
sbuf=miao
sbuf++
if(sbuf>=60)
sbuf=0
num1=miao=sbuf
write_sfm(6,miao)
write_com(0x80+0x40+6)
break
}
case 2:
{
mbuf=fen
mbuf++
if(mbuf>=60)
mbuf=0
num2=fen=mbuf
write_sfm(3,fen)
write_com(0x80+0x40+3)
break
}
case 3:
{
hbuf=shi
hbuf++
if(hbuf>=24)
hbuf=0
num3=shi=hbuf
write_sfm(0,shi)
write_com(0x80+0x40+0)
break
}
case 4:
{
wbuf=xin
wbuf++
if(wbuf>=7)
wbuf=0
num4=xin=wbuf
write_week(12,xin)
write_com(0x80+12)
break
}
case 5:
{
dbuf=ri
dbuf++
if(dbuf>=month_day[mobuf])
dbuf=1
num5=ri=dbuf
write_nyr(8,ri)
write_com(0x80+8)
break
}
case 6:
{
mobuf=yue
mobuf++
if(mobuf>=13)
mobuf=1
num6=yue=mobuf
write_nyr(5,yue)
write_com(0x80+5)
break
}
case 7:
{
ybuf=nian
ybuf++
if(ybuf>=100)
ybuf=0
num7=nian=ybuf
write_nyr(2,nian)
write_com(0x80+0)
break
}
}
}
}
}
}
void main()
{
init()
while(1)
{
key1()
}
}
void time0() interrupt 1
{
TH0=(65536-10000)/256
TL0=(65536-10000)%256
tt++
if(tt==100)
{
tt=0
ReadTemperature() //读取温度值
lcd_display_tempmain( ) //对读到的温度值进行处理
num1++
if(num1>=60)
{
num1=0
num2++
if(num2>=60)
{
num2=0
num3++
if(num3>=24)
{
num3=0
num4++
num5++
if(num4>=7)
num4=0
xin=num4
write_week(12,xin)
if(num5>=month_day[num6])
{
num5=1
num6++
if(num6>=13)
{
num6=1
num7++
if(num7>=100)
num7=0
nian=num7
write_nyr(2,nian)
}
yue=num6
write_nyr(5,yue)
}
ri=num5
write_nyr(8,ri)
}
shi=num3
write_sfm(0,shi)
}
fen=num2
write_sfm(3,fen)
}
miao=num1
write_sfm(6,miao)
/*if(HT>37|HT<20) // 判断温度范围
{beng=0} // 如果温度高于37度或者低于20度,则报警告示
else
beng=1*/
}
}
/* if( *year%400 == 0 || *year%100 != 0 &&*year%4 == 0 )
dayOfMonth[1] = 29*/
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)