IIC协议学习 及源码分析

在这里插入图片描述

IIC简介

IIC协议是常用的嵌入式器件协议之一,它简单高效,便于应用.
本博客主要为个人学习总结,如有错误,请大家指出
主要的IIC通信有两种方式

1.软件GPIO模拟
2.IIC控制器

GPIO模拟的方式比较通用可移植性好,IIC控制器取决于不同MCU

主要传输时序图

在这里插入图片描述

源码

主要实现的函数API有以下
void IIC_Start()
void IIC_Stop()
unsigned char IIC_SendByte(unsigned char dat)
unsigned char IIC_ReadByte()

void IIC_Write(unsigned char addr,unsigned char dat)
unsigned char IIC_Read(unsigned char addr)

(1) 51源码

void IIC_Start()
{
SDA=1;
Delay10us();
SCL=1;
Delay10us();//建立时间是SDA保持时间>4.7us
SDA=0;
Delay10us();//保持时间是>4us
SCL=0; //拉低进行发送数据准备
Delay10us();
}

void IIC_Stop()
{
SDA=0;
Delay10us();
SCL=1;
Delay10us();//建立时间大于4.7us
SDA=1;
Delay10us(); //全部拉高释放总线
}

unsigned char IIC_SendByte(unsigned char dat)
{
unsigned char a=0,b=0;//最大255,一个机器周期为1us,最大延时255us。
for(a=0;a<8;a++)//要发送8位,从最高位开始
{
SDA=dat>>7; //起始信号之后SCL=0,所以可以直接改变SDA信号
dat=dat<<1;//将发送数据准备好 ,等待正跳变发送数据
Delay10us();
SCL=1;
Delay10us();//建立时间>4.7us
SCL=0;
Delay10us();//时间大于4us
}
SDA=1;
Delay10us();
SCL=1;//暂时拉高接受数据
while(SDA)//等待应答,也就是等待从设备把SDA拉低
{
b++;
if(b>200) //如果超过2000us没有应答发送失败,或者为非应答,表示接收结束
{
SCL=0;
Delay10us();//将SCL拉成低电平,等待器件反应
return 0;
}
}
SCL=0;//继续写或者进行读
Delay10us();
return 1;
}

unsigned char IIC_ReadByte()
{
unsigned char a=0,dat=0;
SDA=1; //起始和发送一个字节之后SCL都是0
Delay10us();
for(a=0;a<8;a++)//接收8个位
{
SCL=1;
Delay10us();
dat<<=1;
dat|=SDA;//之前SCL为低,在拉高之前将接收数据准备好
Delay10us();
SCL=0;//拉低读取数据
Delay10us();
}
return dat;
}

void IIC_Write(unsigned char addr,unsigned char dat)
{
I2cStart();
I2cSendByte(XXX);//发送写器件地址
I2cSendByte(addr);//发送要写入内存地址
I2cSendByte(dat); //发送数据
I2cStop();
}

unsigned char IIC_Read(unsigned char addr)
{
unsigned char num;
I2cStart();
I2cSendByte(XXX); //发送写器件地址
I2cSendByte(addr); //发送要读取的地址
I2cStart();
I2cSendByte(0xa1); //发送读器件地址
num=I2cReadByte(); //读取数据
I2cStop();
return num;
}

(2) 32源码

STM32进行IIC GPIO模拟的时候,需要配置两个宏,由于进行GPIO模拟的时候必须配置SDA为输入输出方向选择,所以必须实现一个切换方向的宏
#define SDA_IN()
{GPIOB->MODER&=~(3<<(92));GPIOB->MODER|=0<<92;}
#define SDA_OUT()
{GPIOB->MODER&=~(3<<(92));GPIOB->MODER|=1<<92;}

#define IIC_SCL PBout(8) //SCL
#define IIC_SDA PBout(9) //SDA
#define READ_SDA PBin(9) //配置输入
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
在上面进行GPIO初始化

IIC_SCL=1;
IIC_SDA=1;//将总线拉高置于空闲

}

void IIC_Start(void)
{
SDA_OUT(); //配置为输出
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);//注意延时时间
IIC_SDA=0;//在负跳变进行起始
delay_us(4);
IIC_SCL=0;//将时钟线拉低,等待发送数据就位
}

void IIC_Stop(void)
{
SDA_OUT();
IIC_SCL=0;
IIC_SDA=0;//正跳变停止
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//拉高总线置为空闲
delay_us(4);
}

u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //配置为输入
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1); //总线释放,等待输入
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//拉低等待下一次发送或接受
return 0;
}
//产生一个应答(在接收)
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//产生一个应答
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}

void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低时钟线,之前已经置为0
for(t=0;t<8;t++)
{
IIC_SDA=(txd&0x80)>>7;
txd<<=1; //准备好数据,等待跳变传送
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0; //拉低准备接受下一个
delay_us(2);
}
}

u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//配置为输入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;//正跳变接收数据
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck(); //不产生应答
else
IIC_Ack(); //产生应答接收下一组数据
return receive;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值