DS1302+MAX7221+8位CC数码管

本文档详述了一位工程师使用STM32微控制器驱动DS1302实时时钟设置时间和从DS1302读取时间,并将结果显示在MAX7221驱动的数码管上的过程。涉及的步骤包括DS1302和MAX7221的引脚配置、驱动函数编写、中断服务函数实现以及定时器初始化。文章还提到了BCD码转换、数码管位选和闪烁效果的实现细节。
摘要由CSDN通过智能技术生成

1、查找相关资料,了解相关知识下手:

1.DS1302的相关资料:DS1302的相关寄存器资料——1DS1302的相关寄存器资料-2DS1302的相关引用和总结STM32的DS1302总结,详细版DS1302的驱动代码相关链接
2.MAX7221的相关资料:自己的总结和探索,不成毛皮

2、构造原理图

我构造的是建议版本的:
在这里插入图片描述

3、开始实现功能(写代码探索)(闪烁和翻页我卡壳了)

#include <reg51.h>
#include <intrins.h>

typedef  unsigned char u8;
typedef	 unsigned int  u16;
//MAX7221的PIN
sbit DIN = P2^0; //数据串出引脚
sbit CS  = P2^1; //片选端
sbit CLK = P2^2; //移位时钟端
 //DS1302的PIN
sbit RST  =P2^3;//RET,使能输入引脚,当读写时,置高位
sbit IO   =P2^5;//IO     ,双向通信引脚,读写数据都是通过这个完成
sbit SCLK =P2^4;//SCLK,时钟信号

//u8 code DSY_CODE[]={1,2,3,4,5,6,7,8};   //code段的数据写入不可改变
//显示的初始化数据
u8 DSY_CODE[8];  //数码管显示
u8 DataTime[7];  //时间数据    

//---DS1302时钟初始化2016年5月7日星期六12点00分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
u8 TIME[7]={0x59,0x30,0x23,0x21,0x09,0x03,0x15};    //初始化的时间8421BCD码的形式
		/*    秒   分  时   年    月 星期  日      */

void delayms(u16 x){
	u8 i;
	while(x--)	for(i = 0;i < 120;i++);
}

/************DS1302的相关驱动函数**********************************/
void Write_DS1302_onebyte(u8 dat){
	u8 i;
	for(i=0;i<8;i++)
	{
		IO =(bit)(dat&0x01);    //取最低位的数据
		SCLK=0,_nop_(),_nop_(),SCLK=1;    //SCLK上升沿写入数据
		dat=dat >>1;   //为下一次做准备
	}
}

u8 Read_DS1302_onebyte(){
	u8 i,dat=0;
	for(i=0;i<8;i++)
	{
		SCLK=1,_nop_(),_nop_(),SCLK=0;  //下降沿读出数据
		dat=dat >>1;             //由低读到高
		if(IO)	dat=dat |0x80;  //如果读出的数据为1,将1取出,放在高位
	}
	return dat;
}

void Write_DS1302_add_dat(u8 addr,u8 dat){
	//DS1302初始化管脚
	RST=0,SCLK=0,RST=1;  //SCLK为0时,RST才可以写成1   ----启动
	Write_DS1302_onebyte(addr);   //先写地址 再写数据
	Write_DS1302_onebyte(dat);
	SCLK=1,RST=1;    //将时钟放置为已知状态,静止数据传输
}

u8 Read_DS1302_addr(u8 addr){
	u8 dat;
	RST=0,SCLK=0,RST=1;  //SCLK为0时,RST才可以写成1   ----启动
	Write_DS1302_onebyte(addr);   //写地址
	dat=Read_DS1302_onebyte();    //读数据
	SCLK=1,RST=1;    //将时钟放置为已知状态,静止数据传输
	return dat;
}

u8 DEC_BCD_conv(u8 x){  //十进制转换成BCD8421数据
	u8 bcd=x%10;  //取余,低四位
	x =x /10;     //取整
	x =x <<4;	  //低四位变高四位
	bcd=bcd | x;
	return bcd;
}

u8 BCD_DEC_conv(u8 x){
	u8 dec=0x0f&x; //保留低四位
	x=x>>4;        //高位变低四位
	dec=dec + x*10;
	return dec;
}

//获得时间信息函数
void Get_ds1302_time(){    //放在DataTime数组里
	
	u8 i,temp;
	for(i=0;i<7;i++)
	{
		temp=Read_DS1302_addr(0x81+i*2);  //读到数据
		DataTime[i]=BCD_DEC_conv(temp); //BCD转换DEC数据,存在DataTime中
	}
	
	
//	u8 d;
//	d = read_ds1302_add(0x81);												//读秒
//	sec = BCD_DEC_conv(d);													//得到秒	
//	d = read_ds1302_add(0x83);												//读分
//	min = BCD_DEC_conv(d);													//得到分
//	d = read_ds1302_add(0x85);												//读小时
//	hour = BCD_DEC_conv(d);													//得到小时
//	d = read_ds1302_add(0x87);												//读日
//	date = BCD_DEC_conv(d);													//得到日
//   	d = read_ds1302_add(0x89);												//读月
//	month = BCD_DEC_conv(d);												//得到月
//	d = read_ds1302_add(0x8b);												//读星期
//	week = BCD_DEC_conv(d);													//得到星期
//	d = read_ds1302_add(0x8d);												//读年
//	year = BCD_DEC_conv(d);													//得到年		
}


//DS1302初始化设置时间
void Ds1302_Init()
{
    u8 i;
    Write_DS1302_add_dat(0x8e,0x00);      //禁止写保护,就是关闭写保护功能
    for (i=0; i<7; i++)//写入7个字节的时钟信号:分秒时日月周年
    {
         Write_DS1302_add_dat(0x80+i*2,TIME[i]); 
    }
     Write_DS1302_add_dat(0x8e,0x80);      //打开写保护功能
}

/***************MAX7221的相关驱动*******************************/
void write_data(u8 addr,u8 dat){
	u8 i;
	CS = 0;       
	for(i = 0;i < 8;i++){
		  CLK = 0,addr <<= 1,DIN = CY,CLK = 1;      
		  _nop_(),_nop_(),CLK = 0;      
     }
    for(i = 0;i < 8;i++){
		  CLK = 0,dat <<= 1,DIN = CY,CLK = 1;      
		  _nop_(),_nop_(),CLK = 0;      
     }
	 CS = 1;      //CS上升沿,数据锁存
}

//初始化函数
void init_max7221(void){
	 write_data(0x09,0xff);    
	 write_data(0x0a,0x07);    
	 write_data(0x0b,0x07);    
	 write_data(0x0c,0x01);    
	 write_data(0x0f,0x00);    
}
//MAX7221的运行
void MAX7221_Run(void){
	u8 i;
	Get_ds1302_time();  //获取时间
	for(i=0;i<8;i++)	write_data(i+1,DSY_CODE[i]); 
}

/************************定时器初始化函数***************************************/
void Timer0_init()														//Timer0初始化
{																			//方式一
	TMOD = 0x01;															//TH0 预置,65536十六进制低8位。
	TH0 = (65536 - 2000) / 256;												//TL0 预置,65536十六进制低8位。
	TL0 = (65536 - 2000) % 256;
	TR0 = 1;															   //定时器T0开
	ET0 = 1;															   //溢出中断控制位T0开
	EA  = 1;															   //总开关打开
}

void main(void)
{
	Ds1302_Init();
	init_max7221();
	Timer0_init();
	while(1);
}
/*************************中断服务函数*************************************/
void time0_isr(void) interrupt 1{  //MAX7221的运行和数码管的显示和闪烁
	static u8 cp1,cp2;
	static bit flash,conv;
	TH0 = (65536 - 2000) / 256;											   //TH0重置函数
	TL0 = (65536 - 2000) % 256;											  //TL0重置函数
	cp1++;
	if(cp1 >= 250)															//0.5秒
	{
		cp1 = 0;
		flash = ~flash;														//产生闪烁变量
		cp2++;
		if(cp2 >= 5)                                                  //2.5秒显示交换
		{  
			cp2 = 0;
			conv = ~conv;												//产生交替显示变量	
		}	
	}
	if(conv == 1)    //日期   D5为星期(本人无法显示)
	{
		DSY_CODE[7]=DataTime[6]%10;     //日
		DSY_CODE[6]=DataTime[6]/10;
		DSY_CODE[5]=flash==1?10:15;   //10 '-'   15 全灭
		DSY_CODE[4]=DataTime[4]%10;    //月
		DSY_CODE[3]=DataTime[4]/10;
		DSY_CODE[2]=flash==1?10:15;   //10 '-'   15 全灭
		DSY_CODE[1]=DataTime[3]%10;   //年
		DSY_CODE[0]=DataTime[3]/10;
	}
	else        //时间
	{	
		DSY_CODE[7]=DataTime[0]%10;    //秒   
		DSY_CODE[6]=DataTime[0]/10;
		DSY_CODE[5]=flash==1?10:15;   
		DSY_CODE[4]=DataTime[1]%10;   //分
		DSY_CODE[3]=DataTime[1]/10;
		DSY_CODE[2]=flash==1?10:15;     
		DSY_CODE[1]=DataTime[2]%10;   //时
		DSY_CODE[0]=DataTime[2]/10;
	}  
	MAX7221_Run();			
}

4、形成的现象

日期
在这里插入图片描述
在这里插入图片描述

5、注意事项

  1. DS1302的初始化需要开时钟
  2. BCD转十进制数需要花点时间转换
  3. 数码管的位选要和对应的数据对应上(eg:年月日,不要搞成月星期日的现象)
  4. 数码管的变动需要尝试
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值