FPGAi2c实验.docx
《FPGAi2c实验.docx》由会员分享,可在线阅读,更多相关《FPGAi2c实验.docx(10页珍藏版)》请在冰豆网上搜索。
![FPGAi2c实验.docx](https://file1.bdocx.com/fileroot1/2022-12/15/1e854610-3913-4ca1-ad64-4d2b1dcc1e88/1e854610-3913-4ca1-ad64-4d2b1dcc1e881.gif)
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