[牛人杂谈] I2C的学习

[复制链接]
979|2
 楼主| huahuagg 发表于 2025-2-14 14:32 | 显示全部楼层 |阅读模式
对于例子的学习,肯定要从程序开始看到最后,看和它相关的内容
比如I2C,在系统初始化函数内包含了,I2C模块的时钟使能和引脚映射
  1. CLK_EnableModuleClock(I2C0_MODULE);
  2.     /* Configure the SDA0 & SCL0 of I2C0 pins */
  3.     SYS->P3_MFP &= ~(SYS_MFP_P34_Msk | SYS_MFP_P35_Msk);
  4.     SYS->P3_MFP |= SYS_MFP_P34_SDA0 | SYS_MFP_P35_SCL0;
在I2C的初始化函数
设置了I2C的模块时钟设置,以及使能了相关中断功能
  1. <div><div>    /* Open I2C module and set bus clock */</div><div>    I2C_Open(I2C0, 100000);</div></div><div><div>    /* Enable I2C interrupt */</div><div>    I2C_EnableInt(I2C0);</div><div>    NVIC_EnableIRQ(I2C0_IRQn);</div></div>


 楼主| huahuagg 发表于 2025-2-14 14:43 | 显示全部楼层
下面这个函数其实要控制的是几个全局变量
  1. int32_t I2C0_Read_Write_SLAVE(uint8_t slvaddr)
  2. {
  3.     uint32_t i;

  4.     g_u8DeviceAddr = slvaddr;

  5.     for(i = 0; i < 0x100; i++)
  6.     {
  7.         g_au8MstTxData[0] = (uint8_t)((i & 0xFF00) >> 8);
  8.         g_au8MstTxData[1] = (uint8_t)(i & 0x00FF);
  9.         g_au8MstTxData[2] = (uint8_t)(g_au8MstTxData[1] + 3);

  10.         g_u8MstDataLen = 0;
  11.         g_u8MstEndFlag = 0;

  12.         /* I2C function to write data to slave */
  13.         s_I2C0HandlerFn = (I2C_FUNC)I2C_MasterTx;

  14.         /* I2C as master sends START signal */
  15.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA);

  16.         /* Wait I2C Tx Finish */
  17.         while(g_u8MstEndFlag == 0);
  18.         g_u8MstEndFlag = 0;

  19.         /* I2C function to read data from slave */
  20.         s_I2C0HandlerFn = (I2C_FUNC)I2C_MasterRx;

  21.         g_u8MstDataLen = 0;
  22.         g_u8DeviceAddr = slvaddr;

  23.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA);

  24.         /* Wait I2C Rx Finish */
  25.         while(g_u8MstEndFlag == 0);

  26.         /* Compare data */
  27.         if(g_u8MstRxData != g_au8MstTxData[2])
  28.         {
  29.             printf("I2C Byte Write/Read Failed, Data 0x%x\n", g_u8MstRxData);
  30.             return -1;
  31.         }
  32.     }
  33.     printf("Master Access Slave (0x%X) Test OK\n", slvaddr);
  34.     return 0;
  35. }
实际应用中,肯定不是这么写,但是可以根据它的内容知道这些函数如何用
I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA);
不管是发送完成还是接收完成都是通过中断标志g_u8MstEndFlag置位来实现。
发送和接收都在中断回调函数里执行。并根据状态字执行不同的动作
  1. /*---------------------------------------------------------------------------------------------------------*/
  2. /*  I2C Rx Callback Function                                                                               */
  3. /*---------------------------------------------------------------------------------------------------------*/
  4. void I2C_MasterRx(uint32_t u32Status)
  5. {
  6.     if(u32Status == 0x08)                       /* START has been transmitted and prepare SLA+W */
  7.     {
  8.         I2C_SET_DATA(I2C0, (g_u8DeviceAddr << 1));    /* Write SLA+W to Register I2CDAT */
  9.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  10.     }
  11.     else if(u32Status == 0x18)                  /* SLA+W has been transmitted and ACK has been received */
  12.     {
  13.         I2C_SET_DATA(I2C0, g_au8MstTxData[g_u8MstDataLen++]);
  14.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  15.     }
  16.     else if(u32Status == 0x20)                  /* SLA+W has been transmitted and NACK has been received */
  17.     {
  18.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA_STO_SI);
  19.     }
  20.     else if(u32Status == 0x28)                  /* DATA has been transmitted and ACK has been received */
  21.     {
  22.         if(g_u8MstDataLen != 2)
  23.         {
  24.             I2C_SET_DATA(I2C0, g_au8MstTxData[g_u8MstDataLen++]);
  25.             I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  26.         }
  27.         else
  28.         {
  29.             I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA_SI);
  30.         }
  31.     }
  32.     else if(u32Status == 0x10)                  /* Repeat START has been transmitted and prepare SLA+R */
  33.     {
  34.         I2C_SET_DATA(I2C0, ((g_u8DeviceAddr << 1) | 0x01));   /* Write SLA+R to Register I2CDAT */
  35.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  36.     }
  37.     else if(u32Status == 0x40)                  /* SLA+R has been transmitted and ACK has been received */
  38.     {
  39.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  40.     }
  41.     else if(u32Status == 0x58)                  /* DATA has been received and NACK has been returned */
  42.     {
  43.         g_u8MstRxData = (unsigned char) I2C_GET_DATA(I2C0);
  44.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STO_SI);
  45.         g_u8MstEndFlag = 1;
  46.     }
  47.     else
  48.     {
  49.         /* TO DO */
  50.         printf("Status 0x%x is NOT processed\n", u32Status);
  51.     }
  52. }
  53. /*---------------------------------------------------------------------------------------------------------*/
  54. /*  I2C Tx Callback Function                                                                               */
  55. /*---------------------------------------------------------------------------------------------------------*/
  56. void I2C_MasterTx(uint32_t u32Status)
  57. {
  58.     if(u32Status == 0x08)                       /* START has been transmitted */
  59.     {
  60.         I2C_SET_DATA(I2C0, g_u8DeviceAddr << 1);    /* Write SLA+W to Register I2CDAT */
  61.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  62.     }
  63.     else if(u32Status == 0x18)                  /* SLA+W has been transmitted and ACK has been received */
  64.     {
  65.         I2C_SET_DATA(I2C0, g_au8MstTxData[g_u8MstDataLen++]);
  66.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  67.     }
  68.     else if(u32Status == 0x20)                  /* SLA+W has been transmitted and NACK has been received */
  69.     {
  70.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA_STO_SI);
  71.     }
  72.     else if(u32Status == 0x28)                  /* DATA has been transmitted and ACK has been received */
  73.     {
  74.         if(g_u8MstDataLen != 3)
  75.         {
  76.             I2C_SET_DATA(I2C0, g_au8MstTxData[g_u8MstDataLen++]);
  77.             I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  78.         }
  79.         else
  80.         {
  81.             I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STO_SI);
  82.             g_u8MstEndFlag = 1;
  83.         }
  84.     }
  85.     else
  86.     {
  87.         /* TO DO */
  88.         printf("Status 0x%x is NOT processed\n", u32Status);
  89.     }
  90. }



蝶弄美人簪 发表于 2025-8-28 13:09 | 显示全部楼层
学习 I2C 需掌握两根线(SDA/SCL)、起始 / 停止信号、应答机制,熟悉时序图,练习配置寄存器、写读写代码,多调试实践。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

159

主题

1430

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部