ZYNQ使用IIC读写EEPROM实验
简介
EEPROM是指带电可擦可编程只读取存储器是一种掉电后数据不丢失的存储芯片。EEPROM可以在电脑上或专用设备上擦除已有信息,重新编程。
本次实验使用ZYNQ的自带IIC库函数读写EEPROM,笔者也是最近由于某些原因才开始学习ZYNQ,并完成了基础部分的学习开始通信协议的库函数部分。
ZYNQ硬件设计部分
第一步创建Block Design,在其中添加ZYNQ7 Processing System
第二步双击配置
查看开发板原理图后,添加配置将IIC0,映射到EMIO上。
设置引出的EMIO引脚
选中后右击,选择Make External,将映射到EMIO的IIC0引脚引出,并添加引脚配置文件
Make External
在资源页面右键选中设计完成的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自带的库函数,其中的读数据是将需要读的从机寄存器地址放入读的数组的第一位,然后需要写入寄存器的数据也要放入读数组中,但是写入的数据是从数组的第二位开始写入的。(就因为这点导致笔者的代码一直出现问题)
有问题评论区或者私信!
分类:
ZYNQ/Ultrascale
标签:
ZYNQ
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升