【PIC32MZ】I2C通信

    xiaoxiao2021-04-16  64

    I2C跟串口一样,仅需2根线通讯即可,在某些引脚紧张的应用中非常有用,不过I2C相比于串口,通讯协议更简单一点,距离也更短一些,仅限于板间通信。大多数IC都支持I2C协议。   I2C的时序图为:

     

    I2C数据传输是在起始条件和停止条件之间。 起始条件和停止条件都是SCL为高一段时间产生。起始条件为SDA从高变为低,停止条件为SDA从低变为高。 I2C数据传输规则为,第一字节必须为地址,一般器件地址都是7位(也有10位的),放在高7位,最后一位时读写标识,所以,读写地址是不相同的,并且很多IC都可以配置多个地址选择,这是为了在一组I2C上接多个IC,因为I2C是通过地址来识别从机的。 每传输一个字节,从机都要回复一个ACK来表示是否完成接受,回复0继续接受,回复1停止接受。 I2C写操作很简单,传输从机地址以及数据即可。 I2C读也是一样,传输从机地址即可。   写操作: 一般而言,写操作要配合DataSheet,有写命令的操作,写数据的操作。 例如一般的OLED就有写命令和写数据两种操作,做法是,写地址命令/数据 标识 一个字节或多个字节命令信息。 一般EEPROM的写操作为:写地址需要写入的EEPROM内部起始地址(1字节或多字节) 1字节或多字节信息(从起始地址开始写入1个字节或者多个字节信息)   读操作: 以读EEPROM为例,需要两步:一是写入需要读的地址,写地址需要读的EEPROM内部起始地址(1字节或多字节);二是读地址。读取长度由主机ASK信号来控制,当主机不想继续读取时,ACK回复1。   使用流程如下:   1、配置驱动

    2、配置引脚   3、生成代码,使用I2C 以下为实际封装的函数文件,在app.c或者其它文件中包含再调用即可。 首先要initial(open一个客户端),然后才能读写。 delay函数     #ifndef _DELAY_H #define _DELAY_H #include <stdint.h> #include <stdbool.h> #include <stddef.h> #include <stdlib.h> #include "system_config.h" #include "system_definitions.h" void delay_ms(uint32_t milliSeconds) { uint32_t frequencyHz = milliSeconds * (SYS_CLK_SystemFrequencyGet()/2000); //while occupy 2 period while(frequencyHz--); } void delay_us(uint32_t microSeconds) { uint32_t frequencyHz = microSeconds * (SYS_CLK_SystemFrequencyGet()/2000000); //while occupy 2 period while(frequencyHz--); } #endif I2C-Hardware.h #ifndef _I2C_HARDWARE_H #define _I2C_HARDWARE_H #include "delay.h" typedef struct { DRV_HANDLE i2c_drvHandle; DRV_I2C_BUFFER_HANDLE i2c_bufferHandle; }IIC_DATA; IIC_DATA i2cData; bool IIC_Initial(void); bool IIC_WriteByte(uint8_t slaveAddr, uint8_t IIC_Byte); bool IIC_WriteBytes(uint8_t slaveAddr, uint8_t *IIC_Bytes, uint8_t length); bool IIC_ReadBytes(uint8_t slaveAddr, uint8_t *IIC_Bytes, uint8_t readLength); #endif i2c-Hardware.c #include "i2c-hardware.h" bool IIC_Initial(void) { i2cData.i2c_drvHandle = DRV_I2C_Open(0,DRV_IO_INTENT_READWRITE); if(i2cData.i2c_drvHandle==NULL) return false; else return true; } DRV_I2C_BUFFER_EVENT IIC_Check_Transfer_Status(DRV_HANDLE drvOpenHandle, DRV_I2C_BUFFER_HANDLE drvBufferHandle) { return (DRV_I2C_TransferStatusGet (drvOpenHandle, drvBufferHandle)); } bool IIC_WriteByte(uint8_t slaveAddr, uint8_t IIC_Byte) { uint8_t tmp[] = {IIC_Byte}; if ( (i2cData.i2c_bufferHandle == (DRV_I2C_BUFFER_HANDLE) NULL) || (IIC_Check_Transfer_Status(i2cData.i2c_drvHandle, i2cData.i2c_bufferHandle) == DRV_I2C_BUFFER_EVENT_COMPLETE) || (IIC_Check_Transfer_Status(i2cData.i2c_drvHandle, i2cData.i2c_bufferHandle) == DRV_I2C_BUFFER_EVENT_ERROR) ) { i2cData.i2c_bufferHandle = DRV_I2C_Transmit(i2cData.i2c_drvHandle,slaveAddr,tmp,1,NULL); delay_ms(1); return true; } else return false; } bool IIC_WriteBytes(uint8_t slaveAddr, uint8_t *IIC_Bytes, uint8_t length) { if ( (i2cData.i2c_bufferHandle == (DRV_I2C_BUFFER_HANDLE) NULL) || (IIC_Check_Transfer_Status(i2cData.i2c_drvHandle, i2cData.i2c_bufferHandle) == DRV_I2C_BUFFER_EVENT_COMPLETE) || (IIC_Check_Transfer_Status(i2cData.i2c_drvHandle, i2cData.i2c_bufferHandle) == DRV_I2C_BUFFER_EVENT_ERROR) ) { i2cData.i2c_bufferHandle = DRV_I2C_Transmit(i2cData.i2c_drvHandle,slaveAddr,IIC_Bytes,length,NULL); delay_ms(1); return true; } else return false; } bool IIC_ReadBytes(uint8_t slaveAddr, uint8_t *IIC_Bytes, uint8_t readLength) { if ( (i2cData.i2c_bufferHandle == (DRV_I2C_BUFFER_HANDLE) NULL) || (IIC_Check_Transfer_Status(i2cData.i2c_drvHandle, i2cData.i2c_bufferHandle) == DRV_I2C_BUFFER_EVENT_COMPLETE) || (IIC_Check_Transfer_Status(i2cData.i2c_drvHandle, i2cData.i2c_bufferHandle) == DRV_I2C_BUFFER_EVENT_ERROR) ) { i2cData.i2c_bufferHandle = DRV_I2C_Receive(i2cData.i2c_drvHandle, slaveAddr, IIC_Bytes, readLength, NULL); delay_ms(1); return true; } else return false; } 注意: I2C不连接Device时,会导致没收到回应而卡死在system_interrupt.c的error_instancex里面,这是到2.03版本harmony的bug,可以自行仿照下面方式添加函数来避免,注意intance与i2c通路的对应,这里是intance0-instance4对应i2c1-i2c5   void __ISR(_I2C1_MASTER_VECTOR, ipl1AUTO) _IntHandlerDrvI2CMasterInstance0(void) { DRV_I2C_Tasks(sysObj.drvI2C0); } void __ISR(_I2C1_BUS_VECTOR, ipl1AUTO) _IntHandlerDrvI2CErrorInstance0(void) { PLIB_INT_SourceFlagClear( INT_ID_0, INT_VECTOR_I2C1_BUS ); PLIB_I2C_Disable (I2C_ID_1); PLIB_I2C_Enable (I2C_ID_1); SYS_ASSERT(false, "I2C Driver Instance 0 Error"); } void __ISR(_I2C2_MASTER_VECTOR, ipl1AUTO) _IntHandlerDrvI2CMasterInstance1(void) { DRV_I2C_Tasks(sysObj.drvI2C1); } void __ISR(_I2C2_BUS_VECTOR, ipl1AUTO) _IntHandlerDrvI2CErrorInstance1(void) { PLIB_INT_SourceFlagClear( INT_ID_0, INT_VECTOR_I2C2_BUS ); PLIB_I2C_Disable (I2C_ID_2); PLIB_I2C_Enable (I2C_ID_2); SYS_ASSERT(false, "I2C Driver Instance 1 Error"); } void __ISR(_I2C3_MASTER_VECTOR, ipl1AUTO) _IntHandlerDrvI2CMasterInstance2(void) { DRV_I2C_Tasks(sysObj.drvI2C2); } void __ISR(_I2C3_BUS_VECTOR, ipl1AUTO) _IntHandlerDrvI2CErrorInstance2(void) { PLIB_INT_SourceFlagClear( INT_ID_0, INT_VECTOR_I2C3_BUS ); PLIB_I2C_Disable (I2C_ID_3); PLIB_I2C_Enable (I2C_ID_3); SYS_ASSERT(false, "I2C Driver Instance 2 Error"); } void __ISR(_I2C4_MASTER_VECTOR, ipl1AUTO) _IntHandlerDrvI2CMasterInstance3(void) { DRV_I2C_Tasks(sysObj.drvI2C3); } void __ISR(_I2C4_BUS_VECTOR, ipl1AUTO) _IntHandlerDrvI2CErrorInstance3(void) { PLIB_INT_SourceFlagClear( INT_ID_0, INT_VECTOR_I2C4_BUS ); PLIB_I2C_Disable (I2C_ID_4); PLIB_I2C_Enable (I2C_ID_4); SYS_ASSERT(false, "I2C Driver Instance 3 Error"); } void __ISR(_I2C5_MASTER_VECTOR, ipl1AUTO) _IntHandlerDrvI2CMasterInstance4(void) { DRV_I2C_Tasks(sysObj.drvI2C4); } void __ISR(_I2C5_BUS_VECTOR, ipl1AUTO) _IntHandlerDrvI2CErrorInstance4(void) { PLIB_INT_SourceFlagClear( INT_ID_0, INT_VECTOR_I2C5_BUS ); PLIB_I2C_Disable (I2C_ID_5); PLIB_I2C_Enable (I2C_ID_5); SYS_ASSERT(false, "I2C Driver Instance 4 Error"); }
    转载请注明原文地址: https://ju.6miu.com/read-673093.html

    最新回复(0)