本博客大部分参考了其它人的文章,仅用来学习存储,知识积累
IIC总线协议与软件实现
第一次写博客,主要是将自己自学的一点东西记下来,与其做笔记,不如写博客。这几天看了I2C协议,这是大部分芯片必用的协议,花了几天时间,找了很多资料,终于有所悟,我来分享给大家。
一、I2C协议时序图
写时序:
- 起始信号:处理器将SCL置高电平,SDA下降沿,进入数据传输状态。
- 数据传输:不论是写还是读,i2c规定SCL被拉高之前,数据必须放在SDA上待读取,SCL一旦处于高电平,SDA上的数据必须稳定,如果有跳变就会成为起始信号和停止信号发生错误,这点在写程序时一定要注意。
- 读写位:高电平读,即主机接收从机发来的数据;低电平写,即主机将数据发送给从机。
- 应答信号:总线上每传完一个字节,被传送方都会在第9个时钟总线拉低,以示回应。
- 停止信号:SCL高电平时,SDA上升沿,结束此次传输。
整个传输过程就是:
主机发出起始信号->高7位写设备地址,低0位写0->等待回应->写设备内部寄存器地址->等待回应->写n个字节,并等待回应(你>=1)->主机发出停止信号
读时序:
- 读信号。
- 应答信号:和写入不同,应该由主机发出,读取一个字节发出一个应答信号。
无应答信号:第9个时钟不拉低SDA。注意,在一次读取多个字节的时候,最后一个字节应该不应答,直接stop,否则出错,实测。
整个流程如下:
主机发出起始信号->写7位从机地址+1位写信号->等从机应答->写寄存器地址->等从机应答->主机发出起始信号->写7位从机地址+1位读信号->等从机应答->读字节->发出应答信号->…->读字节->无应答->主机发出停止信号注意几点:
1、 i2c总线在硬件上,应该保证线与,即一条线上有一个位低,那么整条线就为低。解决办法就是挂载在总线上的设备io口设置为开漏模式,并挂一个上拉电阻。
2、 在不需要使用SDA的时候,主机应该释放,保证从机能够传输电平信号,比如上图的ack by slave,如果主机不释放SDA,始终为低电平,根本无法判断是主机拉低的还是从机拉低的。
3、 在进入传输状态的时候,如果没有传输数据,SCL应该为 低电平,因为SCL如果为高电平,SDA有任何的抖动都会被识别为起始或是停止信号,导致此次传输失败。
二、C代码
OIIC.h
/***************************************************************
portable iic driver
author:logic
date:2016-7-23
***************************************************************/
#ifndef _OIIC_H
#define _OIIC_H
#include "MK60_port.h"
#include "MK60_gpio.h"
/*
*public:
*/
void OIIC_init();
void OIIC_writeByte(unsigned char devAddr,unsigned char regAddr,unsigned char byte);
void OIIC_writeWord(unsigne