`
yunchow
  • 浏览: 324476 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

51单片机操作DS1302时钟芯片

阅读更多
这是我做的最后一个单片机的实验了,不过没有把程序调通,先作个记号,以后如有时间再来慢慢调



头文件
#define uint unsigned int
#define uchar unsigned char

sbit lcdrs = P1^0;
sbit lcdrw = P1^1;
sbit lcden = P1^2;

sbit key0 = P2^0;//功能键,选择时分秒
sbit key1 = P2^1;//加1键
sbit key2 = P2^2;//减1键
sbit key4 = P2^4;
sbit clk_1302 = P1^5; //1302芯片位定义
sbit io_1302 = P1^6;
sbit rst_1302 = P1^7;
uchar bdata dat;
sbit dat0 = dat^0;
sbit dat7 = dat^7;

uchar key0_count;//按键0被按的次数(0~3)
uchar flag;
char hour,minute,second;
uchar table_date[] = "2009-4-12  Mon";
uchar table_time[] = "00:00:00";

/****** 函数申明 ********/
void write_cmd_1602(uchar cmd);
void write_data_1602(uchar dat);
void write_add(uchar add,uchar dat);
void init1602();
void delay(uint z);
uchar reverse(uchar c);
void keyscan();
void init();
void RTC_initial ();

void wr_1302(uchar wr_data);
uchar rd_1302(void);
uchar uc_R1302(uchar ucAddr);
void v_W1302(uchar ucAddr, uchar ucDa);

主程序
#include <reg52.h>
#include <intrins.h>
#include "header.h"

/****** 主函数 ********/
void main()
{
	RTC_initial();
	init();
	//init1602();
	//while(1);
	while(1)
	{
		if(flag)
		{
			second = uc_R1302(0x81);
			minute = uc_R1302(0x83);
			hour = uc_R1302(0x85);
			write_add(0x40+10,second);
			write_add(0x40+7,minute);
			write_add(0x40+4,hour);
		}
		keyscan();
		delay(1);
	}
}
void RTC_initial ()
{
	v_W1302(0x8e,0x00);	  //使能
	v_W1302(0x80,0x80);	  //停止晶振
	v_W1302(0x90,0x00);	  //关闭充电
	v_W1302(0x8c,0x07);	  //设置年
	v_W1302(0x8a,0x06);	  //设置周
	v_W1302(0x88,0x01);	  //设置月
	v_W1302(0x86,0x13);	  //设置日
	v_W1302(0x84,0x18);	  //设置小时
	v_W1302(0x82,0x05);	  //设置分
	v_W1302(0x80,0x00);	  //启动晶振,设置秒
	v_W1302(0x8e,0x80);	  //使能
}
/*****************************
* 功  能: 往DS1302写入1Byte数据
* 输  入: wr_data写入的数据
* 返回值: 无
*******************************/
void wr_1302(uchar wr_data)
{
	uchar i = 0;
	dat = wr_data;
	rst_1302 = 1;
	clk_1302 = 0;
	delay(5);
	for(i=0;i<8;i++)
	{
		io_1302 = dat0;
		clk_1302 = 0;
		_nop_();
		clk_1302 = 1;
		_nop_();	
		dat >>= 1;
	}
	//rst_1302 = 0;	
}
/*****************************
* 功  能: 从DS1302读出1Byte数据
* 返回值: dat
*******************************/
uchar rd_1302(void)
{
	uchar i;
	rst_1302 = 1;
	clk_1302 = 1;
	delay(5);
	for(i=0;i<8;i++)
	{
		dat >>= 1;
		dat7 = io_1302;
		clk_1302 = 1;
		_nop_();
		_nop_();
		clk_1302 = 0;
		_nop_();
	}
	rst_1302 = 0;
	return dat;
}
/******************************************************************** 
* 名  称: uc_R1302
* 说  明: 先写地址,后读命令/数据
* 功  能: 读取DS1302某地址的数据
* 调  用: v_RTInputByte() , uc_RTOutputByte()
* 输  入: ucAddr: DS1302地址
* 返回值: ucDa :读取的数据
***********************************************************************/
uchar uc_R1302(uchar add)
{
	uchar temp= 0xff;
	wr_1302(add);
	temp = rd_1302();		
	return temp;
}

/******************************************************************** 
* 名  称: v_W1302
* 说  明: 先写地址,后写命令/数据
* 功  能: 往DS1302写入数据
* 调  用: v_RTInputByte() 
* 输  入: ucAddr: DS1302地址, ucDa: 要写的数据
* 返回值: 无
**********************************************************************/
void v_W1302(uchar ucAddr, uchar ucDa)
{
	wr_1302(ucAddr);	
	wr_1302(ucDa);
	rst_1302 = 0;
	clk_1302 = 0;
} 
//1602液晶初始化
void init1602()
{
	lcdrw = 0;  		   //本程序只读不写,故将其置低
	lcden = 0;			   //关闭1602
	delay(5);
	write_cmd_1602(0x01);  //清屏
	write_cmd_1602(0x38);  //显示模式
	write_cmd_1602(0x0c);  //开显示,不显示光标,不闪烁
	write_cmd_1602(0x06);  //地址指针自动加1
	write_cmd_1602(0x80+1);//将光标指向第一行第二个位置
	delay(5);
}
void delay(uint z)
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);
}
/** 将发送的数据进行翻转,高位到低位,低位转到高位 **/   
uchar reverse(uchar c)   
{   
   uchar chbuff=0;   
   if (c&0x01) chbuff=chbuff|0x80;   
   if (c&0x02) chbuff=chbuff|0x40;   
   if (c&0x04) chbuff=chbuff|0x20;   
   if (c&0x08) chbuff=chbuff|0x10;   
   if (c&0x10) chbuff=chbuff|0x08;   
   if (c&0x20) chbuff=chbuff|0x04;   
   if (c&0x40) chbuff=chbuff|0x02;   
   if (c&0x80) chbuff=chbuff|0x01;   
   return chbuff;   
}
//向液晶写命令
void write_cmd_1602(uchar cmd)
{
	lcdrs = 0; //低表示写命令,高表示写数据
	delay(5);
	P0 = reverse(cmd);
	delay(5);
	lcden = 1; //给一个高脉冲
	delay(5);	
	lcden = 0;
	delay(5);
}
//向液晶写数据
void write_data_1602(uchar dat)
{
	lcdrs = 1; //低表示写命令,高表示写数据
	delay(5);
	P0 = reverse(dat);
	delay(5);
	lcden = 1; //给一个高脉冲
	delay(5);	
	lcden = 0;
	delay(5);
} 
//根据地址向液晶写数据
void write_add(uchar add,uchar dat)
{
	uchar shi,ge;
	shi = dat/10;
	ge = dat%10;
	delay(5);
	write_cmd_1602(0x80+add);
	write_data_1602(shi+0x30);
	delay(5);
	write_data_1602(ge+0x30);
}
//键盘扫描函数
void keyscan()
{
 	key4 = 0;
	if(0==key0) //第一个键被按下
	{
	 	delay(5); //消抖
		if(0==key0)
		{
			key0_count ++;
			if(4==key0_count)
			{
				key0_count = 0;
				flag = 1;
			}
			while(!key0); //松手检测
			flag = 0;
			if(0==key0_count)
			{
				flag = 0; 
				write_cmd_1602(0x0c);  //禁止显示光标并不让其闪烁	
			}
			if(1==key0_count)
			{
				flag = 0;
				write_cmd_1602(0x80+0x40+11);//将地址指针指向秒的位置
				write_cmd_1602(0x0f);  //显示光标并闪烁
				delay(5);	
			}
			if(2==key0_count)
			{
				flag = 0;
				write_cmd_1602(0x80+0x40+8);//将地址指针指向分的位置
				write_cmd_1602(0x0f);  //显示光标并闪烁
				delay(5);
			}
			if(3==key0_count)
			{
				flag = 0;
				write_cmd_1602(0x80+0x40+5);//将地址指针指向小时的位置
				write_cmd_1602(0x0f);  //显示光标并闪烁	
				delay(5);
			}
		}
	}
	if(0==key1) //第二个键被按下
	{
	 	delay(5); //消抖
		if(0==key1)
		{
			while(!key1); //松手检测
			flag = 0;
			if(key0_count==1)
			{
				second ++;
				if(60==second)	
					second = 0;
				 write_add(0x40+10,second);
				 v_W1302(0x80,second);
			}
			if(key0_count==2)
			{
				minute ++;
				if(60==minute)	
					minute = 0;
				 write_add(0x40+7,minute);
				 v_W1302(0x82,minute);
			}
			if(key0_count==3)
			{
				hour ++;
				if(24==hour)	
					hour = 0;
				 write_add(0x40+4,hour);
				 v_W1302(0x84,hour);
			}
		}
	}
	if(0==key2) //第三个键被按下
	{
	 	delay(5); //消抖
		if(0==key2)
		{
			while(!key2); //松手检测
			flag = 0;
			if(key0_count==1)
			{
				second --;
				if(-1==second)	
					second = 59;
				write_add(0x40+10,second);
				v_W1302(0x80,second);	
			}
			if(key0_count==2)
			{
				minute --;
				if(-1==minute)	
					minute = 59;
				write_add(0x40+7,minute);
				v_W1302(0x82,minute);	
			}
			if(key0_count==3)
			{
				hour --;
				if(-1==hour)	
					hour = 23;
				write_add(0x40+4,hour);
				v_W1302(0x84,hour);	
			}
		}
	}

}
//程序初始化函数
void init()
{
	uchar i;
	flag = 1;
	hour = 0;
	minute = 0;
	second = 0;
	init1602();
	delay(20);  //延长时间,确保液晶处于非忙状态
	for(i=0;i<14;i++)
	{
		write_data_1602(table_date[i]);
		delay(5);	
	}
	write_cmd_1602(0x80+0x40+4);  //调整地址指针
	for (i=0;i<8;i++)
	{
		write_data_1602(table_time[i]);
		delay(5);	
	}
	delay(50);
	v_W1302(0x81,25);
	v_W1302(0x83,48);
	v_W1302(0x85,10);
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics