单片机1602液晶显示的DS1302实时时钟帮我分析以下程序运行步骤,详细解释一下,尤其是Bcd转换

单片机1602液晶显示的DS1302实时时钟帮我分析以下程序运行步骤,详细解释一下,尤其是Bcd转换,第1张

这是我写的一个成功的,你仔细对比下就知道了!

#include<reg52.h>

#include<intrins.h>

#define U8 unsigned char

#define U16 unsigned int

#define BOOL bit

U8 secondh,secondl,minuteh,minutel,hourh,hourl,second,minute,hour

U8 monthl,monthh,month,day,datel,dateh,date,year,yearl,yearh

/***********定义LCD功能管脚**************************************/

sbit LCDRS = P2^6 //控世空制LCD数据或命灶李令的读写

sbit LCDRW = P2^5//控制LCD读写信号

sbit LCDEN = P2^7 /搜辩瞎/使能LCD

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

/***********定义DS1302功能管脚*********************************/

sbit DSRST = P3^5 //DS1302复位管脚

sbit DSIO = P3^4 //控制DS1302数据传输

sbit DSCLK = P3^6//DS1302时钟

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

/*******************延时函数***********************************/

void delay(U16 time)

{

U16 time1,time2

for(time1=timetime1>0time1--)

for(time2=110time2>0time2--)

}

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

/***********检测LCD忙碌状态***********************************/

BOOL judge_lcd()

{

BOOL flag

LCDEN = 0

LCDRS = 0

LCDRW = 1

LCDEN = 1

delay(1)

flag=(BOOL)(P0&0x80) //状态位第7位为1时禁止读写,为0时可读写

LCDEN = 0

return flag

}

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

/***********实现LCD写指令**************************************/

void write_lcd_command(U16 command)

{

while(judge_lcd()) //检测LCD是否为忙碌状态

P0 = command

LCDRS = 0

LCDRW = 0

LCDEN = 1

delay(1)

LCDEN = 0

}

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

/***********实现LCD写数据**************************************/

void write_lcd_date(U16 date)

{

while(judge_lcd()) //检测LCD是否为忙碌状态

P0 = date

LCDRS = 1

LCDRW = 0

LCDEN = 1

delay(1)

LCDEN = 0

}

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

/***********实现LCD写指令及数据********************************/

void write_lcd_com_date(U16 addr,U16 date)

{

write_lcd_command(addr)

delay(1)

write_lcd_date(date)

}

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

/******************初始化LCD***********************************/

void init_lcd()

{

write_lcd_command(0x38) //设置16x2显示,5x7点阵,8位数据口

delay(1)

write_lcd_command(0x0c) //开显示,不显示光标,光标不闪烁

delay(1)

write_lcd_command(0x06)//读写一个字符后,地址自动加1,不移动屏幕

delay(1)

write_lcd_command(0x01) //清屏

delay(1)

}

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

/**********************读DS1302********************************/

U8 read_ds1302(U8 addr)

{

U8 i,temp=0x00

DSRST=0

DSIO=1

DSCLK=0

DSRST=1

for (i=0i<8i++) //循环8次 写入地址数据

{

DSCLK=0

DSIO=addr&0x01 //每次传输低字节

addr>>=1 //右移一位

DSCLK=1

}

delay(1)

if(DSIO)

temp|=0x80 //每次传输低字节

DSCLK=0

temp>>=1

for (i=0i<7i++) //循环8次 读取数据

{

DSCLK=0

if(DSIO)

temp|=0x80 //每次传输低字节

DSCLK=1

temp>>=1 //右移一位

}

DSCLK=1

DSRST=0

DSIO=0

return temp //返回

}

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

/******************写DS1302**********************************/

void write_ds1302(U8 addr, U8 date)

{

U8 i

DSRST=0

DSCLK=0

DSRST=1

for (i=0i<8i++) //循环8次 写入地址数据

{

DSCLK=0

_nop_()

DSIO=addr&0x01 //每次传输低字节

addr>>=1 //右移一位

DSCLK=1

_nop_()

}

for (i=0i<8i++) //循环8次 写入数据

{

DSCLK=0

_nop_()

DSIO=date&0x01 //每次传输低字节

date>>=1 //右移一位 DSCLK=1

DSCLK=1

_nop_()

}

DSRST=0

delay(1)

}

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

/*****************初始化DS1302********************************/

void init_ds1302()

{

//读秒

if((((second=read_ds1302(0x81))>>7)&&0x01)==1)

{

write_ds1302(0x8e,0x00) //关闭写保护

write_ds1302(0x80,0x00) //00秒

write_ds1302(0x82,0x54) //54分

write_ds1302(0x84,0x17) //17点

write_ds1302(0x86,0x14) //14日

write_ds1302(0x88,0x10) //10月

write_ds1302(0x8a,0x05) //星期五

write_ds1302(0x8c,0x11) //2011年

write_ds1302(0x8e,0x80) //允许写保护

}

}

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

/*********************主函数****************************/

void main()

{

init_lcd()

delay(2)

write_lcd_com_date(0x81,'2')

write_lcd_com_date(0x82,'0')

delay(1)

init_ds1302()

delay(1)

while(1)

{

second=read_ds1302(0x81)

secondl=second&0x0f

secondh=second>>4

minute=read_ds1302(0x83)

minutel=minute&0x0f

minuteh=minute>>4

hour=read_ds1302(0x85)

hourl=hour&0x0f

hourh=hour>>4

month=read_ds1302(0x89)

monthl=month&0x0f

monthh=month>>4

year=read_ds1302(0x8d)

yearl=year&0x0f

yearh=year>>4

date=read_ds1302(0x87)

datel=date&0x0f

dateh=date>>4

day=read_ds1302(0x8b)

day=day&0x0f

delay(15)

write_lcd_com_date(0xca,0x30+secondl)

write_lcd_com_date(0xc9,0x30+secondh)

write_lcd_com_date(0xc8,':')

write_lcd_com_date(0xc7,0x30+minutel)

write_lcd_com_date(0xc6,0x30+minuteh)

write_lcd_com_date(0xc5,':')

write_lcd_com_date(0xc4,0x30+hourl)

write_lcd_com_date(0xc3,0x30+hourh)

write_lcd_com_date(0x84,0x30+yearl)

write_lcd_com_date(0x83,0x30+yearh)

write_lcd_com_date(0x85,'-')

write_lcd_com_date(0x87,0x30+monthl)

write_lcd_com_date(0x86,0x30+monthh)

write_lcd_com_date(0x88,'-')

write_lcd_com_date(0x8a,0x30+datel)

write_lcd_com_date(0x89,0x30+dateh)

write_lcd_com_date(0x8c,0x30+day)

}

}

这是一个时钟显示程序,里面有1602的 *** 作程序,比较完敏岩整绝对能运行

RS=P2.0 RW=P2.1 E=P2.2 DB0---DB7接P0口

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

#include<reg51.h>

#include<intrins.h>

#define uchar unsigned char

#define uint unsigned int

sbit LCD_RS = P2^0

sbit LCD_RW = P2^1

sbit LCD_EN = P2^2

sbit LCD_LED = P2^6

bitflag=1,hour=0,min=0,sec=0

bityear=0,month=0,day=0,week=0

bitalarm_flag=0

uchar timecount=0,count=0

uchar str1[]=" - - Week: "

uchar str2[]="Time: "

uchar str3[]="Alarm: "

uchar init [] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00} //

uchar init1[] ={0x00,0x00}

uchar init2[] ={0x00,0x59,0x23,0x01,0x05,0x01,0x06}//

//秒, 分, 时, 日, 月,星期,年

uchar bj_time[] ={0x00,0x00,0x00}

//秒,物拿运 分, 时

uchar code mytab[8] = {0x01,0x1b,0x1d,0x19,0x1d,0x1b,0x01,0x00}//小喇叭

#define delayNOP(){_nop_()_nop_()_nop_()_nop_()}

void Set_place(uchar row,uchar col)

void Play_nowtime()

void key_set(uchar num,uchar row,uchar col )

void alarm_time()

void Play_alarmtime()

void Time_compare()

/******************************************************************/罩梁

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

void delay1(int ms)

{

unsigned char y

while(ms--)

{

for(y = 0y<250y++)

{

_nop_()

_nop_()

_nop_()

_nop_()

}

}

}

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

/**/

/*检查LCD忙状态 */

/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。 */

/**/

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

bit lcd_busy()

{

bit result

LCD_RS = 0

LCD_RW = 1

LCD_EN = 1

delayNOP()

result = (bit)(P0&0x80)

LCD_EN = 0

return(result)

}

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

/* */

/*写指令数据到LCD*/

/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 */

/* */

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

void lcd_wcmd(uchar cmd)

{

while(lcd_busy())

LCD_RS = 0

LCD_RW = 0

LCD_EN = 0

_nop_()

_nop_()

P0 = cmd

delayNOP()

LCD_EN = 1

delayNOP()

LCD_EN = 0

}

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

/* */

/*写显示数据到LCD*/

/*RS=H,RW=L,E=高脉冲,D0-D7=数据。 */

/* */

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

void lcd_wdat(uchar dat)

{

while(lcd_busy())

LCD_RS = 1

LCD_RW = 0

LCD_EN = 0

P0 = dat

delayNOP()

LCD_EN = 1

delayNOP()

LCD_EN = 0

}

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

/* */

/* LCD初始化设定*/

/* */

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

void init_lcd()

{

delay1(15)

lcd_wcmd(0x01) //清除LCD的显示内容

lcd_wcmd(0x38) //16*2显示,5*7点阵,8位数据

delay1(5)

lcd_wcmd(0x38)

delay1(5)

lcd_wcmd(0x38)

delay1(5)

lcd_wcmd(0x0c) //显示开,关光标

delay1(5)

lcd_wcmd(0x06) //移动光标

delay1(5)

lcd_wcmd(0x01) //清除LCD的显示内容

delay1(5)

}

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

//

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

void delay()

{

uchar j

for(j=250j>0j--)

}

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

/* */

/* 写字符串函数 */

/* */

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

void write_str(uchar addr,uchar *p)

{

uchar i=0

lcd_wcmd(addr)

while(p[i]!='\0')

{

lcd_wdat(p[i])

i++

}

}

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

/* */

/* 设定显示位置 */

/* */

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

void write_position(uchar row,uchar col)

{

uchar place

if(row==1)

{

place=0x80+col-1

lcd_wcmd(place)

}

else

{

place=0xc0+col-1

lcd_wcmd(place)

}

}

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

/* */

/*自定义字符写入CGRAM*/

/* */

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

void writetab()

{

unsigned char i

lcd_wcmd(0x40) //写CGRAM

for (i = 0i<8i++)

lcd_wdat(mytab[i])

}

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

//

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

void write_byte(uchar inbyte)

{

uchar i

for(i=0i<8i++)

{

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=0i<7i++)

{

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>0n--)

{

write_ds1302(addr,*p)

p++

addr=addr+2

}

write_ds1302(0x8e,0x80) //写保护,不允许写

}

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

// 读取当前时间

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

void read_nowtime(uchar addr,uchar *p,uchar n)

{

for(n>0n--)

{

*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(0x8e,0x80)//写保护控制字,禁止写

}

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

/**/

/* 蜂鸣器响一声 */

/**/

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

void beep()

{

unsigned char y

for (y=0y<100y++)

{

delay()

BEEP=!BEEP //BEEP取反

}

BEEP=1 //关闭蜂鸣器

delay1(50)

}

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

/**/

/* :闪动函数 */

/**/

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

void flash()

{

if(flag)

{

write_position(2,9)

lcd_wdat(':')

write_position(2,12)

lcd_wdat(':')

}

else

{

write_position(2,9)

lcd_wdat(0x20)

write_position(2,12)

lcd_wdat(0x20)

}

}

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

// 主函数

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

void main()

{

LCD_LED=0

P1=0xff

TMOD=0x01

TH0=0x4c //50ms定时

TL0=0x00

EA=1

ET0=1

TR0=1

init_lcd()//初始化LCD

write_str(0x80,str1) //液晶显示提示信息

write_str(0xc0,str2) //液晶显示提示信息

init_ds1302() //初始化ds1302

writetab() //自定义字符写入CGRAM

// delay1(5)

// write_position(2,16)

// lcd_wdat(0x00) //显示自定义字符小喇叭

while(1)

{

//---------------------------------------------------------

if(!K1)

{

if(!K2)

{

set_ds1302(0x80,init2,7) //设置初始时间,日期,年月

beep()

}

if(!K3)

{

write_str(0xc0,str3) //显示报警信息

if(alarm_flag) //alarm_flag=1,开定时

{

write_position(2,16)

lcd_wdat(0x00) //显示自定义字符小喇叭

}

Play_alarmtime() //查看报警时间

beep()

delay1(700)

write_str(0xc0,str2) //显示时间信息

if(alarm_flag) //alarm_flag=1,开定时

{

write_position(2,16)

lcd_wdat(0x00) //显示自定义字符小喇叭

}

}

if(!K4)

{

alarm_time()//K4键设定报警时间

if(alarm_flag) //alarm_flag=1,开定时

{

write_position(2,16)

lcd_wdat(0x00) //显示自定义字符小喇叭

}

}

}

//---------------------------------------------------------

if(!K4)

{

beep()

alarm_flag=~alarm_flag

if(alarm_flag) //alarm_flag=1,开定时

{

write_position(2,16)

lcd_wdat(0x00) //显示自定义字符小喇叭

}

else

{

write_position(2,16)

lcd_wdat(0x20) //显示自定义字符小喇叭

}

}

//---------------------------------------------------------

if(!K3&flag) //开始设定时间

{

write_ds1302(0x8e,0x00) //写保护控制字,允许写

write_ds1302(0x80,0x80) //停止时钟运行

write_ds1302(0x8e,0x80) //写保护控制字,禁止写

beep()

year=1

count=((init[6]&0xf0)>>4)*10+(init[6]&0x0f) //读当前年数据

}

while(year) //设定年

{

key_set(99,1,1)

if(!K3)

{

Set_W1302(0x8c)

Set_place(1,1)

year=0

month=1

count=((init[4]&0xf0)>>4)*10+(init[4]&0x0f) //读当前月数据

}

}

while(month) //设定月

{

key_set(12,1,4)

if(!K3)

{

Set_W1302(0x88)

Set_place(1,4)

month=0

day=1

count=((init[3]&0xf0)>>4)*10+(init[3]&0x0f)//读当前日数据

}

}

while(day) //设定日

{

key_set(31,1,7)

if(!K3)

{

Set_W1302(0x86)

Set_place(1,7)

day=0

week=1

count=init[5]&0x0f //读当前星期数据

}

}

while(week) //设定星期

{

if(!K2)

{

beep()

if(count!=7)

count++

else count=1

}

if(!K1)

{

beep()

if(count!=1)

count--

else count=7

}

init1[1]=count%10

if(flag)

{

write_position(1,15)

lcd_wdat(init1[1]+0x30)

}

else

{

write_position(1,15)

lcd_wdat(0x20)

}

if(!K3)

{

Set_W1302(0x8a)

write_position(1,15)

lcd_wdat(init1[1]+0x30)

week=0

hour=1

count=((init[2]&0xf0)>>4)*10+(init[2]&0x0f)//读当前时数据

}

}

while(hour) //设定时

{

key_set(23,2,7)

if(!K3)

{

Set_W1302(0x84)

Set_place(2,7)

hour=0

min=1

count=((init[1]&0xf0)>>4)*10+(init[1]&0x0f)//读当前分数据

}

}

while(min)//设定分

{

key_set(59,2,10)

if(!K3)

{

Set_W1302(0x82)

Set_place(2,10)

min=0

sec=1

count=((init[0]&0xf0)>>4)*10+(init[0]&0x0f) //读当前秒数据

}

}

while(sec)//设定秒

{

key_set(59,2,13)

if(!K3)

{

Set_W1302(0x80)

Set_place(2,13)

sec=0

count=0

}

}

Play_nowtime()

Time_compare()

}

}

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

// Time0中断函数

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

void Time0(void) interrupt 1 using 0

{

TH0=0x4c//50ms定时

TL0=0x00

timecount++

if(timecount>9)

{

timecount=0

flag=~flag

}

}

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

// 设定值写入DS1302

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

void Set_W1302(uchar addr)

{

uchar temp

write_ds1302(0x8e,0x00)

temp=(init1[0]<<4)+init1[1]

write_ds1302(addr,temp)

write_ds1302(0x8e,0x80)

beep()

}

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

// 被设置数据闪动

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

void Set_Flash(uchar row,uchar col )

{

init1[0]=count/10

init1[1]=count%10

if(flag)

{//显示

write_position(row,col)

lcd_wdat(init1[0]+0x30)

write_position(row,col+1)

lcd_wdat(init1[1]+0x30)

}

else

{//清屏

write_position(row,col)

lcd_wdat(0x20)

write_position(row,col+1)

lcd_wdat(0x20)

}

}

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

// 指定位置显示

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

void Set_place(uchar row,uchar col)

{

write_position(row,col)

lcd_wdat(init1[0]+0x30)

write_position(row,col+1)

lcd_wdat(init1[1]+0x30)

}

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

// 显示当前时间

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

void Play_nowtime()

{

read_nowtime(0x81,init,7) //读出当前时间,读出7个字节

write_position(2,7)

lcd_wdat(((init[2]&0xf0)>>4)+0x30)

write_position(2,8)

lcd_wdat('0'+(init[2]&0x0f))//读小时

//write_position(2,9)

//lcd_wdat(':')

write_position(2,10)

lcd_wdat('0'+((init[1]&0xf0)>>4))

write_position(2,11)

lcd_wdat('0'+(init[1]&0x0f))//读分钟

//write_position(2,12)

//lcd_wdat(':')

write_position(2,13)

lcd_wdat('0'+((init[0]&0xf0)>>4))

write_position(2,14)

lcd_wdat('0'+(init[0]&0x0f))//读秒

write_position(1,1)

lcd_wdat('0'+((init[6]&0xf0)>>4))

write_position(1,2)

lcd_wdat('0'+(init[6]&0x0f))//读年

//write_position(1,3)

//lcd_wdat('/')

write_position(1,4)

lcd_wdat('0'+((init[4]&0xf0)>>4))

write_position(1,5)

lcd_wdat('0'+(init[4]&0x0f))//读月

//write_position(1,6)

//lcd_wdat('/')

write_position(1,7)

lcd_wdat('0'+((init[3]&0xf0)>>4))

write_position(1,8)

lcd_wdat('0'+(init[3]&0x0f))//读日

write_position(1,15)

lcd_wdat('0'+(init[5]&0x0f))//读周

flash()

}

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

// 键设定函数

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

void key_set(uchar num,uchar row,uchar col )

{

if(!K2)

{

beep()

if(count!=num)

count++

else count=0

}

if(!K1)

{

beep()

if(count!=0)

count--

else count=num

}

Set_Flash(row,col)

}

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

// 报警时间设定

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

void alarm_time()

{

// if(!K4&flag) //开始设定报警时间

{

write_str(0xc0,str3) //液晶显示提示信息

Play_alarmtime()

beep()

hour=1

count=((bj_time[2]&0xf0)>>4)*10+(bj_time[2]&0x0f) //读当前时报警数据

while(hour) //设定时

{

key_set(23,2,7)

if(!K4)

{

Set_place(2,7)

bj_time[2]=((init1[0]<<4)|init1[1])

beep()

hour=0

min=1

count=((bj_time[1]&0xf0)>>4)*10+(bj_time[1]&0x0f)//读当前分报警数据

}

}

while(min) //设定分

{

key_set(59,2,10)

if(!K4)

{

Set_place(2,10)

bj_time[1]=((init1[0]<<4)|init1[1])

beep()

min=0

sec=0

count=((bj_time[0]&0xf0)>>4)*10+(bj_time[0]&0x0f)//读当前秒报警数据

write_str(0xc0,str2) //液晶显示提示信息

}

}

/*

while(sec) //设定秒

{

key_set(59,2,13)

if(!K4)

{

Set_place(2,13)

bj_time[0]=((init1[0]<<4)|init1[1])

beep()

min=0

sec=0

count=0

write_str(0xc0,str2) //液晶显示提示信息

}

}*/

}

}

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

// 报警时间显示

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

void Play_alarmtime()

{

write_position(2,7)

lcd_wdat(((bj_time[2]&0xf0)>>4)+0x30)

write_position(2,8)

lcd_wdat('0'+(bj_time[2]&0x0f))//读小时

write_position(2,9)

lcd_wdat(':')

write_position(2,10)

lcd_wdat('0'+((bj_time[1]&0xf0)>>4))

write_position(2,11)

lcd_wdat('0'+(bj_time[1]&0x0f))//读分钟

write_position(2,12)

lcd_wdat(':')

write_position(2,13)

lcd_wdat('0'+((bj_time[0]&0xf0)>>4))

write_position(2,14)

lcd_wdat('0'+(bj_time[0]&0x0f))//读秒

}

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

// 时间比较

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

void Time_compare()

{

if(alarm_flag)

{

if(init[2]==bj_time[2])

{

if(init[1]==bj_time[1])

beep()

}

}

}

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


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12441247.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存