51单片机————DS1302实时时钟——动态数码管显示

总结:

        一、DS1302实时时钟spi时序程序编写

        1.底层spi时序编写

        2.上层调用(底层时序)程序编写

二、定义数组变量存储时间(秒、分、时、日、月、周、年)时间数据

三、定义ds1302读和写函数

四、定义数码管(SMG)函数

五、主函数调用

编程实例:

/*********************  DS1302实时时钟 —— 动态数码管显示 **************************/

/* DS1302的程序设计遵循 底层逻辑 和 上层逻辑。底层逻辑指ds1302的spi时序,上层逻辑指定义新函数并调用底层spi时序并输入数据  */

#include "reg51.h"
// 首先需要定义ds1302管脚
sbit DS1302_IO 	 = P3^4;
sbit DS1302_RST  = P3^5;
sbit DS1302_SCLK = P3^6;
//定义 位选 管脚
sbit LSA = P2^0;	 
sbit LSB = P2^1;
sbit LSC = P2^2;
//define SMG = P0;

typedef unsigned char uchar;  //全局变量定义 : 定义名为uchar 的unsigned char 类型的别名变量 

// WRITE 要写入ds1302的地址数据数组
uchar code WRITE_RTC_ADDR[7] = {0X80, 0X82, 0X84, 0X86, 0X88, 0X8A, 0X8C};//88   // code   常量数组,数据设定后不再发生改变
// 定义: 全局变量数组   定义要写入ds1302的时间寄存器的数据
//uchar ds1302_time[7] = {0x24, 0x39, 0x11, 0x06, 0x12, 0x02, 0x16}; 

// read  要读出的数据的地址数据数组
uchar code READ_RTC_ADDR[7] = {0X81, 0X83, 0X85, 0X87, 0X89, 0X8B, 0X8D};  // code   常量数组,数据设定后不再发生改变

//用于保存 读出的时间的数据数组  (全局变量)
uchar time[7] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x23};
//				  秒	分	  时	  

//定义数码管段选数组d\位选数组w
uchar code dx_value[16] = {0xfc, 0x60, 0xda, 0xf2, 0x66, 0xb6, 0xbe, 0xe0, 0XFe, 0XF6, 0XEe, 0XBe, 0X9c, 0X7a, 0X9e, 0X8e};  //0 - f


void Delay_ds1302_ms(uchar i) //函数用于spi底层时序间隔频率
{
	while(i--);
}

void Delay_SMG_ms(uchar i) //函数用于spi底层时序间隔频率
{
	while(i--);
}

/*
void Delay900ms(void)   //误差 -0.000000000205us 用于串口发送频率
{
    unsigned char a,b,c;
    for(c=127;c>0;c--)
        for(b=128;b>0;b--)
            for(a=24;a>0;a--);
}
*/
/* 一.定义底层SPI (也就是ds1302时序,写入ds1302数据)*/
void Ds1302_write_reg(uchar addr, uchar dat)
{
	uchar i = 0;
	uchar j = 0;
	//时序开始
	DS1302_SCLK = 0;
	Delay_ds1302_ms(3);
	DS1302_RST = 0;
	Delay_ds1302_ms(3);
	DS1302_RST = 1;
	Delay_ds1302_ms(3);
	// 开始向ds1302写入地址和数据
	for(i=0; i<8; i++)
	{
	  DS1302_IO = (addr & 0x01);
	  addr >>= 1;
	  DS1302_SCLK = 1;
	  Delay_ds1302_ms(3);
	  DS1302_SCLK = 0;
	  Delay_ds1302_ms(3);
	}
	for(j=0; j<8; j++)   // 循环8次表示8个bit位
	{
		DS1302_IO = (dat & 0x01);
		dat >>= 1;
		DS1302_SCLK = 1;
		Delay_ds1302_ms(3);
		DS1302_SCLK = 0;
		Delay_ds1302_ms(3);	
	}
	// 重置spi时序
	DS1302_RST = 0;
	Delay_ds1302_ms(3);
	
}
// 定义底层SPI (也就是ds1302时序,下降沿时读出ds1302发出的数据)
uchar Ds1302_READ_reg(uchar addr)
{
	uchar i = 0;
	uchar j = 0;
	uchar dat = 0;
	uchar value = 0;
	//ds1302 spi时序开始
	DS1302_SCLK = 0;
	Delay_ds1302_ms(3);
	DS1302_RST = 0;
	Delay_ds1302_ms(3);
	DS1302_RST = 1;
	Delay_ds1302_ms(3);
	// 写入ds1302的地址数据
	for(i=0; i<8; i++)
	{
		DS1302_IO = (addr & 0x01);
	  	addr >>= 1;
	  	DS1302_SCLK = 1;
	  	Delay_ds1302_ms(3);
	  	DS1302_SCLK = 0;
	  	Delay_ds1302_ms(3);
	}
	//读取ds1302发出的地址数据
	for(j=0; j<8; j++)
	{
		dat = DS1302_IO;
		value |= (dat << j);
		DS1302_SCLK = 1;
		Delay_ds1302_ms(3);
		DS1302_SCLK = 0;
		Delay_ds1302_ms(3);	
	}
	// 重置spi时序
	DS1302_RST = 0;
	Delay_ds1302_ms(3);
	DS1302_SCLK = 1;
	Delay_ds1302_ms(3);
	
	// 解决读取时间是FF的问题
	DS1302_IO = 0;	

	return value;
}		  

/* 二.定义上层函数:定义函数将数据 写入 ds1302函数 与 定义函数使单片机 读出 ds1302的时间数据  */

// 写入ds1302数据初始化函数
void ds1302_write_time(void)   
{	
	uchar i = 0;
	// 定义数组用于write函数数据输入
//	uchar ds1302_time[7] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x23};
	Ds1302_write_reg(0x8E, 0X00); // 关闭保护
	for(i=0; i<7; i++)
	{
		Ds1302_write_reg(WRITE_RTC_ADDR[i], time[i]);	
	}
	Ds1302_write_reg(0x8E, 0X80);//打开保护		
}
//读出ds1302数据
void ds1302_read_time(void)
{
	uchar i = 0;
	for(i=0; i<7; i++)     // 7次循环表示7个时间寄存器
	{
	  time[i] = Ds1302_READ_reg(READ_RTC_ADDR[i]);    //读出7个时间寄存器的值 并用time【】数组保存
	}
	
}

// 三、定义数码管读取函数    value[]:段选    addr:位选
void SMG_display(uchar dat[])
{
	uchar i = 0;
	for(i=0; i<8; i++)
		{
			switch(i)					  //  定义位选循环与选择
			{
				case 0: LSC=0; LSB=0; LSA=0; break;
				case 1: LSC=0; LSB=0; LSA=1; break;
				case 2: LSC=0; LSB=1; LSA=0; break;
				case 3: LSC=0; LSB=1; LSA=1; break;
				case 4: LSC=1; LSB=0; LSA=0; break;
				case 5: LSC=1; LSB=0; LSA=1; break;
				case 6: LSC=1; LSB=1; LSA=0; break;
				case 7: LSC=1; LSB=1; LSA=1; break;	 
			}
		P0 = dat[i];					   //定义数码管段选函数
		Delay_SMG_ms(100);
		P0 = 0x00;		 //消隐
		}	
}

/* 四、 主函数主程序调用 */

void main(void)
{
	// 1.先定义一个数组用于存储BCD码转换出来的数组元素
	uchar time_buf[8];

	// 2.需要调用写时间函数
	ds1302_write_time();
	while(1)
	{
		// 3.调用读出时间函数 
		ds1302_read_time();

		// 4.1302读出的数据是bcd码,将bcd码转换成smg对应数组数据元素后赋值新数组
		time_buf[0] = dx_value[ time[2] >> 4 ];
		time_buf[1] = dx_value[ time[2] & 0x0f ];
		time_buf[2] = 0x02;
		// 时
		time_buf[3] = dx_value[ time[1] >> 4 ];
		time_buf[4] = dx_value[ time[1] & 0x0f ];
		time_buf[5] = 0x02;
		// 分
		time_buf[6] = dx_value[ time[0] >> 4 ];
		time_buf[7] = dx_value[ time[0] & 0x0f ];
		// 5.调用smg 函数调入段码参数值
		SMG_display(time_buf);
	}
	
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值