【STC单片机学习】第十四课:SPI通信-实时时钟DS1302

【朱老师课程总结 侵删】

第一部分、章节目录

1.14.1.RTC有关的背景知识

1.14.2.原理图和接线

1.14.3.数据手册带读

1.14.4.时序图的读法1​

1.14.5.编程实践1

1.14.6.编程实践2

1.14.7.添加串口调试1

1.14.8.添加串口调试2

1.14.9.DS1302的时间格式详解

1.14.10.向DS1302写入时间

1.14.11.对程序进行规整


第二部分、章节介绍

1.14.1.RTC有关的背景知识
    本节引入RTC,并且讲了学习RTC会用到的有关知识点,这些背景知识对于掌握RTC非常必要
1.14.2.原理图和接线
    本节带大家从源头分析原理图,并且重点讲解接线图中为什么要这么接线。
1.14.3.数据手册带读
    本节带大家一起读DS1302的数据手册,目的是让大家学会自己看数据手册。
1.14.4.时序图的读法1
    本节带大家分析数据手册中最重要的时序图,教会大家理解时序的概念和从图中读出有效信息,帮助自己编写代码。对示例代码的分析,教会大家如何结合时序图来分析代码,进而能够自己根据时序图能编写出正确的代码
1.14.5.编程实践1
    本节开始编程实践,我们要在完全无参考情况下根据时序图编写DS1302的底层读写代码
1.14.6.编程实践2
    本节继续编程实践,主要是比对我们自写的代码和官方例程,然后封装出读取DS1302时间的函数
1.14.7.添加串口调试
    本节向代码中移植上个课程写的串口调试的代码,并且测试ok,并且试图用串口输出DS1302中读取到的时间数据。
1.14.8.添加串口调试2    
    本节对串口输出的数据进行分析,并且解决输出数值有FF的bug。
1.14.9.DS1302的时间格式详解
    本节对DS1302中时间格式做说明,其实主要是BCD码的介绍,然后说明了年份的起始基点。
1.14.10.向DS1302写入时间
    本节添加向ds1302写入时间的代码,主要是写入寄存器地址、写保护、写后读出验证等关键点。
1.14.11.及时对程序进行规整
    本节对程序进行整理和规整,主要是分为多文件实现,以及将模块内分为c文件和h头文件来实现。

    
第三部分、随堂记录

1.14.1.RTC有关的背景知识

1.14.1.1、什么是实时时钟RTCReal Time Clock)
(1)时间点和时间段的概念区分

  • 时间段 :定时器/计数器 ;       烧水;                    不唯一
  • 时间点 :RTC;                       闹钟、日历;          唯一

(2)单片机为什么需要时间点

  • 单片机有时候需要做一些必须到某一个时间才能做的事,所以需要用RTC,比如定点炸弹!
  • RTC之于单片机,就是钟表(手表、手机)之于人

(3)RTC如何存在于系统中(STC芯片内部集成 or STC芯片外部扩展)

  • DS1302芯片,集成在单片机开发板上,属于STC51外部扩展

1.14.1.2、DS1302介绍
(1)数据手册
DS1302数据手册

  • CE:=1,允许数据读写; =0,禁止数据读写
  • SCLK:一系列的上升沿伴随下降沿,CPU向DS1302发的时序信号
  • I/O:数据输入/输出

实物图

(2)SPI(Serial Peripheral Interface:串行外设接口)
SPI数据手册
同一个板子上的两个芯片之间,就常用SPI

  • SCLK:串行时钟
  • SDO:串行输出
  • SDI:串行输入
  • SS:用于片选

(3)一句话总结DS1302:

内部存着一个时间点信息(年月日时分秒星期几),可以读写,上电自动走表

1.14.1.3、RTC学习的关键点

STC芯片和RTC芯片通过SPI接口进行通信,所以学习的重点就在读懂SPI。

  • SPI 接口在 CPU 和外围低速器件之间进行同步串行数据传输,在主器件的移位脉冲下,数据按位传输, 高位在前先传 ,低位在后,为全双工通信。

(1)SPI接口及其相关概念:

  • 3线or4线:咱们用3线:SCLK、IO(SDO+SDI)、CE(STC芯片引脚)。
  • 同步:靠的就是SCLK。
  • 主从:STC是Master、DS1302是Slave。
  • 串行: SPI 允许数据一位一位的传送,主设备通过对 SCLK 时钟线的控制可以完成对通讯的控制。
  • 工作模式:有4中模式,由CPOL和CPHA决定,后面会讲!
  • ......

(2)时序的理解和编程实现
时序图是非常重要的,看懂时序图,单片机就学通了!

编程任务:简易电子钟。

1.将各种数据写入 DS1302 的寄存器,以设置它当前的时间格式;
2.DS1302 时钟会按照设置情况运转;
3.单片机将DS1302寄存器内的数据读出,并通过串口打印到PC。


1.14.2.原理图和接线

1.14.2.1、原理图分析
DS1302引脚介绍

  • 该电路是独立的,DS1302 芯片的控制管脚(CLK、I/O、CE)接至 J3 端子
  • 芯片的 VCC1 脚外接了一个纽扣电池 BT1,以保证系统断电后时钟仍然可以运行
  • 芯片的 X1、X2 管脚处外接了一个 32.768KHZ 晶振,为时钟运行提供一个稳定的时钟频率。

1.14.2.2、接线
由于该模块电路是独立的,所以 DS1302 芯片的控制管脚 J3 端子可以使用任意单片机管脚连接。我们用单片机P3.4-P3.6接DS1302芯片,接线如下:

P3.4——CE
P3.5——I/O
P3.6——SCLK

 


1.14.3.数据手册带读

直接看DS1302芯片的数据手册!认认真真看!(大约30min)

杂记:

  • 读写时钟方式:单字节/多字节(猝发模式)
  • 2.0V—5V的宽电平
  • AM/PM指示器可选12小时/24小时制
  • 一根I/O来进行一次一个字节/脉冲串多达31字节
  • SCLK用来同步、I/O进行实际数据传输
  • 有备用电源接在Vcc1,主电源接在Vcc2,DS1302工作在max{Vcc1,Vcc2}
  • 框图:
  •  管脚说明

  • 在SCLK上升沿数据被输入,在SCLK下降沿数据被输出
  • 命令字(控制指令)

    命令字是用来启动数据传输的控制指令!
    MSB (位 7)必须是逻辑 1. 如果是 0,则禁止对 DS1302 写入.
    位 6 在逻辑 0 时规定为时钟/日历数据,逻辑 1 时为 RAM 数据.
    位 1 至 位 5 表示了输入输出的指定寄存器.
    LSB (位 0) 在逻辑0时为写操作(输出),逻辑1 时为读操作(输入).
    命令字以 LSB (位 0)开始总是输入.
  • 数据传输摘要:时序图
  •  寄存器地址/定义
    RTC


    时钟脉冲串
  • 在上电时, CE 必须为逻辑 0 直到 Vcc 大于 2.0V
    同样,SCLK 必须为逻辑 0 当 CE 变成逻辑 1 状态. 


1.14.4.时序图的读法1

1.14.4.1、时序图关键点
(1)横轴代表时间,纵轴是同一时间点各个通信线的状态
(2)静态与动态2个角度去看

  • 静态,在每个时间点各自是怎么样
  • 动态:连起来来看

(3)注意SCLK的边沿处:上升沿读入,下降沿写出

1.14.4.2、结合示例代码来理解时序

  • 看懂时序图
  • 看懂代码
  • 看着时序图写代码

\课程配套ARM3.0开发板光盘资料\步骤3 51例程\14、实时时钟DS1302\数码管显示时钟\程序\ds1302.c

代码中:_nop_()指令说明


1.14.4.3、时序之上的东西
(1)大小端:一个字节发出去,先发高位还是低位
     上面的程序是先发低位。
      如果想先发高位怎么办?addr & 0x80,addr >>= 7;

(2)如何读写寄存器
通过addr这个参数,这个参数就是对应上面的RTC寄存器的READ/WRITE地址!


1.14.4.4、总结SPI的时序特征
(1)低位在前
(2)DS1302在上升沿读取,下降沿写入
(3)注意SCLK工作频率(加_nop_()延时)


1.14.5.编程实践1

1.14.5.1、建立工程
1.14.5.2、编写ds1302_write函数
//向ds1302的内部寄存器addr写一个value

(1)引脚定义
       P3.4——CE
       P3.5——I/O
       P3.6——SCLK
(2)delay900ms函数
(3)根据时序图写代码

  • 时序开始
  • 写入地址addr
  • 写入字节(上升沿)
  • 时序结束
  • 每个操作时序后面加_nop_()

1.14.5.3、编写ds1302_read函数
//从ds1302的内部寄存器addr读出一个值,作为返回值

  • 时序开始
  • 写入地址addr
  • 读出ds1302返回的字节(下降沿)
  • 时序结束
  • 每个操作时序后面加_nop_()

关键代码:

		dat |= (IO>>i); //按位或就把第i位赋值给了dat
		//最后dat存的是一个字节的数

如何理解? 


1.14.6.编程实践2

1.14.6.1、比对自写代码和官方例程

  • 官方分成多个文件,修改起来更为简单!
  • 看看逻辑有没有问题!尤其是数据读取有没有错位!

1.14.6.2、读取时间,用ds1302_write
(1)DS1302的时间寄存器的地址

  • 寄存器0:最高位 CH 是一个时钟停止标志位。如果时钟是备用电池,=0正常运转,=1不正常运转。剩下的7 位高 3 位是秒的十位,低 4 位是秒的个位,这里再提请注意一次,DS1302 内部是 BCD 码,而秒的十位最大是 5,所以 3 个二进制位就够了。(BCD码在后面会讲)
  • 寄存器1:最高位未使用,剩下的 7 位中高 3 位是分钟的十位,低 4 位是分钟的个位。
  • 寄存器2:bit7 是 1 的话代表是 12 小时制0 代表是 24 小时制;bit6 固定是 0,bit5 在12 小时制下 0 代表的是上午,1 代表的是下午,在 24 小时制下和 bit4 一起代表了小时的十位,低 4 位代表的是小时的个位。
  • 寄存器3:高 2 位固定是 0,bit5 和 bit4 是日期的十位,低 4 位是日期的个位。
  • 寄存器4:高 3 位固定是 0,bit4 是月的十位,低 4 位是月的个位。
  • 寄存器5:高 5 位固定是 0,低 3 位代表了星期。
  • 寄存器 6:高 4 位代表了年的十位,低 4 位代表了年的个位。请特别注意,这里的 00~99 指的是 2000 年~2099 年。
  • 寄存器 7:最高位一个写保护位,如果这一位是 1,那么是禁止给任何其它寄存器或者那 31 个字节的 RAM 写数据的。因此在写数据之前,这一位必须先写成 0。

(2)参考示例代码,写ds1302_read_time函数

u8 TIME[7];	//加入全局变量,用来存储当前时间

//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
u8 code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; 
u8 code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};

void ds_readtime()
{
	u8 i;
	for(i = 0;i<8;i++)
	{
		TIME[i] = ds1302_read(READ_RTC_ADDR[i]);
	}
}

1.14.7.添加串口调试1

1.14.7.1、移植串口代码

把原来的serial.c封装成头文件!

(1)注意波特率设置和晶振设置
     波特率设置为4800
(2)注意串口相关的接线设置
(3)测试串口输出效果
(4)注意二进制显示(HEX)和文本方式(字符)显示

1.14.7.2、串口输出时间信息
(1)写代码

  • 从DS1302读取时间
  • for循环内打印一组7个时间到串口!
  • 延时后继续

1.14.8.添加串口调试2

(2)状况:
1、代码确实得到了一系列的时间数据
2、秒确实在变化,而且变化的规律似乎是正确的。
3、但是时间不合心意!
还有大家没有疑惑吗?咱们的串口中,秒是09--10啊,咱们是hex显示啊,难道9直接到16了??
下面讲一下DS1302的时间格式—BCD码!


1.14.9.DS1302的时间格式详解

1.14.9.1、BCD码
(1)什么是BCD码
 BCD码是一种数字编码,这种计数编码有个特点:很像10进制和16进制的结合。

  • 看起来很像10进制(09+1=10而不是0A)
  • 实际是用十六进制来表示的(BCD码的21其实在计算机中就是0x21)
  • BCD是十进制和十六进制中间的一种状态

综合来讲:BCD码是4位二进制数:0000-1001,表示十进制0-9,是一种二进制的数字编码形式,用二进制编码的十进制代码。

因此上面的09是00001001,10是00010000,因为BCD码逢十进一!

(2)区别BCD码、16进制、10进制三种数
举个例子:

  • 十进制数 15 的BCD码表示为 00010101
  • 16进制数 0x15 的二进制表示为00010101

1.14.9.2、年份从2000开始
直接读出的数+2000就是当前的年份,譬如读出的是BCD码20,对应0x20,其实就表示数字20,所以就是2020年。


1.14.10.向DS1302写入时间

1.14.10.1、写时间函数ds1302_init()
(1)写保护

就是防止时间被随意修改!当WP位为1是,有写保护!

  • 去掉写保护
  • 修改程序
  • 加上写保护

(2)写入地址和读出地址不同
0x8E:写
(3)注意写入时序
1.14.10.2、先写入时间然后读取验证


1.14.11.对程序进行规整

1.14.11.1、程序规整介绍

  • 分c文件和h文件

1.14.11.2、c文件和头文件
(1)c文件是C语言源文件,h文件是头文件
(2)源文件主要用来放:函数和全局变量定义
(3)头文件主要用来放:函数和全局变量的声明、宏定义、结构体共用体类型定义等
(4)一般是一个源文件就配一个头文件
(5)一般包含自己建立的头文件时用""而不用<>
(6)头文件中还有个固定格式

#ifndef __DS1302_H_
#define __DS1302_H_

头文件内容

#endif

本节课程序下载地址:DS1302

本节课结束!

猜你喜欢

转载自blog.csdn.net/qq_27148893/article/details/109967939