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

来源:互联网 发布:娃娃编程scratchjr安卓 编辑:程序博客网 时间:2024/05/22 17:48



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== writereturn value       0 if address is acknowledged       1 if address was not acknowledged15-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。










阅读全文
0 1
原创粉丝点击