专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

基于单片机、DS1302、DS1602的电子时钟,可以设置时间日期

作者:佚名   来源:不详   点击数:  更新时间:2014年08月17日   【字体:

 

 
 
 这是DS1602+DS1302完整程序,其中P1口接独立键盘。
 
DS1602部分:
 
# include "SYSTEM.H"             
 
//#ifndef __LCD1602_8_H__
//#define __LCD1602_8_H__
 
 
 
//LCD接口定义     
sfr   io = 0x80;    //P0-0x80,P1-0x90,P2-0xA0,P3-0xB0;
sbit  rs = P2^6;    //LCD数据/命令选择端(H/L)
sbit  rw = P2^5;    //LCD读/写选择端(H/L)
sbit  ep = P2^7;    //LCD使能控制
sbit     bz = io^7;    //LCD忙标志位
 
 
//函数声明  
void lcd_busy(void);     //测试LCD忙碌状态程序
void lcd_wcmd(unsigned char cmd);  //写入指令到LCD程序
void lcd_wdat(unsigned char dat);  //写入数据到LCD程序
void lcd_pos (unsigned char x, bit y); //LCD数据指针位置程序
void lcd_sef_chr();
//void printc(unsigned char CHAR);  //显示字符
 
void lcd_init(void);     //LCD初始化设定程序
 
 
//测试LCD忙碌状态
void lcd_busy(void)
 do{
  ep = 0;
  rs = 0;  //指令
  rw = 1;  //读出
  io = 0xff;
  ep = 1;
  _nop_(); //高电平读出 1us 
 }while(bz);  //bz=1表示忙,bz=0表示空闲
 ep = 0;  
}
 
 
//写入指令到LCD
void lcd_wcmd(unsigned char cmd)
{       
 lcd_busy(); //检测忙
 rs = 0;  //指令
 rw = 0;  //写入
 ep = 1; 
 io = cmd; //指令
 ep = 0;  //下降沿有效 
}
 
 
//写入数据函数
void lcd_wdat(unsigned char Data)
{
 lcd_busy();  //检测忙
 rs = 1;   //数据
 rw = 0;   //写入
 ep = 1;
 io = Data;  //数据
 ep = 0;   //下降沿有效
}
 
 
//LCD数据指针位置程序
void lcd_pos(unsigned char x, bit y)
{      
 if(y)lcd_wcmd(x|0xc0); //y=1,第二行显示;y=0,第一行显示  0<=x<16
 else lcd_wcmd(x|0x80); //数据指针=80+地址码(00H~27H,40H~67H)
  
}
 
 
//显示字符
//
void printc(unsigned char CHAR)
{
 lcd_wdat(CHAR);
}
//
 
 
//显示字符串
void prints(unsigned char //string)
{
 //unsigned char i;
 //do{lcd_wdat(string[i]);i++;}while(string[i]!='\0');//生成代码比for循环大
 for(i=0;string[i]!='\0';i++)lcd_wdat(string[i]);  //有时用for循环也好哈//
 
 while(//string) {lcd_wdat(//string);string++;}
 
}
 
 
 
 
//LCD初始化设定
void lcd_init()
{      
 lcd_wcmd(0x38);  //设置LCD为16X2显示,5X7点阵,八位数据接口
 lcd_wcmd(0x06);  //LCD显示光标移动设置(光标地址指针加1,整屏显示不移动)
 lcd_wcmd(0x0c);  //LCD开显示及光标设置(光标不闪烁,不显示"_")
 lcd_wcmd(0x01);  //清除LCD的显示内容
 
}
 
 
DS1302部分:
 
# include "SYSTEM.H"
 
 
//#ifndef __DS1302_A_H__
//#define __DS1302_A_H__
 
 
 
//引脚及位的定义
sbit DS1302_CLK = P3^6;   //时钟引脚
sbit DS1302_IO  = P3^4;   //数据引脚
sbit DS1302_RST = P3^5;   //复位引脚
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
 
 
//函数声明
void DS1302_InputByte(unchar Data);           //写入一个字节(内部函数)
unchar DS1302_OutputByte(void);               //读取一个字节(内部函数)
void Write1302(unchar Address, unchar Data);  //在指定地址写入指定的数据
unchar Read1302(unchar Address);              //读取DS1302指定地址中的数据
void DS1302_SetProtect(bit Flag);             //DS1302是否写入保护
void DS1302_SetTime(unchar Address, unchar Value);//设置时间函数
void DS1302_GetTime(SYSTEMTIME *Time);        //读出时间
void DateToStr(SYSTEMTIME *Time);             //日期转化成字符
void TimeToStr(SYSTEMTIME *Time);             //时间转化成字符
void DS1302_Initial (void);                   //DS1302初始化
 
//写入一个字节(内部函数)
void DS1302_InputByte(unchar Data) 
{
 unchar i;
 ACC = Data;
 for(i=8; i>0; i--)
 { 
  DS1302_CLK = 0;  
  DS1302_IO = ACC0; //由低位到高位  
  DS1302_CLK = 1;  //上升沿写入数据
  ACC >>= 1;
 }
}
 
 
 
//读取一个字节(内部函数)
unchar DS1302_OutputByte(void)
{
 unchar i;
 for(i=8; i>0; i--)
 {   
  DS1302_CLK = 0;      //下降沿读出DS1302的数据
  ACC >>= 1;    //读出由低到高位,只能移7次有效位!!!
  ACC7 = DS1302_IO;  //第一个数据           
  DS1302_CLK = 1;         
 }      
 return (ACC);
}
 
 
//在指定地址写入指定的数据
void Write1302(unchar Address, unchar Data)
{
 DS1302_RST = 0;
 DS1302_CLK = 0;
 DS1302_RST = 1;
 DS1302_InputByte(Address);
 DS1302_InputByte(Data);
 DS1302_CLK = 1;
 DS1302_RST = 0;
}
 
 
//读取1302指定地址中的数据
unchar Read1302(unchar Address)
{
 unchar Data;
 DS1302_RST = 0;
 DS1302_CLK = 0;
 DS1302_RST = 1;       //RST拉高,启动数据传送
 DS1302_InputByte(Address|0x01);//读取指定地址数据指令
 Data = DS1302_OutputByte();
 DS1302_CLK = 1;
 DS1302_RST = 0;
 return (Data);
}
 
//是否写入保护
void DS1302_SetProtect(bit Flag)
{
 if(Flag)
  Write1302(0x8E,0x80);  //0x8e控制字节地址,bit7=WP WP=1 禁止数据写入DS1302
 else
  Write1302(0x8E,0x00);  //WP=0 允许数据写入DS1302
}
 
 
//设置时间函数
void DS1302_SetTime(unchar Address, unchar Value)
{
 DS1302_SetProtect(0);
 Write1302(Address,((Value/10)<<4|(Value)));
 DS1302_SetProtect(1);
 
}
 
 
//读出时间
void DS1302_GetTime(SYSTEMTIME *Time)
{
 unchar ReadValue;
 ReadValue = Read1302(DS1302_SECOND);
 Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0f);
 ReadValue = Read1302(DS1302_MINUTE);
 Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0f);
 ReadValue = Read1302(DS1302_HOUR);
 Time->Hour   = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0f);
 ReadValue = Read1302(DS1302_DAY);
 Time->Day    = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0f);
 ReadValue = Read1302(DS1302_WEEK);
 Time->Week   = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0f);
 ReadValue = Read1302(DS1302_MONTH);
 Time->Month  = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0f);
 ReadValue = Read1302(DS1302_YEAR);
 Time->Year   = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0f);
}
 
 
//日期转化成字符
void DateToStr(SYSTEMTIME *Time)
{
 Time->DateString[0] = Time->Year/10 + '0';
 Time->DateString[1] = Time->Year + '0';
 Time->DateString[2] = '-';
 Time->DateString[3] = Time->Month/10 + '0';
 Time->DateString[4] = Time->Month + '0';
 Time->DateString[5] = '-';
 Time->DateString[6] = Time->Day/10 + '0';
 Time->DateString[7] = Time->Day + '0';
 Time->DateString[8] = '\0';
}
 
 
//时间转化成字符
void TimeToStr(SYSTEMTIME *Time)
{
 Time->TimeString[0] = Time->Hour/10 + '0';
 Time->TimeString[1] = Time->Hour + '0';
 Time->TimeString[2] = ':';
 Time->TimeString[3] = Time->Minute/10 + '0';
 Time->TimeString[4] = Time->Minute + '0';
 Time->TimeString[5] = ':';
 Time->TimeString[6] = Time->Second/10 + '0';
 Time->TimeString[7] = Time->Second + '0';
 Time->TimeString[8] = '\0';
}
 
 
//初始化DS1302
void DS1302_Initial (void)
{
 unchar Second=Read1302(DS1302_SECOND);
 if(Second&0x80)//bit7=CH CH=0 振荡器允许工作,CH=1振荡器停止工作
 DS1302_SetTime(DS1302_SECOND,0);
 
}
 
函数声明SYSTEM.H:
 
 
//包含头文件
#include<REG52.H>
#include <intrins.h>
//#include"LCD1602_8.H"
//#include"DS1302_A.H"
 
//P0 Bit Registers
 
sbit P0_0 = 0x80;
sbit P0_1 = 0x81;
sbit P0_2 = 0x82;
sbit P0_3 = 0x83;
sbit P0_4 = 0x84;
sbit P0_5 = 0x85;
sbit P0_6 = 0x86;
sbit P0_7 = 0x87;
 
 
//P1 Bit Registers
 
sbit P1_0 = 0x90;
sbit P1_1 = 0x91;
sbit P1_2 = 0x92;
sbit P1_3 = 0x93;
sbit P1_4 = 0x94;
sbit P1_5 = 0x95;
sbit P1_6 = 0x96;
sbit P1_7 = 0x97;
 
//P2 Bit Registers
sbit P2_0 = 0xA0;
sbit P2_1 = 0xA1;
sbit P2_2 = 0xA2;
sbit P2_3 = 0xA3;
sbit P2_4 = 0xA4;
sbit P2_5 = 0xA5;
sbit P2_6 = 0xA6;
sbit P2_7 = 0xA7;
 
 
//P3 Bit Registers (Mnemonics & Ports)
sbit P3_0 = 0xB0;
sbit P3_1 = 0xB1;
sbit P3_2 = 0xB2;
sbit P3_3 = 0xB3;
sbit P3_4 = 0xB4;
sbit P3_5 = 0xB5;
sbit P3_6 = 0xB6;
sbit P3_7 = 0xB7;
 
 
//宏定义便于理解
#define unchar unsigned char
#define unint  unsigned int
#define DS1302_SECOND      0x80
#define DS1302_MINUTE      0x82
#define DS1302_HOUR        0x84
#define DS1302_WEEK        0x8A
#define DS1302_DAY         0x86
#define DS1302_MONTH       0x88
#define DS1302_YEAR        0x8C
#define DS1302_RAM(X)      (0xC0+(X)*2) 
//用于计算RAM地址的宏运算
 
//定义时间类型
typedef struct _SYSTEMTIME_
{
 unchar Second;
 unchar Minute;
 unchar Hour;
 unchar Week;
 unchar Day;
 unchar Month;
 unchar Year;
 unchar DateString[9];
 unchar TimeString[9];
}SYSTEMTIME;   
 
 
 
//LCD1602外部引用函数
extern void lcd_init(void);  //LCD初始化设定程序
extern void prints(unsigned char *string); //显示字符串
extern void lcd_pos (unsigned char x, bit y); //LCD数据指针位置程序
extern void lcd_sef_chr() ;
extern void lcd_wcmd(unsigned char cmd);//写入指令到LCD程序
 
 
//*DS1302外部引用函数
extern void DS1302_SetTime(unchar Address, unchar Value);  //设置时间函数
extern void DS1302_Initial (void);                         //DS1302初始化
extern void DS1302_GetTime(SYSTEMTIME *Time);              //读出时间
extern void DateToStr(SYSTEMTIME *Time);                   //日期转化成字符
extern void TimeToStr(SYSTEMTIME *Time);                   //时间转化成字符
 
 
 
 
MAIN函数部分:
 
#include "SYSTEM.H"
SYSTEMTIME CurrentTime;
 
unsigned char k = 0; //键值
unsigned char K1,K2,K3,M1,M2,M3,K1J,K2J,K3J,K4J; //键值
unsigned char Set; //调整值
char Set_Mode = 0;
 
void Keysan(void);
void delay200ms(void);
//主函数
void main(void)
 lcd_init();
 //lcd_sef_chr(); //写入自定义字符号
 DS1302_Initial();
 
  lcd_pos(0,0);
  prints("Date:");
  lcd_pos(0,1);
     prints("Time:");
 k = 6;  //不改变时间 
    while(1)
 {
   Keysan();
     DS1302_GetTime(&CurrentTime);
  DateToStr(&CurrentTime);
  TimeToStr(&CurrentTime);  
  lcd_pos(6,0);
  prints(CurrentTime.DateString);
  lcd_pos(6,1);
  prints(CurrentTime.TimeString);
 
  //lcd_pos(7,0);
     //lcd_wcmd(0x0E);
 
  delay200ms();
  
 }
}
 
//键盘扫描
void Keysan(void)
{
 
    if(~P1_2&K1J)   { k++;  }
   K1J=~(~P1_2);
 
    if(~P1_3&K2J)    { Set++; }
    K2J=~(~P1_3);
 
 if(~P1_4&K3J)    { Set--; }
   K3J=~(~P1_4);
 
    if(k == 7) {k = 0; }
 
 switch(k)
 {
   case 0: DS1302_SetTime(DS1302_SECOND, Set&0x3f); break;
   case 1: DS1302_SetTime(DS1302_MINUTE, Set&0x3f); break;
   case 2: DS1302_SetTime(DS1302_HOUR  , Set&0x1f); break;
   case 3: DS1302_SetTime(DS1302_DAY   , Set&0x0f); break;
   case 4: DS1302_SetTime(DS1302_MONTH , Set&0x0f); break;
   case 5: DS1302_SetTime(DS1302_YEAR  , Set&0x7f); break;
   default: break;
 }
}
//延时200000+0us 函数定义
void delay200ms(void)
{
   unsigned char i,j,k;
   for(i=201;i>0;i--)
   for(j=32;j>0;j--)
   for(k=14;k>0;k--);
}
 
 
 
 
关闭窗口