小模块例程:i2c_at24cxx - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki
i2c读写eeprom(官方例程)
- mb_zynq_periph_test
- 我们用了2个AXI IIC,分别读写z7nano上面的eeprom(at24c32),和我的扩展板上的eeprom(at24c02)
- 使用的是官方的demo例程。需要说明的是,官方的demo例程是可以work的,但需要做一些修改,因为:at24c32的dev地址是0x50, mem地址是16bit, pagesize=32;at24c02的dev地址是0x51, mem地址是8bit,pagesize=8
- 因此,官方例程修改如下: 对于at24c32
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define IIC_DEVICE_ID XPAR_IIC_1_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define IIC_INTR_ID XPAR_INTC_0_IIC_1_VEC_ID
/*
* The following constant defines the address of the IIC Slave device on the
* IIC bus. Note that since the address is only 7 bits, this constant is the
* address divided by 2.
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML510/
* ML501/ML505/ML507/ML510 boards is 0x50. The 7 bit IIC Slave address of the
* IIC EEPROM on the ML605/SP601/SP605 boards is 0x54.
* Please refer the User Guide's of the respective boards for further
* information about the IIC slave address of IIC EEPROM's.
*/
#define EEPROM_ADDRESS 0x50 /* 0xA0 as an 8 bit number. */
/*
* The page size determines how much data should be written at a time.
* The ML310/ML300 board supports a page size of 32 and 16.
* The write function should be called with this as a maximum byte count.
*/
#define PAGE_SIZE 16
/*
* The Starting address in the IIC EEPROM on which this test is performed.
*/
#define EEPROM_TEST_START_ADDRESS 128
/**************************** Type Definitions *******************************/
/*
* The AddressType for ML300/ML310/ML410/ML510 boards should be u16 as the
* address pointer in the on board EEPROM is 2 bytes.
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605 boards should
* be u8 as the address pointer in the on board EEPROM is 1 bytes.
*/
typedef u16 AddressType;
对于at24c02,修改如下:
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define IIC_DEVICE_ID XPAR_IIC_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define IIC_INTR_ID XPAR_INTC_0_IIC_0_VEC_ID
/*
* The following constant defines the address of the IIC Slave device on the
* IIC bus. Note that since the address is only 7 bits, this constant is the
* address divided by 2.
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML510/
* ML501/ML505/ML507/ML510 boards is 0x50. The 7 bit IIC Slave address of the
* IIC EEPROM on the ML605/SP601/SP605 boards is 0x54.
* Please refer the User Guide's of the respective boards for further
* information about the IIC slave address of IIC EEPROM's.
*/
#define EEPROM_ADDRESS 0x51 /* 0xA0 as an 8 bit number. */
/*
* The page size determines how much data should be written at a time.
* The ML310/ML300 board supports a page size of 32 and 16.
* The write function should be called with this as a maximum byte count.
*/
#define PAGE_SIZE 8
/*
* The Starting address in the IIC EEPROM on which this test is performed.
*/
#define EEPROM_TEST_START_ADDRESS 128
/**************************** Type Definitions *******************************/
/*
* The AddressType for ML300/ML310/ML410/ML510 boards should be u16 as the
* address pointer in the on board EEPROM is 2 bytes.
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605 boards should
* be u8 as the address pointer in the on board EEPROM is 1 bytes.
*/
typedef u8 AddressType;
运行结果
i2c读写eeprom(小梅哥例程,用的是zynq核,可以直接在microblaze核上运行。程序是完全兼容的。)
- 注意条件与前面的一样,需要注意AT24C02和AT24C32的设备地址,mem地址位宽,以及pagesize的差异
- AXI IIC这个IP本身不需要初始化,直接就可以使用。所以用在mb核上,直接可以进入读写
- 库函数请参考Code部分的ACZ702_Lib\AXI_IIC at24c02程序
/**
*****************************************************************************
* 使用AXI IIC IP核读写EEEPROM
*****************************************************************************
*
* @File : main.c
* @By : Sun
* @Version : V1.1
* @Date : 2022 / 06 / 13
*
*****************************************************************************
**/
#include "COMMON.h"
#include "AXI_IIC.h"
#define SEND_PACK_SIZE 8 //AT24C02 EEPROM最多只能连续写一页数据(8byte)
int main(void)
{
uint8_t Write_Data[SEND_PACK_SIZE];
uint8_t Read_Data[SEND_PACK_SIZE];
uint16_t i;
uint16_t Error_Cnt=0;
AXI_IIC_Init(&AXI_IIC0,XPAR_IIC_0_DEVICE_ID); //初始化设备Iic,时钟频率为100kHz
//将数据0~31放入数组Write_Data里
for(i=0;i<SEND_PACK_SIZE;i++)
{
Write_Data[i]=i;
}
//将0~31写入EEPROM的第一页0~31地址里
AXI_IIC_SeqWrite_Reg(&AXI_IIC0,0x51,REG8, 0x00,Write_Data,SEND_PACK_SIZE);
usleep(100000);
//读取EEPROM的第一页0~31地址里的数据,存放在Read_Data数组里
AXI_IIC_SeqRead_Reg(&AXI_IIC0, 0x51,REG8, 0x00,Read_Data,SEND_PACK_SIZE);
//对比Write_Data与Read_Data是否一致
for(i=0;i<SEND_PACK_SIZE;i++)
{
if(Write_Data[i] != Read_Data[i])
{
Error_Cnt++;//记录错误数据个数
}
}
printf("Error = %d !\n",Error_Cnt);//打印错误数据的个数,全对则为0,代表试验成功
if(Error_Cnt == 0)
printf("Write EEPROM successful !!!\n");
else
printf("Write EEPROM failed !!!\n");
return 0;
}
at24c32程序
/**
*****************************************************************************
* 使用AXI IIC IP核读写EEEPROM
*****************************************************************************
*
* @File : main.c
* @By : Sun
* @Version : V1.1
* @Date : 2022 / 06 / 13
*
*****************************************************************************
**/
#include "COMMON.h"
#include "AXI_IIC.h"
#define SEND_PACK_SIZE 32 //EEPROM最多只能连续写一页数据(32byte)
int main(void)
{
uint8_t Write_Data[SEND_PACK_SIZE];
uint8_t Read_Data[SEND_PACK_SIZE];
uint16_t i;
uint16_t Error_Cnt=0;
AXI_IIC_Init(&AXI_IIC0,XPAR_IIC_1_DEVICE_ID); //初始化设备Iic,时钟频率为100kHz
//将数据0~31放入数组Write_Data里
for(i=0;i<SEND_PACK_SIZE;i++)
{
Write_Data[i]=i;
}
//将0~31写入EEPROM的第一页0~31地址里
AXI_IIC_SeqWrite_Reg(&AXI_IIC0,0x50,REG16, 0x00,Write_Data,SEND_PACK_SIZE);
usleep(100000);
//读取EEPROM的第一页0~31地址里的数据,存放在Read_Data数组里
AXI_IIC_SeqRead_Reg(&AXI_IIC0, 0x50,REG16, 0x00,Read_Data,SEND_PACK_SIZE);
//对比Write_Data与Read_Data是否一致
for(i=0;i<SEND_PACK_SIZE;i++)
{
if(Write_Data[i] != Read_Data[i])
{
Error_Cnt++;//记录错误数据个数
}
}
printf("Error = %d !\n",Error_Cnt);//打印错误数据的个数,全对则为0,代表试验成功
if(Error_Cnt == 0)
printf("Write EEPROM successful !!!\n");
else
printf("Write EEPROM failed !!!\n");
return 0;
}
补充说明
小梅哥的程序,编译后比较大,达到66kB,超过了我们给microblaze分配的64kB的空间。我们将ld文件中的部分section放到了ddr中。
- 看框图,microblaze的DP通过zynq的GP0接口可以访问到ddr/ocm。因此数据是可以访问到ddr的,但是指令不能访问到ddr。
- 实际的测试结果是:将.bss/.heap/.stack分配到ddr中可以运行,而如果将.text分配到ddr中则不能运行,因为.text需要取指令。进一步的测试表明,除了.text/.init/.fini外,其余的都可以放到ddr中,如下图所示。也就是说,只有.text/.init/.fini是跟取指令有关系的。