博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【PIC32MZ】I2C通信
阅读量:4280 次
发布时间:2019-05-27

本文共 6122 字,大约阅读时间需要 20 分钟。

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 
#include
#include
#include
#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");}
你可能感兴趣的文章
networkx使用笔记(二)之小试牛刀篇
查看>>
Python 优雅的操作字典
查看>>
Latex设置表格字体大小
查看>>
Latex公式及编号
查看>>
Python __future__ 模块
查看>>
softmax回归
查看>>
TensorFlow入门学习(让机器/算法帮助我们作出选择)
查看>>
把项目从Python2.x移植到Python3.x的经验总结
查看>>
如何在python下安装xgboost
查看>>
xgboost特征选择
查看>>
kaggle数据挖掘竞赛初步--Titanic<数据变换>,kaggle--titanic
查看>>
XGBoost-Python完全调参指南-参数解释篇
查看>>
【scikit-learn】scikit-learn的线性回归模型
查看>>
广告点击率预测 [离线部分]
查看>>
广告点击率预估中的特征选择
查看>>
LIBSVM与LIBLINEAR(二)
查看>>
定向展示广告投放中的点击率预估模型简介
查看>>
十分钟搞定pandas
查看>>
数据科学入门,使用 xgboost 初试 kaggle
查看>>
利用 Python 进行数据分析(十二)pandas:数据合并
查看>>