移植OPENCORES上的I2C MASTER到AXI接口处理器层面实现驱动 之2

59 篇文章 4 订阅
46 篇文章 8 订阅



IP核已经写好,可以通过AXI_LITE总线连接到PS上,接下来就写C语言驱动。

其实硬件底层的I2C驱动很简单,就是以下这四个函数。

void I2C_init(unsigned int  base,unsigned int  clk,unsigned int  speed);
int I2C_start(unsigned int  base, unsigned int  add, unsigned int  read);
unsigned int  I2C_read(unsigned int  base,unsigned int  last);
unsigned int  I2C_write(unsigned int  base,unsigned char   data, unsigned int  last);

 这些代码是我在N年前搜索到的代码,当实现了24CXX系列的EEPROM的烧写。

/****************************************************************
int I2C_start
            Sets the start bit and then sends the first byte which
            is the address of the device + the write bit.
inputs
      base = the base address of the component
      add = address of I2C device
      read =  1== read    0== write
return value
       0 if address is acknowledged
       1 if address was not acknowledged
15-OCT-07 initial release
*****************************************************************/
int I2C_start(unsigned int  base, unsigned int  add, unsigned int  read)
{
#ifdef  I2C_DEBUG
        printf(" Start  I2C at 0x%x, \n\twith address 0x%x \n\tand read 0x%x \n\tand prescale 0x%x\n",base,add,read);
#endif

          /* transmit the address shifted by one and the read/write bit*/
  IOWR_I2C_OPENCORES_TXR(base, ((add<<1) + (0x1 & read)));

          /* set start and write  bits which will start the transaction*/
  IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_STA_MSK | I2C_OPENCORES_CR_WR_MSK );

          /* wait for the trnasaction to be over.*/
  while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK);

         /* now check to see if the address was acknowledged */
   if(IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_RXNACK_MSK)
   {
#ifdef  I2C_DEBUG
        printf("\tNOACK\n");
#endif
        return (I2C_NOACK);
   }
   else
   {
#ifdef  I2C_DEBUG
        printf("\tACK\n");
#endif
       return (I2C_ACK);
   }
}

这里以I2C_START 为例子,看到有IORD_I2C_OPENCORES_SR这样的宏单元实际上就是对应了底层的寄存器读写,我们跟进去看定义:

#define IORD_I2C_OPENCORES_SR(base)         IORD(base, 4)

继续跟进IORD,其实就是底层操作,原来我是使用UART转WISHBONE接口模块UART2BUS,定义对应了一个函数,
#define IORD UART2BUS_RDIO 

如果采用内存映射地址就是

#define IORD (base , off )        *(unsigned int *) (base + off <<2 )

base地址就是基地址,可以从VIVADO界面获取。这里是43C0_0000.




驱动层面的编写完毕也就实现了上述了四个函数:

接下来看看一个实现24c02的函数,

unsigned char  randm_read02 (unsigned char dev_addr,unsigned char  byte_addr  ){


unsigned char r;
unsigned char i;

	while(1){
	r = I2C_start(0,dev_addr,0);
	if ( r==0 ) break ;
	}
	
	I2C_write(0,byte_addr,0);

	while(1){
	r = I2C_start(0,dev_addr,1);
	if ( r==0 ) break ;
	}

	r = I2C_read(0,1);

	return r;
}

写应用层程序有下属几点考虑:

1,这里直接操作器件的应用层程序其实也牵扯底层操作,应用层编写的时候要对照器件的I2C时序图,以从设备地址等信息自己画出来。

2,实际产品需要加上超时处理机制,这是所有的I2C应用必须考虑的,尤其使用连接线连接传感器。

3,注意设置合适的I2C时钟。一般应用不要超过100K。










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值