LCD12864.h
#ifndef __LCD12864_H__
#define __LCD12864_H__
//用户调用函数:
void LCD12864_init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
#endif
LCD12864.c
#include <STC89C5xRC.H>
#include <intrins.h>
sbit LCD12864_RS = P1^0;
sbit LCD12864_WR = P1^1;
sbit LCD12864_E = P2^5;
sbit LCD12864_PSB = P1^2;
#define LCD_DataPort P0
void Delay1ms(void) //@11.0592MHz
{
unsigned char data i, j;
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
/*******LCD_WriteCmd要写入的命令********************/
void LCD_WriteCmd( unsigned char cmd )
{
LCD12864_RS=0;//选择命令
LCD12864_WR=0;//选择写
LCD12864_E=0;
LCD_DataPort = cmd;//准备命令
Delay1ms();
LCD12864_E=1;//使能脚 E 先上升沿写入
Delay1ms();
LCD12864_E=0;//使能脚 E 后负跳变完成写入
}
/*******LCD_WriteData要写入的字节********************/
void LCD_WriteData( unsigned char dat )
{
LCD12864_RS=1;//选择数据
LCD12864_WR=0;//选择写
LCD12864_E=0;
LCD_DataPort = dat;//准备数据
Delay1ms();
LCD12864_E=1;//使能脚 E 先上升沿写入
Delay1ms();
LCD12864_E=0;//使能脚 E 后负跳变完成写入
}
void LCD12864_init()
{
LCD12864_PSB = 1; //并口方式
LCD_WriteCmd(0x30); //基本指令操作
LCD_WriteCmd(0x0C); //显示开,关光标
LCD_WriteCmd(0x06); //写入新数据后光标右移,显示屏不移动
LCD_WriteCmd(0x01); //清除LCD的显示内容
}
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if( Line <= 0 ) {
Line = 0;
}
if( Line > 3 ) {
Line = 3;
}
Column &= 0x0f; //限制 Line,Column 不能大于显示范围
switch( Line )
{
case 0: Column |= 0x80;break;//第 1 行地址+Column 的偏移
case 1: Column |= 0x90;break;//第 2 行地址+Column 的偏移
case 2: Column |= 0x88;break;//第 3 行地址+Column 的偏移
case 3: Column |= 0x98;break;//第 4 行地址+Column 的偏移
}
LCD_WriteCmd( Column );
}
/**
* @brief 在LCD12864指定位置上显示一个字符
* @param Line 行位置,范围:0~3
* @param Column 列位置,范围:0~15
* @param Char 要显示的字符
* @retval 无
*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}
/**
* @brief 在LCD12864指定位置上显示一个字符串
* @param Line 行位置,范围:0~3
* @param Column 列位置,范围:0~15
* @param String 要显示的字符串
* @retval 无
*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
LCD_SetCursor( Line, Column );
while(*String!='\0')
{
LCD_WriteData(*String);
String++;
}
}
/**
* @brief 返回值=X的Y次方
*/
int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i<Y;i++)
{
Result*=X;
}
return Result;
}
/**
* @brief 在LCD12864指定位置开始显示所给数字
* @param Line 起始行位置,范围:0~3
* @param Column 起始列位置,范围:0~15
* @param Number 要显示的数字,范围:0~65535
* @param Length 要显示数字的长度,范围:1~5
* @retval 无
*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
}
}
/**
* @brief 在LCD12864指定位置开始以有符号十进制显示所给数字
* @param Line 起始行位置,范围:0~3
* @param Column 起始列位置,范围:0~15
* @param Number 要显示的数字,范围:-32768~32767
* @param Length 要显示数字的长度,范围:1~5
* @retval 无
*/
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
unsigned char i;
unsigned int Number1;
LCD_SetCursor(Line,Column);
if(Number>=0)
{
LCD_WriteData('+');
Number1=Number;
}
else
{
LCD_WriteData('-');
Number1=-Number;
}
for(i=Length;i>0;i--)
{
LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
}
}
/**
* @brief 在LCD12864指定位置开始以十六进制显示所给数字
* @param Line 起始行位置,范围:0~3
* @param Column 起始列位置,范围:0~15
* @param Number 要显示的数字,范围:0~0xFFFF
* @param Length 要显示数字的长度,范围:1~4
* @retval 无
*/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i,SingleNumber;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingleNumber=Number/LCD_Pow(16,i-1)%16;
if(SingleNumber<10)
{
LCD_WriteData(SingleNumber+'0');
}
else
{
LCD_WriteData(SingleNumber-10+'A');
}
}
}
/**
* @brief 在LCD12864指定位置开始以二进制显示所给数字
* @param Line 起始行位置,范围:0~3
* @param Column 起始列位置,范围:0~15
* @param Number 要显示的数字,范围:0~1111 1111 1111 1111
* @param Length 要显示数字的长度,范围:1~16
* @retval 无
*/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
}
}
DS1302.h
#ifndef __DS1302_H__
#define __DS1302_H__
extern unsigned char DS1302_Time[];
void DS1302_Init();
void DS1302_WriteBety( unsigned char command, unsigned char Data );
unsigned char DS1302_ReadBety(unsigned char command);
void DS1302_SetTime();
void DS1302_ReadTime();
#endif
DS1302.c
#include <STC89C5xRC.H>
#include <intrins.h>
sbit DS1302_SCLK=P2^1;
sbit DS1302_IO=P2^0;
sbit DS1302_CE=P2^4;
//对应寄存器位置定义
#define DS1302_SECOND 0X80
#define DS1302_MINUTE 0X82
#define DS1302_HOUR 0X84
#define DS1302_DATE 0X86
#define DS1302_MONTH 0X88
#define DS1302_DAY 0X8A
#define DS1302_YEAR 0X8C
#define DS1302_WP 0X8E
//定义数组,用于存放设定的时间,年月日时分秒星期
unsigned char DS1302_Time[]={ 24, 8, 23, 13, 52, 0, 5 };//顺序:年月日时分秒星期
/**
*@breaf DS1302初始化
*@param无
*@retval无
*/
void DS1302_Init()
{
DS1302_CE=0;//将使能位置0,低电平;
DS1302_SCLK=0;//将时钟位置0,低电平;
}
/**
*@breaf DS1302单字节写入函数
*@param command:写入控制指令的指令,包含要写入寄存器的地址;
*@param Data:将要写入的数据内容;
*@retval 无
*/
void DS1302_WriteBety( unsigned char command, unsigned char Data )
{
unsigned char i;
DS1302_CE = 1;//使能位置高电平;
_nop_();
for(i=0;i<8;i++)//控制寄存器数据需要通过IO线一个一个写入控制寄存器;低位先写入
{
// DS1302_IO=command&(0x01<<i);//相当于把第1--7位置0,只留第0位,如果第0位是0,则为0;反之则为1;
DS1302_IO = command & 0x01;
command >>= 1;
_nop_();
DS1302_SCLK=1;
_nop_();
DS1302_SCLK=0;
_nop_();
}
for(i=0;i<8;i++)//数据写入
{
// DS1302_IO=Data&(0x01<<i);//相当于把第1--7位置0,只留第0位,如果第0位是0,则为0;反之则为1;
DS1302_IO = Data & 0x01;
Data >>= 1;
_nop_();
DS1302_SCLK=1;
_nop_();
DS1302_SCLK=0;
_nop_();
}
DS1302_CE=0;
_nop_();
}
/**
*@breaf DS1302单字节读出函数
*@param command:写入控制指令的指令,包含要读出寄存器的地址;
*@retval Data:读出的数据;
*/
unsigned char DS1302_ReadBety( unsigned char command )
{
unsigned char i,Data=0x00;
command |= 0x01;//写入指令与读出指令只在最后一位相差1,故在此利用或运算消除;
DS1302_CE = 1;//使能位置高电平;
for(i=0;i<8;i++)//控制寄存器数据需要通过IO线一个一个写入控制寄存器;低位先写入
{
// DS1302_IO=command&(0x01<<i);//相当于把第1--7位置0,只留第0位,如果第0位是0,则为0;反之则为1;
DS1302_IO = command & 0x01;
command >>= 1;
_nop_();
DS1302_SCLK=1;
_nop_();
DS1302_SCLK=0;
_nop_();
}
// DS1302_IO=0;
// _nop_();
for(i=0;i<8;i++)//数据读出
{
if( DS1302_IO ) {
Data |= ( 0X01 << i );
}
DS1302_SCLK=1;
_nop_();
DS1302_SCLK=0;
_nop_();
// if( DS1302_IO )
// {Data |=(0X01<<i);}
}
DS1302_CE=0;
_nop_();
return Data;
}
/**
*@breaf 向DS1302内设定时间
*@param无
*@retval无
*/
void DS1302_SetTime()
{
DS1302_WriteBety(DS1302_WP,0x00);//操作 DS1302 之前,关闭写保护,不然指令无法进入控制寄存器;
DS1302_WriteBety(DS1302_YEAR, DS1302_Time[0]/10*16+DS1302_Time[0]%10);//写入年,并将10进制转化BCD码;
DS1302_WriteBety(DS1302_MONTH, DS1302_Time[1]/10*16+DS1302_Time[1]%10);//写入月,并将10进制转化BCD码;
DS1302_WriteBety(DS1302_DATE, DS1302_Time[2]/10*16+DS1302_Time[2]%10);//写入日,并将10进制转化BCD码;
DS1302_WriteBety(DS1302_HOUR, DS1302_Time[3]/10*16+DS1302_Time[3]%10);//写入时,并将10进制转化BCD码;
DS1302_WriteBety(DS1302_MINUTE, DS1302_Time[4]/10*16+DS1302_Time[4]%10);//写入分,并将10进制转化BCD码;
DS1302_WriteBety(DS1302_SECOND, DS1302_Time[5]/10*16+DS1302_Time[5]%10);//写入秒,并将10进制转化BCD码;
DS1302_WriteBety(DS1302_DAY, DS1302_Time[6]/10*16+DS1302_Time[6]%10);//写入星期,并将10进制转化BCD码;
DS1302_WriteBety( DS1302_WP,0x80);//写入结束,开启写保护;
}
/**
*@breaf 读取DS1302内时间
*@param无
*@retval无
*/
void DS1302_ReadTime()
{
unsigned char Temp;//定义变量,用于暂时存储BCD码
Temp=DS1302_ReadBety(DS1302_YEAR);//读取年BCD码;
DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转十进制;
Temp=DS1302_ReadBety(DS1302_MONTH);//读取月BCD码;
DS1302_Time[1]=Temp/16*10+Temp%16;//BCD码转十进制;
Temp=DS1302_ReadBety(DS1302_DATE);//读取日BCD码;
DS1302_Time[2]=Temp/16*10+Temp%16;//BCD码转十进制;
Temp=DS1302_ReadBety(DS1302_HOUR);//读取小时BCD码;
DS1302_Time[3]=Temp/16*10+Temp%16;//BCD码转十进制;
Temp=DS1302_ReadBety(DS1302_MINUTE);//读取分钟BCD码;
DS1302_Time[4]=Temp/16*10+Temp%16;//BCD码转十进制;
Temp=DS1302_ReadBety(DS1302_SECOND);//读取秒BCD码;
DS1302_Time[5]=Temp/16*10+Temp%16;//BCD码转十进制;
Temp=DS1302_ReadBety(DS1302_DAY);//读取星期BCD码;
DS1302_Time[6]=Temp/16*10+Temp%16;//BCD码转十进制;
}
main.c
#include <STC89C5xRC.H>
#include "LCD12864.h"
#include "DS1302.h"
void main()
{
LCD12864_init(); //LCD12864初始化
DS1302_Init();//DS1302初始化
LCD_ShowString(0,0,"日期:");
LCD_ShowString(1,0," 年 月 日");//设置年月日格式
LCD_ShowString(2,0,"星期");
LCD_ShowString(3,0," : : ");//设置时分秒格式
DS1302_SetTime();//设置时间,通过数组进行设置
while( 1 ) {
DS1302_ReadTime();//读取内部时间
LCD_ShowNum(1,0,DS1302_Time[0],2);//显示年
LCD_ShowNum(1,2,DS1302_Time[1],2);//显示月
LCD_ShowNum(1,4,DS1302_Time[2],2);//显示日
LCD_ShowNum(3,0,DS1302_Time[3],2);//显示时
LCD_ShowNum(3,2,DS1302_Time[4],2);//显示分
LCD_ShowNum(3,4,DS1302_Time[5],2);//显示秒
LCD_ShowNum(2,2,DS1302_Time[6], 1);//显示星期
}
}
video_20240823_140726