清翔零基础教你学51单片机_个人学习笔记(16)_实时时钟DS1302(理论+实践)

说明

本人使用的是清翔的51单片机开发板,如果型号相同最方便,但是如果型号不同也可以参考,因为芯片都是一样的,只是外设不同而已,使用时只需要对照自己的开发板原理图稍微修改下引脚即可。

|

本次笔记对应视频教程的第44,45集 实时时钟DS1302(理论+实践)

如果笔记之中有任何错误,请在评论区指出,谢谢

一、DS1302

1.1 简介

 1.2 引脚图

引脚功能

 DS1302与单片机相连只需要3根线:I/O, CE, SCLK

1.3 参考电路

芯片5,6,7引脚接单片机

开发板上的原理图为

1.4 结构框图

 

 1.5 控制方法

 1.6 时序图

注意,由于数据是从最低位开始传输的,因此要注意顺序

1.7 数据地址

 DS1302的数据要用BCD码,最常用的是8421(如无特殊说明,以下BCD码均指8421码),也就是用4位二进制表示1位十进制数,这四位二进制从高到低表示十进制的8 4 2 1,比如数字7=4+2+1,那么用8421码表示就是0111,注意BCD码只能表示1位十进制数字,也就是0~9,要表示多位,每一位都要用BCD码表示,比如37,就要分成3和7分别表示,3的BCD码是0011,7的BCD码是0111,那么37的BCD码就是0011 0111。

前段时间看数字电路教材刚好看到了,就弄张图来看看

此图为教材拍照

 主要就看这个表就行,意思就是我说的那个意思

此图来源于百度百科

1.8 寄存器的介绍

 

涓流充电控制寄存器 

涓流充电结构图

 数据手册给的一个不太直观的图

 其中B. RAM部分就是PPT中的这个表

瞬间就直观了 

 1.9 突发模式

 二、编程

2.1 创建工程

复制上一份工程文件夹,修改名称为“16.实时时钟DS1302”,进入项目文件夹,打开工程文件,删除main.c函数的内容。

 2.2 main.c

main.c里面写一下函数定义,比如发送,读取函数,突发模式函数等,以及main函数

先给出一些相关函数

1. 发出1个字节(只管在数据引脚上发送,不管CE(也就是TRST)是否为高电平)

/**********************************************************************************/
/*************************  DS1302  *********************************************/
/**********************************************************************************/
    //只管发送1个字节过去,前期准备需要在调用的时候写
void DS1302_WChar(uchar dat)
{
    uchar i;
    for (i = 0; i < 8; i++)
    {
        TSCLK = 0;
        TI0 = dat & 0x01;
        TSCLK = 1;  //上升沿,数据被DS1302读取
        dat >>= 1;  //数据从最低位开始传输
    }
}

2.发送一条写入命令并写入给出的数值,这里要调用2次刚才的函数,并且要控制CE(TRST的高低电平)

void DS1302_Write(uchar cmd, uchar dat)
{
    TRST = 0;
    TRST = 1;
    DS1302_WChar(cmd);
    DS1302_WChar(dat);
    TRST = 0;
}

3.读取1字节的函数,需要给出命令,并接收数据线上的值

uchar DS1302Read(uchar cmd)
{
    ucahr i,dat;//读取数据使用
    TRST = 0;
    TRST = 1;
    DS1302_WChar(cmd);//发送读数据命令
    for (i = 0; i < 8; i++)
    {
        TSCLK = 0;//产生下降沿,让DS1302输出数据
        dat >>= 1;
        dat |= (TIO << 7);
        TSCLK = 1;//拉高时钟,准备下一次下降沿产生
    }
    return (dat);
}

下面两个是数据转BCD码以及BCD码转数字,这两个视频教程里面写的太复杂不好理解,我修改了一下,在CodeBlock验证过是正确的。转换解释在代码里面注释部分,我就不再写一遍了,已经注释非常清晰了。

    //数据转换BCD码
uchar dat2BCD(uchar dat)
{
    //十位左移4位,加上个位,由于十位和个位都是0~9的数,所以十位和个位都是只占用了8位二进制的低4位,
    //而低4位又是按照8421排列的,只需要把十位左移到个位前面,就得到了BCD码
    return ((dat/10<<4) + (dat%10));
}

    //BCD码转换数据
ucahr BCD2dat(uchar dat)
{
    //BCD码的高4位是十位,低4位是个位,只需要把高4位(十位)取出来×10再加上低4位(个位)就得到原来的数值
    return ((dat>>4)*10 + (dat&0x0f));
}

展示一下视频的代码,瞬间觉得我的代码眉清目秀了,视频里面的代码我理解了好一会儿才明白他什么意思,为什么能这样做,视频里也没解释清楚直接说这样就得到了BCD码

//数据转BCD码
uchar Dat_Chg_BCD(uchar dat)
{
	uchar dat1, dat2;
	dat1 = dat / 10;
	dat2 = dat % 10;
	dat2 = dat2 + dat1 * 16;
	return dat2;
}

//BCD码转换为数据
uchar BCD_Chg_Dat(uchar dat)
{
	uchar dat1, dat2;
	dat1 = dat / 16;
	dat2 = dat % 16;
	dat2 = dat2 + dat1 * 10;
	return dat2;
}

main函数如下

void main()
{
    ucahr second,minute,hour;
    uchar i;
    DS1302_Write(0x8e,0x00);//关闭写保护
    DS1302_Write(0x80,dat2BCD(30));//在秒寄存器写入30
    DS1302_Write(0x82,dat2BCD(15));
    DS1302_Write(0x84,dat2BCD(19));
    DS1302_Write(0x8e,0x80);//打开写保护
    while (1)
    {
        DS1302_Write(0x8e,0x00);//关闭写保护
        second = BCD2dat(DS1302Read(0x81));
        minute = BCD2dat(DS1302Read(0x83));
        hour = BCD2dat(DS1302Read(0x85));
        DS1302_Write(0x8e,0x80);//打开写保护
        for (i = 0; i < 50; i++)
        {
            SEG_DIS(1,hour/10);
            SEG_DIS(2,hour%10);
            SEG_DIS(2,22);
            
            SEG_DIS(3,minute/10);
            SEG_DIS(4,minute%10);
            SEG_DIS(4,22);
            
            SEG_DIS(5,second/10);
            SEG_DIS(6,second%10);
        }
    }
}

在while循环前面几行写入数据时,直接写入了秒,分,小时的数据,而并没有考虑要设置秒寄存器的 BIT7 定义为时间暂停位,以及是否设置12/24小时模式,是因为我这里面的BCD代码转换只写了转换2位的,而并没有写转换3位的(配置最高位时是一个3位数),而寄存器低位才是真正存放数据的位置,所以我们代码没改变BIT7。写入的数据全放在了存放数据的位置。

所以如果想要配置他们,需要自己修改BCD转换代码,三位数,每位数用4个二进制表示,那么就需要12位来表示,所以返回值应该是一个int类型,然后自己在根据转换2位数的思路去转换3位数,然后还要修改一下发送部分代码,让它能发送12位。

如果就是普通使用,其实直接设置年月日,默认24小时制也够用了。

2.3 main.h

/************************************************  DS1302  *******************/
sbit TSCLK = P1^0;
sbit TIO = P1^1;
sbit TRST = P1^2;

/************************************************  定义数据类型  *******************/
typedef unsigned char uchar;
typedef unsigned char ucahr;
typedef unsigned int uint;

unsigend char我定义了两次,一次uchar ,一次ucahr,
是因为我容易把a和h打反,编译报错,懒得去改,
索性直接定义两个,随便用

2.4 现象

 

 三、突发功能和静态RAM读写

先留着,以后写【doge】

本次笔记对应视频教程的第44,45集 实时时钟DS1302(理论+实践),到此结束。

|

下次笔记将对应视频教程的第46,47集 LCD1602与指针(理论+实践)

|

如果笔记之中有任何错误,请在评论区指出,谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值