51综合程序05-LCD12864相关应用

一、LCD12864显示图形

1. 仿真电路图

在这里插入图片描述

2. 源代码

LCD12864.h

#ifndef LCD12864
#define LCD12864

#include <intrins.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <absacc.h>
#include <string.h>


#define STX 0x02
#define ETX 0x03
#define EOT 0x04
#define ENQ 0x05
#define BS  0x08
#define CR  0x0d
#define LF  0x0a
#define DLE 0x10
#define ETB 0x17
#define SPACE 0x20
#define COMMA 0x2c

#define TRUE 1
#define FALSE 0
#define HIGH 1
#define LOW 0

#define LCMDW XBYTE[0x8000]
#define LCMCW XBYTE[0x8100]

//显示内存分配
#define DISRAM_SIZE 0X7FFF  //设置显示ram的大小
#define TXTSTART    0x0000  //设置文本区的起始地址
#define GRSTART     0x6800  //设置图形区的起始地址
#define CGRAMSTART  0x7800  //设置CGRAM的起始地址

//T6963C 命令定义
#define LC_CUR_POS  0x21    //光标位置设置
#define LC_CGR_POS  0x22    //CGRAM偏置地址设置
#define LC_ADD_POS  0x24    //地址指针位置
#define LC_TXT_STP  0x40    //文本区首址
#define LC_TXT_WID  0x41    //文本区宽度
#define LC_GRH_STP  0x42    //图形区首址
#define LC_GRH_WID  0x43    //图形区宽度
#define LC_MOD_OR   0x80    //显示方式:逻辑或
#define LC_MOD_XOR  0x81    //显示方式:逻辑异或
#define LC_MOD_AND  0x82    //显示方式:逻辑与
#define LC_MOD_TCH  0x83    //显示方式:文本特征
#define LC_DIS_SW   0x90    //显示开关:
                            //D0=1/0:光标闪烁启用/禁用;
					 	    //D1=1/0:光标显示启用/禁用;
					 	    //D2=1/0:文本显示启用/禁用;
					 	    //D3=1/0:图形显示启用/禁用;
#define LC_CUR_SHP  0xA0    //光标形状选择:0xA0-0xA7表示光标占的行数
#define LC_AUT_WR   0xB0    //自动写设置
#define LC_AUT_RD   0xB1    //自动读设置
#define LC_AUT_OVR  0xB2    //自动读/写结束
#define LC_INC_WR   0xC0    //数据写,地址加1
#define LC_INC_RD   0xC1    //数据读,地址加1
#define LC_DEC_WR   0xC2    //数据写,地址减1
#define LC_DEC_RD   0xC3    //数据读,地址减1
#define LC_NOC_WR   0xC4    //数据写,地址不变
#define LC_NOC_RD   0xC5    //数据读,地址不变
#define LC_SCN_RD   0xE0    //屏读
#define LC_SCN_CP   0xE8    //屏拷贝
#define LC_BIT_OP   0xF0    //位操作:D0-D2:定义D0-D7位;D3:1置位,0:清除

unsigned char fnST01(void);
unsigned char LCD12864_Write_Cmd_2(unsigned char uCmd,unsigned char uPar1,unsigned char uPar2);
unsigned char LCD12864_Write_Cmd_1(unsigned char uCmd,unsigned char uPar1);
unsigned char LCD12864_Write_Cmd_0(unsigned char uCmd);
void fnSetPos(unsigned char urow, unsigned char ucol);
void LCD12864_cls(void);
char LCD12864_Init(void);
unsigned char fnST3(void);
unsigned char LCD12864_Write_Date(unsigned char uData);
#endif

LCD12864.c

#include <reg52.h>
#include "LCD12864.h"
#include "DS1302.h"


unsigned char gCurRow,gCurCol;	//图形当前行、列存储,行高16点,列宽8点
unsigned int txthome,grhome;


unsigned char fnST01(void) // 状态位STA1,STA0判断(读写指令和读写数据)
{
	unsigned char i;
	
	for(i=10;i>0;i--)
	{
		if((LCMCW & 0x03) == 0x03)
		break;
	}
	return i; // 若返回零,说明错误
}

unsigned char fnST3(void) // 状态位ST3判断(数据自动写状态)
{
	unsigned char i;
	
	for(i=10;i>0;i--)
	{
		if((LCMCW & 0x08) == 0x08)
		break;
	}
	return i; // 若返回零,说明错误
}

unsigned char LCD12864_Write_Cmd_2(unsigned char uCmd,unsigned char uPar1,unsigned char uPar2) // 写双参数的指令
{
	if(fnST01() == 0)
	return 1;
	LCMDW = uPar1;
	if(fnST01() == 0)
	return 2;
	LCMDW = uPar2;
	if(fnST01() == 0)
	return 3;
	LCMCW = uCmd;
	return 0; // 返回0成功
}

unsigned char LCD12864_Write_Cmd_1(unsigned char uCmd,unsigned char uPar1) // 写单参数的指令
{
	if(fnST01() == 0)
	return 1;
	LCMDW = uPar1;
	if(fnST01() == 0)
	return 2;
	LCMCW = uCmd;
	return 0; // 返回0成功
}

unsigned char LCD12864_Write_Cmd_0(unsigned char uCmd) // 写无参数的指令
{
	if(fnST01() == 0)
	return 1;
	LCMCW = uCmd;
	return 0; // 返回0成功
}

unsigned char LCD12864_Write_Date(unsigned char uData) // 写数据
{
	if(fnST3() == 0)
	return 1;
	LCMDW = uData;
	return 0; // 返回0成功
}

void fnSetPos(unsigned char urow, unsigned char ucol)	//设置当前地址
{
	unsigned int iPos;
	
	iPos = urow * 20 + ucol;
	LCD12864_Write_Cmd_2(LC_ADD_POS,iPos & 0xFF,iPos / 256);
	gCurRow = urow;
	gCurCol = ucol;
}

// 清屏/**/
void LCD12864_cls(void)
{
	unsigned int i;
	
	LCD12864_Write_Cmd_2(LC_ADD_POS,0x00,0x00); // 置地址指针
	LCD12864_Write_Cmd_0(LC_AUT_WR); // 自动写
	for(i=0;i<0x2000;i++)
	{
		fnST3();
		LCD12864_Write_Date(0x00); // 写数据
	}
	LCD12864_Write_Cmd_0(LC_AUT_OVR); // 自动写结束
	LCD12864_Write_Cmd_2(LC_ADD_POS,0x00,0x00); // 重置地址指针
	gCurRow = 0; // 置地址指针存储变量
	gCurCol = 0;
}


char LCD12864_Init(void)  /*LCD初始化*/
{
	LCD12864_Write_Cmd_2(LC_TXT_STP,0x00,0x00); // 文本显示区首地址
	LCD12864_Write_Cmd_2(LC_TXT_WID,0x14,0x00); // 文本显示区宽度
	LCD12864_Write_Cmd_2(LC_GRH_STP,0x00,0x00); // 图形显示区首地址
	LCD12864_Write_Cmd_2(LC_GRH_WID,0x14,0x00); // 图形显示区宽度
	LCD12864_Write_Cmd_1(LC_CGR_POS,CGRAMSTART >> 11);
	LCD12864_Write_Cmd_0(LC_CUR_SHP | 0x01); // 光标形状
	LCD12864_Write_Cmd_0(LC_MOD_OR); // 显示方式设置
	LCD12864_Write_Cmd_0(LC_DIS_SW |0x08);
	grhome = GRSTART;
    txthome = TXTSTART;

	return 0;
}

wave.h

#ifndef WAVE
#define WAVE


void Pixel(unsigned char PointX,unsigned char PointY, bit Mode);

void Line( unsigned char x1,unsigned char y1, unsigned char x2,unsigned char y2,  bit Mode);

void Line_2( unsigned char x1,unsigned char y1, unsigned char x2,unsigned char y2,  bit Mode);

void Line_1( unsigned char x1,unsigned char y1, unsigned char x2,unsigned char y2,  bit Mode);



#endif

wave.c

#include "wave.h"
#include "LCD12864.h"

void Pixel(unsigned char PointX,unsigned char PointY, bit Mode)/*在指定坐标位置显示一个点*/
{														//Mode 1:显示 0:清除该点
    unsigned char StartAddr;
    unsigned char dat;
    StartAddr=7-(PointX%8);
    dat=LC_BIT_OP|StartAddr; //生产位操作命令画点的数据
    if(Mode) dat=dat|0x08;
	fnSetPos(PointY,PointX/8);
	LCD12864_Write_Cmd_0(LC_BIT_OP|dat); // 写数据
}


/*划线函数, 参数: 坐标1,坐标2,显示点或清除点*/


//绘制正弦波
void Line( unsigned char x1,unsigned char y1, unsigned char x2,unsigned char y2,  bit Mode)
{
    float x,y;
    double k,b;
	for (x=(float)x1;x<=(float)x2;x+=0.1)
	{
		y=30+15*sin(x*3.14/30);
		Pixel(x, y, Mode);
	}
}


 //绘制菱形
void Line_1( unsigned char x1,unsigned char y1, unsigned char x2,unsigned char y2,  bit Mode)
{
    float x,y;
    double k,b;

	k=((double)y2-y1) / ((double)x2-x1) ;
	b=y1-k*x1;
	if( x1 <= x2 )                         
	{
		for(x=(float)x1;x<=(float)x2;x+=0.1)
		{
			y=(unsigned char)(k*x+b);
			Pixel(x, y, Mode);
		}
	}
	else
	{
		for(x=(float)x1;x>=(float)x2;x-=0.1)
		{
			y=(unsigned char)(k*x+b);
			Pixel(x, y, Mode);
		}
	}
}


//绘制矩形
void Line_2( unsigned char x1,unsigned char y1, unsigned char x2,unsigned char y2,  bit Mode)
{
    float x,y;
	for(x=(float)x1;x<=(float)x2;x+=0.1)
	{
		Pixel(x,0,Mode);
		Pixel(0,x,Mode);
		Pixel(50-x,50,Mode);
		Pixel(50,50-x,Mode);
	}
}

main.c

#include <reg52.h>
#include "LCD12864.h"
#include "wave.h"

#define PI 3.1415926


//绘制圆形
void Clock_yuanxing()  
{
	float sta,x,y;
	for (sta=0;sta<=2*PI;sta+=0.01)
	{ 
		x = sin(sta); 
		y = cos(sta);
		Pixel(30+30*x,30+30*y,1);
	}
}


//绘制矩形
void Clock_juxing()
{
	float x=50,y=50;
	Line_2(0,0,x,y,1);
}


//绘制菱形
void Clock_lingxing()
{
	Line_1(20,30,60,0,1);
	Line_1(60,0,100,30,1);
	Line_1(100,30,60,60,1);
	Line_1(60,60,20,30,1);
}


//绘制正弦波
void Clock_zhengxuanbo()
{
	unsigned char x=108,y=50;
	Line(16,0,x,y,1);
}

void  main()  /*主程序*/
{
	LCD12864_Init();   //液晶初始化
	fnSetPos(0,0);     //从LCD左上角开始清屏
	LCD12864_cls();

	while(1)
	{
		//Clock_zhengxuanbo();
		Clock_lingxing();
		//Clock_yuanxing(); 
		//Clock_juxing();
	}
}

3. 实验结果

二、LCD12864显示指针式时钟

1. 仿真电路图

在这里插入图片描述

2. 源代码

LCD12864.h

与上述代码相同,不在赘述

LCD12864.c

与上述代码相同,不在赘述

DS1302.h

#ifndef DS1302_H
#define DS1302_H

#include <reg52.h>

sbit SDA=P1^0;		 //	DS1302数据线
sbit CLK=P1^1;		 //	DS1302时钟线
sbit RST=P1^2;		 //	DS1302复位线
sbit K1=P3^0;		 //选择
sbit K2=P3^1;		 //调整
sbit K3=P3^3;		 //确定

void DS1302_Write(unsigned char x);
unsigned char DS1302_Read();
unsigned char DS1302_Read_Data(unsigned char addr);
void DS1302_Write_Data(unsigned char addr,unsigned char dat);

#endif

DS1302.c

#include "DS1302.h"
#include "LCD12864.h"


/*向DS1302写入一字节*/
void DS1302_Write(unsigned char x)  
{
     unsigned char i;
	 for(i=0;i<8;i++)
	 {
	     SDA = x&1; 
		 CLK = 1; 
		 CLK = 0; 
		 x >>= 1;
	 }
}

/*从DS1302读取一字节*/
unsigned char DS1302_Read()  
{
   unsigned char i, b, t;
   for(i = 0; i < 8; i++)
   {
		b >>= 1; 
		t = SDA; 
		b |= t << 7; 
		CLK = 1; 
		CLK = 0;
   }
// BCD码转换
    return b /16 * 10 + b % 16;
}

/*从DS1302指定位置读取数据*/
unsigned char DS1302_Read_Data(unsigned char addr)   
{
    unsigned char dat;
	RST = 0; 
	CLK = 0; 
	RST = 1;
	DS1302_Write(addr);
	dat = DS1302_Read();
	CLK = 1; 
	RST = 0;
	return dat;
}

/*向DS1302某地址写入数据*/
void DS1302_Write_Data(unsigned char addr,unsigned char dat)  
{
	CLK = 0; 
	RST = 1;
	DS1302_Write(addr);
	DS1302_Write(dat);
	CLK = 0;
	RST = 0;
}

main.c

#include <reg52.h>
#include "LCD12864.h"
#include "DS1302.h"

#define PI 3.1415926

unsigned char count=0,d_Flag=0;  //定时器累加次数,标志位
unsigned char Current_Time[3];   //所获取的日期时间
char  Adjust_Index=-1;		     //当前调节的时间对象:秒,分,时(0,1,2)		
char Time_Back[]= {-1,-1,-1};    //秒,分,时变化以后的备份,用于避免时针与分针在每秒时均被重画 ,形成抖动						   
unsigned char HMS_Hand_Length[]={24,20,15};  


/*绘制电子钟圆形面板函数*/
void Clock_plate()   
{
	float sta,x,y;
	//绘制外围圆圈,如果希望绘制较连续的圆圈线条,可减少步长,将0.1改为0.02
	for (sta=0;sta<=2*PI;sta+=0.01)
	{ 
		x = sin(sta); 
		y = cos(sta);
		Pixel(30+30*x,30+30*y,1);
	}
	//绘制刻度1~12,每隔2xPI/12.0绘制一段
	for(sta=0;sta<=2*PI;sta+=2*PI/12)
	{
		x=sin(sta);
		y=cos(sta);
		Pixel(30+27*x,30+27*y,1);
		Pixel(30+26*x,30+26*y,1);
	}
}

/*重绘HMS中的某一指针函数(参数0,1,2分别为秒,分,时)*/
void Repaint_A_Hand(unsigned char i)  
{
	float r,m;
	unsigned int  x,y;
	m=(i==0||i==1) ? 60.0:12.0;
	//擦除
	r=Time_Back[i]/m*2*PI+1.5*PI;
	x=HMS_Hand_Length[i]*cos(r);
	y=HMS_Hand_Length[i]*sin(r);
	Line (30,30,x+30,y+30,0);
	//重绘
	r=Current_Time[i]/m*2*PI+1.5*PI;
	x=HMS_Hand_Length[i]*cos(r);
	y=HMS_Hand_Length[i]*sin(r);
	Line(30,30,x+30,y+30,1);
	//时间备份
	Time_Back[i]=Current_Time[i];
}

void  Display_HMS_Hand()  //时间变化时重绘
{                         //秒针与分针、时针接近重叠,或分钟与时钟接近重叠时也重绘
	Repaint_A_Hand(0); 
	Repaint_A_Hand(1);
	Repaint_A_Hand(2);
}

/*设置时间*/
void SET_DS1302()  
{
	DS1302_Write_Data(0x8E,0X00);  //写控制字,取消写保护
	DS1302_Write_Data(0x82,(Current_Time[1]/10<<4)|(Current_Time[1]%10));  //写入分
    DS1302_Write_Data(0x84,(Current_Time[2]/10<<4)|(Current_Time[2]%10));  //写入时
 	DS1302_Write_Data(0x8E,0x80);  //加保护
}

/*读取当前时间(秒,分,时)*/
void GetTime()  
{
	Current_Time[0]=DS1302_Read_Data(0x81);  //读取秒
	Current_Time[1]=DS1302_Read_Data(0x83);  //读取分 
	Current_Time[2]=DS1302_Read_Data(0x85);  //读取时
}

/*时,分调整*/
void Current_Time_Adjust()  
{
	switch(Adjust_Index)
	{
		case 2: Current_Time[2]=(Current_Time[2]+1)%24; break;  //时 
		case 1: Current_Time[1]=(Current_Time[1]+1)%60; break;  //分	
	}
}

/*定时器0每秒刷新LCD显示*/
void T0_INT()  interrupt  1   
{
	TL0=0x00;
	TH0=0x4c;
	if(++count!=2) return;
	count=0;
	if(d_Flag==0)      //如果是首次启动则绘制时钟面板,
	{                  //绘制面板的调用可放在主程序中
		Clock_plate();    //但因为绘制指针和绘制面板都调用了sin函数
		d_Flag=1;         //Keil C 会警告出现多重调用,因此本例将绘制
	}                     //面板的调用移到中断内部
	Display_HMS_Hand();   //显示当前时间指针
}

/*键盘中断(INT0)*/
void EX_INT0() interrupt 0   
{
	if(K1==0)       //选择调用对象
	{
		if(Adjust_Index==-1|| Adjust_Index==1) Adjust_Index=3;
		Adjust_Index--;
	}
	else if(K2==0)    //调整
		Current_Time_Adjust();
	else if(K3==0)    //确定
	{
		SET_DS1302();                                  //将调整后的时间写入DS1302
		Adjust_Index=-1;                               //操作索引重设为-1,时间继续正常显示
	}
}

/*主程序*/
void  main()  
{
	LCD12864_Init();   //液晶初始化
	fnSetPos(0,0);     //从LCD左上角开始清屏
	LCD12864_cls();
	IE=0x83;           //允许INT0,T0中断,使能总中断
	IT0=0x01;
	TMOD=0x01;
	TL0=0x00;
	TH0=0x4c;
	TR0=1;

	while(1)
	{
		//如果未执行调整操作则正常读取当前时间
		if(Adjust_Index==-1)  GetTime();
	}
}

3. 实验结果

三、LCD12864温度型时钟

1. 源代码

DS18B20.h

#ifndef __DS18B20_H_
#define __DS18B20_H_


#include<reg51.h>

void Delay1ms(unsigned int y);  //1ms延时
void Delay480us();  //480us延时
unsigned char Ds18b20Init();	//初始化DS18B20
void Ds18b20WriteByte(unsigned char dat);	 //写字节
unsigned char Ds18b20ReadByte();   //读字节
void  Ds18b20ChangTemp();   //温度转换
void  Ds18b20ReadTempCom();  //发送读取温度命令
int Ds18b20ReadTemp();	 //读取温度


#endif

DS18B20.c

#include "DS18B20.h"
#include "lcd12864.h"

sbit DQ=P3^7;

void Delay1ms(unsigned int y)	/*1ms延时*/
{
	unsigned int x;
	for( ; y>0; y--)
	{
		for(x=110; x>0; x--);
	}
}

void Delay480us()		/*480us延时*///@11.0592MHz
{
	unsigned char i, j;
	i = 6;
	j = 38;
	do
	{
		while (--j);
	} while (--i);
}


unsigned char Ds18b20Init()   /*DS18B20初始化*/
{
	DQ = 0;	//将总线拉低480us~960us
	Delay480us();   //480us的延时
	DQ = 1;			//然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
	while(DQ)	//等待DS18B20拉低总线
	{
		Delay1ms(5);
		if(DQ==1)//等待>5MS
		{
			return 0;//初始化失败
		}
	}
	return 1;//初始化成功
}


void Ds18b20WriteByte(unsigned char dat)   /*写字节函数*/
{
	unsigned char i,j;
	for(j=0; j<8; j++)
	{
		DQ = 0;	     	  //每写入一位数据之前先把总线拉低1us
		i++;
		DQ = dat & 0x01;  //然后写入一个数据,从最低位开始
		i=6;
		while(i--); //延时68us,持续时间最少60us
		DQ = 1;	//然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值
		dat >>= 1;
	}
}

unsigned char Ds18b20ReadByte()	  /*读取字节函数*/
{
	unsigned char byte, bi;
	unsigned int i, j;	
	for(j=8; j>0; j--)
	{
		DQ = 0;//先将总线拉低1us
		i++;
		DQ = 1;//然后释放总线
		i++;
		i++;//延时6us等待数据稳定
		bi = DQ;	 //读取数据,从最低位开始读取
		/*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/
		byte = (byte >> 1) | (bi << 7);						  
		i = 4;		//读取完之后等待48us再接着读取下一个数
		while(i--);
	}
	return byte;
}

void  Ds18b20ChangTemp()   /*让18b20开始转换温度*/
{
	Ds18b20Init();
	Delay1ms(1);
	Ds18b20WriteByte(0xcc);		//跳过ROM操作命令		 
	Ds18b20WriteByte(0x44);	    //温度转换命令 
}

void  Ds18b20ReadTempCom()   /*发送读取温度命令*/
{	
	Ds18b20Init();
	Delay1ms(1);
	Ds18b20WriteByte(0xcc);	 //跳过ROM操作命令
	Ds18b20WriteByte(0xbe);	 //发送读取温度命令
}

int Ds18b20ReadTemp()	 /*读取温度*/
{
	int temp = 0;
	unsigned char tmh, tml;
	Ds18b20ChangTemp();	//先写入转换命令
	Ds18b20ReadTempCom();  //然后等待转换完后发送读取温度命令
	tml = Ds18b20ReadByte();  //读取温度值共16位,先读低字节
	tmh = Ds18b20ReadByte();  //再读高字节
	temp = tmh;
	temp <<= 8;
	temp |= tml;
	return temp;
}

DS1302.h

#ifndef __DS1302_H_
#define __DS1302_H_

#include<reg51.h>

extern unsigned char TIME[7];	//加入全局变量

sbit DSIO=P3^4;
sbit RST=P3^5;
sbit SCLK=P3^6;

void delay_us();  //延时2us
void Ds1302Write(unsigned char addr, unsigned char dat);	//写地址,写数据
unsigned char Ds1302Read(unsigned char addr);  //读地址
void Ds1302Init();  //初始化
void Ds1302ReadTime();  


#endif

DS1302.c

#include "DS1302.h"


unsigned char code READ[7] =  {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};//读命令 秒分时日月周年
unsigned char code WRITE[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};//写命令 秒分时日月周年
unsigned char TIME[7] = {0, 0, 0x09, 0x18, 0x08, 0x03, 0x18};  //秒分时日月周年,存储格式是用BCD码
										   //初始值的设定
void delay_us()	/*延时2us*/
{	
}

void Ds1302Write(unsigned char addr, unsigned char dat)  /*向DS1302写命令(地址+数据)*/
{
	unsigned char n;
	RST = 0;
	delay_us();
	SCLK = 0;  //先将SCLK置低电平。
	delay_us();
	RST = 1;  //然后将RST(CE)置高电平。
	delay_us();

	for (n=0; n<8; n++)  //开始传送八位地址命令
	{
		DSIO=addr&0x01;  //数据从低位开始传送
		addr>>=1;
		SCLK=1;  //数据在上升沿时,DS1302读取数据
		delay_us();
		SCLK=0;
		delay_us();
	}
	for (n=0; n<8; n++)  //写入8位数据
	{
		DSIO = dat&0x01;
		dat>>=1;
		SCLK=1;   //数据在上升沿时,DS1302读取数据
		delay_us();
		SCLK=0;
		delay_us();	
	}	
		 
	RST = 0;  //传送数据结束,拉低CE端
	delay_us();
}

unsigned char Ds1302Read(unsigned char addr)   /*读取一个地址的数据*/
{
	unsigned char n,dat,dat1;
	RST = 0;
	delay_us();
	 SCLK = 0;//先将SCLK置低电平。
	delay_us();
	RST = 1;//然后将RST(CE)置高电平。
	delay_us();

	for(n=0; n<8; n++)//开始传送八位地址命令
	{
		DSIO = addr & 0x01;//数据从低位开始传送
		addr >>= 1;
		SCLK = 1;//数据在上升沿时,DS1302读取数据
		delay_us();
		SCLK = 0;//DS1302下降沿时,放置数据
		delay_us();
	}
	delay_us();
	for(n=0; n<8; n++)//读取8位数据
	{
		dat1 = DSIO;//从最低位开始接收
		dat = (dat>>1) | (dat1<<7);
		SCLK = 1;
		delay_us();
		SCLK = 0;//DS1302上升沿时,放置数据
		delay_us();
	}

//	RST = 0;
//	delay_us();	//以下为DS1302复位的稳定时间,必须的。
	SCLK = 1;
	delay_us();
	DSIO = 0;
	delay_us();
	DSIO = 1;
	delay_us();
	return dat;	
}

void Ds1302Init()	  /*初始化DS1302*/
{
	unsigned char n;
	Ds1302Write(0x8E,0X00);  //禁止写保护,就是关闭写保护功能
	for (n=0; n<7; n++)  //写入7个字节的时钟信号:分秒时日月周年
	{
		Ds1302Write(WRITE[n],TIME[n]);	//参数为地址和数据
	}
	Ds1302Write(0x8E,0x80);		 //打开写保护功能
}

void Ds1302ReadTime()	/*读取时钟信息*/
{
	unsigned char n;
	for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
	{
		TIME[n] = Ds1302Read(READ[n]);  //参数为地址
	}
		
}

LCD12864.h

#ifndef __LCD12864_H
#define __LCD12864_H

# include <reg51.h>

/*接口定义模块*/
#define LCD12864_DATAPORT P0	  //数据IO口

sbit LCD12864_RS  =  P2^6;             //(数据命令)寄存器选择输入 
sbit LCD12864_RW  =  P2^5;             //液晶读/写控制
sbit LCD12864_EN  =  P2^7;             //液晶使能控制
sbit LCD12864_PSB =  P3^2;             //串/并方式控制
sbit LCD12864_RST =  P3^3;			   //复位端
														  
/*函数声明模块*/
void LCD12864_Delay1ms(unsigned int c);	//延时函数		
void LCD12864_WriteCmd(unsigned char cmd);	//写指令函数
void LCD12864_WriteData(unsigned char dat);	//写数据函数
void LCD12864_Init();  //12864初始化函数					

#endif

LCD12864.c

#include"lcd12864.h"

void LCD12864_Delay1ms(unsigned int c)   /*延时函数*/
{
	unsigned int a,b;
	for(; c>0; c--)
	{
	    for(b=199; b>0; b--)
		{
	        for(a=1; a>0; a--);	
		}
	}
}


void LCD12864_WriteCmd(unsigned char cmd)	 /*写指令函数*/
{	
	LCD12864_RS = 0;     //选择命令
	LCD12864_RW = 0;     //选择写入
	LCD12864_EN = 0;     //初始化使能端

	LCD12864_DATAPORT = cmd;   //放置数据

	LCD12864_EN = 1;		   //写时序
	LCD12864_Delay1ms(5);
	LCD12864_EN = 0;    					
}


void LCD12864_WriteData(unsigned char dat)	  /*写数据函数*/
{
	LCD12864_RS = 1;     //选择数据
	LCD12864_RW = 0;     //选择写入
	LCD12864_EN = 0;     //初始化使能端

	LCD12864_DATAPORT = dat;   //放置数据

	LCD12864_EN = 1;		   //写时序
	LCD12864_Delay1ms(5);				   
	LCD12864_EN = 0;    								
}


 void LCD12864_Init()	/*初始化函数*/
{
	LCD12864_PSB = 1;	  //选择并行输入
	LCD12864_RST = 1;	  //复位
	LCD12864_WriteCmd(0x30);  //选择基本指令操作
	LCD12864_WriteCmd(0x0c);  //显示开,关光标
	LCD12864_WriteCmd(0x01);  //清除LCD12864的显示内容
}

main.c

#include <reg51.h>			 
#include "DS18B20.h"	
#include "LCD12864.h"
#include "DS1302.h"


unsigned DisplayData[8];
unsigned char code digit[]="0123456789";
unsigned char code Lcdshow[]="0123456789";
unsigned char code D1[]="温度:           ";
unsigned char code D2[]="时间:           ";
unsigned char code D3[]="星期:           ";
unsigned char code D4[]="年份:           ";


void delay_us(unsigned int i)	  /*延时函数*/
{
	while(i--);	
}

void datapros(int temp) /*温度读取处理转换函数*/	 
{
   	float tp;  
	if(temp<0)				//当温度值为负数
  	{
		LCD12864_WriteCmd(0x80+0x00);
		LCD12864_WriteData('-'); //   -
		temp=temp-1;
		temp=~temp;
		tp=temp;
		temp=tp*0.0625*100+0.5;	
  	}
 	else
  	{			
		LCD12864_WriteCmd(0x80+0x03);
		LCD12864_WriteData('+');
		tp=temp;     //因为数据处理有小数点所以将温度赋给一个浮点型变量
		temp=tp*0.0625*100+0.5;	
	}
	DisplayData[1] = digit[temp/10000];
	DisplayData[2] = digit[temp/1000%10];
	DisplayData[3] = digit[temp/100%10];
	DisplayData[4] = digit[temp/10%10];
	DisplayData[5] = digit[temp % 10];
}

void display_sta()   /*正确显示函数*/
{
	unsigned char i;

	LCD12864_WriteCmd(0x80);
	i=0;
	while(D1[i]!='\0')
	{
		LCD12864_WriteData(D1[i]);
		i++;	
	}
	
	LCD12864_WriteCmd(0x90);
	i=0;
	while(D2[i]!='\0')
	{
		LCD12864_WriteData(D2[i]);
		i++;	
	}
	
	LCD12864_WriteCmd(0x88);
	i=0;
	while(D3[i]!='\0')
	{
		LCD12864_WriteData(D3[i]);
		i++;	
	}
	
	LCD12864_WriteCmd(0x98);
	i=0;
	while(D4[i]!='\0')
	{
		LCD12864_WriteData(D4[i]);
		i++;	
	}
}

void display_temp()   /*显示温度函数*/
{
	LCD12864_WriteData(DisplayData[1]);
	LCD12864_WriteData(DisplayData[2]);
	LCD12864_WriteData(DisplayData[3]);
	LCD12864_WriteData('.');
	LCD12864_WriteData(DisplayData[4]);
	LCD12864_WriteData(DisplayData[5]);
	LCD12864_WriteData(' ');
	LCD12864_WriteData(0xa1);
	LCD12864_WriteData(0xe6);
}

void display_time()  /*显示时间函数*/
 {
	LCD12864_WriteCmd(0x93);
	LCD12864_WriteData(Lcdshow[TIME[2]/16]);  //显示小时
	LCD12864_WriteData(Lcdshow[TIME[2]%16]);
	LCD12864_WriteData('-');
	LCD12864_WriteData(Lcdshow[TIME[1]/16]);  //显示分
	LCD12864_WriteData(Lcdshow[TIME[1]%16]);
	LCD12864_WriteData('-');
	LCD12864_WriteData(Lcdshow[TIME[0]/16]);  //显示秒
	LCD12864_WriteData(Lcdshow[TIME[0]%16]);
	
	LCD12864_WriteCmd(0x8b);
	LCD12864_WriteData(Lcdshow[TIME[5]&0x07]);  //显示星期
	
	LCD12864_WriteCmd(0x9b);
	LCD12864_WriteData(Lcdshow[TIME[6]/16]);
	LCD12864_WriteData(Lcdshow[TIME[6]%16]);
	LCD12864_WriteData('-');
	LCD12864_WriteData(Lcdshow[TIME[4]/16]);
	LCD12864_WriteData(Lcdshow[TIME[4]%16]);
	LCD12864_WriteData('-');
	LCD12864_WriteData(Lcdshow[TIME[3]/16]);
	LCD12864_WriteData(Lcdshow[TIME[3]%16]);
}

void main()
{
	LCD12864_Init();  
	Ds1302Init();	
	display_sta();	
	while(1)
	{
		Ds1302ReadTime();  //读取时间
		display_time();    //显示时间
		datapros(Ds18b20ReadTemp());	 //数据处理函数
		display_temp();
		delay_us(1000);	   //延时1ms
	}		
}

2. 实验结果

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值