文章目录
1、前言
在前面的文章中介绍了51单片机之LED点阵屏,今天介绍单片机的LED点阵屏。
2、DS1302
2-1、芯片简介
DS1302是美国DALLAS公司推出的实时时钟电路。DS1302具有高性能、低功耗的特点,其芯片采用SPI三线接口与CPU进行同步通信 ,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能,工作电压宽达2.5~5.5V。
2-2、RTC
RTC(Real Time Clock) :实时时钟,是一种集成电路,通常称为时钟芯片。
Figure1. Real Time Clock
3、DS1302 Datasheet
3-1、引脚定义及应用电路
Figure2. 管脚定义
Table1. 管脚定义
引脚名 | 作用 |
---|---|
VCC2 | 主电源 |
VCC1 | 备用电源 |
GND | 电源地 |
X1、X2 | 32.768KHz晶振 |
CE | 芯片使能 |
IO | 数据输入/输出 |
SCLK | 串行时钟 |
Figure3. 典型工作电路
3-2、硬件电路
从下图可知 ,没有连接VCC1,则表示没有备用电源使用。下电后就不能计时。
Figure4. 原理图
3-3、内部结构框图
Figure5. 内部结构框图
3-4、寄存器定义
Figure6. 寄存器地址/定义
3-5、地址命令字
命令字启动每一次数据传输。MSB((位7)必须是逻辑1。如果是0,则禁止对DS1302写入。位6在逻辑0时规定为时钟/日历数据,逻辑1时为RAM数据 。位1至位5表示了输入输出的指定寄存器。LSB(位0)在逻辑0时为写操作(输出),逻辑1时为读操作(输入) 。命令字以LSB(位0)开始总是输入。
Figure7. 地址命令字
3-6、时序定义
Figure8. 时序定义
3-6-1、CE与时钟控制
所有数据传输开始驱动CE输入高电平。CE输入实现两个功能:第一,CE开启允许对地址/命令序列的移位寄存器进行读写的控制逻辑。第二,CE信号为单字节和多字节CE数据传输提供了终止的方法。
一个时钟周期是一系列的上升沿伴随随下降沿。要写入数据在时钟的上升沿数据必须有效,而且在下降沿要输出数据位。如果CE输入为低电平,则所有数据传输终止,并且I/O口成高阻抗状态。在上电时, CE必须为逻辑0直到VCC大于 2.0V时才变为逻辑1。同样,SCLK必须为逻辑0当CE变成逻辑1状态。
3-6-2、数据输入
输入写命令字的8个SCLK周期 后,接下来的8个SCLK周期的上升沿数据字节被输入,如不慎发生,多余的SCLK周期将被忽略,数据输入以位0开始。
3-6-3、数据输出
输入读命令字的8个SCLK周期后,随后的8个SCLK周期的下降沿,一个数据字节被输出 。注意第一个数据位的传送发生在命令字节被写完后的第一个下降沿。只要CE保持高电平,若不慎发生,多余的 SCLK周期会重新发送数据字节。此操作允许连续不断的脉冲串模式读取能力。并且I/O管脚在SCLK的每个上升沿被置为三态。数据输出从位 0开始。
3-6-4、脉冲串模式
通过寻址31(十进制)存储单元(地址/命令位1到位5为逻辑1),脉冲串模式可以指定时钟/日历或者RAM寄存器 。如前所述,位6指定时钟或者RAM,位0指定读写。时钟/日历寄存器的存储单元9至31和RAM寄存器的存储单元31无数技据存储能力。脉冲串模式下的读写从地址0的位0开始。在脉冲串模式下写时钟寄存器时,前8个寄存器必须按顺序写要发送的数据。然而,在脉冲串模式下写RAM时,不必写入要发送数据的所有31个字节。不管是否所有31个字节都被写入,每个写入字节都会被发送到RAM。
3-6-5、时钟/日历
读取适当的寄存器字节可以得到时间和日历信息。Figure6. 寄存器地址/定义说明了RTC寄存器。写入适当的寄存器字节可以设置或初始化时间和日历。时间和日历寄存器的内容是二进制编码的十进制(BCD)格式的。周中的天寄存器在午夜12点增加。周中的天相应的值可以由用户定义,但是必须是连续的(例如,如果1代表周日,那么2代表周一,等等。)。非法的时间和日期输入导致未定义操作。当读写时钟和日期寄存器时,第二(用户)缓存用来防1上内部寄存器更新时出错。读时钟和日期寄存器时,在CE上升沿用户缓存与内部寄存器同步。
每当秒寄存器被写入,递减计数电路被复位。写传输发生在CE的下降沿 。为了避免翻转问题,一旦递减计数电路复位,剩下的时间和日期寄存器必须不在一秒内被写入,DS1302可以工作在12小时制 和24小时制两种模式下。小时寄存器的位7定义为小时模式选择位。为高时是12小时制,12小时制模式下,位5是上午/下午位且高电平是下午。24小时制模式下,位5是第二10-小时位(20点-23点)。一旦12/24改变,小时数据必须被重新初始化。
3-6-6、时钟暂停标志
秒寄存器的位7被定义为时钟暂停标志。当此为置1时,时钟振荡器暂停,DS1302进入漏电流小于100nA的低功耗备用模式。当此为置0时,时钟开始。初始加电状态未定义。
3-6-7、写保护位
控制寄存器的位7是写保护位,前7位(位0至位6)被强制为0且读取时总是读0。在任何对时钟或RAM的写操作以前,位7必须为0 。当为高时,写保护位禁止任何寄存器的写操作。初始加电状态未定义,因此,在试图写器件之前应该清WP位。
4、工程编码
4-1、基础功能
Figure9. Demo编码
c
#ifndef __LCD1602_H__
#define __LCD1602_H__
//用户调用函数:
void LCD_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
c
#include <REGX52.H>
#include "LCD1602.h"
//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0
//函数定义:
/**
* @brief LCD1602延时函数,12MHz调用可延时1ms
* @param 无
* @retval 无
*/
void LCD_Delay()
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
/**
* @brief LCD1602写命令
* @param Command 要写入的命令
* @retval 无
*/
void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/**
* @brief LCD1602写数据
* @param Data 要写入的数据
* @retval 无
*/
void LCD_WriteData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/**
* @brief LCD1602设置光标位置
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @retval 无
*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));
}
else if(Line==2)
{
LCD_WriteCommand(0x80|(Column-1+0x40));
}
}
/**
* @brief LCD1602初始化函数
* @param 无
* @retval 无
*/
void LCD_Init()
{
LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
LCD_WriteCommand(0x01);//光标复位,清屏
}
/**
* @brief 在LCD1602指定位置上显示一个字符
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @param Char 要显示的字符
* @retval 无
*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}
/**
* @brief 在LCD1602指定位置开始显示所给字符串
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param String 要显示的字符串
* @retval 无
*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++)
{
LCD_WriteData(String[i]);
}
}
/**
* @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 在LCD1602指定位置开始显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @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 在LCD1602指定位置开始以有符号十进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @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 在LCD1602指定位置开始以十六进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @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 在LCD1602指定位置开始以二进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @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');
}
}
c
#ifndef __DS1302_H__
#define __DS1302_H__
#define DS1302_SECONDS_ADDR 0x80
#define DS1302_MINUTES_ADDR 0x82
#define DS1302_HOUR_ADDR 0x84
#define DS1302_DATE_ADDR 0x86
#define DS1302_MONTH_ADDR 0x88
#define DS1302_DAY_ADDR 0x8A
#define DS1302_YEAR_ADDR 0x8C
#define DS1302_WP_ADDR 0x8E
#define DS1302_WP_DISABLE 0x00
#define DS1302_WP_ENABLE 0x01
#define DS1302_CURRENTTIME_LENGTH 7U
extern unsigned char DS1302_CurrentTime[DS1302_CURRENTTIME_LENGTH];
extern void DS1302_Init(void);
extern void DS1302_WriteByte(unsigned char WriteAddr, unsigned char Data);
extern unsigned char DS1302_ReadByte(unsigned char ReadAddr);
extern void DS1302_SetTime(void);
extern void DS1302_GetTime(void);
extern unsigned char DS1302_BCD2HEX(unsigned char InputData);
extern unsigned char DS1302_HEX2BCD(unsigned char InputData);
#endif
c
#include <REGX52.H>
#include "DS1302.h"
sbit DS1302_IO = P3^4;
sbit DS1302_CE = P3^5;
sbit DS1302_SCLK = P3^6;
unsigned char DS1302_CurrentTime[DS1302_CURRENTTIME_LENGTH] = {25,8,20,23,24,25,6};
void DS1302_Init(void)
{
DS1302_CE = 0;
DS1302_SCLK = 0;
}
void DS1302_WriteByte(unsigned char WriteAddr, unsigned char Data) /* 16 pulses */
{
unsigned char i;
DS1302_CE = 1; /* enable DS1302 */
/* address command order */
for(i = 0; i < 8; i++)
{
DS1302_IO = WriteAddr & (0x01 << i); /* Set bit0 */
DS1302_SCLK = 1; /* set rising edge to wirte bit */
DS1302_SCLK = 0; /* back to low level for next bit writing. */
}
for(i = 0; i < 8; i++)
{
DS1302_IO = Data & (0x01 << i); /* Set bit0 */
DS1302_SCLK = 1; /* set rising edge to wirte bit */
DS1302_SCLK = 0; /* back to low level for next bit writing. */
}
DS1302_CE = 0; /* disable DS1302 */
}
unsigned char DS1302_ReadByte(unsigned char ReadAddr) /* 15 pulses */
{
unsigned char i;
unsigned char Data = 0x00;
ReadAddr |= 0x01; /* read ReadAddr lowest bit is 1. */
DS1302_CE = 1; /* enable DS1302 */
/* address command order */
for(i = 0; i < 8; i++)
{
DS1302_IO = ReadAddr & (0x01 << i); /* Set bit0 */
DS1302_SCLK = 0; /* back to low level for next bit writing. */
DS1302_SCLK = 1; /* set rising edge to wirte bit */
}
for(i = 0; i < 8; i++)
{
DS1302_SCLK = 1; /* set rising edge to read bit starting */
DS1302_SCLK = 0; /* back to low level for bit reading. */
if(DS1302_IO != 0)
{
Data |= (0x01 << i);
}
}
DS1302_IO = 0;
return Data;
}
void DS1302_SetTime(void)
{
DS1302_WriteByte(DS1302_WP_ADDR, DS1302_WP_DISABLE); /* disable write protection */
DS1302_WriteByte(DS1302_YEAR_ADDR, DS1302_BCD2HEX(DS1302_CurrentTime[0]));
DS1302_WriteByte(DS1302_MONTH_ADDR, DS1302_BCD2HEX(DS1302_CurrentTime[1]));
DS1302_WriteByte(DS1302_DATE_ADDR, DS1302_BCD2HEX(DS1302_CurrentTime[2]));
DS1302_WriteByte(DS1302_HOUR_ADDR, DS1302_BCD2HEX(DS1302_CurrentTime[3]));
DS1302_WriteByte(DS1302_MINUTES_ADDR, DS1302_BCD2HEX(DS1302_CurrentTime[4]));
DS1302_WriteByte(DS1302_SECONDS_ADDR, DS1302_BCD2HEX(DS1302_CurrentTime[5]));
DS1302_WriteByte(DS1302_DAY_ADDR, DS1302_BCD2HEX(DS1302_CurrentTime[6]));
DS1302_WriteByte(DS1302_WP_ADDR, DS1302_WP_ENABLE); /* enable write protection */
}
void DS1302_GetTime(void)
{
DS1302_CurrentTime[0] = DS1302_HEX2BCD(DS1302_ReadByte(DS1302_YEAR_ADDR));
DS1302_CurrentTime[1] = DS1302_HEX2BCD(DS1302_ReadByte(DS1302_MONTH_ADDR));
DS1302_CurrentTime[2] = DS1302_HEX2BCD(DS1302_ReadByte(DS1302_DATE_ADDR));
DS1302_CurrentTime[3] = DS1302_HEX2BCD(DS1302_ReadByte(DS1302_HOUR_ADDR));
DS1302_CurrentTime[4] = DS1302_HEX2BCD(DS1302_ReadByte(DS1302_MINUTES_ADDR));
DS1302_CurrentTime[5] = DS1302_HEX2BCD(DS1302_ReadByte(DS1302_SECONDS_ADDR));
DS1302_CurrentTime[6] = DS1302_HEX2BCD(DS1302_ReadByte(DS1302_DAY_ADDR));
}
unsigned char DS1302_BCD2HEX(unsigned char InputData)
{
return (InputData / 10 * 16 + InputData % 10);
}
unsigned char DS1302_HEX2BCD(unsigned char InputData)
{
return (InputData / 16 * 10 + InputData % 16);
}
c
#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
void main()
{
LCD_Init();
DS1302_Init();
DS1302_SetTime();
LCD_ShowString(1,1," - - ");
LCD_ShowString(2,1," : : ");
while(1)
{
DS1302_GetTime();
LCD_ShowNum(1,1,DS1302_CurrentTime[0],2);
LCD_ShowNum(1,4,DS1302_CurrentTime[1],2);
LCD_ShowNum(1,7,DS1302_CurrentTime[2],2);
LCD_ShowNum(2,1,DS1302_CurrentTime[3],2);
LCD_ShowNum(2,4,DS1302_CurrentTime[4],2);
LCD_ShowNum(2,7,DS1302_CurrentTime[5],2);
}
}
4-2、按键操作
Figure10. 按键调节时间编码
c
#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Key.h"
#include "Timer0.h"
unsigned char KeyNum;
unsigned char Mode;
unsigned char TimeSetSelect;
unsigned char TimeFlashFlag;
void TimeShow(void)
{
DS1302_GetTime();
LCD_ShowNum(1,1,DS1302_CurrentTime[0],2);
LCD_ShowNum(1,4,DS1302_CurrentTime[1],2);
LCD_ShowNum(1,7,DS1302_CurrentTime[2],2);
LCD_ShowNum(2,1,DS1302_CurrentTime[3],2);
LCD_ShowNum(2,4,DS1302_CurrentTime[4],2);
LCD_ShowNum(2,7,DS1302_CurrentTime[5],2);
}
void TimeSet(void)
{
if(KeyNum == 2)
{
TimeSetSelect++;
TimeSetSelect %= 6; /* Out of range to clear. */
}
if(KeyNum == 3)
{
DS1302_CurrentTime[TimeSetSelect]++;
if(DS1302_CurrentTime[0] > 99) /* Year */
{
DS1302_CurrentTime[0] == 0;
}
if(DS1302_CurrentTime[1] > 12) /* Month */
{
DS1302_CurrentTime[1] == 1;
}
if((DS1302_CurrentTime[1] == 1) || (DS1302_CurrentTime[1] == 3) || (DS1302_CurrentTime[1] == 5) || (DS1302_CurrentTime[1] == 7)
|| (DS1302_CurrentTime[1] == 8) || (DS1302_CurrentTime[1] == 10) || (DS1302_CurrentTime[1] == 12))
{
if(DS1302_CurrentTime[1] > 31) /* Day */
{
DS1302_CurrentTime[2] == 1;
}
}
else if ((DS1302_CurrentTime[1] == 4) || (DS1302_CurrentTime[1] == 6) || (DS1302_CurrentTime[1] == 9) || (DS1302_CurrentTime[1] == 11))
{
if(DS1302_CurrentTime[1] > 30) /* Day */
{
DS1302_CurrentTime[2] == 1;
}
}
else if(DS1302_CurrentTime[1] == 2)
{
if(DS1302_CurrentTime[0] % 4 ==0 )
{
if(DS1302_CurrentTime[1] > 29) /* Day */
{
DS1302_CurrentTime[2] == 1;
}
}
else
{
if(DS1302_CurrentTime[1] > 28) /* Day */
{
DS1302_CurrentTime[2] == 1;
}
}
}
if(DS1302_CurrentTime[3] > 23) /* Hour */
{
DS1302_CurrentTime[3] == 0;
}
if(DS1302_CurrentTime[4] > 59) /* Mins */
{
DS1302_CurrentTime[4] == 0;
}
if(DS1302_CurrentTime[5] > 59) /* Seconds */
{
DS1302_CurrentTime[5] == 0;
}
}
if(KeyNum == 4)
{
DS1302_CurrentTime[TimeSetSelect]--;
if(DS1302_CurrentTime[0] < 0) /* Year */
{
DS1302_CurrentTime[0] == 99;
}
if(DS1302_CurrentTime[1] < 1) /* Month */
{
DS1302_CurrentTime[1] == 12;
}
if((DS1302_CurrentTime[1] == 1) || (DS1302_CurrentTime[1] == 3) || (DS1302_CurrentTime[1] == 5) || (DS1302_CurrentTime[1] == 7)
|| (DS1302_CurrentTime[1] == 8) || (DS1302_CurrentTime[1] == 10) || (DS1302_CurrentTime[1] == 12))
{
if(DS1302_CurrentTime[1] < 1) /* Day */
{
DS1302_CurrentTime[2] == 31;
}
else if(DS1302_CurrentTime[1] > 31) /* Day */
{
DS1302_CurrentTime[2] == 1;
}
}
else if ((DS1302_CurrentTime[1] == 4) || (DS1302_CurrentTime[1] == 6) || (DS1302_CurrentTime[1] == 9) || (DS1302_CurrentTime[1] == 11))
{
if(DS1302_CurrentTime[1] < 1) /* Day */
{
DS1302_CurrentTime[2] == 30;
}
else if(DS1302_CurrentTime[1] > 30) /* Day */
{
DS1302_CurrentTime[2] == 1;
}
}
else if(DS1302_CurrentTime[1] == 2)
{
if(DS1302_CurrentTime[0] % 4 ==0 )
{
if(DS1302_CurrentTime[1] < 1) /* Day */
{
DS1302_CurrentTime[2] == 29;
}
else if(DS1302_CurrentTime[1] > 29) /* Day */
{
DS1302_CurrentTime[2] == 1;
}
}
else
{
if(DS1302_CurrentTime[1] < 1) /* Day */
{
DS1302_CurrentTime[2] == 28;
}
else if(DS1302_CurrentTime[1] > 28) /* Day */
{
DS1302_CurrentTime[2] == 1;
}
}
}
if(DS1302_CurrentTime[3] < 0) /* Hour */
{
DS1302_CurrentTime[3] == 23;
}
if(DS1302_CurrentTime[4] < 0) /* Mins */
{
DS1302_CurrentTime[4] == 59;
}
if(DS1302_CurrentTime[5] < 0) /* Seconds */
{
DS1302_CurrentTime[5] == 59;
}
}
if((TimeSetSelect == 0) && (TimeFlashFlag == 1))
{
LCD_ShowString(1,1," ");
}
else
{
LCD_ShowNum(1,1,DS1302_CurrentTime[0],2);
}
if((TimeSetSelect == 1) && (TimeFlashFlag == 1))
{
LCD_ShowString(1,4," ");
}
else
{
LCD_ShowNum(1,4,DS1302_CurrentTime[1],2);
}
if((TimeSetSelect == 2) && (TimeFlashFlag == 1))
{
LCD_ShowString(1,7," ");
}
else
{
LCD_ShowNum(1,7,DS1302_CurrentTime[2],2);
}
if((TimeSetSelect == 3) && (TimeFlashFlag == 1))
{
LCD_ShowString(2,1," ");
}
else
{
LCD_ShowNum(2,1,DS1302_CurrentTime[3],2);
}
if((TimeSetSelect == 4) && (TimeFlashFlag == 1))
{
LCD_ShowString(2,4," ");
}
else
{
LCD_ShowNum(2,4,DS1302_CurrentTime[4],2);
}
if((TimeSetSelect == 5) && (TimeFlashFlag == 1))
{
LCD_ShowString(2,7," ");
}
else
{
LCD_ShowNum(2,7,DS1302_CurrentTime[5],2);
}
LCD_ShowNum(2,10,TimeSetSelect,2);
LCD_ShowNum(2,13,TimeFlashFlag,2);
}
void main(void)
{
LCD_Init();
DS1302_Init();
Timer0_Init();
DS1302_SetTime();
LCD_ShowString(1,1," - - ");
LCD_ShowString(2,1," : : ");
while(1)
{
KeyNum = Key();
if(KeyNum)
{
if(Mode == 0)
{
Mode = 1;
}
else if(Mode == 1)
{
Mode = 0;
DS1302_SetTime();
}
}
switch(Mode)
{
case 0:TimeShow();break;
case 1:TimeSet();break;
}
}
}
void Timer0_Isr(void) interrupt 1
{
static unsigned int T0Cnt;
/* Inhibit timer0 count overflow. */
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
T0Cnt++;
if(T0Cnt >= 500) //1s = 1000ms
{
T0Cnt = 0;
TimeFlashFlag = !TimeFlashFlag; /* 0 or 1 */
}
}
4-3、实验结果
Figure11. 按键调节时间实验结果
参考资料
- DS1302实时时钟
- 51单片机入门教程-2020版 程序全程纯手打 从零开始入门