1、查找相关资料,了解相关知识下手:
1.DS1302的相关资料:DS1302的相关寄存器资料——1,DS1302的相关寄存器资料-2;DS1302的相关引用和总结;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、注意事项
- DS1302的初始化需要开时钟
- BCD转十进制数需要花点时间转换
- 数码管的位选要和对应的数据对应上(eg:年月日,不要搞成月星期日的现象)
- 数码管的变动需要尝试