SOPC中PIO模拟I2C总线通信

时间:2021-08-08 17:52:05

//=============================================================================
//   模拟 I2C_Bus
//   I2C.h
//=============================================================================
#ifndef I2C_BUS_H_
#define I2C_BUS_H_

#include "altera_avalon_pio_regs.h"

typedef unsigned char uint8
typedef unsigned int  uint16
typedef int           int16
typedef unsigned long uint32
typedef long          int32

#define bool          uint8

#define I2C_SCL(x)  IOWR_ALTERA_AVALON_PIO_DATA(I2C_SCL_BASE,x)
#define I2C_SDA_OUT() IOWR_ALTERA_AVALON_PIO_DIRECTION(I2C_SDA_BASE,1)
#define I2C_SDA_IN() IOWR_ALTERA_AVALON_PIO_DIRECTION(I2C_SDA_BASE,0)
#define I2C_RD_SDA() IORD_ALTERA_AVALON_PIO_DATA(I2C_SDA_BASE)
#define I2C_WR_SDA(x) IOWR_ALTERA_AVALON_PIO_DATA(I2C_SDA_BASE,x)

bool I2C_Start(void);
bool I2C_Stop(void);
bool I2C_Write_Byte(uint8 data);
void  delayus(int16 time);

#endif

//=============================================================================
//module:    I2C_Bus.c
//date:     2012-7-17    
//=============================================================================
#include "I2C_Bus.h"

bool I2C_Start(void)
{
 I2C_SDA_OUT();
 I2C_WR_SDA(1); //from High
 delayus(1); 
 I2C_SCL(1); //clk =1
 delayus(5); //set up = 4.7us
 I2C_WR_SDA(0); //to Low
 delayus(5); //hold time > 4us
 I2C_SCL(0); //locked enable
 delayus(1);
 return 1; //start success
}
bool I2C_Stop(void)
{
 I2C_SDA_OUT();
 I2C_WR_SDA(0); //from Low
 delayus(1);
 I2C_SCL(1); //clk = 1
 delayus(5); //setup time > 4us
 I2C_WR_SDA(1); //to High
 delayus(5); //hold time > 4us
   //clk = any
 return 1; //stop success
}
bool I2C_Write_Byte(uint8 data)
{
 uint8 bit;
 bool ACK;  //response
 I2C_SDA_OUT();
 for(bit=0;bit<8;bit++)
 {
  I2C_SCL(0); //clk = 0, enable change data
  delayus(1);
  if(data & 0x80)  //MSB-First
   I2C_WR_SDA(1);
  else
   I2C_WR_SDA(0);
  delayus(5); //set up time
  I2C_SCL(1); //send
  delayus(5); //hold time
  data<<=1; //
 } //send finished
 delayus(1);
 //ready recive response
 I2C_WR_SDA(1);  //free
 delayus(1);
 I2C_SCL(1);  //clk = 1
 I2C_SDA_IN();
 delayus(3);
 ACK=(!I2C_RD_SDA()); //read data
 I2C_SCL(0);
 return ACK;
}
void delayus(int16 time)
{
 int16 i,j;
 for(i=time;i>0;i--)
  for(j=50;j>0;j--)
   ;
}