FPGA实时时钟实验.docx

上传人:b****8 文档编号:12836108 上传时间:2023-06-08 格式:DOCX 页数:16 大小:214.79KB
下载 相关 举报
FPGA实时时钟实验.docx_第1页
第1页 / 共16页
FPGA实时时钟实验.docx_第2页
第2页 / 共16页
FPGA实时时钟实验.docx_第3页
第3页 / 共16页
FPGA实时时钟实验.docx_第4页
第4页 / 共16页
FPGA实时时钟实验.docx_第5页
第5页 / 共16页
FPGA实时时钟实验.docx_第6页
第6页 / 共16页
FPGA实时时钟实验.docx_第7页
第7页 / 共16页
FPGA实时时钟实验.docx_第8页
第8页 / 共16页
FPGA实时时钟实验.docx_第9页
第9页 / 共16页
FPGA实时时钟实验.docx_第10页
第10页 / 共16页
FPGA实时时钟实验.docx_第11页
第11页 / 共16页
FPGA实时时钟实验.docx_第12页
第12页 / 共16页
FPGA实时时钟实验.docx_第13页
第13页 / 共16页
FPGA实时时钟实验.docx_第14页
第14页 / 共16页
FPGA实时时钟实验.docx_第15页
第15页 / 共16页
FPGA实时时钟实验.docx_第16页
第16页 / 共16页
亲,该文档总共16页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

FPGA实时时钟实验.docx

《FPGA实时时钟实验.docx》由会员分享,可在线阅读,更多相关《FPGA实时时钟实验.docx(16页珍藏版)》请在冰点文库上搜索。

FPGA实时时钟实验.docx

FPGA实时时钟实验

简介

     这一节,我将给大家讲解实时时钟部分的内容,我在黑金板上用的实时时钟芯片是DS1302,这块芯片很常见,性价比也很高。

我们主要来讲如何在NIOS中实现其功能,所以DS1302功能介绍我简单概括一下,有问题的XX一下就都知道了。

     DS1302是DALLAS公司推出的涓流充电实时时钟芯片,内含一个实时时钟/日历和31字节静态RAM,仅需要三根线:

RES(复位),I/O(数据线),SCLK(串行时钟)。

时钟/RAM的读/写数据以一个字节或多达31个字节的字符组方式通信DS1302工作时功耗很低,保持数据和时钟信息时功率小于1mW。

下面看一下电路图吧,下图所示,很简单,三根线就可以搞定了。

硬件开发

     首先,我们需要在软核中构建三个PIO模块,方法跟以前讲的一样。

需要注意的是RTC_DATA这个PIO,在构建的过程中,我们将其选择为双向的IO口,因为它是数据线,既要输入也需要输出,如下图所示,红圈处就是我们需要注意的地方,其他两个IO口设置为仅输出。

看看构建好以后的样子吧,如下图是所示

接下来就是自动分配地址,中断,然后开始编译,等待……

回到Quartus后,分配引脚,还是需要注意数据线,也是双向的,分配引脚的时候,要构建双向引脚(bidir),如下图所示。

都设置好以后,我们运行TCL脚本文件,然后开始编译,又是等待……

软件开发

     编译好后,我们打开NIOSIIIDE,首先,还是需要编译一下,CTRL+b,编译之后,我们看看system.h有什么变化。

观察后可以看出,里面对了,RTC部分的代码,如下表所示,

#defineRTC_DATA_NAME"/dev/RTC_DATA"

#defineRTC_DATA_TYPE"altera_avalon_pio"

#defineRTC_DATA_BASE0x00201030

……

/*

*RTC_SCLKconfiguration

*

*/

#defineRTC_SCLK_NAME"/dev/RTC_SCLK"

#defineRTC_SCLK_TYPE"altera_avalon_pio"

#defineRTC_SCLK_BASE0x00201040

……

/*

*RTC_nRSTconfiguration

*

*/

#defineRTC_NRST_NAME"/dev/RTC_nRST"

#defineRTC_NRST_TYPE"altera_avalon_pio"

#defineRTC_NRST_BASE0x00201050

……

/*

在这些代码中,我们需要用到的是以下部分

#defineRTC_DATA_BASE0x00201030

#defineRTC_SCLK_BASE0x00201040

#defineRTC_NRST_BASE0x00201050

好的,接下来,我们就开始写程序吧

第一步,修改sopc.h文件,加入以下代码到sopc.h中

#define_RTC

#ifdef_RTC

#defineRTC_SCLK((PIO_STR*)RTC_SCLK_BASE)

#defineRTC_DATA((PIO_STR*)RTC_DATA_BASE)

#defineRTC_RST((PIO_STR*)RTC_NRST_BASE)

#endif/*_RTC*/

没什么可说的,接下来我们在inc文件夹下建立ds1302.h,在其中加入以下内容,跟串口程序一样,里面也有个结构体,用这种方式整合所有的函数和变量。

/*

*===============================================================

*

*Filename:

ds1302.h

*Description:

*Version:

1.0

*Created:

*Revision:

none

*Compiler:

NiosII9.0IDE

*Author:

AVIC

*Company:

金沙滩工作室

*==============================================================

*/

#ifndefDS1302_H_

#defineDS1302_H_

#include"../inc/sopc.h"

//对于双向的IO,操作的过程中要注意改变IO口的方向,置1为输出,置0为输入

#defineRTC_DATA_OUTRTC_DATA->DIRECTION=1

#defineRTC_DATA_INRTC_DATA->DIRECTION=0

typedefstruct{

void(*set_time)(unsignedchar*ti);

void(*get_time)(char*ti);

}DS1302;

externDS1302ds1302;

#endif/*DS1302_H_*/

准备工作都做好以后,接下来我们要做的就是写ds1302的驱动了,根据DS1302的时序图来进行编写,首先我来给看看时序图吧,如下图所示,这个是读数据的时序图,

这个是写数据时序图

还有一个有关寄存器的表格,大家也要注意看一下,如下所示,前面两列是读和写的地址,每次操作时,都先写地址,再传数据。

现在,我们就根据时序图来编写ds1302的驱动,在driver文件夹下建ds1302.c文件,然后添加以下内容,

/*

*=============================================================

*Filename:

ds1302.c

*Description:

*Version:

1.0

*Created:

2009-11-23

*Revision:

none

*Compiler:

NiosII9.0IDE

*Author:

AVIC

*Company:

金沙滩工作室

*

*=============================================================

*/

#include"../inc/ds1302.h"

//函数声明

staticvoiddelay(unsignedintdly);

staticvoidwrite_1byte_to_ds1302(unsignedcharda);

staticunsignedcharread_1byte_from_ds1302(void);

staticvoidwrite_data_to_ds1302(unsignedcharaddr,unsignedcharda);

staticunsignedcharread_data_from_ds1302(unsignedcharaddr);

voidset_time(unsignedchar*ti);

voidget_time(char*ti);

//对DS1302结构体进行初始化,注意结构体中函数指针的初始化方式

DS1302ds1302={

.set_time=set_time,

.get_time=get_time

};

/*

*===FUNCTION====================================================

*Name:

delay

*Description:

延时函数

*==================================================================

*/

voiddelay(unsignedintdly)

{

for(;dly>0;dly--);

}

/*

*===FUNCTION=================================================

*Name:

write_1byte_to_ds1302

*Description:

向ds1302写入1byte数据

*===============================================================

*/

voidwrite_1byte_to_ds1302(unsignedcharda)

{

unsignedinti;

//写数据的时候,RTC_DATA为输出,先设置其为输出

RTC_DATA_OUT;

//以下步骤是处理串行数据的的典型方法,一个位一个位的来判断

for(i=8;i>0;i--)

{

if((da&0x01)!

=0)

RTC_DATA->DATA=1;

else

RTC_DATA->DATA=0;

//根据芯片手册,适当加些延时,不是精确延时

delay(10);

RTC_SCLK->DATA=1;

delay(20);

RTC_SCLK->DATA=0;

delay(10);

da>>=1;

}

}

/*

*===FUNCTION==================================================

*Name:

read_1byte_from_ds1302

*Description:

从ds1302读取1byte数据

*================================================================

*/

unsignedcharread_1byte_from_ds1302(void)

{

unsignedchari;

unsignedcharda=0;

//当读数据的时候,我们要将数据IO设置为输入

RTC_DATA_IN;

//以下是典型的读串行数据的方法

for(i=8;i>0;i--)

{

delay(10);

da>>=1;

if(RTC_DATA->DATA!

=0)

da+=0x80;

RTC_SCLK->DATA=1;

delay(20);

RTC_SCLK->DATA=0;

delay(10);

}

RTC_DATA_OUT;

return(da);

}

/*

*===FUNCTION=================================================

*Name:

write_data_to_ds1302

*Description:

向ds1302写入数据

*===============================================================

*/

voidwrite_data_to_ds1302(unsignedcharaddr,unsignedcharda)

{

RTC_DATA_OUT;

RTC_RST->DATA=0;//复位,低电平有效

RTC_SCLK->DATA=0;

delay(40);

RTC_RST->DATA=1;

//先写地址,再写数据,每次写1字节

write_1byte_to_ds1302(addr);//地址,命令

write_1byte_to_ds1302(da);//写1Byte数据

RTC_SCLK->DATA=1;

RTC_RST->DATA=0;

delay(40);

}

/*

*===FUNCTION===================================================

*Name:

read_data_from_ds1302

*Description:

从ds1302读取数据

*=================================================================

*/

unsignedcharread_data_from_ds1302(unsignedcharaddr)

{

unsignedcharda;

RTC_RST->DATA=0;

RTC_SCLK->DATA=0;

delay(40);

RTC_RST->DATA=1;

//先写地址,再读数据

write_1byte_to_ds1302(addr);

da=read_1byte_from_ds1302();

RTC_SCLK->DATA=1;

RTC_RST->DATA=0;

delay(40);

return(da);

}

/*

*===FUNCTION==================================================

*Name:

set_time

*Description:

设置时间

*================================================================

*/

voidset_time(unsignedchar*ti)

{

unsignedchari;

unsignedcharaddr=0x80;

write_data_to_ds1302(0x8e,0x00);//控制命令,WP=0,写操作

for(i=7;i>0;i--)

{

write_data_to_ds1302(addr,*ti);//秒分时日月星期年

ti++;

addr+=2;

}

write_data_to_ds1302(0x8e,0x80);//控制命令,WP=1,写保护

}

/*

*===FUNCTION==================================================

*Name:

get_time

*Description:

获取时间,读取的时间为BCD码,需要转换成十进制

*================================================================

*/

voidget_time(char*ti)

{

unsignedchari;

unsignedcharaddr=0x81;

chartime;

for(i=0;i<7;i++){

time=read_data_from_ds1302(addr);//读取的时间为BCD码

ti[i]=time/16*10+time%16;//格式为:

秒分时日月星期年

addr+=2;

}

}

OK,我们的驱动写好了,现在我们来写一个main函数来验证一下我们的驱动是否好用吧。

#include

#include"../inc/uart.h"

#include"../inc/ds1302.h"

#include

unsignedchartime[7]={0x00,0x19,0x14,0x17,0x03,0x17,0x10};//格式为:

秒分时日月星期年

intmain()

{

unsignedcharbuffer[50]="\0";

//设置时间

ds1302.set_time(time);

while

(1){

//获取时间

ds1302.get_time(time);

//将我们要的时间格式化一下,如2010-4-415:

25:

00

sprintf(buffer,"20%d-%d-%d%d:

%d:

%d\n",

time[6],time[4],time[3],time[2],time[1],time[0]);

//通过串口发送出去

uart.send_string(sizeof(buffer),buffer);

//延时1秒

usleep(1000000);

}

return0;

}

在上面的程序中,我们获取时间后通过串口发送到上位机,这样也复习了我们上一节讲的串口程序。

当然,大家也可以直接通过printf()打印出来。

在操作ds1302的时候有一点需要注意,ds1302的输入和输出都是8421BCD码进行的,所以我们需要对其进行转换。

不过,输入的时候我是直接输入16进制,比如,我们设置分钟为10的话,我直接输入十六进制的0x10,这样就不需要转化了。

而在输出的时候是必须要转化的,大家在写程序的时候注意这一点。

好了,我们来看看我们的劳动果实,看看串口传出的数据吧。

这一节就讲到这吧,如果有问题请给我留言,或者加入我们的NIOS技术群:

107122106,让我们共同讨论解决,谢谢大家!

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > IT计算机 > 电脑基础知识

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2