📄 i2cdrv.c
字号:
both SCL and SDA are high */ i2c_start(cptr); /* start condition */ i2c_writebyte(cptr, cptr->dev_addr); /* control byte */ if( addr >= 0 ) { i2c_writebyte(cptr, 0x0); /* starting address */ i2c_writebyte(cptr, w_addr); /* starting address */ } for (i = 0; i < n; i++) { i2c_writebyte(cptr, s[i]); } i2c_stop(cptr); /* stop condition */ wait_timer(cptr->tWR); /* write cycle time */ if (!timeout) return(0); } return(-1);}#endif /* REAL_TIME_CLK *//**************************************************** Read n bytes from the i2c device specified by its device id. No subaddress is specified. arguments: dev_id device id read n no. of bytes to be written s array of storing n data to be read return: 0 okay (got ack) -1 error (no ack)*****************************************************/int I2C_arrayread(int dev_id, int addr, int n, unsigned char *s){ int i, rt; uchar w_addr = (uchar)(addr & 0xff); int tmp = (n-1); IIC_CONFIG *cptr;#ifdef BIG_E2PROM uchar hw_addr = (uchar)(((addr & 0x700)>>7)&0x0e);#endif /* ptr to device parameters */ cptr = i2c_dev + dev_id; for (rt = 0; rt < TRY_COUNT; rt++) { /* try again if no ack */ timeout = 0; /* reset timeout */ wait_timer(cptr->tBUF); /* bus free time: both SCL and SDA are high */ if( addr >= 0 ) { i2c_start(cptr); /* start condition */#ifdef BIG_E2PROM if(addr>255) { i2c_writebyte(cptr, (cptr->dev_addr)|hw_addr); } else i2c_writebyte(cptr, cptr->dev_addr);#else i2c_writebyte(cptr, cptr->dev_addr); /* control byte: for write */#endif i2c_writebyte(cptr, w_addr); /* word address */ } i2c_start(cptr); /* start condition */#ifdef BIG_E2PROM if(addr>255) { i2c_writebyte(cptr, ((cptr->dev_addr)|hw_addr) | 0x01); } else i2c_writebyte(cptr, (cptr->dev_addr) | 0x01);#else i2c_writebyte(cptr, (cptr->dev_addr) | 0x01);#endif /* control byte: for read */ for (i = 0; i < tmp; i++) { s[i] = i2c_readbyte(cptr); i2c_ack(cptr, 2); /* give ack */ } s[n-1] = i2c_readbyte(cptr); i2c_ack(cptr, 0); /* ack clock cycle: no ack is needed for last read */ i2c_stop(cptr); /* stop condition */ if (!timeout) return(0); /* data read */ } return(-1);}#ifdef REAL_TIME_CLK /**************************************************** Read n bytes from the i2c device specified by its device id. No subaddress is specified. arguments: dev_id device id read n no. of bytes to be written s array of storing n data to be read return: 0 okay (got ack) -1 error (no ack)*****************************************************/int RtcI2CArrayRead(int dev_id, int addr, int n, unsigned char *s){ int i, rt; uchar w_addr = (uchar)(addr & 0xff); int tmp = (n-1); IIC_CONFIG *cptr; /* ptr to device parameters */ cptr = i2c_dev + dev_id; for (rt = 0; rt < TRY_COUNT; rt++) { /* try again if no ack */ timeout = 0; /* reset timeout */ wait_timer(cptr->tBUF); /* bus free time: both SCL and SDA are high */ if( addr >= 0 ) { i2c_start(cptr); /* start condition */ i2c_writebyte(cptr, cptr->dev_addr); /* control byte: for write */ i2c_writebyte(cptr, 0x0); /* word address */ i2c_writebyte(cptr, w_addr); /* word address */ } i2c_start(cptr); /* start condition */ i2c_writebyte(cptr, (cptr->dev_addr) | 0x01); /* control byte: for read */ for (i = 0; i < tmp; i++) { s[i] = i2c_readbyte(cptr); i2c_ack(cptr, 2); /* give ack */ } s[n-1] = i2c_readbyte(cptr); i2c_ack(cptr, 0); /* ack clock cycle: no ack is needed for last read */ i2c_stop(cptr); /* stop condition */ if (!timeout) return(0); /* data read */ } return(-1);}#endif /* REAL_TIME_CLK *//**************************************************** Acknowledge polling to see if the write cycle is finished or not. arguments: dev_id device id return: 1 device acknowledge 0 device not acknowledge*****************************************************/int I2C_ackpolling(int dev_id){ int tmp, stime; IIC_CONFIG *cptr; /* ptr to device parameters */ cptr = i2c_dev + dev_id; stime = mvd[riface_timer2]; while (1) { /* polling */ timeout = 0; wait_timer(cptr->tBUF); i2c_start(cptr); i2c_writebyte(cptr, cptr->dev_addr); need_to_stop = 0; /* reset the flag after one attempt */ if (!timeout) { /* got ack */ return(1); } else { /* no ack */ tmp = mvd[riface_timer2] - stime; if (tmp < 0) tmp += -timer2_period; if (tmp >= cptr->poll_wtime) { return(0); /* no ack (exit after timeout) */ } } }}/* * Local Functions *//**************************************************** set and wait till scl is really high. arguments: *cptr ptr to the current device parameters. return:*****************************************************/static void i2c_raise_scl(IIC_CONFIG *cptr){ cptr->SCL_set(1); while (1) { if (cptr->SCL_sense()) break; }}/**************************************************** I2C start condition. arguments: *cptr ptr to the current device parameters. return:*****************************************************/static void i2c_start(IIC_CONFIG *cptr){ if (!need_to_stop) { cptr->SDA_set(1); /* SDA high */#ifndef CHEAT wait_timer(cptr->tLOW); /* SCL low time */#endif i2c_raise_scl(cptr); /* SCL high */ wait_timer((cptr->tR)+(cptr->tSU_STA)); /* SCL rise time + start condition setup time */ cptr->SDA_set(0); /* SDA low */ wait_timer((cptr->tF)+(cptr->tHD_STA)); /* SDA fall time + start condition hold time */ cptr->SCL_set(0); /* SCL low */#ifndef CHEAT wait_timer((cptr->tF)+(cptr->tLOW)); /* SCL fall time + SCL low time */#endif }}/**************************************************** i2c_stop: I2C stop condition. arguments: *cptr ptr to the current device parameters. return: *****************************************************/static void i2c_stop(IIC_CONFIG *cptr){ need_to_stop = 0; /* reset "need_to_stop" */ cptr->SDA_set(0); /* SDA low */#ifndef CHEAT wait_timer(cptr->tLOW); /* SCL low time */#endif i2c_raise_scl(cptr); /* SCL high */ wait_timer((cptr->tR)+(cptr->tSU_STO)); /* SCL rise time + stop condition setup time */ cptr->SDA_set(1); /* SDA high */#ifndef CHEAT wait_timer(cptr->tR); /* SDA rise time */#endif}/**************************************************** i2c_writebyte: Write a byte to I2C bus. arguments: *cptr ptr to the current device parameters. c a byte to be written return: *****************************************************/static void i2c_writebyte(IIC_CONFIG *cptr, unsigned char c){ int i;#if defined(BD_ABELA3) || defined(BD_HERTZ) SET_VFD_STROBE;#endif if (!need_to_stop) { for (i = 0; i < 8; i++) { wait_timer(cptr->tLOW); /* SCL low time */ if (c & 0x80) { /* most significant bit */ cptr->SDA_set(1); /* SDA high */ } else { cptr->SDA_set(0); /* SDA low */ }#ifndef CHEAT wait_timer(cptr->tSU_DAT); /* data in setup time */#endif i2c_raise_scl(cptr); /* SCL high */ wait_timer((cptr->tR)+(cptr->tHIGH)); /* SCL rise time + SCL high time */ cptr->SCL_set(0); /* SCL low */#ifndef CHEAT wait_timer((cptr->tF)+(cptr->tHD_DAT)); /* SDA and SCL fall time + data in hold time */#endif c <<= 1; } i2c_ack(cptr, 1); /* get acknowledge */ if (timeout) need_to_stop = 1; else need_to_stop = 0; }}/**************************************************** i2c_ack: I2C acknowledge of byte transfer. arguments: *cptr ptr to the current device parameters. mode 0 (no ack needed) 1 (get ack) 2 (give ack) return: 0 okay (got ack) -1 error (no ack)*****************************************************/static int i2c_ack(IIC_CONFIG *cptr, int mode){ int tmp; int ack_starttime; int k = -1; if (!need_to_stop) { if (mode == 1) { /* get acknowledge */ cptr->SDA_set(1); /* SDA high */ #ifndef CHEAT wait_timer((cptr->tR)+(cptr->tSU_DAT)); /* SDA rise time and setup time */#endif wait_timer(cptr->tLOW); /* SCL low time */ i2c_raise_scl(cptr); wait_timer(cptr->tHIGH); /* SCL rise time and high time */ ack_starttime = mvd[riface_timer2]; /* ack start time */ while (1) { if (!(cptr->SDA_sense())) { k = 0; yes_ack++; break; /* got acknowledge */ } else { k = -1; tmp = mvd[riface_timer2] - ack_starttime; if (tmp < 0) tmp += -timer2_period; if (tmp >= cptr->ack_wtime) { timeout++; no_ack++; break; /* acknowledge timeout */ } } } } else if (mode == 2) { /* acknowledge is needed */ wait_timer(cptr->tLOW); /* SCL low time */ cptr->SDA_set(0); /* SDA low */ wait_timer((cptr->tF)+(cptr->tSU_DAT)); /* SDA fall time and setup time */ wait_timer(cptr->tLOW); /* SCL low time */ /* clock cycle for acknowledge */ i2c_raise_scl(cptr); /* SCL high */ wait_timer((cptr->tR)+(cptr->tHIGH)); /* SDA and SCL rise time + SCL high time */ } else { /* no acknowledge is needed */ i2c_raise_scl(cptr); /* SCL high */ wait_timer((cptr->tR)+(cptr->tHIGH)); /* SDA and SCL rise time + SCL high time */ } cptr->SCL_set(0); /* SCL low */ wait_timer((cptr->tF)+(cptr->tLOW)); /* SCL fall time + SCL low time */ /* For mode 2, need to tristate SDA again. MY20010314 */ if( mode == 2 ) { cptr->SDA_set(1); /* SDA tristate */ wait_timer((cptr->tR)); /* SCL rise time */ } } return(k);}/**************************************************** i2c_readbyte: Read a byte from the I2C bus. arguments: *cptr ptr to the current device parameters. return: b byte read*****************************************************/static uchar i2c_readbyte(IIC_CONFIG *cptr){ int i; unsigned char b;#if defined(BD_ABELA3) || defined(BD_HERTZ) SET_VFD_STROBE;#endif b = 0; if (!need_to_stop) { for (i = 0; i < 8; i++) { b <<= 1; wait_timer(cptr->tAA); /* data output delay time */ i2c_raise_scl(cptr); /* SCL high */ wait_timer(cptr->tR); /* SCL rise time */ if (cptr->SDA_sense()) /* SDA out */ b |= 1; else b |= 0; wait_timer(cptr->tHIGH); /* SCL high time */ cptr->SCL_set(0); /* SCL low */ wait_timer((cptr->tF)+(cptr->tDH)+(cptr->tLOW)); /* SCL fall time + data out hold time + clock low time */ } } return(b);}#endif /* IIC */int RDS_I2C_arrayread(int dev_id, int n, unsigned char *s){ int i, rt; int tmp = (n-1); IIC_CONFIG *cptr;if(dev_id <0) return 0; /* ptr to device parameters */ cptr = i2c_dev + dev_id; for (rt = 0; rt < TRY_COUNT; rt++) { /* try again if no ack */ timeout = 0; /* reset timeout */ wait_timer(cptr->tBUF); /* bus free time: both SCL and SDA are high */ i2c_start(cptr); /* start condition */ i2c_writebyte(cptr, (cptr->dev_addr) | 0x01); /* control byte: for read */ for (i = 0; i < tmp; i++) { s[i] = i2c_readbyte(cptr); i2c_ack(cptr, 2); /* give ack */ } s[n-1] = i2c_readbyte(cptr); i2c_ack(cptr, 0); /* ack clock cycle: no ack is needed for last read */ i2c_stop(cptr); /* stop condition */ if (!timeout) return(0); /* data read */ } return(-1);}int RDS_I2C_arraywrite(int dev_id, int n, uchar *s){ int i, rt; // uchar w_addr = (uchar)(addr & 0xff); IIC_CONFIG *cptr;if(dev_id < 0) return 0; /* ptr to device parameters */ cptr = i2c_dev + dev_id; for (rt = 0; rt < TRY_COUNT; rt++) { /* try again if no ack */ timeout = 0; /* reset timeout */ wait_timer(cptr->tBUF); /* bus free time: both SCL and SDA are high */ i2c_start(cptr); /* start condition */#ifdef BIG_E2PROM#else i2c_writebyte(cptr, cptr->dev_addr); /* control byte */#endif for (i = 0; i < n; i++) { i2c_writebyte(cptr, s[i]); } i2c_stop(cptr); /* stop condition */ wait_timer(cptr->tWR); /* write cycle time */ if (!timeout) return(0); } return(-1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -