⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.lst

📁 基于周立功开发系统的I2C总线实验源代码
💻 LST
字号:
C51 COMPILER V7.20   I2C                                                                   01/01/2002 03:12:21 PAGE 1   


C51 COMPILER V7.20, COMPILATION OF MODULE I2C
OBJECT MODULE PLACED IN I2C.OBJ
COMPILER INVOKED BY: C:\Keil\C51\BIN\C51.EXE I2C.c DEBUG OBJECTEXTEND

line level    source

   1          /*
   2          I2C.c
   3          标准80C51 单片机模拟I2C 总线的主机程序
   4          Copyright (c) 2005,广州周立功单片机发展有限公司
   5          All rights reserved.
   6          本程序仅供学习参考,不提供任何可靠性方面的担保;请勿用于商业目的
   7          */
   8          #include "I2C.h"
   9          //定义延时变量,用于宏I2C_Delay()
  10          unsigned char data I2C_Delay_t;
  11          /*
  12          宏定义:I2C_Delay()
  13          功能:延时,模拟I2C 总线专用
  14          */
  15          #define I2C_Delay()\
  16          {\
  17          I2C_Delay_t = (I2C_DELAY_VALUE);\
  18          while ( --I2C_Delay_t != 0 );\
  19          }
  20          /*
  21          函数:I2C_Init()
  22          功能:I2C 总线初始化,使总线处于空闲状态
  23          说明:在main()函数的开始处,通常应当要执行一次本函数
  24          */
  25          void I2C_Init()
  26          {
  27   1      I2C_SCL = 1;
  28   1      I2C_Delay();
  29   1      I2C_SDA = 1;
  30   1      I2C_Delay();
  31   1      }
  32          /*
  33          函数:I2C_Start()
  34          功能:产生I2C 总线的起始状态
  35          说明:
  36          SCL处于高电平期间,当SDA 出现下降沿时启动I2C 总线
  37          不论SDA 和SCL 处于什么电平状态,本函数总能正确产生起始状态
  38          本函数也可以用来产生重复起始状态
  39          本函数执行后,I2C 总线处于忙状态
  40          */
  41          void I2C_Start()
  42          {
  43   1      I2C_SDA = 1;
  44   1      I2C_Delay();
  45   1      I2C_SCL = 1;
  46   1      I2C_Delay();
  47   1      I2C_SDA = 0;
  48   1      I2C_Delay();
  49   1      I2C_SCL = 0;
  50   1      I2C_Delay();
  51   1      }
  52          /*
  53          函数:I2C_Write()
  54          功能:向I2C 总线写1 个字节的数据
  55          参数:
C51 COMPILER V7.20   I2C                                                                   01/01/2002 03:12:21 PAGE 2   

  56          dat:要写到总线上的数据
  57          */
  58          void I2C_Write(char dat)
  59          {
  60   1      unsigned char t = 8;
  61   1      do
  62   1      {
  63   2      I2C_SDA = (bit)(dat & 0x80);
  64   2      dat <<= 1;
  65   2      I2C_SCL = 1;
  66   2      I2C_Delay();
  67   2      I2C_SCL = 0;
  68   2      I2C_Delay();
  69   2      } while ( --t != 0 );
  70   1      }
  71          /*
  72          函数:I2C_Read()
  73          功能:从从机读取1 个字节的数据
  74          返回:读取的一个字节数据
  75          */
  76          char I2C_Read()
  77          {
  78   1      char dat;
  79   1      unsigned char t = 8;
  80   1      I2C_SDA = 1; //在读取数据之前,要把SDA 拉高
  81   1      do
  82   1      {
  83   2      I2C_SCL = 1;
  84   2      I2C_Delay();
  85   2      dat <<= 1;
  86   2      if ( I2C_SDA ) dat |= 0x01;
  87   2      I2C_SCL = 0;
  88   2      I2C_Delay();
  89   2      } while ( --t != 0 );
  90   1      return dat;
  91   1      }
  92          /*
  93          函数:I2C_GetAck()
  94          功能:读取从机应答位
  95          返回:
  96          0:从机应答
  97          1:从机非应答
  98          说明:
  99          从机在收到每个字节的数据后,要产生应答位
 100          从机在收到最后1 个字节的数据后,一般要产生非应答位
 101          */
 102          bit I2C_GetAck()
 103          {
 104   1      bit ack;
 105   1      I2C_SDA = 1;
 106   1      I2C_Delay();
 107   1      I2C_SCL = 1;
 108   1      I2C_Delay();
 109   1      ack = I2C_SDA;
 110   1      I2C_SCL = 0;
 111   1      I2C_Delay();
 112   1      return ack;
 113   1      }
 114          /*
 115          函数:I2C_PutAck()
 116          功能:主机产生应答位或非应答位
 117          参数:
C51 COMPILER V7.20   I2C                                                                   01/01/2002 03:12:21 PAGE 3   

 118          ack=0:主机产生应答位
 119          ack=1:主机产生非应答位
 120          说明:
 121          主机在接收完每一个字节的数据后,都应当产生应答位
 122          主机在接收完最后一个字节的数据后,应当产生非应答位
 123          */
 124          void I2C_PutAck(bit ack)
 125          {
 126   1      I2C_SDA = ack;
 127   1      I2C_Delay();
 128   1      I2C_SCL = 1;
 129   1      I2C_Delay();
 130   1      I2C_SCL = 0;
 131   1      I2C_Delay();
 132   1      }
 133          /*
 134          函数:I2C_Stop()
 135          功能:产生I2C 总线的停止状态
 136          说明:
 137          SCL处于高电平期间,当SDA 出现上升沿时停止I2C 总线
 138          不论SDA 和SCL 处于什么电平状态,本函数总能正确产生停止状态
 139          本函数执行后,I2C 总线处于空闲状态
 140          */
 141          void I2C_Stop()
 142          {
 143   1      unsigned int t = I2C_STOP_WAIT_VALUE;
 144   1      I2C_SDA = 0;
 145   1      I2C_Delay();
 146   1      I2C_SCL = 1;
 147   1      I2C_Delay();
 148   1      I2C_SDA = 1;
 149   1      I2C_Delay();
 150   1      while ( --t != 0 ); //在下一次产生Start 之前,要加一定的延时
 151   1      }
 152          /*
 153          函数:I2C_Puts()
 154          功能:I2C 总线综合发送函数,向从机发送多个字节的数据
 155          参数:
 156          SlaveAddr:从机地址(7 位纯地址,不含读写位)
 157          SubAddr:从机的子地址
 158          SubMod:子地址模式,0-无子地址,1-单字节子地址,2-双字节子地址
 159          *dat:要发送的数据
 160          Size:数据的字节数
 161          返回:
 162          0:发送成功
 163          1:在发送过程中出现异常
 164          说明:
 165          本函数能够很好地适应所有常见的I2C 器件,不论其是否有子地址
 166          当从机没有子地址时,参数SubAddr 任意,而SubMod 应当为0
 167          */
 168          bit I2C_Puts
 169          (
 170          unsigned char SlaveAddr,
 171          unsigned int SubAddr,
 172          unsigned char SubMod,
 173          char *dat,
 174          unsigned int Size
 175          )
 176          {
 177   1      //定义临时变量
 178   1      unsigned char i;
 179   1      char a[3];
C51 COMPILER V7.20   I2C                                                                   01/01/2002 03:12:21 PAGE 4   

 180   1      //检查长度
 181   1      if ( Size == 0 ) return 0;
 182   1      //准备从机地址
 183   1      a[0] = (SlaveAddr << 1);
 184   1      //检查子地址模式
 185   1      if ( SubMod > 2 ) SubMod = 2;
 186   1      //确定子地址
 187   1      switch ( SubMod )
 188   1      {
 189   2      case 0:
 190   2      break;
 191   2      case 1:
 192   2      a[1] = (char)(SubAddr);
 193   2      break;
 194   2      case 2:
 195   2      a[1] = (char)(SubAddr >> 8);
 196   2      a[2] = (char)(SubAddr);
 197   2      break;
 198   2      default:
 199   2      break;
 200   2      }
 201   1      //发送从机地址,接着发送子地址(如果有子地址的话)
 202   1      SubMod++;
 203   1      I2C_Start();
 204   1      for ( i=0; i<SubMod; i++ )
 205   1      {
 206   2      I2C_Write(a[i]);
 207   2      if ( I2C_GetAck() )
 208   2      {
 209   3      I2C_Stop();
 210   3      return 1;
 211   3      }
 212   2      }
 213   1      //发送数据
 214   1      do
 215   1      {
 216   2      I2C_Write(*dat++);
 217   2      if ( I2C_GetAck() ) break;
 218   2      } while ( --Size != 0 );
 219   1      //发送完毕,停止I2C 总线,并返回结果
 220   1      I2C_Stop();
 221   1      if ( Size == 0 )
 222   1      {
 223   2      return 0;
 224   2      }
 225   1      else
 226   1      {
 227   2      return 1;
 228   2      }
 229   1      }
 230          /*
 231          函数:I2C_Gets()
 232          功能:I2C 总线综合接收函数,从从机接收多个字节的数据
 233          参数:
 234          SlaveAddr:从机地址(7 位纯地址,不含读写位)
 235          SubAddr:从机的子地址
 236          SubMod:子地址模式,0-无子地址,1-单字节子地址,2-双字节子地址
 237          *dat:保存接收到的数据
 238          Size:数据的字节数
 239          返回:
 240          0:接收成功
 241          1:在接收过程中出现异常
C51 COMPILER V7.20   I2C                                                                   01/01/2002 03:12:21 PAGE 5   

 242          说明:
 243          本函数能够很好地适应所有常见的I2C 器件,不论其是否有子地址
 244          当从机没有子地址时,参数SubAddr 任意,而SubMod 应当为0
 245          */
 246          bit I2C_Gets
 247          (
 248          unsigned char SlaveAddr,
 249          unsigned int SubAddr,
 250          unsigned char SubMod,
 251          char *dat,
 252          unsigned int Size
 253          )
 254          {
 255   1      //定义临时变量
 256   1      unsigned char i;
 257   1      char a[3];
 258   1      //检查长度
 259   1      if ( Size == 0 ) return 0;
 260   1      //准备从机地址
 261   1      a[0] = (SlaveAddr << 1);
 262   1      //检查子地址模式
 263   1      if ( SubMod > 2 ) SubMod = 2;
 264   1      //如果是有子地址的从机,则要先发送从机地址和子地址
 265   1      if ( SubMod != 0 )
 266   1      {
 267   2      //确定子地址
 268   2      if ( SubMod == 1 )
 269   2      {
 270   3      a[1] = (char)(SubAddr);
 271   3      }
 272   2      else
 273   2      {
 274   3      a[1] = (char)(SubAddr >> 8);
 275   3      a[2] = (char)(SubAddr);
 276   3      }
 277   2      //发送从机地址,接着发送子地址
 278   2      SubMod++;
 279   2      I2C_Start();
 280   2      for ( i=0; i<SubMod; i++ )
 281   2      {
 282   3      I2C_Write(a[i]);
 283   3      if ( I2C_GetAck() )
 284   3      {
 285   4      I2C_Stop();
 286   4      return 1;
 287   4      }
 288   3      }
 289   2      }
 290   1      //这里的I2C_Start()对于有子地址的从机是重复起始状态
 291   1      //对于无子地址的从机则是正常的起始状态
 292   1      I2C_Start();
 293   1      //发送从机地址
 294   1      I2C_Write(a[0]+1);
 295   1      if ( I2C_GetAck() )
 296   1      {
 297   2      I2C_Stop();
 298   2      return 1;
 299   2      }
 300   1      //接收数据
 301   1      for (;;)
 302   1      {
 303   2      *dat++ = I2C_Read();
C51 COMPILER V7.20   I2C                                                                   01/01/2002 03:12:21 PAGE 6   

 304   2      if ( --Size == 0 )
 305   2      {
 306   3      I2C_PutAck(1);
 307   3      break;
 308   3      }
 309   2      I2C_PutAck(0);
 310   2      }
 311   1      //接收完毕,停止I2C 总线,并返回结果
 312   1      I2C_Stop();
 313   1      return 0;
 314   1      }


MODULE INFORMATION:   STATIC OVERLAYABLE
   CODE SIZE        =    449    ----
   CONSTANT SIZE    =   ----    ----
   XDATA SIZE       =   ----    ----
   PDATA SIZE       =   ----    ----
   DATA SIZE        =      1      24
   IDATA SIZE       =   ----    ----
   BIT SIZE         =   ----       2
END OF MODULE INFORMATION.


C51 COMPILATION COMPLETE.  0 WARNING(S),  0 ERROR(S)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -