查看: 5003|回复: 1

[原创] [LPC1768]I2C驱动架构

[复制链接]
  • TA的每日心情
    开心
    2025-8-8 16:43
  • 签到天数: 1504 天

    连续签到: 1 天

    [LV.Master]伴坛终老

    97

    主题

    4692

    帖子

    12

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    10093
    最后登录
    2025-8-8
    发表于 2019-2-28 13:15:49 | 显示全部楼层 |阅读模式
    本帖最后由 jobszheng5 于 2019-2-28 13:18 编辑

    [LPC1768]I2C驱动架构
        I2C接口的专利现在属于NXP公司,ST芯片的I2C接口据说为了规避专利所以采用了一些技术手段,最终导致其I2C接口的稳定性大大折扣。现在我们使用自家的I2C接口定是会感觉极好的!
        I2C硬件驱动的实现仍然需要采用状态机的设计模式,我们将使用中断处理的方式来操作I2C接口,因此其状态流转图如下图所示:
    timg.jpg
        具体的实现流程与操作寄存器,我们这里参考以下示例:

    1. void I2C0_IRQHandler(void)  
    2. {
    3.   uint8_t StatValue;
    4.   StatValue = LPC_I2C0->I2STAT & 0xf8;
    5.         
    6.   switch ( StatValue )
    7.   {
    8.         case 0x08:                                                              /*已发送起始条件*/
    9.         if (I2C_suba_en == 1)
    10.         {        LPC_I2C0->I2DAT = I2C_sla &0xfe;              /*存放刚发送或接收的一个字节*/
    11.         }
    12.         else
    13.         {        LPC_I2C0->I2DAT = I2C_sla;        
    14.         }        
    15.         LPC_I2C0->I2CONCLR = 0x28;                              /*清除中断标志位、起始标志位*/
    16.         break;
    17.         
    18.         case 0x10:                                                              /*已发送重复起始条件*/
    19.         LPC_I2C0->I2DAT = I2C_sla;
    20.         LPC_I2C0->I2CONCLR = 0x28;                              /*清零中断标志位、起始标志位*/
    21.         break;
    22.         
    23.         case 0x18:                                                              /*已接收ACK 发送数据*/
    24.         case 0x28:                                                              /*已发送I2DAT中的数据,已接收ACK */
    25.         if (I2C_suba_en == 0)                                             /*子地址已经处理或者不需要子地址*/
    26.         {
    27.          
    28.           if(I2C_num>0)
    29.           {  
    30.                   LPC_I2C0->I2DAT = *I2C_buf++;                /*写入数据*/
    31.                   LPC_I2C0->I2CONCLR = 0x28;                    /*清除中断标志位、起始标志位*/
    32.                   I2C_num--;
    33.                   Delay(1);
    34.           }
    35.           else
    36.           {
    37.                 LPC_I2C0->I2CONSET = (1 << 4);                 /*置位停止标志位*/
    38.                 LPC_I2C0->I2CONCLR = 0x28;                      /*清除中断标志位、起始标志位*/
    39.                 I2C_end =1;
    40.           }
    41.                
    42.         }
    43.         if(I2C_suba_en == 1)                                              /*读取操作*/
    44.         {
    45.                 if(I2C_suba_num == 2)
    46.                 {
    47.                   LPC_I2C0->I2DAT = ((I2C_suba >> 8) & 0xff);
    48.                   LPC_I2C0->I2CONCLR = 0x28;                     /*清除中断标志位、起始标志位*/
    49.                   I2C_suba_num--;
    50.                   break;
    51.                  }
    52.                 if(I2C_suba_num == 1)                                    /*字节数为1 */
    53.                 {
    54.                   LPC_I2C0->I2DAT = (I2C_suba & 0xff);
    55.                   LPC_I2C0->I2CONCLR = 0x28;
    56.                   I2C_suba_num--;
    57.                   break;
    58.                  }
    59.                  if(I2C_suba_num == 0)
    60.                  {
    61.                   LPC_I2C0->I2CONCLR = 0x08;                     /*清除中断标志位*/
    62.                   LPC_I2C0->I2CONSET = 0x20;                     /*置位起始标志位*/
    63.                   I2C_suba_en = 0;
    64.                   break;                                   
    65.                  }           
    66.         }

    67.         if ( I2C_suba_en == 2 )                                              /*写操作        */
    68.         {
    69.           if(I2C_suba_num > 0)
    70.           {
    71.                   if(I2C_suba_num == 2)                                    /*字节数为2*/
    72.                   {
    73.                          LPC_I2C0->I2DAT = ((I2C_suba >> 8) & 0xff);
    74.                          LPC_I2C0->I2CONCLR = 0x28;
    75.                          I2C_suba_num--;
    76.                          break;
    77.                   }
    78.                   if(I2C_suba_num == 1)                                    /*字节数为1*/
    79.                   {
    80.                           LPC_I2C0->I2DAT = (I2C_suba & 0xff);
    81.                           LPC_I2C0->I2CONCLR = 0x28;
    82.                           I2C_suba_num--;
    83.                           I2C_suba_en  = 0;
    84.                           break;
    85.                   }
    86.           }
    87.         }
    88.         break;
    89.         
    90.         case 0x40:                                                                  /*已发送SLA+R,已接收ACK*/
    91.         if (I2C_num <= 1)
    92.         {        LPC_I2C0->I2CONCLR = 1 << 2;                     /*清除应答标志位*/
    93.         }
    94.         else
    95.         {
    96.                 LPC_I2C0->I2CONSET = 1 << 2;                      /*置位应答标志位*/
    97.          }
    98.         LPC_I2C0->I2CONCLR = 0x28;                                 /*清除中断标志位、起始标志位*/
    99.         break;

    100.         case 0x20:                                                                 /*已发送SLA+W,已接收非应答 */
    101.         case 0x30:                                                                 /*已发送I2DAT中的数据,已接收非应答*/   
    102.         case 0x38:               
    103.         case 0x48:                                                                 /*已发送SLA+R,已接收非应答*/            
    104.         LPC_I2C0->I2CONCLR = 0x28;                                 /*清零中断标志位、起始标志位*/
    105.         I2C_end = 0xFF;
    106.         break;
    107.                
    108.         case 0x50:                                                                  /*已接收数据字节,已返回ACK8*/
    109.         *I2C_buf++ = LPC_I2C0->I2DAT;
    110.         I2C_num--;
    111.         if (I2C_num ==1)                                                       /*接收最后一个字节*/            
    112.         {        LPC_I2C0->I2CONCLR = 0x2c;                        /*STA,SI,AA = 0 */            
    113.         }
    114.         else
    115.         {        LPC_I2C0->I2CONSET = 0x04;                        /*置位应答标志位 */
    116.                 LPC_I2C0->I2CONCLR = 0x28;                         /*清除中断标志位、起始标志位 */
    117.         }
    118.         break;

    119.         case 0x58:                                                                  /*已接收数据字节,已返回非应答*/         
    120.         *I2C_buf++ = LPC_I2C0->I2DAT;                             /*读出数据*/
    121.         LPC_I2C0->I2CONSET = 0X10;                                  /*assert ACK after data is received*/
    122.         LPC_I2C0->I2CONCLR = 0X28;                                  /*清除中断标志位、起始标志位*/
    123.         I2C_end = 1;                                                                                 
    124.         break;

    125.         default:
    126.         break;
    127.   }
    128. }
    复制代码

        参考终究是参考,我们还是要有自己的设计模式,这里本人采用Linux的编程设计风格来处理。声明以下接口:

    1. /**
    2.   * @brief  open I2C interface, init slaveAddr and get the I2C bus
    3.   * @param  
    4.   * @retval 0=success; -1=I2C bus busy;
    5.   * @date   2019-02-28   13:00
    6.   * @note   blocking mode and timeout
    7.   */

    8. int8_t openI2C(tI2cMasterClass *dev);
    9. int8_t closeI2C(tI2cMasterClass *dev);

    10. /**
    11.   * @brief  write buf[] to I2C interface
    12.   * @param  
    13.   * @retval
    14.   * @date   2019-02-28   13:04
    15.   * @note   blocking mode and timeout
    16.   */

    17. int8_t writeI2C(tI2cMasterClass *dev, uint8_t *wBufPtr, uint16_t wLen);
    18. int8_t readWriteI2c(tI2cMasterClass *dev, uint8_t *rdBufPtr, uint16_t rdLen, uint8_t wBufPtr, uint16_t wLen);
    19. int8_t readI2c(tI2cMasterClass *dev, uint8_t *rdBufPtr, uint16_t rdLen);
    复制代码

        在完成底层硬件驱动后,我们就开始为器件编写针对我们开发套件的读写驱动了。我们会为每一个器件而分立的编写一个实验去验证与说明。

        TO BE CONTINUED.





    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    11

    帖子

    0

    注册会员

    Rank: 2

    积分
    87
    最后登录
    2021-9-23
    发表于 2021-7-8 09:51:52 | 显示全部楼层
    学习一下
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-8-21 17:49 , Processed in 0.085556 second(s), 21 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表