求lm016l与ds1302 52 单片机实现时钟显示的程序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求lm016l与ds1302 52 单片机实现时钟显示的程序相关的知识,希望对你有一定的参考价值。

参考技术A #define LCM_RW P2^4 //定义引脚
#define LCM_RS P2^3
#define LCM_E P2^5
#define LCM_Data P0
#define Busy 0x80 //用于检测LCM状态字中的Busy标识
#include <reg52.h>
void WriteDataLCM (unsigned char WDLCM);
void WriteCommandLCM (unsigned char WCLCM,BuysC);
void DisplayOneChar (unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar (unsigned char X, unsigned char Y, unsigned char code *DData);
unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);

void pro_timedate(void);
bit leap_year(); //判断是否为闰年
unsigned char data year=11,month=5,date=22;//年、月、日、星期
unsigned char disbuf[16];
unsigned char data hour=23,min=59,sec=55,sec20=0; //时、分、秒、百分之一秒
unsigned char code email[] = "YEA:MON:DAT:TIME";
void updatetime (void);
void LCMInit (void);
void pro_display(void);
void Delay400Ms (void);
void Delay5Ms (void);
void main(void)

Delay400Ms(); //启动等待,等LCM讲入工作状态
LCMInit(); //LCM初始化
DisplayListChar(0, 1, email);
TMOD=0X01;
TH0=0X4C;
TL0=0X00;
TR0=1;
ET0=1;
EA=1;
while(1);


void pro_timedate()

sec++;
if(sec > 59)
sec = 0;
min++;
if(min>59)
min=0;
hour++;
if(hour>23)
hour=0;
date++;
if (month==1||month==3||month==5||month==7||month==8||month==10||month==12)
if (date>31)
date=1;month++; //大月31 天
if (month==4||month==6||month==9||month==11)
if (date>30)
date=1;month++; //小月30 天
if (month==2)
if( leap_year()) //闰年的条件
if (date>29) date=1;month++; //闰年2 月为29 天
else
if (date>28) date=1;month++; //平年2 月为28 天

if (month>12) month=1;year++;
if (year>99) year=0;






bit leap_year()

bit leap;
if((year%4==0&&year%100!=0)||year%400==0)//闰年的条件
leap=1;
else
leap=0;
return leap;

//Timer0 中断处理程序,秒的产生
void timer0() interrupt 1

TH0=0x4C; //Timer0 置10ms 定时初值dc00H(2^16=65536D,dc00H=56320D)
TL0=0x00; //定时时间=(65536-56320)*(1/11.0592)*12=10ms (f0=11.0592Mhz)
sec20++;
if(sec20 >= 20) //1 秒时间 (100*10ms=1000ms=1s)
sec20=0;
updatetime ();
pro_timedate();
pro_display ();
if(sec&0x01)
disbuf[13]=' ';
else disbuf[13]=':';



void updatetime(void)
disbuf[0] ='2';
disbuf[1] ='0';
disbuf[2] =year/10+48;
disbuf[3] =year%10+48;
disbuf[4] =' ';
disbuf[5] =month/10+48;
disbuf[6] =month%10+48;
disbuf[7] ='.';
disbuf[8] =date/10+48;
disbuf[9] =date%10+48;
disbuf[10] =' ';
disbuf[11]=hour/10+48;
disbuf[12]=hour%10+48;
//disbuf[13]=' ';
disbuf[14]=min/10+48;
disbuf[15]=min%10+48;

//显示处理程序
void pro_display()
unsigned char f;
for (f=0;f<=15;f++)
DisplayOneChar( f, 0, disbuf[f]);


//写数据
void WriteDataLCM(unsigned char WDLCM)

ReadStatusLCM(); //检测忙
//WDLCM = ((WDLCM&0x01)<<7)|((WDLCM&0x02)<<5)|((WDLCM&0x04)<<3)|((WDLCM&0x08)<<1)|((WDLCM&0x10)>>1)|((WDLCM&0x20)>>3)|((WDLCM&0x40)>>5)|((WDLCM&0x80)>>7);
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0; //延时
LCM_E = 1;


//写指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测

if (BuysC) ReadStatusLCM(); //根据需要检测忙
//WCLCM = ((WCLCM&0x01)<<7)|((WCLCM&0x02)<<5)|((WCLCM&0x04)<<3)|((WCLCM&0x08)<<1)|((WCLCM&0x10)>>1)|((WCLCM&0x20)>>3)|((WCLCM&0x40)>>5)|((WCLCM&0x80)>>7);
LCM_Data = WCLCM;

LCM_RS = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;


//读数据
unsigned char ReadDataLCM(void)

LCM_RS = 1;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
return(LCM_Data);


//读状态
unsigned char ReadStatusLCM(void)

LCM_Data = 0xFF;
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
while (LCM_Data & Busy); //检测忙信号
return(LCM_Data);


void LCMInit(void) //LCM初始化

LCM_Data = 0;
WriteCommandLCM(0x38,0);

1

//三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();

WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
WriteCommandLCM(0x08,1); //关闭显示
WriteCommandLCM(0x01,1); //显示清屏
WriteCommandLCM(0x06,1); // 显示光标移动设置
WriteCommandLCM(0x0C,1); // 显示开及光标设置


//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)

Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; //算出指令码
WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码
WriteDataLCM(DData);

//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)

unsigned char ListLength;
ListLength = 0;
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
while (DData[ListLength]>0x20) //若到达字串尾则退出

if (X <= 0xF) //X坐标应小于0xF

DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
ListLength++;
X++;



//50ms延时
void Delay5Ms(void)

unsigned int TempCyc = 5552;
while(TempCyc--);


//400ms延时
void Delay400Ms(void)

unsigned char TempCycA = 5;
unsigned int TempCycB;
while(TempCycA--)

TempCycB=7269;
while(TempCycB--);
;
参考技术B lm016?是仿真中的1602吧?有的,咋给你?追问

发我邮箱吧 834981490@qq.com

本回答被提问者采纳

8051单片机Proteus仿真与开发实例-DS1302 RTC驱动仿真

DS1302 RTC驱动仿真

1、DS1302介绍

DS1302 涓流充电计时芯片包含一个实时时钟/日历和 31 字节的静态 RAM。它通过一个简单的串行接口与微处理器通信。实时时钟/日历提供秒、分、小时、日、日、月和年信息。对于少于 31 天的月份,月末日期会自动调整,包括闰年的更正。时钟以 24 小时或 12 小时格式运行,带有 AM/PM 指示器。

通过使用同步串行通信简化了 DS1302 与微处理器的接口。与时钟/RAM 通信只需要三根线:CE( R S T \\over RST RST)、I/O(数据线)和 SCLK(串行时钟)。数据可以一次 1 个字节或最多 31 个字节的突发传输到时钟/RAM 或从时钟/RAM 传输。 DS1302 旨在以极低的功耗运行,并以低于 1µW 的功率保留数据和时钟信息。 DS1302 是 DS1202 的后继产品。除了 DS1202 的基本计时功能外,DS1302 还具有用于主电源和备用电源的双电源引脚、用于 VCC1 的可编程涓流充电器和七个额外字节的暂存器存储器的附加功能。

1)DS1302的命令组成

  • Bit7 必须始终为逻辑 1。否则写入 DS1302 将被禁用。
  • Bit6 指定时钟/日历或 RAM 选择。 如果它是 logic0 我们与时钟交谈,或者如果它是 logic1 我们与 RAM 交谈。
  • 位 5 至 1 指定要输入或输出的指定寄存器。 (地址)
  • Bit0 指定对 DS1302 的写或读操作。 如果是逻辑 0 则执行写操作,如果是逻辑 1 则执行读操作。
  • 命令字节总是从 LSB 开始(Bit0)。

2)DS1302数据传输过程

  • 在开始传输任何内容之前,必须将 CE 引脚拉高,以便与芯片通话。 (选择)

  • 之后,发送命令字节,通知 DS1302 将进行的操作。 (无论是读还是写,对时钟还是 RAM。)

  • 然后,如果执行写操作,则将要写入的数据发送到 RAM 或时钟中,或者如果执行读操作,则可以
    从时钟或 RAM 中读取数据。

如果从 DS1302 读取数据,则在写入命令字节的最后一位后的第一个下降沿上,数据将可用。相反,写入 DS1302 发生在命令字节传输后的低电平到高电平转换。要记住的四个注意事项,是所有发送和接收字节都是 LSB 优先,在命令字节和数据字节之后的写操作中发送到 DS1302 的附加 SCLK 脉冲将被忽略。

读取操作后立即发送的附加 SCLK 脉冲,数据将再次可供读取。最后,当与 DS1302 通信时,微控制器的时钟应处于 2MHZ 的最大速度,如下面的数据表所示。如果使用不同的速度,那么必须校准频率以满足 DS1302 的需要,并将其重新校准为之前的频率。

3)DS1302设置

DS1302的寄存器如下:

从左边开始,前两列是指命令字节。 是否要读取或写入 RTC 或 RAM。从 (bit7 到 bit0) 的列是指它将在 RTC 或 RAM 中传输的数据字节。

2、仿真电路原理图

3、仿真代码实现

1)发送数据

// 发送一位节数据
void ds1302_send(unsigned char byte_t) {	
	unsigned char mask = 0x01;				

	IO_OUT(DS1302_DDR, DS1302_SIO);			
	do {
		IO_CLR(DS1302_PORT, DS1302_SCK);		
		if (byte_t & mask) IO_SET(DS1302_PORT, DS1302_SIO);	
		else IO_CLR(DS1302_PORT, DS1302_SIO);				
		IO_SET(DS1302_PORT, DS1302_SCK);	
		mask = mask << 1;					
	} while (mask);
	IO_CLR(DS1302_PORT, DS1302_SCK);
}

// 向指定寄存写数据
void ds1302_write(unsigned char ch, unsigned char byte_t) {
	ds1302_select(DS1302_CS);				
	ds1302_send(ch | DS1302_CMD_WRITE);		
	ds1302_send(byte_t);
	ds1302_deselect(DS1302_CS);				
}

2)读数据

// 读取一位数据
unsigned char ds1302_get(void) {			
	unsigned char mask = 0x01;				
	unsigned char tmp = 0x00;				

	IO_IN(DS1302_DDR, DS1302_SIO);			
	do {
		IO_CLR(DS1302_PORT, DS1302_SCK);	
		NOP(); NOP();
		if (DS1302_PORT_IN & DS1302_SIO) tmp |= mask;	
		else tmp |= 0x00;					
		IO_SET(DS1302_PORT, DS1302_SCK);	
		mask = mask << 1;					
	} while (mask);
	IO_CLR(DS1302_PORT, DS1302_SCK);
	return tmp;
}

// 读指定寄存器数据
unsigned char ds1302_read(unsigned char ch) {
	unsigned char tmp;
	ds1302_select(DS1302_CS);				
	ds1302_send(ch | DS1302_CMD_READ);		
	tmp = ds1302_get();
	ds1302_deselect(DS1302_CS);				
	return tmp;				
}

3)年、月、日、时、分秒设置与读取

// 秒设置与读取
#define ds1302_sec_write(n)					ds1302_write(DS1302_SEC, (n))	
#define ds1302_sec_read()					ds1302_read(DS1302_SEC)	

// 分设置与读取
#define ds1302_min_write(n)					ds1302_write(DS1302_MIN, (n))	
#define ds1302_min_read()					ds1302_read(DS1302_MIN)			

// 时设置与读取
#define ds1302_hour_write(n)				ds1302_write(DS1302_HOUR, (n))
#define ds1302_hour_read()					ds1302_read(DS1302_HOUR)		

// 一个月的日设置与读取
#define ds1302_mdat_write(n)				ds1302_write(DS1302_MDAT, (n))	
#define ds1302_mdat_read()					ds1302_read(DS1302_MDAT)		

// 月读取与设置
#define ds1302_mon_write(n)					ds1302_write(DS1302_MON, (n))	
#define ds1302_mon_read()					ds1302_read(DS1302_MON)			

// 一周的日设置与读取
#define ds1302_wday_write(n)				ds1302_write(DS1302_WDAY, (n))
#define ds1302_wday_read()					ds1302_read(DS1302_WDAY)

// 年的设置与读取
#define ds1302_year_write(n)				ds1302_write(DS1302_YEAR, (n))
#define ds1302_year_read()					ds1302_read(DS1302_YEAR)

4)主程序

//#include <regx52.h>							//we use keil c51
#include "gpio.h"
#include "delay.h"
#include "ds1302.h"
#include "uart.h"
#include "i2c_sw.h"
#include <stdio.h>

unsigned int year,month,day,hours,minutes,seconds;

void mcu_init(void) {
	uart_init();
	ds1302_init();
	// 初始读取
	year = ds1302_year_read();
  month = ds1302_mon_read();
  day = ds1302_mdat_read();
  hours = ds1302_hour_read();
  minutes = ds1302_min_read();
  seconds = ds1302_sec_read();
}

int main(void) {
	mcu_init();								//reset the mcu
	uart_send_str("****DS1302****\\r\\n");
	while (1) {
		year = ds1302_year_read();
    month = ds1302_mon_read();
    day = ds1302_mdat_read();
    hours = ds1302_hour_read();
    minutes = ds1302_min_read();
    seconds = ds1302_sec_read();
		
		printf("%d-%d-%d %d:%d:%d\\r\\n",BCD2DEC(year),BCD2DEC(month),BCD2DEC(day),BCD2DEC(hours),BCD2DEC(minutes),BCD2DEC(seconds));
		
		delay_ms(1000);
	}
}

4、仿真结果

以上是关于求lm016l与ds1302 52 单片机实现时钟显示的程序的主要内容,如果未能解决你的问题,请参考以下文章

51单片机+74HC595联级+DS1302简易时钟+Proteus仿真

单片机课程设计——《基于AT89S52单片机和DS1302时钟芯片的电子时钟(可蓝牙校准)》

51单片机+ds1302+lcd1602简易电子时钟(带闹钟功能)

ds1302时钟芯片。。。谁给我看下这个程序?液晶可以显示,但是时钟不会走显示的也不是我初始化的时间。

51单片机+DS1302+LCD1602时钟示例+ Proteus仿真

51单片机+DS1302+LCD1602+DS18B20时钟示例+ Proteus仿真