IIC通讯学习笔记

IIC通讯学习笔记

什么是IIC总线 ?

IIC总线是有一条SDA数据线和一条SCL时钟线组成,在这两条线上可以挂接多个IIC设备。每个IIC设备都有自己的地址,这些地址由硬件的出厂固定地址位和可编程地址位组成,只有在两条线上传输的值是IIC设备的地址时,这个IIC设备才会作出响应。

/*******************************************************************************

  • 函 数 名 : IIC_Init

  • 函数功能 : IIC初始化

  • 输 入 : 无

  • 输 出 : 无
    *******************************************************************************/
    void IIC_Init(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(IIC_SCL_PORT_RCC|IIC_SDA_PORT_RCC,ENABLE);

    GPIO_InitStructure.GPIO_Pin=IIC_SCL_PIN;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_Init(IIC_SCL_PORT,&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
    GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);

    IIC_SCL=1;
    IIC_SDA=1;
    }

/*******************************************************************************

  • 函 数 名 : SDA_OUT

  • 函数功能 : SDA输出配置

  • 输 入 : 无

  • 输 出 : 无
    *******************************************************************************/
    void SDA_OUT(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);
    }

/*******************************************************************************

  • 函 数 名 : SDA_IN

  • 函数功能 : SDA输入配置

  • 输 入 : 无

  • 输 出 : 无
    *******************************************************************************/
    void SDA_IN(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
    GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);
    }

/*******************************************************************************

  • 函 数 名 : IIC_Start
  • 函数功能 : 产生IIC起始信号
  • 输 入 : 无
  • 输 出 : 无
    *******************************************************************************/
    void IIC_Start(void)
    {
    SDA_OUT(); //sda设置为输出模式
    IIC_SDA=1;
    IIC_SCL=1;
    delay_us(5);
    IIC_SDA=0;//SDA由高跳到低
    delay_us(6);
    IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
    }

/*******************************************************************************

  • 函 数 名 : IIC_Stop
  • 函数功能 : 产生IIC停止信号
  • 输 入 : 无
  • 输 出 : 无
    *******************************************************************************/
    void IIC_Stop(void)
    {
    SDA_OUT();//sda线输出
    IIC_SCL=0;
    IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
    IIC_SCL=1;
    delay_us(6);
    IIC_SDA=1;//发送I2C总线结束信号
    delay_us(6);
    }

/*******************************************************************************

  • 函 数 名 : IIC_Wait_Ack

  • 函数功能 : 等待应答信号到来

  • 输 入 : 无

  • 输 出 : 1,接收应答失败
    0,接收应答成功
    *******************************************************************************/
    u8 IIC_Wait_Ack(void)
    {
    u8 tempTime=0;

    IIC_SDA=1;
    delay_us(1);
    SDA_IN(); //SDA设置为输入
    IIC_SCL=1;
    delay_us(1);
    while(READ_SDA)
    {
    tempTime++;
    if(tempTime>250)//等待一段时间还没应答则发送停止信号
    {
    IIC_Stop();
    return 1;
    }
    }
    IIC_SCL=0;//时钟输出0
    return 0;
    }

/*******************************************************************************

  • 函 数 名 : IIC_Ack
  • 函数功能 : 产生ACK应答
  • 输 入 : 无
  • 输 出 : 无
    *******************************************************************************/
    void IIC_Ack(void)
    {
    IIC_SCL=0;
    SDA_OUT();
    IIC_SDA=0;
    delay_us(2);
    IIC_SCL=1;
    delay_us(5);
    IIC_SCL=0;
    }

/*******************************************************************************

  • 函 数 名 : IIC_NAck
  • 函数功能 : 产生NACK非应答
  • 输 入 : 无
  • 输 出 : 无
    *******************************************************************************/
    void IIC_NAck(void)
    {
    IIC_SCL=0;
    SDA_OUT();
    IIC_SDA=1;
    delay_us(2);
    IIC_SCL=1;
    delay_us(5);
    IIC_SCL=0;
    }

/*******************************************************************************

  • 函 数 名 : IIC_Send_Byte
  • 函数功能 : IIC发送一个字节
  • 输 入 : txd:发送一个字节
  • 输 出 : 无
    /
    void IIC_Send_Byte(u8 txd)
    {
    u8 t;
    SDA_OUT();
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {
    if((txd&0x80)>0) //因为先发的是最高位
    IIC_SDA=1;//如果刚刚的位是1则证明SDA为高,所以置1 
    else
    IIC_SDA=0;
    txd<<=1; //为读下一位作准备
    delay_us(2); //对TEA5767这三个延时都是必须的
    IIC_SCL=1;//时钟线高的时候,数据保持稳定,保证正确读取
    delay_us(2);
    IIC_SCL=0; //时钟线拉低,允许读下一位 
    delay_us(2);
    }
    }
    为什么要先把SCL设置为低电平?其实上面已经有提示,因为在SCL为高电平的时候,SDA的变化代表着起始或者终止信号,所以在SCL为低的时候,才允许SDA变化(这些变化代表数据)
    /
  • 函 数 名 : IIC_Read_Byte
  • 函数功能 : IIC读一个字节
  • 输 入 : ack=1时,发送ACK,ack=0,发送nACK
  • 输 出 : 应答或非应答
    *******************************************************************************/
    u8 IIC_Read_Byte(u8 ack)
    {
    u8 i,receive=0;
    SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )//一个字节一个字节读出来,所以要循环8次
    {
    IIC_SCL=0;
    delay_us(2);
    IIC_SCL=1;
    receive<<=1;//左移一位
    if(READ_SDA)//当SDA为1的时候读入1,否则直接补零
    receive|=0x01;
    delay_us(1);
    }
    if (!ack)
    IIC_NAck();//发送nACK
    else
    IIC_Ack(); //发送ACK
    return receive;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值