首页 > 其他分享 >实验十七 实时时钟实验

实验十七 实时时钟实验

时间:2023-05-18 23:23:51浏览次数:38  
标签:disp 十七 uchar 00 地址 实验 寄存器 时钟

实验十七 实时时钟实验

实验目的

1.学习模拟I2C总线的软件实现方法。
2.了解实时芯片PCF8563的读写方法。
3.掌握单片机读写实时时钟芯片PCF8563的模块程序设计方法。

实验说明

  1. 实时时钟(RTC)器件介绍
    实时时钟(RTC)器件是一种能提供日历/时钟、数据存储等功能的专用集成电路,常用作各种计算机系统的时钟信号源和参数设置存储电路。RTC具有计时准确、耗电低和体积小等特点,特别是在各种嵌入式系统中用于记录事件发生的时间和相关信息,如通信工程、电力自动化、工业控制等自动化程度高的领域的无人值守环境中。随着集成电路技术的不断发展,RTC器件的新品也不断推出,这些新品不仅具有准确的RTC,还有大容量的存储器、温度传感器是A/D数据采集通道等,已成为集RTC、数据采集和存储于一体的综合功能器件,特别适用于以微控制器为核心的嵌入式系统。
    RTC器件与微控制器之间的接口大都采用连线简单的串行接口,诸如I2C、SPI、MICROWIRE和CAN等串行总线接口。
  2. 实时时钟芯片PCF8563
    PCF8563是低功耗CMOS时钟/日历芯片(引脚如图4.3.1所示),它提供一个可编程时钟输出,一个中断输出和一个掉电检测器,所有的地址和数据通过I2C总线接口串行传送。每次读写数据后,内嵌的字地址寄存器会自动产生总量。
    引脚说明:
    1:OSCI 振荡器输入
    2:OSCO 振荡器输出
    3:/INT 中断输出(开漏;低电平有效)
    4:VSS 地
    5:SDA 串行数据I/O
    6:SCL 串行时钟输入
    7:CLKOUT 时钟输出 (开漏)
    8:VDD 正电源


图4.3.1 PCF8563引脚

PCF8563 有16 个8位寄存器:一个可自动增量的地址寄存器,一个内置32.768KHz 的振荡器(带有一个内部集成的电容),一个分频器(用于给实时时钟RTC 提供源时钟),一个可编程时钟输出,一个定时器,一个报警器,一个掉电检测器和一个I2C总线接口。
所有16个寄存器设计成可寻址的8 位并行寄存器,但不是所有位都有用。前两个寄存器(内存地址00H,01H)用于控制寄存器和状态寄存器,内存地址02H~08H 用于时钟计数器(秒~年计数器),地址09H~0CH 用于报警寄存器(定义报警条件),地址0DH 控制CLKOUT 管脚的输出频率,地址0EH 和0FH 分别用于定时器控制寄存器和定时器寄存器。秒、分钟、小时、日、月、年、分钟报警、小时报警、日报警寄存器,编码格式为BCD,星期和星期报警寄存器不以BCD 格式编码。

表17-1 PCF8563寄存器结构

地址 寄存器名称 D7 D6 D5 D4 D3 D2 D1 D0
00H 控制/状态寄存器1 TEST 0 STOP 0 TTESTC 0 0 0
01H 控制/状态寄存器2 0 0 0 TI/TP AF TF AIE TIE
02H 秒寄存器 VL 00~59 BCD码格式数
03H 分寄存器 - 00~59 BCD码格式数
04H 时寄存器 - 00~23 BCD码格式数
05H 日寄存器 - 00~31 BCD码格式数
06H 星期寄存器 - 00~06 BCD码格式数
07H 月/世纪寄存器 C 00~12 BCD码格式数
08H 年寄存器 00~99 BCD码格式数
09H 分钟报警寄存器 AE 00~59 BCD码格式数
0AH 时钟报警寄存器 AE 00~23 BCD码格式数
0BH 日报警寄存器 AE 00~31 BCD码格式数
0CH 星期报警寄存器 AE 00~06 BCD码格式数
0DH CLKOUT频率寄存器 FE FD1 FD0
0EH 定时控制寄存器 TE - - - - - TD1 TD0
0FH 定时器倒计时数值寄存器 定时器倒数计数数值

3.PCF8563与MCU的连接硬件电路


图17-1 PCF8563的硬件电路图

系统中用到的PCF8563与MCU采用的连接方式是模拟I2C总线进行数据传输的,硬件电路如图17-1所示。

4.PCF8563读写子程序模块
(1)写N个字节数据子程序模块(C51程序)

bit Nsend(uchar sla, uchar suba, uchar *s,uchar no)
{
 uchar i;
 Start_I2c();
 SendByte(sla);
 if (ack==0) return(0);
 for (i=0;i<no;i++) 
  {
    SendByte(*s);
    if (ack==0)return(0);
    s++;
}
Stop_I2c();
return(1);
}

(2)读N个字节数据子程序模块(C51程序)

bit Read(uchar sla, uchar suba, uchar *s, uchar no)
{
uchar i;
Start_I2c();
SendByte(sla);
if (ack==0)return(0);
Start_I2c();
SendByte(sla+1);
if(ack==0)return(0);
for (i=0;i<no-1;i++)
{
*s=RcvByte();
Ack_I2c(0);
s++;
}
Ack_I2c(0);
Stop_I2c();
return(1);
}

(3)初始化PCF8563程序模块及其写数据程序(A51)

FIRSTINT:
			MOV  	MTD,#00H    	  ;送初始化命令字1
			MOV  	MTD+1,#21H		    ;送初始化命令字2
			MOV  	SLA,#PCF8563	   ;送器件地址
			MOV  	SUBA,#00H		     ;送子地址为00H
			MOV  	NUMBYTE,#02	     ;写2个字节数据
			LCALL  IWRNBYTE		   ;调用写程序
			RET

(4)读取PCF8563数据程序模块(A51)

RDSFM:	MOV	SLA,#PCF8563     		;送器件地址
		MOV  	SUBA,#02H			             ;送子地址
		MOV  	NUMBYTE,#3		           ;读取3个字节
		LCALL  IRDNBYTE            			;调用读字节子程序
		RET

实验内容及步骤

1、7279阵列式键盘中的J9的短路帽打在上方,J10打在右边VCC处,JD7和JD8分别接数码显示的JD11和JD12。
2、实时时钟的SDA接最小系统的T1,SCL接INT1。
3、把89S52或89S51插到最小系统的40P插座中(ISP烧录器的使用查看附录二),把RCT.HEX文件烧录到S52/S51芯片中。运行程序,看八位数码管显示时钟,正确运行时在数码管上首先显示“00-00-00”,时间将不停的走动,把其中的一根导线断开一段时间,再接上可以看到时钟已经走了一段时间。

源程序

7279.h

extern void reset(void);
extern void write7279(unsigned char cmd, unsigned char dta);
extern unsigned char read7279(unsigned char command);
extern void send_byte1( unsigned char out_byte);
extern unsigned char receive_byte();

C8563.C

/*
1、7279阵列式键盘中的J9的短路帽打在上方,J10打在右边VCC处,
JD7和JD8分别接数码显示的JD11和JD12。
2、实时时钟的SDA接最小系统的T1,SCL接INT1。
3、把89S52或89S51插到最小系统的40P插座中(ISP烧录器的使用查看附录二),
把RTC.HEX文件烧录到S52/S51芯片中。运行程序,看八位数码管显示时钟,
正确运行时在数码管上首先显示"00-00-00",时间将不停的走动,
把其中的一根导线断开一段时间,再接上可以看到时钟已经走了一段时间。

*/
#include	<reg52.h>
#include	<I2C_C51.H>	//包含VI2C软件包
#include    <7279.h>
#include <stdio.h>

#define	PCF8563	0xA2	//定义器件地址
#define	PCF85631	0xA3	//定义器件地址
#define	WRADDR	0x00	//定义写单元首地址
#define	RDADDR	0x02	//定义读单元首地址
#define DECODE0 0x80
#define DECODE1 0xc8
#define BLINKCTL 0x88
unsigned char disp_buf[8]={0,0,0,0,0,0,0,0};

/*********************************************************************************************************
** 函数名称: 	display
** 功能描述: 	7298A led显示
** 输 入: *sd :	显示缓冲区的头地址
**         
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
unsigned char display(unsigned char  *sd)
{     
	sd[0]=sd[0]&0x7f;
	sd[1]=sd[1]&0x7f;
	sd[2]=sd[2]&0x3f;
  	disp_buf[0] =(sd[0]%16);			
    disp_buf[1] =(sd[0]/16);		
    disp_buf[2] = 0x0a;
    disp_buf[3] =(sd[1]%16);
    disp_buf[4] =(sd[1]/16);
    disp_buf[5] = 0x0a;
    disp_buf[6] =(sd[2]%16);	
    disp_buf[7] =(sd[2]/16);
	write7279(BLINKCTL,0xff);
    write7279(DECODE0,disp_buf[0]); 
    write7279(DECODE0+1,disp_buf[1]);
    write7279(DECODE0+2,disp_buf[2]); 
    write7279(DECODE0+3,disp_buf[3]);
    write7279(DECODE0+4,disp_buf[4]); 
    write7279(DECODE0+5,disp_buf[5]);
    write7279(DECODE0+6,disp_buf[6]); 
    write7279(DECODE0+7,disp_buf[7]);
	return 0;
}

/*********************************************************************************************************
** 函数名称: 	DelayNS
** 功能描述: 	长软件延时
** 输 入: no :	延时参数,值越大时延时越久
**         
** 输 出: 0 :	OK;
**         1 :	FAIL;
** 全局变量:	无
** 调用模块: 	无
** 日 期: 2003-3-4
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
unsigned char DelayNS(unsigned char  no)
{ 
	unsigned char  i,j;					//延时参数
  	for(; no>0; no--)
  	{ 
		for(i=0; i<100; i++)
     	for(j=0; j<100; j++);
  	}
  	return 0; 
}

void	main()
{
  unsigned char td[5]={0x00,0x00,0x00,0x00,0x00};	//定义初始化字
  unsigned char rd[5];	//定义接收法缓冲区
  ISendStr(PCF8563,WRADDR,td,0x5);	//初始化PCF8563,如果需要的话可以不去掉
  while(1)
  { //DelayNS(1);
	IRcvStr(PCF8563,RDADDR,rd,0x3);	//读现在的时、分、秒
	DelayNS(1);
	display(rd);	//调显示子程序
	DelayNS(1);
  }
}

I2C_C51.h

/*****************************************************************
/*文件名:I2C_C51.H(头文件名)
/*创建人:晁洪超
   这个头文件对应的库是I2C_C51.LIB,库中有几个模拟I2C的函数,加入此文件 
即可使用I2C平台(主方式的软件平台),            
   注意: 函数是采用软件延时的方法产生SCL脉冲,固对高晶振频率要作 
一定的修改....(本例是1us机器周期,即晶振频率要小于12MHZ).
(函数的使用可参考给出的事例程序.)
*****************************************************************/

#ifdef uchar 
  #define READYDEF 1   /*宏uchar已定义*/
#else  
  #define uchar unsigned char
#endif


/*******************************************************************
                     无子地址发送字节数据函数               

功能: 从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.
      如果返回1表示操作成功,否则操作有误。
********************************************************************/
extern bit ISendByte(uchar sla,uchar c);
 




/*******************************************************************
                     有子地址发送多字节数据函数               

功能:  从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
       地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
       如果返回1表示操作成功,否则操作有误。
********************************************************************/
extern bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no) ;



/*******************************************************************
                    无子地址读字节数据函数               

功能:     从启动总线到发送地址,读数据,结束总线的全过程,从器件地
          址sla,返回值在c.
           如果返回1表示操作成功,否则操作有误。
********************************************************************/
extern bit IRcvByte(uchar sla,uchar *c);





/*******************************************************************
                    有子地址读取多字节数据函数               
   
功能:  从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
       地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
       如果返回1表示操作成功,否则操作有误。
********************************************************************/
extern bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no);



#ifndef READYDEF
  #undef uchar
#endif


标签:disp,十七,uchar,00,地址,实验,寄存器,时钟
From: https://www.cnblogs.com/bujidao1128/p/17413586.html

相关文章

  • 实验四 函数与异常处理编程
    print(sum)sum=42print(sum)definc(n):sum=n+1print(sum)returnsumsum=inc(7)+inc(7)print(sum)deffunc1(a,b,c,d,e,f):return[a,b,c,d,e,f]deffunc2(a,b,c,*,d,e,f):return[a,b,c,d,e,f]deffunc3(a,b,c,/,d,e,f):re......
  • 实验4 函数与异常处理编程
    实验任务1实验源码:1print(sum)2sum=423print(sum)45definc(n):6sum=n+17print(sum)8returnsum910sum=inc(7)+inc(7)11print(sum)运行测试截图:答:不是。line1:内置函数line3:变量名line7:局部变量line11:全局变量  ......
  • 第十七日
    以人类Person为基类公有派生学生类Student和教师类Teacher,main(void)函数完成对其的测试。Person类结构说明: Person类的数据成员包括:①私有数据成员:身份证号no(char[20]型),姓名name(char[20]型)。Person类成员函数包括:①有参构造函数Person(char*,char*)和拷贝构造函......
  • 实验4
    task1 print(sum)sum=42print(sum)definc(n):sum=n+1print(sum)returnsumsum=inc(7)+inc(7)print(sum) 1.打印sum函数2.打印变量名为“sum”的变量3.局部变量4.全局变量task2.2list1=[1,9,8,4]print(sorted(list1))print(sorted(list1,......
  • 打卡第二十七天
    动态输入排序实现一个函数input,能够输入n个整数。一、1。设置一个输入函数,将输入的值存在数组中2.再设置一个进行排序的函数二、三、#include<iostream>#include<string>usingnamespacestd;voidinput(int*(&a),intn){a=newint[n];for(inti=0;i<n;i++){......
  • 实验三 Java类的继承与派生
    第1关类的继承packagestep1;importjava.util.Scanner;classPerson{/**********Begin**********///自行设计类的实现//姓名privateStringname;//性别privateStringsex;//年龄privateintage;//构造方法publi......
  • 有源蜂鸣器实验
    按键控制LED灯有源蜂鸣器实验实验目的每按键一次,蜂鸣器滴一次理论学习有源蜂鸣器和无源蜂鸣器的区别:有源和无源的区别是指震荡源,通常有源蜂鸣器内部带有震荡源,所以只要一通电就会鸣叫一声,无源内部不带震荡源,所以如果用直流信号无法令其鸣叫,必须用2k到5k的方波去驱动它......
  • LED闪烁实验
    数电基础LED闪烁实验实验目的实现LED1秒钟闪烁原理图通过让电平的高低来实现LED灯的闪烁代码编写intled=2;//定义引脚为2voidsetup(){pinMode(led,OUTPUT);//将引脚设置为输出状态}voidloop(){digitalWrite(led,HIGH);delay(1000);//延迟1秒......
  • 无源蜂鸣器实验
    PWM调光实验无源蜂鸣器实验实验目的用电位器调节无源蜂鸣器发出不同的声音理论学习无源蜂鸣器和实际的音响的信号是一样的,是靠频率驱动的原理图代码编写#definepotA0#definebuzzer2intpotbuffer=0;voidsetup(){pinMode(buzzer,OUTPUT);}voidloop(){potbuffe......
  • 火焰传感器实验
    火焰传感器实验实验目的检测到火源报警理论学习火焰传感可以探测火源、热源。外籍红外光越强,数值越小,红外光越弱,数值越大原理图代码编写#defineadpinA0#definebuzzer2intadbuffer=0;voidsetup(){ pinMode(buzzer,OUTPUT); Serial.begin(9600);}voidloop(){ adb......