20141108 【 单片机——万年历DS1302——中断 】 用DS1302模块 & 数码管显示万年历

不得不说,DS1302的接口规则挺麻烦的,不查规格书不好用啊。

【我是菜鸟,感觉就算是大神,也不会背着玩意吧。。】



8个八段数码管显示:

【1】 星期 . 上午下午 . 小时 . 分钟 . 秒钟

【2】 年份 . 月份 . 天数 



10/11的时间显示 状态【1】:星期(占1,显示1~7),上午下午(占1,显示“A”或“P”),小时(占2,十二小时制显示00~12),分钟(占2,显示00~59),秒钟(占2,显示00~59)。


  1/11的时间显示 状态【2】:年份(占4,显示2000~2099),月份(占2,显示1~12),天数(占2,显示00~day[ 平年/闰年+月份 ])。




战果:

搞了老半天,最终还是跪在 DS1302的读写函数 上。

最后面把标程的 DS1302的读写函数 拷贝来用,就成了。

【原来的 DS1302读写函数 在下面代码的注释区那里,有空再查吧!!】













#include <reg52.h>
#include <intrins.h>


#define uint		unsigned int
#define uchar		unsigned char
#define DIGIT_MAX	16
#define LCD			P0	
#define LCD_BIN		P2

const uchar digital[DIGIT_MAX+5] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x80};		
// 0123456789 AbCdEF.  + 17

const uchar digital_bin[8] = {0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF};
//{0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C};	    

const uint TIME_H = (65536 - 9174)/256;	//0x9C;		// 0x9C~100us  1000us/1.09us = 921.6
const uint TIME_L = (65536 - 9174)%256;	//0x9C;
uint TIME;
void Timer0_int1_init();
void delay(uint dt);


const uchar DS_Rbin[8] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8B, 0x8D, 0x8F};
//	DS1302	Read-register
const uchar DS_Wbin[8] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E};
//	DS1302	Write-register

sbit SCLK = P3^6;
sbit DSIO = P3^4;	//IO		
sbit RST = P3^5;	//CE

uchar LCD_CHOOSE;


void DS1302_write(uchar addr, uchar dat)
{    
	uchar n;

    EA = 0;
	RST = 0;
	_nop_();

	SCLK = 0;//先将SCLK置低电平。
	_nop_();
	RST = 1; //然后将RST(CE)置高电平。
	_nop_();

	for (n=0; n<8; n++)//开始传送八位地址命令
	{
		DSIO = addr & 0x01;//数据从低位开始传送
		addr >>= 1;
		SCLK = 1;//数据在上升沿时,DS1302读取数据
		_nop_();
		SCLK = 0;
		_nop_();
	}
	for (n=0; n<8; n++)//写入8位数据
	{
		DSIO = dat & 0x01;
		dat >>= 1;
		SCLK = 1;//数据在上升沿时,DS1302读取数据
		_nop_();
		SCLK = 0;
		_nop_();	
	}	
		 
	RST = 0;//传送数据结束
	_nop_();
    EA = 1;
}

uchar DS1302_read(uchar addr)
{   
    uchar n,dat,dat1;
    
    EA =0;
	RST = 0;
	_nop_();

	SCLK = 0;//先将SCLK置低电平。
	_nop_();
	RST = 1;//然后将RST(CE)置高电平。
	_nop_();

	for(n=0; n<8; n++)//开始传送八位地址命令
	{
		DSIO = addr & 0x01;//数据从低位开始传送
		addr >>= 1;
		SCLK = 1;//数据在上升沿时,DS1302读取数据
		_nop_();
		SCLK = 0;//DS1302下降沿时,放置数据
		_nop_();
	}
	_nop_();
	for(n=0; n<8; n++)//读取8位数据
	{
		dat1 = DSIO;//从最低位开始接收
		dat = (dat>>1) | (dat1<<7);
		SCLK = 1;
		_nop_();
		SCLK = 0;//DS1302下降沿时,放置数据
		_nop_();
	}

	RST = 0;
	_nop_();	//以下为DS1302复位的稳定时间,必须的。
	SCLK = 1;
	_nop_();
	DSIO = 0;
	_nop_();
	DSIO = 1;
	_nop_();
    EA = 1;
	return dat;	
}




uchar DS_dat[8] = {0x00, 0x30, 0xB1, 0x01, 0x11, 0x12, 0x00};
//	second - minth - hour[A/P] - day - month - weeken - year - protect
uchar LCD_now[8];

void DS1302_init(){
	uchar i;
	DS1302_write(DS_Wbin[7], 0x00);
	for(i=0; i<7; i++){
		DS1302_write(DS_Wbin[i], DS_dat[i]);
	}
	DS1302_write(DS_Wbin[7], 0x80);
}

void DS1302_now(){
	uchar i;
	for(i=0; i<7; i++)
		DS_dat[i] = DS1302_read( DS_Rbin[i] );
}

void skip_init(); 
void main(){
	uint i=0, cnt;
	skip_init();
	
	DS1302_init();
	while( 1 ){
		for(cnt=10000; cnt; cnt--){
			DS1302_now();
			LCD_now[7] = digital[ DS_dat[0]&0x0F ];		  
			LCD_now[6] = digital[ DS_dat[0]>>4 ];	
			LCD_now[5] = digital[ DS_dat[1]&0x0F ] | 0x80;	
			LCD_now[4] = digital[ DS_dat[1]>>4 ];	
			LCD_now[3] = digital[ DS_dat[2]&0x0F ] | 0x80;	
			LCD_now[2] = digital[ (DS_dat[2]>>4)&1 ];	
			LCD_now[1] = DS_dat[2]&0x20 ? 0xF7 : 0xF3;	
			LCD_now[0] = digital[ DS_dat[5]&0x0F ] | 0x80;		
		}
		for(cnt=1000; cnt; cnt--) {
			DS1302_now();
			LCD_now[7] = digital[ DS_dat[3]&0x0F ];		  
			LCD_now[6] = digital[ DS_dat[3]>>4 ];	
			LCD_now[5] = digital[ DS_dat[4]&0x0F ] | 0x80;	
			LCD_now[4] = digital[ DS_dat[4]>>4 ];	
			LCD_now[3] = digital[ DS_dat[6]&0x0F ] | 0x80;	
			LCD_now[2] = digital[ DS_dat[6]>>4 ];	
			LCD_now[1] = 0x3F;	
			LCD_now[0] = 0x5B;
		}
	}
}

void skip_init(){
	TMOD = 0x02;   		//定时器模式
	TH0 = TIME_H;
	TL0 = TIME_L;

	EA = 1;
	ET0 = 1;
	TR0 = 1;
}  
void skip()	interrupt 1{
	LCD = 0x00;
	LCD_BIN = digital_bin[ 7-LCD_CHOOSE ];
	LCD = LCD_now[ LCD_CHOOSE ];
	LCD_CHOOSE = ( ++LCD_CHOOSE )&0x07;
}


/*


uchar DS1302_read(uchar addr){
	uchar i, res;
	EA = 0;
	RST = 0;	_nop_();
	SCLK = 0;	_nop_();
	RST = 1;	_nop_();
	for(i=0; i<8; i++){
		DSIO = (addr>>i) & 0x01;
		SCLK=1;	_nop_();		//DS1302 读数据
		SCLK=0;	_nop_();		//DS1302 存数据
	}
	_nop_();
	for(i=7; i>=0; i--){
		res |= (uchar)DSIO<<i;
		SCLK=1;	_nop_();		//DS1302 读数据
		SCLK=0;	_nop_();		//DS1302 存数据
	}
	RST = 0;	_nop_();		//下面 DS1302复位的稳定时间,必须的。
	SCLK = 1;	_nop_();
	DSIO = 0;	_nop_();
	DSIO = 1;	_nop_();
	EA = 1;
	return res;
}

void DS1302_write(uchar addr, uint dat){
	uchar i;
	EA = 0;
	SCLK = 0;	_nop_();
	RST = 1;	_nop_();
	for(i=0; i<8; i++){
		DSIO = (addr>>i)&0x01;
		SCLK=1;	_nop_();
		SCLK=0;	_nop_();
	}
	for(i=0; i<8; i++){
		DSIO = (dat>>i) & 0x01;
		SCLK=1;	_nop_();
		SCLK=0;	_nop_();
	}
	RST = 0;	_nop_();		//数据传输完毕
	EA = 1;
}

*/


  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值