1、现象:
2、参考程序
2.1 主程序
#include
#include "LCD1602.H"
#include "DS1302.H"
void main()
{
LCD1602_Init();
DS1302_Init();
LCD1602_ShowString(1,1," - - "); //静态字符初始化显示
LCD1602_ShowString(2,1," : : ");
DS1302_SetTime( ); //设置时间
while(1)
{
DS1302_ReadTime( ); //读取时间
LCD1602_ShowNum(1,1,DS1302_Time[0],2); //显示年
LCD1602_ShowNum(1,4,DS1302_Time[1],2); //显示月
LCD1602_ShowNum(1,7,DS1302_Time[2],2); //显示日
LCD1602_ShowNum(2,1,DS1302_Time[3],2); //显示时
LCD1602_ShowNum(2,4,DS1302_Time[4],2); //显示分
LCD1602_ShowNum(2,7,DS1302_Time[5],2); //显示秒
}
}
2.2 DS1302源程序及头文件
#include
//引脚定义,与硬件原理图有关
sbit DS1302_SCLK = P3^6;
sbit DS1302_IO = P3^4;
sbit DS1302_CE = P3^5;
#define DS1302_SECOND_ADDR 0x80 //DS1302秒寄存器写地址
#define DS1302_MINUTE_ADDR 0x82 //DS1302分寄存器写地址
#define DS1302_HOUR_ADDR 0x84 //DS1302时寄存器写地址
#define DS1302_DATE_ADDR 0x86 //DS1302日寄存器写地址
#define DS1302_MONTH_ADDR 0x88 //DS1302月寄存器写地址
#define DS1302_DAY_ADDR 0x8A //DS1302星期寄存器写地址
#define DS1302_YEAR_ADDR 0x8C //DS1302年寄存器写地址
#define DS1302_WP_ADDR 0x8E //DS1302控制寄存器写地址
unsigned char DS1302_Time[]={22,8,7,20,8,55,7};
//时间数字,索引0-6分别为年、月、日、时、分、秒、星期
/**
* @brief DS1302初始化
* @param 无
* @retval 无
*/
void DS1302_Init(void)
{
DS1302_CE = 0;
DS1302_SCLK = 0;
}
/**
* @brief DS1302写一个字节
* @param Command 命令字/地址
* @param Data 要写入的数据
* @retval 无
*/
void DS1302_WriteByte(unsigned char Command,Data)
{
unsigned char i;
DS1302_CE = 1;
for(i=0;i<8;i++) //写地址/命令
{
DS1302_IO = Command & (0x01< DS1302_SCLK = 1; //SCLK上升沿,MCU向DS1302写入数据
DS1302_SCLK = 0; //一个完整的脉冲
}
for(i=0;i<8;i++) //写数据
{
DS1302_IO = Data & (0x01< DS1302_SCLK = 1; //SCLK上升沿,MCU向DS1302写入数据
DS1302_SCLK = 0; //一个完整的脉冲
}
DS1302_CE = 0;
}
/**
* @brief DS1302读一个字节
* @param Command 命令字/地址
* @retval 读出的数据
*/
unsigned char DS1302_ReadByte(unsigned char Command)
{
unsigned char i;
unsigned char Data = 0x00;
Command = Command | 0x01; //将读地址指令转换为相应的读地址指令
DS1302_CE = 1;
for(i=0;i<8;i++) //写地址/命令
{
DS1302_IO = Command & (0x01< DS1302_SCLK = 0; //一个完整的脉冲,与写地址写数据相反
DS1302_SCLK = 1; //SCLK上升沿,MCU向DS1302写入数据
}
for(i=0;i<8;i++)
{
DS1302_SCLK = 1; //写地址读数据
DS1302_SCLK = 0; //SCLK下降沿,MUC读取DS1302的数据
if(DS1302_IO) {Data = Data | (0x01< }
DS1302_CE = 0;
DS1302_IO = 0; //读取后将IO设置为0,否则读出的数据会出错
return Data;
}
/**
* @brief DS1302设置时间,调用之后,DS1302_Time数组的数字会被设置到DS1302中
* @param 无
* @retval 无
*/
void DS1302_SetTime(void)
{
DS1302_WriteByte(DS1302_WP_ADDR,0x00); //解除芯片写保护
DS1302_WriteByte(DS1302_YEAR_ADDR, DS1302_Time[0]/10*16+DS1302_Time[0]%10); //写入年数据,十进制转为十六进制
DS1302_WriteByte(DS1302_MONTH_ADDR, DS1302_Time[1]/10*16+DS1302_Time[1]%10); //写入月数据
DS1302_WriteByte(DS1302_DATE_ADDR, DS1302_Time[2]/10*16+DS1302_Time[2]%10); //写入日数据
DS1302_WriteByte(DS1302_HOUR_ADDR, DS1302_Time[3]/10*16+DS1302_Time[3]%10); //写入小时数据
DS1302_WriteByte(DS1302_MINUTE_ADDR, DS1302_Time[4]/10*16+DS1302_Time[4]%10); //写入分钟数据
DS1302_WriteByte(DS1302_SECOND_ADDR, DS1302_Time[5]/10*16+DS1302_Time[5]%10); //写入秒钟数据
DS1302_WriteByte(DS1302_DAY_ADDR, DS1302_Time[6]/10*16+DS1302_Time[6]%10); //写入星期数据
DS1302_WriteByte(DS1302_WP_ADDR,0x80); //开启芯片写保护
}
/**
* @brief DS1302读取时间,调用之后,DS1302中的数据会被读取到DS1302_Time数组中
* @param 无
* @retval 无
*/
void DS1302_ReadTime(void)
{
unsigned char Temp;
Temp = DS1302_ReadByte(DS1302_YEAR_ADDR); DS1302_Time[0]=Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_MONTH_ADDR); DS1302_Time[1]=Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_DATE_ADDR); DS1302_Time[2]=Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_HOUR_ADDR); DS1302_Time[3]=Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_MINUTE_ADDR); DS1302_Time[4]=Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_SECOND_ADDR); DS1302_Time[5]=Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_DAY_ADDR); DS1302_Time[6]=Temp/16*10+Temp%16;
}
#ifndef __DS1302_H__
#define __DS1302_H__
//外部可调用时间数组,索引0~6分别为年、月、日、时、分、秒、星期
extern unsigned char DS1302_Time[];
void DS1302_Init(void);
void DS1302_WriteByte(unsigned char Command,Data);
unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_SetTime(void);
void DS1302_ReadTime(void);
#endif
2.3 LCD1602源程序及头文件
#include
#include "intrins.h"
//引脚配置,硬件原理图,普中A2
sbit LCD1602_RS = P2^6;
sbit LCD1602_RW = P2^5;
sbit LCD1602_E = P2^7;
#define LCD1602_DATAPORT P0
/**
* @brief LCD1602延时函数
* @param xms=1, 延时1ms
* @retval 无
*/
void LCD1602_Delayms(unsigned char xms) //@11.0592MHz
{
unsigned char i, j,k;
for(k=0;k
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
/**
* @brief LCD1602写命令,时序图
* @param Command 要写入的命令
* @retval 无
*/
void LCD1602_WriteCommand(unsigned char Command)
{
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DATAPORT = Command;
LCD1602_E = 1;
LCD1602_Delayms(1); //延时1ms
LCD1602_E = 0;
LCD1602_Delayms(1); //延时1ms
}
/**
* @brief LCD1602写数据,时序图
* @param Data 要写入的数据
* @retval 无
*/
void LCD1602_WriteData(unsigned char Data)
{
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DATAPORT = Data;
LCD1602_E = 1;
LCD1602_Delayms(1); //延时1ms
LCD1602_E = 0;
LCD1602_Delayms(1); //延时1ms
}
/**
* @brief LCD1602初始化函数
* @param 无
* @retval 无
*/
void LCD1602_Init(void)
{
LCD1602_WriteCommand(0x38); //0011_1000 功能设置,设置16x2显示,5x7点阵,8位数据接口
LCD1602_WriteCommand(0x0C); //0000_1100 显示开关控制,显示开,光标关,闪烁关
LCD1602_WriteCommand(0x06); //0000_0110 输入方式设置,数据写后,AC自动加一,画面不动
LCD1602_WriteCommand(0x01); //0000_0001 清屏,数据指针清零、所有显示清零
}
/**
* @brief LCD1602设置光标位置
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @retval 无
*/
void LCD1602_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line == 1)
{
LCD1602_WriteCommand(0x80|(Column-1)); //设置要存入数据的DDROM地址,第一行地址
}
else
{
LCD1602_WriteCommand(0x80|(Column-1)+0x40); //设置要存入数据的DDROM地,第二行地址
}
}
/**
* @brief 在LCD1602指定位置上显示一个字符
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @param Char 要显示的字符
* @retval 无
*/
void LCD1602_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
{
LCD1602_SetCursor(Line,Column);
LCD1602_WriteData(Char);
}
/**
* @brief 在LCD1602指定位置上显示所给字符串