一、实验任务
使用领航者 Zynq 开发板上的 PCF8563 器件实现实时时钟的显示
二、实验介绍
(1)PCF8563 简介
PCF8563 是 PHILIPS 公司推出的一款工业级多功能时钟/日历芯片,具有报警功能、定时器功能、时钟 输出功能以及中断输出功能,能完成各种复杂的定时服务。其内部功能模块的框图如下图所示:
先看外左上角,那一块可以看作是提供时钟的一个模块,同时还具有分频功能,一个用来输出一个驱动功能。左下角是一个IIC接口和一个看门狗,看门狗当芯片工作不正常提供报警和复位。中间的功能模块是通过IIC协议和外部通信的。
PCF8563 有 16 个可寻址的 8 位寄存器,但不是所有位都有用到。前两个寄存器(内存地址 00H、01H) 用作控制寄存器和状态寄存器(CONTROL_STATUS);内存地址 02H~08H 用作 TIME 计时器(秒~年计时 器);地址 09H~0CH 用于报警(ALARM)寄存器(定义报警条件);地址 0DH 控制 CLKOUT 管脚的输出频率(时钟输出控制);地址 0EH 和 0FH 分别用于定时器控制寄存器和定时器寄存器。
右下角是中断,当定时器和报警达到一定条件就输出中断
(2)寄存器配置
N配置0,X任意。上图是每个寄存器的配置介绍。一般情况默认模式就可以。下面介绍时间功能。以秒为例
最高位并不参与时间显示,当电源电压低于 PCF8563 器件的最低供电电压时,VL 为“1”,表明内部完整的时钟周期信号不能被保证,可能导致时钟/日历数据不准确。
而计数的编码是BCD8421码
其他部分详细见数据手册。
(3)硬件设计
接口如图
左边是晶振提供时钟,中间是功能芯片PCF8563,6和5接口时IIC接口。8是接电源,由于我们的时钟断电后就会停止归零,所以用了右上角的设计,断电时还会有个电池供电。IIC通信就是我们FPGA要设计的了。
三、程序设计
根据实验任务,我们可以大致规划出系统的控制流程:ZYNQ 首先通过 I2C 总线向 PCF8563 写入初始时间值,然后不断地读取时间数据,并将读到的时间数据显示到 LCD 上。由此画出系统的功能框图如下所 示:
我们需要设计的就是FPGA中的三个模块。
设计好的原理图如下:
每个模块需要完成的功能可以从接口看。
IIC_DRI是和PCF8563通信的模块,1)负责写入初始值(PCF8563模块提供)和读取芯片内时间数据然后传给pcf8563_ctrl。2)负责输出驱动时钟 3)完成信号的输出
pcf8563_ctrl模块 1)接受来自i2c模块的数据,输出时间信息。2)负责控制读写和使能dri模块 3)提供写入地址和数据给dri模块即时间初始值。
lcd_disp显示模块 1)将控制模块输出的时间信息转换成RGB信号显示到显示屏上 2)注意这个模块的时钟不是dri_clk,而是系统时钟sys_clk。
以下是模块的详细介绍
控制模块 ,当前时间由顶层例化的设置优先TIME_INIT。这个模块主要是和IIC通信,写入数据和读芯片时间数据。最后是输出秒分时等信息。这里要按照PCF的配置去写入初始值,比如02h是秒,所以在ADDR为02h时写入TIME_INIT[7:0].因为都是8421码,都是十位数所以用8位表示。
读数据按照PCF8563有些是读6:0是时间数据。时间上,秒分时等十位都不超过7,只有年会。
同理天读[5:0]即可,5:4表示十位,天最多31天,就是3。两位刚好够其他的同理。不过写入的时候都是写八位。我们要按规定从秒开始写读,所以状态流如下。代码还是好理解的,要注意的是芯片上电要求等待8ms以上.所以状态0是等待。我们设置成16ms.且我们不写星期数据
写完年之后要拉高读写控制,使其为读状态。当其为读状态,就不会写数据了。以数据流1为例,读状态下,状态流和地址都会有作用但是无法写入数据所以初始值之后就不起作用了,写完地址接着执行2状态读数据。和之前的哑写一样。
module pcf8563_ctrl #(
// 初始时间设置,从高到低为年到秒,各占8bit
parameter TIME_INIT = 48'h19_10_26_09_30_00)(
input clk , //时钟信号
input rst_n , //复位信号
//i2c interface
output reg i2c_rh_wl , //I2C读写控制信号
output reg i2c_exec , //I2C触发执行信号
output reg [15:0] i2c_addr , //I2C器件内地址
output reg [7:0] i2c_data_w, //I2C要写的数据
input [7:0] i2c_data_r, //I2C读出的数据
input i2c_done , //I2C一次操作完成
//PCF8563T的秒、分、时、日、月、年数据
output reg [7:0] sec, //秒
output reg [7:0] min, //分
output reg [7:0] hour, //时
output reg [7:0] day, //日
output reg [7:0] mon, //月
output reg [7:0] year //年
);
//reg define
reg [3:0] flow_cnt ; // 状态流控制
reg [12:0] wait_cnt ; // 计数等待
//*****************************************************
//** main code
//*****************************************************
//先向PCF8563中写入初始化日期和时间,再从中读出日期和时间
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
sec <= 8'h0;