电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
【小熊派BearPi-loT开发板连载】标准库的i2c驱动开发
分 享
扫描二维码分享
【小熊派BearPi-loT开发板连载】标准库的i2c驱动开发
i2c
小熊派
BearPi
瑟寒凌风
关注
发布时间: 2021-05-26
丨
阅读: 674
I2C仅需两根线就可以支持一主多从或者多主连接,I2C使用两个双向开漏线,配合上拉电阻进行连接. 起始和停止条件及重复起始条件(START and STOP conditions and Repeated start condition): 起始和终止条件都是由主机(master)发起产生。总线在起始条件之后处于忙碌状态,在停止条件之后又处于空闲状态。 起始条件:SCL线是高电平时,SDA线从高电平向低电平切换。 停止条件:SCL线是高电平时,SDA线从低电平向高电平切换。 重复起始条件:和起始条件相似,重复起始条件发生在停止条件之前。主机想继续给从机发送消息时,一个字节传输完成后可以发送重复起始条件,而不是产生停止条件。 I2C数据线拉高拉低输出模拟 ```c void I2Cm_SDAO(u8 Flag) { if(Flag == 1) // GPIO_SetBits(Ix->SDA_Port,Ix->SDA_Pin); //拉高 IIC_SDA_PORT->BSRRL = IIC_SDA_PIN; else // GPIO_ResetBits(Ix->SDA_Port,Ix->SDA_Pin); //拉低 IIC_SDA_PORT->BSRRH = IIC_SDA_PIN; } ``` 时钟拉高拉低模拟 ```c void I2Cm_SCKO(u8 Flag) { if(Flag == 1) // GPIO_SetBits(Ix->SCK_Port,Ix->SCK_Pin); IIC_SCK_PORT->BSRRL = IIC_SCK_PIN; else // GPIO_ResetBits(Ix->SCK_Port,Ix->SCK_Pin); IIC_SCK_PORT->BSRRH = IIC_SCK_PIN; } ``` I2C引脚初始化 ```c u8 I2Cx_Init() { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); IoSetMode(IIC_SDA,IO_MODE_OUTPUT); IoOpenDrain(IIC_SDA); IoSetSpeed(IIC_SDA,IO_SPEED_50M); IoSetMode(IIC_SCK,IO_MODE_OUTPUT); IoOpenDrain(IIC_SCK); IoSetSpeed(IIC_SCK,IO_SPEED_50M); IoHi(IIC_SCK); IoHi(IIC_SDA); return 1; } ``` 启动I2C总线 ```c u8 I2Cx_Start() //I2C启动 { // I2Cm_SDAO(1); IoHi(IIC_SDA); I2CmDelay(20); // I2Cm_SCKO(1); IoHi(IIC_SCK); I2CmDelay(20); if(I2Cm_SDAI() == 0) //SDA线未能拉高则总线忙,退出 return 0; // I2Cm_SDAO(0); //低跳变 IoLo(IIC_SDA); I2CmDelay(20); // 大于0.6uS //72条命令1us if(I2Cm_SDAI() == 1) //SDA线未能拉低则总线出错,退出 return 0; // I2Cm_SDAO(0); IoLo(IIC_SDA); I2CmDelay(20); return 1; //启动成功 } ``` 关闭I2C总线 ```c u8 I2Cx_Stop() //I2C关闭 { // I2Cm_SDAO(0); IoLo(IIC_SDA); I2CmDelay(20); // I2Cm_SCKO(1); IoHi(IIC_SCK); I2CmDelay(20); //大于0.6uS // I2Cm_SDAO(1); //高跳变 IoHi(IIC_SDA); I2CmDelay(20); //大于1.3uS // I2Cm_SDAO(0); IoLo(IIC_SDA); I2CmDelay(20); return 1; } ``` 发送一个应答信号 低应答 ```c u8 I2Cx_Ack() //应答 时钟由低-高-低跳变,发送一次数据 { I2Cm_SCKO(0); I2CmDelay(20); I2Cm_SDAO(0); //发送数据SDA_L,应答 I2CmDelay(20); //大于1.3uS I2Cm_SCKO(1); I2CmDelay(20); //大于1uS I2Cm_SCKO(0); I2CmDelay(20); return 1; } ``` 不发送应答信号 高不应答 u8 I2Cx_NoAck() //不应答 { I2Cm_SCKO(0); I2CmDelay(20); I2Cm_SDAO(1); //发送数据SDA_H,不应答 I2CmDelay(20); I2Cm_SCKO(1); I2CmDelay(20); I2Cm_SCKO(0); I2CmDelay(20); return 1; } 从I2C接口上发送字节数据 ```c u8 I2Cx_SendByte(u8 SendByte) //数据从高位到低位 { u8 i = 8; while(i--) //发送8位数据 { // I2Cm_SCKO(0); IoLo(IIC_SCK); I2CmDelay(20); if((SendByte & 0x80) == 0x80) // I2Cm_SDAO(1); IoHi(IIC_SDA); else // I2Cm_SDAO(0); IoLo(IIC_SDA); SendByte <<= 1; I2CmDelay(20); //大于1.3uS // I2Cm_SCKO(1); IoHi(IIC_SCK); I2CmDelay(20); //大于1uS } // I2Cm_SCKO(0); IoLo(IIC_SCK); return 1; } ``` 从I2C接口上接收字节数据 u8 I2Cx_ReceiveByte() //数据从高位到低位 { u8 i = 8; //8位 u8 ReceiveByte = 0; //1字节接收数据缓存 I2Cm_SDAO(1); while(i--) { ReceiveByte <<= 1; I2Cm_SCKO(0); I2CmDelay(20); //大于1.3uS I2Cm_SCKO(1); I2CmDelay(20); if(I2Cm_SDAI() == 1) ReceiveByte |= 0x01; } I2Cm_SCKO(0); return ReceiveByte; //返回接收到的数据 } 发送8位地址数据 ```c u32 I2CSendByteADDRData(I2C_Cfg* Ix,u8 DeviceAddr,u8 ADDR,u8* WData,u32 Length) { u32 Cnt = 0; //实际发送的数据个数 // if(Ix == (I2C_Cfg*)0) //指针检查 // return 0; if(I2Cx_Start() == 0) //I2C开始时对方器件忙 return 0; I2Cx_SendByte(DeviceAddr); //器件地址 if(I2Cx_WaitAck() == 0) //等待应答 { I2Cx_Stop(); return 0; } I2Cx_SendByte(ADDR); //设置8位地址 if(I2Cx_Ack() == 0) //等待应答 { I2Cx_Stop(); return 0; } while(Length) //发送指定长度数据 { I2Cx_SendByte(*WData); //发送数据 if(I2Cx_Ack() == 0) //等待应答 { I2Cx_Stop(); return 0; } WData++; Cnt++; Length--; } I2Cx_Stop(); //关闭I2C //发送完后关闭 return Cnt; //发送的数据个数 } ``` 发送16位地址数据 ```c u32 I2CSendWordADDRData(u8 DeviceAddr,u16 ADDR,u8* WData,u32 Length) { u32 Cnt = 0; //实际发送的数据个数 if(I2Cx_Start() == 0) //I2C开始时对方器件忙 return 0; I2Cx_SendByte(DeviceAddr); //器件地址 if(I2Cx_WaitAck() == 0) //等待应答 { I2Cx_Stop(); return 0; } I2Cx_SendByte((u8)(ADDR >> 8)); //设置高8地址 if(I2Cx_WaitAck() == 0) //等待应答 { I2Cx_Stop(); return 0; } I2Cx_SendByte((u8)(ADDR % 256)); //设置低8地址 if(I2Cx_WaitAck() == 0) //等待应答 { I2Cx_Stop(); return 0; } while(Length) //发送指定长度数据 { I2Cx_SendByte(*WData); //发送数据 if(I2Cx_Ack() == 0) //等待应答 { I2Cx_Stop(); return 0; } WData++; Cnt++; Length--; } I2Cx_Stop(); //关闭I2C //发送完后关闭 return Cnt; //发送的数据个数 } ``` 发送数据 ```c u32 I2CReceiveByteADDRData(u8 DeviceAddr,u8 ADDR,u8* RData,u32 Length) { u32 Cnt = 0; //实际接收的数据个数 // if(Ix == (I2C_Cfg*)0) //指针检查 // return 0; if(I2Cx_Start() == 0) //I2C启动 return 0; //对方器件忙 I2Cx_SendByte(DeviceAddr); //器件地址 if(I2Cx_WaitAck() == 0) //等待应答 { I2Cx_Stop(); return 0; } I2Cx_SendByte(ADDR); //设置8位地址 if(I2Cx_WaitAck() == 0) //等待应答 { I2Cx_Stop(); return 0; } I2Cx_Stop(); I2Cx_SendByte(DeviceAddr | 0x01); //器件地址 读 if(I2Cx_WaitAck() == 0) { I2Cx_Stop(); return 0; //未能接收到应答 } while(Length) //发送指定长度数据 { *RData = I2Cx_ReceiveByte(); if(Length == 1) { if(I2Cx_NoAck() == 0) //数据接收完就不再应答 { I2Cx_Stop(); return 0; //未能接收到应答 } } else { if(I2Cx_Ack() == 0) { I2Cx_Stop(); return 0; //未能接收到应答 } } RData++; Cnt++; Length--; } I2Cx_Stop(); //关闭I2C return Cnt; //实际接收的数据个数 } ``` 接收数据 ```c s32 I2CReceiveWordADDRData(u8 DeviceAddr,u16 ADDR,u8* RData,u32 Length) { u32 Cnt = 0; //读取的数据个数 if(I2Cx_Start() == 0) //I2C启动 return -1; //对方器件忙 I2Cx_SendByte(DeviceAddr); //器件地址 if(I2Cx_WaitAck() == 0) //等待应答 { I2Cx_Stop(); return -1; } I2Cx_SendByte((u8)(ADDR >> 8)); //设置高8位地址 if(I2Cx_WaitAck() == 0) //等待应答 { I2Cx_Stop(); return -1; } I2Cx_SendByte((u8)(ADDR % 256)); //设置低8位地址 if(I2Cx_WaitAck() == 0) //等待应答 { I2Cx_Stop(); return -1; } I2Cx_Stop(); I2Cx_SendByte(DeviceAddr | 0x01); //器件地址 读 if(I2Cx_WaitAck() == 0) { I2Cx_Stop(); return -1; //未能接收到应答 } while(Length) //发送指定长度数据 { *RData = I2Cx_ReceiveByte(); if(Length == 1) { if(I2Cx_NoAck() == 0) //数据接收完就不再应答 { I2Cx_Stop(); return -1; //未能接收到应答 } } else { if(I2Cx_Ack() == 0) { I2Cx_Stop(); return -1; //未能接收到应答 } } RData++; //地址偏移 Cnt++; //读取的数据个数 Length--; //需要接收的数据个数 } I2Cx_Stop(); //关闭I2C return Cnt; //实际数据个数 } ```
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
瑟寒凌风
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交