zynq学习笔记——EMIO方式模拟I2C时序对ADV7511进行读写

创建硬件工程,很简单,PS接出两个EMIO和一个74.25M时钟

zynq学习笔记——EMIO方式模拟I2C时序对ADV7511进行读写_第1张图片

管脚约束

# ADV7511 I2C_SCL
set_property PACKAGE_PIN AA18 [get_ports {gpio_0_tri_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_0_tri_io[0]}]

# ADV7511 I2C_SDA
set_property PACKAGE_PIN Y16 [get_ports {gpio_0_tri_io[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_0_tri_io[1]}]

# ADV7511 HDMI_CLK
set_property PACKAGE_PIN W18  [get_ports {FCLK_CLK1}]
set_property IOSTANDARD LVCMOS33 [get_ports {FCLK_CLK1}]


导出 Hardware,启动SDK,新建一个应用,添加以下代码

EMIO_init.c

#include "EMIO_init.h"

static XGpioPs psGpioInstancePtr;
int EMIO_I2C_init(void)
{
	XGpioPs_Config* GpioConfigPtr;
	int xStatus;

	GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
	if(GpioConfigPtr == NULL)
	return XST_FAILURE;

	xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,GpioConfigPtr,GpioConfigPtr->BaseAddr);
	if(XST_SUCCESS != xStatus)
		print("EMIO INIT FAILED \n\r");

	XGpioPs_SetDirectionPin(&psGpioInstancePtr, SIOC_PIN,DIRECTION_OUTPUT);
	XGpioPs_SetDirectionPin(&psGpioInstancePtr, SIOD_PIN,DIRECTION_OUTPUT);


	XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, SIOC_PIN,1);
	XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, SIOD_PIN,1);

	return xStatus;
}

void CLOCK_HIGH(void)
{
	XGpioPs_WritePin(&psGpioInstancePtr,SIOC_PIN, 1);
}

void CLOCK_LOW(void)
{
	XGpioPs_WritePin(&psGpioInstancePtr,SIOC_PIN, 0);
}

int GET_DATA(void)
{
	return XGpioPs_ReadPin(&psGpioInstancePtr,SIOD_PIN);
}

void DATA_INPUT(void)
{
	XGpioPs_SetDirectionPin(&psGpioInstancePtr, SIOD_PIN,DIRECTION_INPUT);//
}

void DATA_OUTPUT(void)
{
	XGpioPs_SetDirectionPin(&psGpioInstancePtr, SIOD_PIN,DIRECTION_OUTPUT);//
}

void DATA_HIGH(void)
{
	XGpioPs_WritePin(&psGpioInstancePtr,SIOD_PIN, 1);
}

void DATA_LOW(void)
{
	XGpioPs_WritePin(&psGpioInstancePtr,SIOD_PIN,0);
}


EMIO_init.h

#ifndef EMIO_INIT_H_
#define EMIO_INIT_H_

#include "xgpiops.h"

int EMIO_I2C_init(void);


#define SIOC_PIN 	54
#define SIOD_PIN 	55
#define RESET_PIN 	56


#define DIRECTION_INPUT 0
#define DIRECTION_OUTPUT 1

void CLOCK_HIGH(void);

void CLOCK_LOW(void);

void DATA_HIGH(void);

void DATA_LOW(void);

void DATA_INPUT(void);

void DATA_OUTPUT(void);

int GET_DATA(void);


#endif /* EMIO_INIT_H_ */


I2C_ctrl.c

#include "sleep.h"
#include "EMIO_init.h"


#define I2C_DELAY	usleep(10)

void I2C_start(void)
{
	CLOCK_HIGH();
	DATA_HIGH();
	I2C_DELAY;
	DATA_LOW();
	I2C_DELAY;
	CLOCK_LOW();
	I2C_DELAY;
}

void I2C_end(void)
{
	DATA_LOW();
	I2C_DELAY;
	CLOCK_HIGH();
	I2C_DELAY;
	DATA_HIGH();
	I2C_DELAY;
}

int I2C_sendbyte( unsigned char value )
{
	unsigned char tmp = value;
	unsigned char  i=0,ack;

	for(i=0; i<8; i++)
	{
		if(tmp & 0x80 )
				DATA_HIGH();
		else
				DATA_LOW();

		 I2C_DELAY;
		 CLOCK_HIGH();
		 I2C_DELAY;
		 CLOCK_LOW();
		 I2C_DELAY;

		 tmp<<=1;
	 }


	 DATA_HIGH();
	 DATA_INPUT();
	 I2C_DELAY;
	 CLOCK_HIGH();
	 ack = GET_DATA();
	 I2C_DELAY;
	 CLOCK_LOW();
	 I2C_DELAY;
	 DATA_OUTPUT();

	 if(ack==1)
	 {
		 return -1;
	 }

	 return 0;
}


unsigned char I2C_readbyte( unsigned char addr)
{
	unsigned char  i=0,data=0;

	DATA_HIGH();
	DATA_INPUT();

	for(i=0; i<8; i++)
	{
		CLOCK_HIGH();
		I2C_DELAY;

		data <<= 1;
		if(GET_DATA())
			data |= 1;

		 I2C_DELAY;
		 CLOCK_LOW();
		 I2C_DELAY;
	 }

	 DATA_OUTPUT();
	 DATA_HIGH();
	 I2C_DELAY;
	 CLOCK_HIGH();
	 I2C_DELAY;
	 CLOCK_LOW();
	 I2C_DELAY;
	 DATA_HIGH();

	 return data;
}

int I2C_readdata(unsigned char id, unsigned char addr, unsigned char *value)
{
	// 两相写
	I2C_start();
	if(I2C_sendbyte(id<<1) != 0)
	{
		goto error;
	}

	if(I2C_sendbyte(addr) != 0)
	{
		goto error;
	}

	// 两相读
	I2C_start();
	if(I2C_sendbyte((id<<1)|0x1) != 0)
	{
		goto error;
	}
	*value = I2C_readbyte(addr);
	I2C_end();

	return 0;

error:
	I2C_end();
	return -1;
}

int I2C_senddata(unsigned char id, unsigned char addr,unsigned char value)
{
	I2C_start();
	if(I2C_sendbyte(id<<1) != 0)
	{
		goto error;
	}
	if(I2C_sendbyte(addr) != 0)
	{
		goto error;
	}
	if(I2C_sendbyte(value)!= 0)
	{
		goto error;
	}
	I2C_end();

	return 0;

error:
	I2C_end();
	return -1;

}

I2C_ctrl.h

#ifndef I2C_CTRL_H_
#define I2C_CTRL_H_

void I2C_start(void);
void I2C_end(void);


//void I2C_sendbyte( unsigned char value );

int I2C_senddata(unsigned char id, unsigned char subaddr,unsigned char value);
int I2C_readdata(unsigned char id, unsigned char addr, unsigned char *value);

#endif /* I2C_CTRL_H_ */



helloworld.c


#define ADV7511_I2C_ADDR  (0x72 >> 1)

int main()
{
	unsigned char data;
	int Status;

    init_platform();
    
    EMIO_I2C_init();

    usleep(500*1000);

    while(1)
    {

		//读取PID
		data = 0;
		I2C_senddata(ADV7511_I2C_ADDR,0x41,0x40);
		sleep(1);
		if(I2C_readdata(ADV7511_I2C_ADDR,0x41,&data) != 0)
		{
			print("error\n\r");
		}
		else
		{
			if(data != 0x40)
				print("error\n\r");
		}

		data = 0;
		if(I2C_readdata(ADV7511_I2C_ADDR,0xf5,&data) != 0)
		{
			print("error\n\r");
		}
		else
		{
			if(data != 0x75)
				print("error\n\r");
		}

		data = 0;

		if(I2C_readdata(ADV7511_I2C_ADDR,0xf6,&data) != 0)
		{
			print("error\n\r");
		}
		else
		{
			if(data != 0x11)
				print("error\n\r");
		}


		sleep(2);

    }

    cleanup_platform();
    return 0;
}


你可能感兴趣的:(Zynq-7000)