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

📄 i2c.lst

📁 用PIC16F73编写的SMBUS通信测试程序
💻 LST
字号:
     1: #include        <pic.h>
     2: #include        "delay.h"
     3: #include        "i2c.h"
     4: 
     5: /*
     6:  *      I2C functions for HI-TECH PIC C - master mode only
     7:  */
     8: 
     9: /*
    10:  *      TIMING - see Philips document: THE I2C-BUS SPECIFICATION
    11:  */
    12: 
    13: 
    14: /*
    15:  *      Send stop condition
    16:  *        - data low-high while clock high
    17:  */
    18: 
    19: void
    20: i2c_Stop(void)
    21: {
    22:         /* don't assume SCL is high on entry */
    23: 
    24:         SDA_LOW();                      /* ensure data is low first */
    25:         SCL_HIGH();
    26: 
    27:         DelayUs(I2C_TM_DATA_SU);
    28:         SCL_DIR = I2C_INPUT;            /* float clock high */
    29:         DelayUs(I2C_TM_STOP_SU);
    30:         SDA_HIGH();                     /* the low->high data transistion */
    31:         DelayUs(I2C_TM_BUS_FREE);       /* bus free time before next start */
    32:         SDA_DIR = I2C_INPUT;            /* float data high */
    33: 
    34:         return;
    35: }
    36: 
    37: /*
    38:  *      Send (re)start condition
    39:  *        - ensure data is high then issue a start condition
    40:  *        - see also i2c_Start() macro
    41:  */
    42: 
    43: void
    44: i2c_Restart(void)
    45: {
    46:         SCL_LOW();                      /* ensure clock is low */
    47:         SDA_HIGH();                     /* ensure data is high */
    48: 
    49:         DelayUs(I2C_TM_DATA_SU);
    50: 
    51:         SCL_DIR = I2C_INPUT;            /* clock pulse high */
    52:         DelayUs(I2C_TM_SCL_HIGH);
    53: 
    54:         SDA_LOW();                      /* the high->low transition */
    55:         DelayUs(I2C_TM_START_HD);
    56:         return;
    57: }
    58: 
    59: /*
    60:  *      Send a byte to the slave
    61:  *        - returns true on error
    62:  */
    63: 
    64: unsigned char
    65: i2c_SendByte(unsigned char byte)
    66: {
    67:         signed char i;
    68: 
    69:         for(i=7; i>=0; i--)
    70:         {
    71:                 SCL_LOW();                      /* drive clock low */
    72:                                                 /* data hold time = 0, send data now */
    73:                 SDA_DIR = ((byte>>i)&0x01);
    74:                 if ((byte>>i)&0x01) {           /* bit to send */
    75:                     SDA_HIGH();
    76:                 }
    77:                 else {
    78:                     SDA_LOW();
    79:                 }
    80:                 DelayUs(I2C_TM_DATA_SU);
    81:                 SCL_DIR = I2C_INPUT;            /* float clock high */
    82: 
    83:                 if(i2c_WaitForSCL())            /* wait for clock release */
    84:                         return TRUE;            /* bus error */
    85: 
    86:                 DelayUs(I2C_TM_SCL_HIGH);       /* clock high time */
    87:         }
    88: 
    89: 
    90:         return FALSE;
    91: }
    92: 
    93: /*
    94:  *      send an address and data direction to the slave
    95:  *        - 7-bit address (lsb ignored)
    96:  *        - direction (FALSE = write )
    97:  */
    98: 
    99: unsigned char
   100: i2c_SendAddress(unsigned char address, unsigned char rw)
   101: {
   102:         return i2c_SendByte(address | (rw?1:0));
   103: }
   104: 
   105: /*
   106:  *      Check for an acknowledge
   107:  *        - returns ack or ~ack, or ERROR if a bus error
   108:  */
   109: 
   110: signed char
   111: i2c_ReadAcknowledge(void)
   112: {
   113:         unsigned char ack;
   114: 
   115:         SCL_LOW();                              /* make clock is low */
   116:         SDA_DIR = I2C_INPUT;                    /* disable data line - listen for ack */
   117:         DelayUs(I2C_TM_SCL_TO_DATA);            /* SCL low to data out valid */
   118:         SCL_DIR = I2C_INPUT;                    /* float clock high */
   119:         DelayUs(I2C_TM_DATA_SU);
   120:         ack = SDA;                              /* read the acknowledge */
   121: 
   122:         /* wait for slave to release clock line after processing byte */
   123:         if(i2c_WaitForSCL())
   124:                 return I2C_ERROR;
   125:         return ack;
   126: }
   127: 
   128: /*
   129:  *      Read a byte from the slave
   130:  *        - returns the byte, or I2C_ERROR if a bus error
   131:  */
   132: 
   133: int
   134: i2c_ReadByte(void)
   135: {
   136:         unsigned char i;
   137:         unsigned char byte = 0;
   138: 
   139:         for(i=0; i<8; i++)
   140:         {
   141:                 SCL_LOW();                      /* drive clock low */
   142:                 DelayUs(I2C_TM_SCL_LOW);        /* min clock low  period */
   143:                 SDA_DIR = I2C_INPUT;            /* release data line */
   144: 
   145:                 SCL_DIR = I2C_INPUT;            /* float clock high */
   146:                 if(i2c_WaitForSCL())
   147:                         return I2C_ERROR;
   148:                 DelayUs(I2C_TM_SCL_HIGH);
   149:                 byte = byte << 1;               /* read the next bit */
   150:                 byte |= SDA;
   151:         }
   152:         return (int)byte;
   153: }
   154: 
   155: /*
   156:  *      Send an (~)acknowledge to the slave
   157:  *        - status of I2C_LAST implies this is the last byte to be sent
   158:  */
   159: 
   160: void
   161: i2c_SendAcknowledge(unsigned char status)
   162: {
   163:         SCL_LOW();
   164:         if ( status & 0x01) {
   165:             SDA_LOW();                          /* drive line low -> more to come */
   166:         }
   167:         else { 
   168:             SDA_HIGH();
   169:         }
   170:         DelayUs(I2C_TM_DATA_SU);
   171:         SCL_DIR = I2C_INPUT;                    /* float clock high */
   172:         DelayUs(I2C_TM_SCL_HIGH);
   173:         return;
   174: }
   175: 
   176: /*
   177:  *      Send a byte to the slave and acknowledges the transfer
   178:  *        - returns I2C_ERROR, ack or ~ack
   179:  */
   180: 
   181: signed char
   182: i2c_PutByte(unsigned char data)
   183: {
   184:         if(i2c_SendByte(data))
   185:                 return I2C_ERROR;
   186:         return i2c_ReadAcknowledge();   /* returns ack, ~ack */
   187: }
   188: 
   189: /*
   190:  *      Get a byte from the slave and acknowledges the transfer
   191:  *        - returns true on I2C_ERROR or byte
   192:  */
   193: 
   194: int
   195: i2c_GetByte(unsigned char more)
   196: {
   197:         int byte;
   198: 
   199:         if((byte = i2c_ReadByte()) == I2C_ERROR)
   200:                 return I2C_ERROR;
   201: 
   202:         i2c_SendAcknowledge(more);
   203: 
   204:         return byte;
   205: }
   206: 
   207: /*
   208:  *      Send an array of bytes to the slave and acknowledges the transfer
   209:  *        - returns number of bytes not successfully transmitted
   210:  */
   211: 
   212: int
   213: i2c_PutString(const unsigned char *str, unsigned char length)
   214: {
   215:         signed char error;
   216: 
   217:         while(length)
   218:         {
   219:                 if((error = i2c_PutByte(*str)) == I2C_ERROR)
   220:                         return -(int)length;            /* bus error */
   221:                 else
   222:                         if(error)
   223:                                 return (int)length;     /* non acknowledge */
   224:                 str++;
   225:                 length--;
   226:         }
   227: 
   228:         return FALSE;                                   /* everything OK */
   229: }
   230: 
   231: /*
   232:  *      Reads number bytes from the slave, stores them at str and acknowledges the transfer
   233:  *        - returns number of bytes not successfully read in
   234:  */
   235: 
   236: unsigned char
   237: i2c_GetString(unsigned char *str, unsigned char number)
   238: {
   239:         int byte;
   240: 
   241:         while(number)
   242:         {
   243:                 if((byte = i2c_GetByte(number-1)) == I2C_ERROR)
   244:                         return number;                  /* bus error */
   245:                 else
   246:                         *str = (unsigned char)byte;
   247:                 str++;
   248:                 number--;
   249:         }
   250: 
   251:         return FALSE;                                   /* everything OK */
   252: }
   253: 
   254: /*
   255:  *      Opens communication with a device at address. mode
   256:  *      indicates I2C_READ or I2C_WRITE.
   257:  *        - returns TRUE if address is not acknowledged
   258:  */
   259: 
   260: unsigned char
   261: i2c_Open(unsigned char address, unsigned char mode)
   262: {
   263:         i2c_Start();
   264:         i2c_SendAddress(address, mode);
   265:         if(i2c_ReadAcknowledge()) 
   266:                 return TRUE;
   267: 
   268:         return FALSE;
   269: }
   270: 
   271: /*
   272:  *      wait for the clock line to be released by slow slaves
   273:  *        - returns TRUE if SCL was not released after the
   274:  *          time out period.
   275:  *        - returns FALSE if and when SCL released
   276:  */
   277: 
   278: unsigned char
   279: i2c_WaitForSCL(void)
   280: {
   281:         /* SCL_DIR should be input here */
   282: 
   283:         if(!SCL)
   284:         {
   285:                 DelayUs(I2C_TM_SCL_TMO);
   286:                 /* if the clock is still low -> bus error */
   287:                 if(!SCL)
   288:                         return TRUE;
   289:         }
   290:         return FALSE;
   291: }
   292: void
   293: i2c_Free()
   294: {
   295:         unsigned char ucI;
   296: 
   297:         SDA_DIR=I2C_INPUT;
   298:         for(ucI=0;ucI!=9;ucI++)
   299:         {
   300:                 SCL_HIGH();
   301:                 DelayUs(5);
   302:                 SCL_LOW();
   303:                 DelayUs(5);
   304:         }
   305: }
   306: 
   307: unsigned char i2c_read(unsigned char ucAdr)
   308: {
   309:         unsigned char ucDat;
   310: 
   311:         if (i2c_ReadFrom(ucAdr)==0)
   312:         {
   313:                 ucDat=i2c_GetByte(I2C_MORE);
   314:                 i2c_Stop();
   315: 
   316:         }
   317: 
   318:         return(ucDat);
   319: }

⌨️ 快捷键说明

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