【原】在51上简单模拟I2C通信

这是C51采用3个GPIO引脚模拟I2C总线时序,并进行数据收发的例子

P3_7: 作为I2C的时钟控制

P3_6: 作为I2C的数据发送

P3_5: 作为I2C的数据接收
引脚定义
1 //Some including files

2 #define SERDES_I2C_ADDR 0x101A

3  

4 sbit I2C_SCK = P3^7; 

5 sbit I2C_SDA = P3^6;

6 sbit I2C_SDI = P3^5;
模块初始化
 1 BYTE byDrv_I2cInit(VOID)

 2 {

 3         g_tI2cReg.ptI2cReg = (TI2C_REG XDATA *)I2C_REG_BASE;

 4       g_tI2cCtrl.bySlave =EI2C_SLA_OPTICAL_FIRST;

 5       g_tI2cCtrl.byErrFlag = FALSE;

 6       g_tI2cReg.ptI2cReg->wPrescale = I2C_CLK_50K;//I2C_PRESCALE;

 7       g_tI2cReg.ptI2cReg->byCtrl = I2C_CORE_ENABLE| I2C_CORE_INT_EN;

 8       g_tI2cCtrl.byIntFlag = FALSE;

 9 

10       I2C_INT_EN;

11       EA = TRUE;

12 

13       return TRUE;

14 }
确认检测
 1 VOID vI2CCheckAck(BYTE byCmd, BYTE byWaitAck)

 2 { 

 3     WORD wI2cIntDelay = I2C_INT_DELAY;

 4          WORD wI2cAckDelay = I2C_ACK;

 5     g_tI2cReg.ptI2cReg->byCmd = byCmd;

 6 

 7          /*等中断响应*/

 8          while (FALSE == g_tI2cCtrl.byIntFlag);

 9 

10          /*等从机ACK 响应*/

11          if (TRUE == byWaitAck)

12          {

13             while(0 != (g_tI2cReg.ptI2cReg->byCmd & BIT7));

14          }    

15 }
延迟同步
 1 VOID I2C_Delay(VOID)

 2 {

 3     WORD wI = 0;

 4 

 5     for (wI=0; wI < 10; wI++)

 6     {

 7         _nop_();

 8         _nop_();

 9         _nop_();

10         _nop_();

11         _nop_();

12         _nop_();

13     }

14 }
通信开始
 1 VOID I2C_Start(VOID)

 2 {

 3     I2C_SDA = 1;

 4     I2C_Delay();

 5 

 6     I2C_SCK = 1;

 7     I2C_Delay();

 8 

 9     //数据线初始状态

10     I2C_SDA = 0;

11     I2C_Delay();

12 

13     //释放总线控制权

14     I2C_SCK = 0;

15     I2C_Delay();

16 }
通信结束
 1 VOID I2C_Stop(VOID)

 2 {

 3     I2C_SCK = 0;

 4     I2C_Delay();

 5 

 6     I2C_SDA = 0;

 7     I2C_Delay();

 8 

 9     I2C_SCK = 1;

10     I2C_Delay();

11 

12     I2C_SDA = 1;

13     I2C_Delay();

14 }
发送字节
 1 VOID I2C_SendByte(BYTE byData)

 2 {

 3     BYTE byI = 0;

 4 

 5     for (byI=0; byI < 8; byI++)

 6     {

 7         if(0 == (byData & 0x80))

 8         {

 9             I2C_SDA = 0;

10         }

11         else

12         {

13             I2C_SDA = 1; 

14         }

15         I2C_Delay();

16 

17         I2C_SCK = 1;

18         I2C_Delay();

19 

20         //释放总线控制权

21         I2C_SCK = 0;

22         I2C_Delay();

23 

24         byData = byData << 1;

25     }

26 }
接收字节
 1 BYTE I2C_ReceiveByte(VOID)

 2 {

 3     BYTE byI = 0;

 4     BYTE byData = 0;

 5     BYTE byTemp = 0;

 6 

 7     for (byI=0; byI < 8; byI++)

 8     {

 9         I2C_SCK = 1;

10         I2C_Delay();

11 

12         byData = byData << 1;

13         byTemp = I2C_SDI;

14         if(0 != byTemp)

15         {

16             byData = byData | 0x01;

17         }

18         I2C_Delay();

19         I2C_SCK = 0;

20         I2C_Delay();

21     }

22     return (byData);

23 }
ACK检测
 1 BYTE I2C_TestAck(VOID)

 2 {

 3     BYTE byTemp = 0;

 4     //获得总线控制权

 5     I2C_SCK = 1;

 6     I2C_Delay();

 7     //从该引脚获取确认

 8     byTemp = I2C_SDI;

 9     if (0 != byTemp)

10     {

11         byTemp = 1;

12     }

13     else

14     {

15         byTemp = 0;

16     }

17     I2C_Delay();

18     //释放

19     I2C_SCK = 0;

20     I2C_Delay();

21     return (byTemp);

22 }
无确认
 1 VOID I2C_NoAck(VOID)

 2 {

 3     I2C_SDA = 1;

 4     I2C_Delay();

 5 

 6     I2C_SCK = 1;

 7     I2C_Delay();

 8 

 9     I2C_SCK = 0;

10     I2C_Delay();

11 }
读数据
 1 BYTE I2C_ReadData(BYTE byRegAddr, BYTE *pbyRdData)

 2 {

 3     BYTE byI2cSlave = 0;

 4     BYTE byTemp = 0;

 5 

 6     g_tGpioReg.ptGpioReg->bDirP3_5 = GPIO_IN;

 7     g_tGpioReg.ptGpioReg->bDirP3_6 = GPIO_OUT;

 8     g_tGpioReg.ptGpioReg->bDirP3_7 = GPIO_OUT;

 9 

10     /*读取I2C slave 地址*/

11     byAPI_OnuRegRead(SERDES_I2C_ADDR, 1, &byI2cSlave);

12     byI2cSlave = byI2cSlave << 1;

13     I2C_Start();

14     //发送slave 地址

15     I2C_SendByte(byI2cSlave);

16     if (1 == I2C_TestAck()) return (FALSE);

17 

18     I2C_SendByte(byRegAddr);

19 

20     if (1 == I2C_TestAck()) return (FALSE);

21 

22     //正式开始读数据

23     I2C_Start();

24 

25     I2C_SendByte(byI2cSlave |BIT0);

26 

27     if(1 == I2C_TestAck()) return (FALSE);

28 

29      byTemp =I2C_ReceiveByte();

30 

31      I2C_NoAck();

32 

33     I2C_Stop();

34 

35     *pbyRdData = byTemp;

36 

37     return (TRUE);

38 }
写数据
 1 BYTE I2C_WriteData(BYTE byRegAddr, BYTE byWrData)

 2 {

 3     BYTE byI2cSlave = 0;

 4 

 5     g_tGpioReg.ptGpioReg->bDirP3_5= GPIO_IN;

 6     g_tGpioReg.ptGpioReg->bDirP3_6 = GPIO_OUT;

 7     g_tGpioReg.ptGpioReg->bDirP3_7 = GPIO_OUT;

 8 

 9     /*读取I2C slave 地址*/

10     byAPI_OnuRegRead(SERDES_I2C_ADDR, 1, &byI2cSlave);

11     byI2cSlave = byI2cSlave << 1;

12 

13     I2C_Start();

14     //字节发送

15     I2C_SendByte(byI2cSlave);

16     if (1 == I2C_TestAck()) return (FALSE);

17     I2C_SendByte(byRegAddr);

18     if (1 == I2C_TestAck()) return (FALSE);

19     I2C_SendByte(byWrData);

20     if (1 == I2C_TestAck()) return (FALSE);

21     I2C_Stop();

22 

23     return (TRUE);

24 }

 

 

 

 

你可能感兴趣的:(通信)