求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时钟芯片。。。谁给我看下这个程序?液晶可以显示,但是时钟不会走显示的也不是我初始化的时间。