i2c.lst

来自「用单片机级zlg7290做的一个简易计算器」· LST 代码 · 共 350 行

LST
350
字号
C51 COMPILER V7.50   I2C                                                                   11/26/2008 19:53:14 PAGE 1   


C51 COMPILER V7.50, COMPILATION OF MODULE I2C
OBJECT MODULE PLACED IN I2C.OBJ
COMPILER INVOKED BY: C:\Keil\C51\BIN\C51.EXE I2C.c BROWSE ORDER INTVECTOR(0X8000) DEFINE(Monitor,c51) 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.50   I2C                                                                   11/26/2008 19:53:14 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          /*
  94          函数:I2C_GetAck()
  95          功能:读取从机应答位
  96          返回:
  97          0:从机应答
  98          1:从机非应答
  99          说明:
 100          从机在收到每个字节的数据后,要产生应答位
 101          从机在收到最后1 个字节的数据后,一般要产生非应答位
 102          */
 103          bit I2C_GetAck()
 104          {
 105   1      bit ack;
 106   1      I2C_SDA = 1;
 107   1      I2C_Delay();
 108   1      I2C_SCL = 1;
 109   1      I2C_Delay();
 110   1      ack = I2C_SDA;
 111   1      I2C_SCL = 0;
 112   1      I2C_Delay();
 113   1      return ack;
 114   1      }
 115          /*
 116          函数:I2C_PutAck()
 117          功能:主机产生应答位或非应答位
C51 COMPILER V7.50   I2C                                                                   11/26/2008 19:53:14 PAGE 3   

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

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

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

 304   1      {
 305   2      *dat++ = I2C_Read();
 306   2      if ( --Size == 0 )
 307   2      {
 308   3      I2C_PutAck(1);
 309   3      break;
 310   3       }
 311   2      I2C_PutAck(0);
 312   2      }
 313   1      //接收完毕,停止I2C 总线,并返回结果
 314   1      I2C_Stop();
 315   1      return 0;
 316   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 + =
减小字号Ctrl + -
显示快捷键?