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

📄 i2c.lst

📁 汽车ABS系统车速显示和自动空调系统温度显示
💻 LST
字号:
C51 COMPILER V7.50   I2C                                                                   11/06/2008 20:48:59 PAGE 1   


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

line level    source

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

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

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

 180          (
 181          unsigned char SlaveAddr,
 182          unsigned int SubAddr,
 183          unsigned char SubMod,
 184          char *dat,
 185          unsigned int Size
 186          )
 187          {
 188   1      //定义临时变量
 189   1      unsigned char i;
 190   1      char a[3];
 191   1      //检查长度
 192   1      if ( Size == 0 ) return 0;
 193   1      //准备从机地址
 194   1      a[0] = (SlaveAddr << 1);
 195   1      //检查子地址模式
 196   1      if ( SubMod > 2 ) SubMod = 2;
 197   1      //确定子地址
 198   1      switch ( SubMod )
 199   1      {
 200   2      case 0:
 201   2      break;
 202   2      case 1:
 203   2      a[1] = (char)(SubAddr);
 204   2      break;
 205   2      case 2:
 206   2      a[1] = (char)(SubAddr >> 8);
 207   2      a[2] = (char)(SubAddr);
 208   2      break;
 209   2      default:
 210   2      break;
 211   2      }
 212   1      //发送从机地址,接着发送子地址(如果有子地址的话)
 213   1      SubMod++;
 214   1      I2C_Start();
 215   1      for ( i=0; i<SubMod; i++ )
 216   1      {
 217   2      I2C_Write(a[i]);
 218   2      if ( I2C_GetAck() )
 219   2      {
 220   3      I2C_Stop();
 221   3      return 1;
 222   3      }
 223   2      }
 224   1      //发送数据
 225   1      do
 226   1      {
 227   2      I2C_Write(*dat++);
 228   2      if ( I2C_GetAck() ) break;
 229   2      } while ( --Size != 0 );
 230   1      //发送完毕,停止I2C 总线,并返回结果
 231   1      I2C_Stop();
 232   1      if ( Size == 0 )
 233   1      {
 234   2      return 0;
 235   2      }
 236   1      else
 237   1      {
 238   2      return 1;
 239   2      }
 240   1      }
 241          
C51 COMPILER V7.50   I2C                                                                   11/06/2008 20:48:59 PAGE 5   

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

 304   1      I2C_Start();
 305   1      //发送从机地址
 306   1      I2C_Write(a[0]+1);
 307   1      if ( I2C_GetAck() )
 308   1      {
 309   2      I2C_Stop();
 310   2      return 1;
 311   2      }
 312   1      //接收数据
 313   1      for (;;)
 314   1      {
 315   2      *dat++ = I2C_Read();
 316   2      if ( --Size == 0 )
 317   2      {
 318   3      I2C_PutAck(1);
 319   3      break;
 320   3      }
 321   2      I2C_PutAck(0);
 322   2      }
 323   1      //接收完毕,停止I2C 总线,并返回结果
 324   1      I2C_Stop();
 325   1      return 0;
 326   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 + -