AXI_IIC读写操作

本文档记录了作者调试Zynq Processing System (PS) 中AXI IIC的过程,从工程搭建到SDK程序编写,详细解释了每个步骤和关键代码。在参考了相关文档和论坛讨论后,成功实现了IIC通信。文中还分享了需要注意的事项,如读写操作间的延迟、FIFO状态检查等,并提供了完整的SDK程序示例。适用于Xilinx FPGA开发者和嵌入式系统工程师。
摘要由CSDN通过智能技术生成

其实在之前调试过一次AXI_IIC,没调试通,碍于赶进度,就直接使用了zynq-PS侧的IIC,就一直搁置着了,这次抽空将这部分内容继续调试下去,这一次没花多少时间就调通了,现在将我的调试过程,经历,以及参考文档如下:
参考文档:pg090-axi-iic.pdf
参考链接:https://forums.xilinx.com/t5/Design-and-Debug-Techniques-Blog/IIC-Protocol-and-Programming-Sequence/ba-p/1072248
上面的这个参考链接是很值得参考的,相较于直接看pg090还是简练了不少。
工程搭建没有什么特别的,提供一张搭建完成的block_design(外设我这里挂载包括,qspi,mig,uart,iic,这里其实只需要uart,iic即可):
在这里插入图片描述
这里我们在使用IP时先了解一下IP中的寄存器(因为我没有使用中断,这里我们只用到了CR,SR,TX_FIFO,RX_FIFO,TX_FIFO_OCY):
在这里插入图片描述

然后就是sdk程序了,这里我先将程序贴出来:

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xil_io.h"
#include "sleep.h"

#define GIE 			0x01c
#define ISR 			0x020
#define IER				0x028
#define SOFTR			0x040
#define CR				0x100
#define SR				0x104
#define TX_FIFO			0x108
#define RX_FIFO			0x10c
#define ADR				0x110
#define TX_FIFO_OCY		0x114
#define RX_FIFO_OCY		0x118
#define TEN_ADR			0x11c
#define RX_FIFO_PIRQ	0x120
#define GPO				0x124

#define IIC_Device_ID   0x50

void Initialization_IIC();
void Single_Byte_Write(u8 Device_ID, u8 high_8bit_Address,u8 low_8bit_Address,u8 data);
u8 Single_Byte_Read(u8 Device_ID, u8 high_8bit_Address,u8 low_8bit_Address);

int main() {
	u8 Received_data;
	u8 flag=0;
	init_platform();

	Initialization_IIC();
	for(int i=0;i<8192;i++){
	Single_Byte_Write(IIC_Device_ID,i>>8,i,i);
	if(i%1024==0)
	xil_printf("%d\n\r",i);}

	for(int i=0;i<8192;i++){
	Received_data = Single_Byte_Read(IIC_Device_ID,i>>8,i);
	xil_printf("Received:%x\n\r",Received_data);
	if(i%256 != Received_data)
		flag=1;
	}

	if(flag == 1)
		xil_printf("Received data is not correct.Test failed.\n\r");
	xil_printf("Test finish.\n\r");
	cleanup_platform();
	return 0;
}

/**********************************************************************************************/
//	Initialization
//		1.Set the RX_FIFO depth to maximum by setting RX_FIFO_PIRQ = 0x _ _
//		2.Reset the TX_FIFO with 0x_ _
//		3.Enable the AXI IIC, remove the TX_FIFO reset, and disable the general call
//  Parameter:
//		None.
//	Return:
//		None.
void Initialization_IIC() {
		Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + RX_FIFO_PIRQ, 0x0000000f);//Set the RX_FIFO depth
		Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + CR, Xil_In32(XPAR_AXI_IIC_0_BASEADDR + CR)|0x00000002);//Reset the TX_FIFO
		Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + CR, Xil_In32(XPAR_AXI_IIC_0_BASEADDR + CR)|0x00000001);//Enable the AXI IIC
		Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + CR, Xil_In32(XPAR_AXI_IIC_0_BASEADDR + CR)&0xfffffffd);//Remove the TX_FIFO reset
		Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + CR, Xil_In32(XPAR_AXI_IIC_0_BASEADDR + CR)&0xffffffbf);//Disable the general call
		xil_printf("Initialization_IIC Device finished.\n\r");
}

/**********************************************************************************************/
//	Write Bytes to an IIC Slave Device Addressed as 0x_ _
//	Place the data at slave device address 0x__:
//		1.Check that all FIFOs are empty and that the bus is not busy by reading the SR
//		2.Write 0x___ to the TX_FIFO (set the start bit, the device address, write access)
//		3.Write 0x__ to the TX_FIFO (slave address for data)
//		4.Write 0x__ to the TX_FIFO (byte 1)
//		5.Write 0x__ to the TX_FIFO (byte 2)
//		6.Write 0x__ to the TX_FIFO (stop bit, byte x)
//  Parameter:
//		Device_ID:0x01010,A2,A1,A0
//		high_8bit_Address:first word address
//		low_8bit_Address:second word address
//		data:8bit send data
//	Return:
//		None.
void Single_Byte_Write(u8 Device_ID, u8 high_8bit_Address,u8 low_8bit_Address,u8 data){
	while((Xil_In32(XPAR_AXI_IIC_0_BASEADDR + SR) & 0x000000C4) != 0x000000c0) {}//Check that all FIFOs are empty and that the bus is not busy by reading the SR
	Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + TX_FIFO, (Device_ID<<1)|0x00000100);//Write 0x___ to the TX_FIFO (set the start bit, the device address, write access)
	Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + TX_FIFO, high_8bit_Address);//Write 0x__ to the TX_FIFO (slave address for data)
	Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + TX_FIFO, low_8bit_Address);//Write 0x__ to the TX_FIFO (slave address for data)
	Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + TX_FIFO, data|0x00000200);//Write 0x__ to the TX_FIFO (stop bit, byte 1)
	usleep(100000);
}

/**********************************************************************************************/
//	Read Bytes from an IIC Device Addressed as 0x_ _
//		1.Check that all FIFOs are empty and that the bus is not busy by reading the Status register
//		2.Write 0x___ to the TX_FIFO (set the start bit, the device address, write access)
//		3。Write 0x__ to the TX_FIFO (slave address for data)
//		4.Write 0x__ to the TX_FIFO (slave address for data)
//		5.Write 0x___ to the TX_FIFO (set start bit, device address to 0x__, read access)
//		6.Write 0x___ to the TX_FIFO (set stop bit, four bytes to be received by the AXI IIC)
//		7.Wait until the RX_FIFO is not empty.
//	a) Read the RX_FIFO byte.
//	b) If the last byte is read, then exit; otherwise, continue checking while RX_FIFO is not empty.
//  Parameter:
//		Device_ID:0x01010,A2,A1,A0
//		high_8bit_Address:first word address
//		low_8bit_Address:second word address
//		data:8bit send data
//	Return:
//		8bit Recevived data.
u8 Single_Byte_Read(u8 Device_ID, u8 high_8bit_Address,u8 low_8bit_Address){
	u8 Received_data;
	while((Xil_In32(XPAR_AXI_IIC_0_BASEADDR + SR) & 0x000000C4) != 0x000000c0) {}//Check that all FIFOs are empty and that the bus is not busy by reading the Status register
	Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + TX_FIFO, (Device_ID<<1)|0x00000100);Write 0x___ to the TX_FIFO (set the start bit, the device address, write access)
	Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + TX_FIFO, high_8bit_Address);//Write 0x__ to the TX_FIFO (slave address for data)
	Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + TX_FIFO, low_8bit_Address);//Write 0x__ to the TX_FIFO (slave address for data)
	Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + TX_FIFO, (Device_ID<<1)|0x00000101);//Write 0x___ to the TX_FIFO (set start bit, device address to 0x__, read access)
	Xil_Out32(XPAR_AXI_IIC_0_BASEADDR + TX_FIFO, 0x00000200);//Write 0x___ to the TX_FIFO (set stop bit, four bytes to be received by the AXI IIC)
	while((Xil_In32(XPAR_AXI_IIC_0_BASEADDR + SR) & 0x00000040) == 0x00000040) {}//Wait until the RX_FIFO is not empty.
	while((Xil_In32(XPAR_AXI_IIC_0_BASEADDR + SR) & 0x00000040) != 0x00000040){
		Received_data = Xil_In32(XPAR_AXI_IIC_0_BASEADDR + RX_FIFO);
	}
	return Received_data;
}


操作流程上面完全按照上面的链接操作的,所有的操作都在注释信息中标的很清楚,我的EEPROM(24C64) A0,A1,A2均接的GND(器件地址0x50),里面有(64Kb的地址空间,全部访问需要13位,所以有16位地址)。
注意事项:
1.我的代码是单字节的读写。
1.我们在做读操作时,设置stop时,后面紧跟着的8位表示要接收几Byte的数据,0代表0,1代表1,2代表2,以此类推,我没有写错,0特殊
2.如果对同一个地址空间先写后读,中间一定要间隔0.01s以上,不然你读回来的数据都是FF。
3.如果对不同的地址进行连续的单字节写,中间也一定要间隔0.01s以上,不然你会发现写两个Byte就卡住了。
4.Page的读写操作,和这个类似,但一定要注意访问时间的间隔问题(我没试过Page读写)。
5.前面三个问题,我查找各种状态位做判断都不起作用,如果有人发现其他好的解决办法可以告我一声。
6.调试时可以尝试抓取IIC的信号,scl_i/o/t,sda_i/o/t,注意采样深度,我的是20M时钟采样65536个周期才能看到完整的读写。
7.我上述的代码,光写操作就花费将近15分钟时间,scl 100K,好慢啊.
签名:20201029 olivercao 著

  • 16
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
### 回答1: pg090-axi-iic是一个AXI-IIC控制器的文档。这个文档描述了AXI-IIC控制器的工作原理、功能、接口和配置,让用户能够更好地理解和使用该控制器。 该控制器是一种用于串行通信的硬件模块,可用于与其他器件进行通信。它支持多种传输方案,包括标准模式、高速模式和快速模式,可适用于多种不同的设计需求。此外,该控制器还支持多个设备地址,可用于同时与多个设备进行通信。 该文档提供了关于AXI-IIC控制器的详细说明,包括物理接口、控制寄存器、中断控制、状态指示灯和时序图等内容。用户可以根据这些说明,轻松地进行控制器的接口设计、配置和调试,实现串行通信的功能。同时,该文档还提供了一些实际应用例子,能更好地展示AXI-IIC控制器的应用场景,帮助用户更好地理解该器件的使用方法和可能的应用领域。 ### 回答2: pg090-axi-iic是一种AXI式I2C总线控制器,它支持AXI4-Lite、AXI4-Stream和AXI4 Memory-Mapped接口。AXI式I2C总线控制器可用于板间通信,也可用于片上模块间通信。它支持I2C Master Mode、Multi-Master Mode和Slave Mode。PG090-AXI-IIC PDF详细介绍了该控制器的寄存器映射、时序图、数据流图等技术细节。控制器的时序参数可以根据使用场景进行调整,例如时钟频率、数据长度、CS保持时间等。控制器的代码使用Verilog编写,用户可以将其合成到FPGA芯片中,进行控制器的实现。用户可以通过AXI接口和该控制器进行通信,从而进行I2C总线控制。该控制器使用方便、功能齐全,适用于各种嵌入式系统和通信应用。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值