FPGAi2c实验.docx

上传人:b****6 文档编号:5362654 上传时间:2022-12-15 格式:DOCX 页数:10 大小:54.98KB
下载 相关 举报
FPGAi2c实验.docx_第1页
第1页 / 共10页
FPGAi2c实验.docx_第2页
第2页 / 共10页
FPGAi2c实验.docx_第3页
第3页 / 共10页
FPGAi2c实验.docx_第4页
第4页 / 共10页
FPGAi2c实验.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

FPGAi2c实验.docx

《FPGAi2c实验.docx》由会员分享,可在线阅读,更多相关《FPGAi2c实验.docx(10页珍藏版)》请在冰豆网上搜索。

FPGAi2c实验.docx

FPGAi2c实验

简介 

     这一节,我们来讲一讲有关IIC总线的实验,在硬件中,我们实用了24LC04,一个512字节的EEPROM。

在NIOSII中,没有集成IIC接口,为了实现这一功能,我们有两种途径,一种就是自己写IP核或者移植别人的IP核,另一种方法就是通过IO口模拟IIC总线协议。

我们这一节采用的方法是后者,通过IO口模拟IIC总线协议,以达到对24LC04控制读写的目的。

     首先,我简单介绍一下IIC总线的原理,大家稍微了解一下。

IIC(Inter-IntegratedCircuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。

它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。

在CPU与被控IC之间、IC与IC之间进行双向传送,最高传送速率100kbps。

它在传送数据过程中共有三种类型信号,它们分别是:

开始信号、结束信号和应答信号。

开始信号:

SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。

结束信号:

SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。

应答信号:

接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。

CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。

若未收到应答信号,则判断为受控单元出现故障。

这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。

下图就为IIC总线的时序图。

简单介绍之后,我们就要开始实践一下了,开始吧

硬件开发

     首先,需要在软核中添加两个IO模块,并将其命名为SCL和SDA,其中,SCL为output建portsonly(仅输出),SDA为Bidirection(tristate)port(双向),建好以后,如下图所示

     接下来,我们自动分配一下地址,编译。

完成后,我们回到Quartus界面。

然后我们来分配引脚,如下图所示

     分配好管脚以后,我们运行TCL脚本文件,开始编译(Ctrl+L)……

     编译完成后,我们的硬件部分就结束了,接下来,就是我们的软件开发部分了。

软件开发

     首先,我们打开NIOSII9.0IDE,然后进行编译(Ctrl+B)。

     编译好以后,我们看一下system.h文件,看是否多出了SCL和SDA部分代码。

跟我们预期的一样,system.h文件中出现了SCL和SDA部分代码,如下表所示

/*

*SCLconfiguration

*

*/

#defineSCL_NAME"/dev/SCL"

#defineSCL_TYPE"altera_avalon_pio"

#defineSCL_BASE0x00201060

……

/*

*SDAconfiguration

*

*/

#defineSDA_NAME"/dev/SDA"

#defineSDA_TYPE"altera_avalon_pio"

#defineSDA_BASE0x00201070

……

     在跟大家讨论过程中,我了解到很多人都想知道有关NIOSII自带的API的用法,所以,今天我就用这种方式来实现我们的程序。

不过我还是推荐大家用我之前的方式编写程序,道理我已经说过了,在此不再重复。

下面我们在inc目录下建立一个iic.h文件,如下表所示

#ifndefIIC_H_

#defineIIC_H_

#defineOUT1

#defineIN0

typedefstruct{

void(*write_byte)(unsignedshortaddr,unsignedchardat);

unsignedchar(*read_byte)(unsignedshortaddr);

}IIC;

externIICiic;

#endif/*IIC_H_*/

接下来,我们需要在driver下建立iic.c文件,如下表所示

 

#include

#include

#include

#include"system.h"

#include"altera_avalon_pio_regs.h"

#include"alt_types.h"

#include"../inc/iic.h"

staticalt_u8read_byte(alt_u16addr);

staticvoidwrite_byte(alt_u16addr,alt_u8dat);

IICiic={

.write_byte=write_byte,

.read_byte=read_byte

};

 

/*

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

*Name:

start

*Description:

IIC启动

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

*/

staticvoidstart(void)

{

IOWR_ALTERA_AVALON_PIO_DIRECTION(SDA_BASE,OUT);

IOWR_ALTERA_AVALON_PIO_DATA(SDA_BASE,1);

IOWR_ALTERA_AVALON_PIO_DATA(SCL_BASE,1);

usleep(10);

IOWR_ALTERA_AVALON_PIO_DATA(SDA_BASE,0);

usleep(5);

}

/*

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

*Name:

uart_send_byte

*Description:

IIC停止

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

*/

staticvoidstop(void)

{

IOWR_ALTERA_AVALON_PIO_DIRECTION(SDA_BASE,OUT);

IOWR_ALTERA_AVALON_PIO_DATA(SDA_BASE,0);

IOWR_ALTERA_AVALON_PIO_DATA(SCL_BASE,0);

usleep(10);

IOWR_ALTERA_AVALON_PIO_DATA(SCL_BASE,1);

usleep(5);

IOWR_ALTERA_AVALON_PIO_DATA(SDA_BASE,1);

usleep(10);

}

/*

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

*Name:

ack

*Description:

IIC应答

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

*/

staticvoidack(void)

{

alt_u8tmp;

IOWR_ALTERA_AVALON_PIO_DATA(SCL_BASE,0);

IOWR_ALTERA_AVALON_PIO_DIRECTION(SDA_BASE,IN);

usleep(10);

IOWR_ALTERA_AVALON_PIO_DATA(SCL_BASE,1);

usleep(5);

tmp=IORD_ALTERA_AVALON_PIO_DATA(SDA_BASE);

usleep(5);

IOWR_ALTERA_AVALON_PIO_DATA(SCL_BASE,0);

usleep(10);

while(tmp);

}

/*

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

*Name:

iic_write

*Description:

IIC写一个字节

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

*/

voidiic_write(alt_u8dat)

{

alt_u8i,tmp;

IOWR_ALTERA_AVALON_PIO_DIRECTION(SDA_BASE,OUT);

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

IOWR_ALTERA_AVALON_PIO_DATA(SCL_BASE,0);

usleep(5);

tmp=(dat&0x80)?

1:

0;

dat<<=1;

IOWR_ALTERA_AVALON_PIO_DATA(SDA_BASE,tmp);

usleep(5);

IOWR_ALTERA_AVALON_PIO_DATA(SCL_BASE,1);

usleep(10);

}

}

/*

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

*Name:

read

*Description:

IIC读一个字节

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

*/

staticalt_u8iic_read(void)

{

alt_u8i,dat=0;

IOWR_ALTERA_AVALON_PIO_DIRECTION(SDA_BASE,IN);

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

IOWR_ALTERA_AVALON_PIO_DATA(SCL_BASE,0);

usleep(10);

IOWR_ALTERA_AVALON_PIO_DATA(SCL_BASE,1);

usleep(5);

dat<<=1;

dat|=IORD_ALTERA_AVALON_PIO_DATA(SDA_BASE);

usleep(5);

}

usleep(5);

IOWR_ALTERA_AVALON_PIO_DATA(SCL_BASE,0);

usleep(10);

IOWR_ALTERA_AVALON_PIO_DATA(SCL_BASE,1);

usleep(10);

IOWR_ALTERA_AVALON_PIO_DATA(SCL_BASE,0);

returndat;

}

/*

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

*Name:

write_byte

*Description:

向EEPROM写一个字节

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

*/

staticvoidwrite_byte(alt_u16addr,alt_u8dat)

{

alt_u8cmd;

cmd=(0xa0|(addr>>7))&0xfe;

start();

iic_write(cmd);

ack();

iic_write(addr);

ack();

iic_write(dat);

ack();

stop();

}

/*

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

*Name:

read_byte

*Description:

从EEPROM读一个字节

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

*/

staticalt_u8read_byte(alt_u16addr)

{

alt_u8cmd,dat;

cmd=(0xa0|(addr>>7))&0xfe;

start();

iic_write(cmd);

ack();

iic_write(addr);

ack();

start();

cmd|=0x01;

start();

iic_write(cmd);

ack();

dat=iic_read();

stop();

returndat;

}

最后,我们来建立main.c函数

#include

#include"../inc/iic.h"

#include

#include"alt_types.h"

alt_u8write_buffer[512],read_buffer[512];

intmain()

{

alt_u16i,err;

alt_u8dat;

printf("\nWritingdatatoEEPROM!

\n");

//写入512btye的数据,前256个数字为0到255,后256个数据为1

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

if(i<256)

dat=i;

else

dat=1;

iic.write_byte(i,dat);

write_buffer[i]=dat;

printf("0x%02x",dat);

usleep(10000);

}

printf("\nReadingdatafromEEPROM!

\n");

//将512byte数据读出来并打印

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

read_buffer[i]=iic.read_byte(i);

printf("0x%02x",read_buffer[i]);

usleep(1000);

}

err=0;

printf("\nVerifingdata!

\n");

//对比数据是否相同,如果有不同,说明读写过程有错误

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

if(read_buffer[i]!

=write_buffer[i])

err++;

}

if(err==0)

printf("\nDatawriteandreadsuccessfully!

\n");

else

printf("\nDatawriteandreadfailed!

--%derrors\n",err);

return0;

}

     程序很简单,大家只要对IIC总线有一定的了解就会明白的。

     好的,这节的内容就讲到这,谢谢大家对我的支持。

如果有问题,可以给我留言或者直接加入我们的NIOS技术高级群:

107122106,也可以加我的qq:

984597569

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

当前位置:首页 > 高等教育 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1