1.14.1.RTC有关的背景知识
1.14.1.1、什么是实时时钟(RTC :Real 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
上一篇:【STC单片机学习】第十五课:I2C通信-EEPROM
下一篇:【STC单片机学习】第十三课:串口通信和RS485
推荐阅读最新更新时间:2024-11-12 15:19
设计资源 培训 开发板 精华推荐
- STM32F405RGT6最小系统板
- ADP2302 降压稳压器的典型应用,VIN = 12V,VOUT = 1.8V,3A
- LT1506IS8 双路输出 SEPIC 转换器的典型应用电路
- OP213FSZ 低噪声运算放大器电压基准的典型应用
- AKD5374-A,带 USB 接口的 AK5374 立体声 ADC 评估板
- 鸢尾立方->一种基于STM32的USB转JTAG电路设计
- XRD98L63EVAL,XRD98L63 图像数字化仪评估系统
- LTC4156 的典型应用——具有 I2C 控制和 USB OTG 的双输入电源管理器/3.5A LiFePO4 电池充电器
- Si4133G-EVB,Si4133G-BT PLL 频率合成器评估板
- 用于 DDR 存储器终端的 LTC3615MPUF 双路 3A 同步降压型 DC/DC 转换器的典型应用