- /**
 
-  * @ingroup i2c_host
 
-  * [url=home.php?mod=space&uid=247401]@brief[/url] This function writes data from the writeData to the bus 
 
-  *        and then reads data from the Client and stores the received in the
 
-  *        readData. The function generates a Start condition on the bus and 
 
-  *        will then send writeLength number of bytes contained in writeData. 
 
-  *        The function will then insert a Repeated start condition and 
 
-  *        proceed to read readLength number of bytes from the client.
 
-  *        The received bytes are stored in readData buffer. A Stop condition 
 
-  *        is generated after the last byte has been received.
 
-  *
 
-  *        If the Client NAKs the request or a bus error was encountered on 
 
-  *        the bus, the transfer is terminated. The application can call 
 
-  *        I2C1_ErrorGet() function to know that cause of the error.
 
-  *
 
-  *        The function is non-blocking. It initiates bus activity and returns
 
-  *        immediately. The transfer is then completed in the peripheral 
 
-  *        interrupt. For polling mode, user has to call  I2C1_Tasks
 
-  *        in while loop. A transfer request cannot be placed when another 
 
-  *        transfer is in progress. Calling this function when another function 
 
-  *        is already in progress will cause the function to return false.
 
-  *
 
-  * @param [in] address     - 7-bit / 10-bit Client address.
 
-  * @param [in] writeData   - pointer to write data buffer.
 
-  * @param [in] writeLength - write data length in bytes.
 
-  * @param [out] readData    - pointer to read data buffer.
 
-  * @param [in] readLength  - read data length in bytes.
 
-  
 
-  * @return
 
-  *         true  - The request was placed successfully and the bus activity was
 
-  *                 initiated.
 
-  *         false - The request fails,if there was already a transfer in
 
-  *                 progress when this function was called
 
-  */
 
- bool I2C1_WriteRead(uint16_t address, uint8_t *writeData, size_t writeLength, uint8_t *readData, size_t readLength);
参数一共5个:芯片的I2C总线地址,要写入的数据,写入数据的长度,读取的数据,读取的长度。
请注意写入的数据和读取的数据通过指针实现。
我们查看库函数实现的方式
- bool I2C1_WriteRead(uint16_t address, uint8_t *writeData, size_t writeLength, uint8_t *readData, size_t readLength)
 
- {
 
-     bool retStatus = false;
 
-     if (!I2C1_IsBusy())
 
-     {
 
-         i2c1Status.busy = true;
 
-         i2c1Status.address = address;
 
-         i2c1Status.switchToRead = true;
 
-         i2c1Status.writePtr = writeData;
 
-         i2c1Status.writeLength = writeLength;
 
-         i2c1Status.readPtr = readData;
 
-         i2c1Status.readLength = readLength;
 
-         i2c1Status.errorState = I2C_ERROR_NONE;
 
-         I2C1_WriteStart();
 
-         retStatus = true;
 
-     }
 
-     return retStatus;
 
- }
芯片的时序定义如上所示,可以看出读操作是标准的I2C时序。
示例代码如下:
- int main(void)
 
- {
 
-     uint8_t val=0;
 
-     uint8_t reg=0x00;    
 
-     SYSTEM_Initialize();
 
 
-     // If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts 
 
-     // If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global Interrupts 
 
-     // Use the following macros to: 
 
 
-     // Enable the Global Interrupts 
 
-     INTERRUPT_GlobalInterruptEnable(); 
 
 
-     // Disable the Global Interrupts 
 
-     //INTERRUPT_GlobalInterruptDisable(); 
 
- printf("Hello\n");
 
- DELAY_milliseconds(3000);
 
-     while(1)
 
-     {
 
-             DELAY_milliseconds(1000);
 
-             
 
-             I2C1_WriteRead(0x35,®,1,&val,1);
 
-             while(I2C1_IsBusy());
 
-             printf("REG%d=%x\n",reg,val);
 
-             reg++;
 
-             val=0;
 
-             if(reg>30) reg=0;
 
-             
 
-     }    
 
- }
这里使用了阻塞的方式判断,也可以使用非阻塞方式,增加一个时间判断,防止程序卡死。
简单的示例如下所示:
- int main(void)
 
- {
 
-     uint8_t val=0;
 
-     uint8_t reg=0x00; 
 
-     uint8_t delay_time=0;
 
-     SYSTEM_Initialize();
 
 
-     // If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts 
 
-     // If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global Interrupts 
 
-     // Use the following macros to: 
 
 
-     // Enable the Global Interrupts 
 
-     INTERRUPT_GlobalInterruptEnable(); 
 
 
-     // Disable the Global Interrupts 
 
-     //INTERRUPT_GlobalInterruptDisable(); 
 
- printf("Hello\n");
 
- DELAY_milliseconds(3000);
 
-     while(1)
 
-     {
 
-             DELAY_milliseconds(1000);
 
-             
 
-             I2C1_WriteRead(0x35,®,1,&val,1);
 
-             while(I2C1_IsBusy()&&(delay_time++<20));
 
-             printf("REG%d=%x\n",reg,val);
 
-             reg++;
 
-             val=0;
 
-             delay_time=0;
 
-             if(reg>30) reg=0;
 
-             
 
-     }    
 
- }
最后我们看看读取的效果
最后补充一个先写后读取的示例,并测试对应的寄存器哪些位可以进行写操作。
 
- int main(void)
 
- {
 
-     uint8_t val=0;
 
-     uint8_t reg=0x00; 
 
-     uint8_t delay_time=0;
 
-     SYSTEM_Initialize();
 
-     uint8_t daa[2];
 
-     daa[0]=0x04;
 
-     daa[1]=0x00;
 
-     // If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts 
 
-     // If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global Interrupts 
 
-     // Use the following macros to: 
 
 
-     // Enable the Global Interrupts 
 
-     INTERRUPT_GlobalInterruptEnable(); 
 
 
-     // Disable the Global Interrupts 
 
-     //INTERRUPT_GlobalInterruptDisable(); 
 
- printf("Hello\n");
 
- DELAY_milliseconds(3000);
 
-     while(1)
 
-     {
 
-         DELAY_milliseconds(1000);  
 
 
-         I2C1_Write(0x35,daa,2);
 
-         while(I2C1_IsBusy()&&(delay_time++<20));delay_time=0;
 
-         reg=0x04;        
 
-         I2C1_WriteRead(0x35,®,1,&val,1);
 
-         while(I2C1_IsBusy()&&(delay_time++<20));delay_time=0;
 
-         printf("DAA[%x]---REG%d=%x\n",daa[1],reg,val); 
 
-         daa[1]++;      
 
-     }    
 
- }
经过测试在0x04寄存器上,低4位中的BIT3是不能执行写操作的。
正常使用时候这么看明显的不好看,我们可以将函数进行封装使用,不仅方便阅读,还更容易调用,同时这么做不容易弄错。- void KT_Byte_Write(uint8_t kt_reg,uint8_t kt_dat)
 
- {
 
-     uint8_t delay_time=0;
 
-     uint8_t dats[2];
 
-     dats[0] = kt_reg;
 
-     dats[1] = kt_dat;
 
-     I2C1_Write(0x35,dats,2);
 
-     while(I2C1_IsBusy()&&(delay_time++<20));
 
- }
 
 
- uint8_t KT_Byte_Read(uint8_t kt_reg)
 
- {
 
-     uint8_t val=0;
 
-     uint8_t delay_time=0;
 
-     I2C1_WriteRead(0x35,&kt_reg,1,&val,1);
 
-     while(I2C1_IsBusy()&&(delay_time++<20));delay_time=0;
 
-     return val;
 
- }
  调用方式- int main(void)
 
- {
 
-     SYSTEM_Initialize();
 
-     uint8_t i=0;
 
-     // Enable the Global Interrupts 
 
-     INTERRUPT_GlobalInterruptEnable(); 
 
 
-     // Disable the Global Interrupts 
 
-     //INTERRUPT_GlobalInterruptDisable(); 
 
- printf("Hello\n");
 
- DELAY_milliseconds(3000);
 
-     while(1)
 
-     {
 
-         for(i=0;i<10;i++)
 
-         {
 
-             DELAY_milliseconds(1000);
 
-             KT_Byte_Write(0x04,i);
 
-             printf("REG=%x\n",KT_Byte_Read(0x04));  
 
-         }
 
-     }    
 
- }
好了,基于我使用的这个芯片的I2C读写使用方式讲解完了,另外只要是标准I2C协议的芯片都可以这么使用。