【STC51系列文章】
STC51-01-开发软件安装与使用
STC51-02-开发版介绍与LED流水灯系列
STC51-03-独立按键系列
STC51-04-数码管系列
STC51-05-矩阵按键系列
STC51-06-中断和定时器系列
STC51-07-DAC转换输出三角波
STC51-08-温度传感器
STC51-09-DS1302时钟
STC51-10-ADC0808与DAC0808的应用
STC51-11-LCD12864相关应用
STC51-12-代码网盘链接
文章目录
一、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
}
}