ZYNQ使用IIC读写EEPROM实验

简介

EEPROM是指带电可擦可编程只读取存储器是一种掉电后数据不丢失的存储芯片。EEPROM可以在电脑上或专用设备上擦除已有信息,重新编程。
本次实验使用ZYNQ的自带IIC库函数读写EEPROM,笔者也是最近由于某些原因才开始学习ZYNQ,并完成了基础部分的学习开始通信协议的库函数部分。

ZYNQ硬件设计部分

第一步创建Block Design,在其中添加ZYNQ7 Processing System

在这里插入图片描述

第二步双击配置

查看开发板原理图后,添加配置将IIC0,映射到EMIO上。

在这里插入图片描述

设置引出的EMIO引脚

选中后右击,选择Make External,将映射到EMIO的IIC0引脚引出,并添加引脚配置文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在资源页面右键选中设计完成的Black Design(①) 然后选择创建HDL (②)最后输出(③)
在这里插入图片描述

添加引脚配置文件
点击Open Enaborated Design

在这里插入图片描述
查看原理图可知EEPROM_I2C_SCL接开发板T19,EEPROM_I2C_SDA接开发板U19,引脚电压就是3.3V。配置完成后保存,然后就可以创建比特流,最后输出。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

SDK代码部分

/*
 * eeprom.h
 *
 *  Created on: 2021年11月13日
 *      Author: heihei
 */

#ifndef SRC_EEPROM_H_
#define SRC_EEPROM_H_

#include "xiicps.h"
#include "xuartps.h"
#include "sleep.h"

#define IIC_DEVICE_ID XPAR_PS7_I2C_1_DEVICE_ID
#define IIC_SLAVE_ADDR 0x50 //IIC地址这里是7位地址而不是8位
#define IIC_START_ADDR 0 //IIC从机开始读写寄存器数据位置
/*IIC Init*/
u32 IIC_Init_EEPORM(XIicPs *Xiicps,u16 deviceid,u32 FsclHz);

u32 IIC_Write_EEPROM(XIicPs *Xiicps,u8 *MsgPtr,u16 ByteCount);

u32 IIC_Read_EEPROM(XIicPs *Xiicps,u8 *MsgPtr_w,u8 *MsgPtr_r,u16 ByteCount);

#endif /* SRC_EEPROM_H_ */

/*
 * eeprom.c
 *
 *  Created on: 2021年11月13日
 *      Author: heihei
 */
#include "eeprom.h"

/* 初始化IIC
 * Xiicps 驱动实例
 * deviceid 设备ID
 * FsclHz IIC传输速率
 * */
u32 IIC_Init_EEPORM(XIicPs *Xiicps,u16 deviceid,u32 FsclHz)
{
	u32 state;
	XIicPs_Config * IIC_Config;
	IIC_Config=XIicPs_LookupConfig(deviceid);
	state=XIicPs_CfgInitialize(Xiicps,IIC_Config,IIC_Config->BaseAddress);
	if(state!=XST_SUCCESS){
		print("CfgInit Error!\r\n");
		return XST_FAILURE;
	}

	state=XIicPs_SelfTest(Xiicps);//IIC自查
	if(state!=XST_SUCCESS){
		print("SelfTest Error!\r\n");
		return XST_FAILURE;
	}

	state=XIicPs_SetSClk(Xiicps,FsclHz);//IIC设置传输速度
	if(state!=XST_SUCCESS){
			print("SetClk Error!\r\n");
			return XST_FAILURE;
	}
	return XST_SUCCESS;
}
/*
 *在EEPROM中写入数据
 * Xiicps 驱动实例
 * MsgPtr 写入的数组的首地址
 * ByteCount 写入的宽度  单位:字节
 * */
u32 IIC_Write_EEPROM(XIicPs *Xiicps,u8 *MsgPtr,u16 ByteCount){
	u16 Address=IIC_START_ADDR;
	u32 WrOffset;
	u32 status;

	MsgPtr[0] = (u8) (Address);
	WrOffset = 1;

	status = XIicPs_MasterSendPolled(Xiicps,MsgPtr,ByteCount+WrOffset,IIC_SLAVE_ADDR);

		if (status != XST_SUCCESS) {
			print("WriteData Erro\r\n");
			return XST_FAILURE;
		}


	while (XIicPs_BusIsBusy(Xiicps)); //等待总线空闲

	usleep(250000);

	return XST_SUCCESS;
}

u32 IIC_Read_EEPROM(XIicPs *Xiicps,u8 *MsgPtr_w,u8 *MsgPtr_r,u16 ByteCount){
	u16 Address=IIC_START_ADDR;
		u32 WrOffset;
		u32 status;

		MsgPtr_w[0] = (u8) (Address);
		WrOffset = 1;

		status = XIicPs_MasterSendPolled(Xiicps,MsgPtr_w,WrOffset,IIC_SLAVE_ADDR);

		while (XIicPs_BusIsBusy(Xiicps));

		usleep(250000);

		if (status != XST_SUCCESS) {
					print("Find Slave Address Error\r\n");
					return XST_FAILURE;
		}

		status = XIicPs_MasterRecvPolled(Xiicps, MsgPtr_r,ByteCount,IIC_SLAVE_ADDR);
		if (status != XST_SUCCESS) {
				print("Read Address Error\r\n");
					return XST_FAILURE;
		}

		while (XIicPs_BusIsBusy(Xiicps));//等待总线空闲

		return XST_SUCCESS;
}

/*************************************************main.c******************************/
#include "xparameters.h"
#include "sleep.h"
#include "xiicps.h"
#include "xil_printf.h"
#include "xplatform_info.h"
#include "string.h"
#include "eeprom.h"

#define MAX_SIZE 64	//最大传输大小
#define IIC_SCLK_RATE 100000	//IIC速率
#define SIZE 16	//写多少个数据

u8 WriteBuffer[sizeof(u16) + MAX_SIZE]; //发送数组

u8 ReadBuffer[MAX_SIZE];	//接收数组

XIicPs Xiicps; //IIC驱动实例


int main(){
	u16 Address=IIC_START_ADDR;
	u32 WrBOffset;
	u32 states;
	WriteBuffer[0] = (u8) (Address);	//将IIC开始地址赋值给读数组的第一位
	WrBOffset = 1; //写数组存储偏移量
	IIC_Init_EEPORM(&Xiicps,IIC_DEVICE_ID,IIC_SCLK_RATE);//初始化IIC
	//将数据写入 写数组并清空读数组的内容
	for (int Index = 0;Index < SIZE;Index++) {
			WriteBuffer[WrBOffset + Index] = 20+Index;
			ReadBuffer[Index] = 0;
			printf("WriteBuffer:%d,ReadBuffer:%d,Index:%d\r\n",WriteBuffer[WrBfrOffset + Index],ReadBuffer[Index],Index);
		}
	states=IIC_Write_EEPROM(&Xiicps,WriteBuffer,SIZE);	//寻找开始读的地址
	if (states != XST_SUCCESS) {
				print("Write Erro\r\n");
				return XST_FAILURE;
			}

	states=IIC_Read_EEPROM(&Xiicps,WriteBuffer,ReadBuffer,SIZE);		//读IIC
	if (states != XST_SUCCESS) {
					print("read Erro\r\n");
					return XST_FAILURE;
				}

	for (int Index = 0; Index < SIZE; Index++) {
			printf("2__ReadBuff[%d]:%d,WriteBuffer[%d]:%d\r\n",Index,ReadBuffer[Index],Index+WrBOffset,WriteBuffer[Index + WrBOffset]);
		}
	return 0;
}

注意:在使用ZYNQ自带的库函数,其中的读数据是将需要读的从机寄存器地址放入读的数组的第一位,然后需要写入寄存器的数据也要放入读数组中,但是写入的数据是从数组的第二位开始写入的。(就因为这点导致笔者的代码一直出现问题)

有问题评论区或者私信!

  • 4
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 22
    评论
Zynq是一种基于FPGA和ARM处理器的集成电路平台,用于实现嵌入式系统的设计。配置IIC(Inter-Integrated Circuit)是在Zynq平台上实现IIC总线通信的过程。 首先,我们需要在Zynq平台上配置IIC控制器。在Vivado集成开发环境中,可以使用Block Design进行配置。将Zynq的处理系统与相应的IIC控制器连接起来,在系统设计中添加AXI IIC IP核,然后根据需要设置IIC控制器的参数,如时钟频率、传输模式等。 接下来,我们需要在嵌入式软件中编写代码来配置IIC控制器和进行IIC通信。在Zynq平台上,可以使用Xilinx提供的开发套件SDK来进行编程。首先,在Vivado中生成.bit文件并导出硬件,然后打开SDK进行嵌入式软件开发。在工程中,创建一个新的C工程或修改已有的工程,添加IIC控制器的驱动文件,并根据需要编写相关代码。 在软件代码中,我们可以使用IIC控制器的驱动程序接口来配置IIC控制器、发送和接收数据。例如,可以使用函数如"XIicPs_Config *"来获取IIC控制器的默认配置,然后使用函数如"XIicPs_CfgInitialize"初始化IIC控制器。接下来,使用函数如"XIicPs_SetOptions"设置IIC控制器的传输选项,如时钟频率、地址重复模式等。最后,使用函数如"XIicPs_MasterSendPolled"和"XIicPs_MasterRecvPolled"发送和接收数据。 在配置完成后,我们可以使用适当的硬件连接和电路设计来连接Zynq平台上的IIC控制器。使用合适的IIC设备(如传感器、显示器、存储器等)连接IIC总线,然后根据IIC设备的规格和要求进行通信。 总之,通过在Zynq平台上配置IIC控制器,编写软件代码并进行硬件连接,我们可以实现Zynq与其他IIC设备之间的通信。这样,我们可以在嵌入式系统中利用IIC总线来传输数据和与其他设备进行交互。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘉鑫的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值