您的位置:首页 > 其它

proteus仿真之DS1302+LCD1602显示试验

2014-02-17 15:24 495 查看
proteus仿真之DS1302+LCD1602显示试验

仿真效果图为:



C语言源程序如下:

/*

51单片机:DS1302+LCD1602 Proteus 仿真程序。

功能:LCD1602时钟与日期的显示。

仿真结果:LCD1602显示设定的时间与日期。

*/

#include <reg52.h>

/**********LCD1602接口程序**********/

#define LCD_PORT
P1 //液晶LCD1602数据

sbit RS = P2^4;

sbit RW = P2^5;

sbit E = P2^6;

char data str1[16]="Date: ";

char data str2[16]="Time: ";

sbit SCK = P3^6; // DS1302时钟线

sbit SDA = P3^4; // DS1302数据线

sbit RST = P3^5; // DS1302复位线

//DS1302 复位重定义

#define RST_CLR RST=0
//电平置低

#define RST_SET RST=1
//电平置高

//DS1302 数据

#define SDA_CLR SDA=0
//电平置低

#define SDA_SET SDA=1
//电平置高

#define SDA_RD SDA
//电平读取

//DS1302 时钟

#define SCK_CLR SCK=0
//时钟信号

#define SCK_SET SCK=1
//电平置高

#define DS1302_SEC 0x80
//秒数据地址

#define DS1302_MIN 0x82
//分数据地址

#define DS1302_HOUR 0x84
//时数据地址

#define DS1302_DATE 0x86
//日数据地址

#define DS1302_MON 0x88
//月数据地址

#define DS1302_DAY 0x8a
//星期数据地址

#define DS1302_YEAR 0x8c
//年数据地址

#define DS1302_CTRL 0x8e
//控制数据地址

#define DS1302_CHARGE 0x90
//涓流充电

bit ReadRTC_Flag;
//读DS1302标志。1为读 0为不读。

unsigned char time_buf1[8] = {40,14,2,16,23,59,50,7};
// -年月日时分秒周 2014-02-14 10:59:50 7周

unsigned char time_buf[8] ;
// -年月日时分秒周

void DS1302_Init(void);

void DS1302_Write_Byte(unsigned char addr, unsigned char d);

unsigned char DS1302_Read_Byte(unsigned char addr) ;

void DS1302_Read_Time(void);

void DS1302_Write_Time(void);

void InitTIMER0(void);//inital timer0

void Delay_1ms(unsigned char i);

void Delay_10us(unsigned char i);

void Write_Cmd(unsigned char cmd);

void Write_Dat(unsigned char dat);

void Addr_x_y(unsigned char x,bit y);

void Show_Char(unsigned char x,bit y,unsigned char p);

void Show_String(unsigned char x,bit y,char *ptr);

void LCD_Init(void);

void main(void)

{

LCD_Init();

DS1302_Init();

DS1302_Write_Time();

InitTIMER0();

//P2=0xff; //51默认为输入

while(1)

{

if(ReadRTC_Flag==1)

{

ReadRTC_Flag=0;

DS1302_Read_Time();

}

str1[5]=time_buf1[1]/10 + '0';
//年 数据的转换,

str1[6]=time_buf1[1]%10 + '0';
//因我们采用数码管0~9的显示,将数据分开

str1[7]=0x2d;
//加入"-"

str1[8]=time_buf1[2]/10 + '0';
//月

str1[9]=time_buf1[2]%10 + '0';

str1[10]=0x2d;

str1[11]=time_buf1[3]/10 + '0';
//日

str1[12]=time_buf1[3]%10 + '0';

str1[13]=0x20;

str1[14]='W';

str1[15]=time_buf1[7] + '0';
//周几

str2[5]=time_buf1[4]/10 + '0';
//时 数据的转换,

str2[6]=time_buf1[4]%10 + '0';
//因我们采用数码管0~9的显示,将数据分开

str2[7]=0x3a;
//加入"-"

str2[8]=time_buf1[5]/10 + '0';
//分

str2[9]=time_buf1[5]%10 + '0';

str2[10]=0x3a;

str2[11]=time_buf1[6]/10 + '0';
//秒

str2[12]=time_buf1[6]%10 + '0';

Show_String(0,0,str1);

Show_String(0,1,str2);

}

}

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

void Delay_1ms(unsigned char i) //最小延时1ms

{

unsigned char j;

while(i--)

for(j=0;j<125; j++);

}

void Delay_10us(unsigned char i) //最小延时10us

{

unsigned char j;

while(i--)

for(j=0;j<10; j++);

}

void Write_Cmd(unsigned char cmd) //写指令

{

Delay_10us(5);

E=0;

RS=0;

RW=0;

LCD_PORT = cmd;

Delay_10us(5); //>40us

E=1;

Delay_1ms(2); //>150us

E=0;

Delay_10us(4); //>25+10us

}

void Write_Dat(unsigned char dat) //写数据

{

Delay_10us(5);

E=0;

RS=1;

RW=0;

LCD_PORT = dat;

Delay_10us(5);

E=1;

Delay_10us(5);

E=0;

Delay_10us(4);

}

void Addr_x_y(unsigned char x,bit y) //写坐标,定位置

{

unsigned char temp=0x80;
//默认最高位:D7为1 即以0x80开始。

if(y) //y :0为第一行 1为第二行

{

temp|=0x40;

}

temp|=x;

Write_Cmd(temp);

}

void Show_Char(unsigned char x,bit y,unsigned char p)

//在指定位置显示一个字符。

{

Addr_x_y(x,y);

Write_Dat(p);

}

void Show_String(unsigned char x,bit y,char *ptr)

{

unsigned char i;

for (i=0;i<16;i++)

Show_Char(x++,y,*(ptr+i));//循环显示16个字符

}

void LCD_Init(void) //1602初始化代码

{

Delay_1ms(1500);

Write_Cmd(0x38);

Delay_1ms(5);

Write_Cmd(0x38);

Delay_1ms(5);

Write_Cmd(0x38);

Delay_1ms(5);

Write_Cmd(0x38);

Write_Cmd(0x08);

Write_Cmd(0x06);

Write_Cmd(0x0c);

Write_Cmd(0x01);

}

/*------------------------------------------------

DS1302初始化

------------------------------------------------*/

void DS1302_Init(void)

{

RST_CLR;
//RST脚置低

SCK_CLR;
//SCK脚置低

DS1302_Write_Byte(DS1302_SEC,0x00);

}

/*------------------------------------------------

向DS1302写入一字节数据

------------------------------------------------*/

void DS1302_Write_Byte(unsigned char addr, unsigned char dat)

{

unsigned char i;

RST_SET;

addr = addr & 0xFE; //写地址 最低位为W写,低电平

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

{

if (addr & 0x01)

{

SDA_SET;

}

else

{

SDA_CLR;

}

SCK_SET;

SCK_CLR;

addr = addr >> 1;

}

//写入数据:dat

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

{

if (dat & 0x01)

{

SDA_SET;

}

else

{

SDA_CLR;

}

SCK_SET;

SCK_CLR;

dat = dat >> 1;

}

RST_CLR;
//停止DS1302总线

}

/*------------------------------------------------

从DS1302读出一字节数据

------------------------------------------------*/

unsigned char DS1302_Read_Byte(unsigned char addr)

{

unsigned char i;

unsigned char temp;

RST_SET;

addr = addr | 0x01;
//最低RD,有效为高电平

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

{

if (addr & 0x01)

{

SDA_SET;

}

else

{

SDA_CLR;

}

SCK_SET;

SCK_CLR;

addr = addr >> 1;

}

//输出数据:temp

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

{

temp = temp >> 1;

if (SDA_RD)

{

temp |= 0x80;

}

else

{

temp &= 0x7F;

}

SCK_SET;

SCK_CLR;

}

RST_CLR;
//停止DS1302总线

return temp;

}

/*------------------------------------------------

从DS1302读出时钟数据

------------------------------------------------*/

void DS1302_Read_Time(void)

{

unsigned char i,tmp;

time_buf[1]=DS1302_Read_Byte(DS1302_YEAR);
//年

time_buf[2]=DS1302_Read_Byte(DS1302_MON);
//月

time_buf[3]=DS1302_Read_Byte(DS1302_DATE);
//日

time_buf[4]=DS1302_Read_Byte(DS1302_HOUR);
//时

time_buf[5]=DS1302_Read_Byte(DS1302_MIN);
//分

time_buf[6]=(DS1302_Read_Byte(DS1302_SEC))&0x7F;//秒

time_buf[7]=DS1302_Read_Byte(DS1302_DAY);
//周

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

{ //BCD处理

tmp=time_buf[i]/16;

time_buf1[i]=time_buf[i]%16;

time_buf1[i]=time_buf1[i]+tmp*10;

}

}

/*------------------------------------------------

向DS1302写入时钟数据

------------------------------------------------*/

void DS1302_Write_Time(void)

{

unsigned char i,tmp;

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

{ //BCD处理

tmp=time_buf1[i]/10;

time_buf[i]=time_buf1[i]%10;

time_buf[i]=time_buf[i]+tmp*16;

}

DS1302_Write_Byte(DS1302_CTRL,0x00);
//关闭写保护

DS1302_Write_Byte(DS1302_SEC,0x80);
//暂停

//DS1302_Write_Byte(DS1302_CHARGE,0xa9);
//涓流充电

DS1302_Write_Byte(DS1302_YEAR,time_buf[1]);
//年

DS1302_Write_Byte(DS1302_MON,time_buf[2]);
//月

DS1302_Write_Byte(DS1302_DATE,time_buf[3]);
//日

DS1302_Write_Byte(DS1302_HOUR,time_buf[4]);
//时

DS1302_Write_Byte(DS1302_MIN,time_buf[5]);
//分

DS1302_Write_Byte(DS1302_SEC,time_buf[6]);
//秒

DS1302_Write_Byte(DS1302_DAY,time_buf[7]);
//周

DS1302_Write_Byte(DS1302_CTRL,0x80);
//打开写保护

}

/*------------------------------------------------

Timer0 初始化,开中断,2ms定时

------------------------------------------------*/

void InitTIMER0(void)

{

TMOD|=0x01;
//定时器设置 16位

TH0=(65536-2000)/256;
//定时时间 2ms

TL0=(65536-2000)%256;

EA=1;

ET0=1;

TR0=1;

}

void tim0_isr(void) interrupt 1 // timer0 中断

{

static unsigned char num;

TH0=(65536-2000)/256;
//重新赋值 2ms

TL0=(65536-2000)%256;

num++;

if(num==50) //大致100ms

{

num=0;

ReadRTC_Flag=1; //读标志位置1

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: