基于STM8的IIC协议通信

时间:2020-01-09
本文章向大家介绍基于STM8的IIC协议通信,主要包括基于STM8的IIC协议通信使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、 综述

  I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。

  它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU和被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。但在STM8中,400kHZ已经是最快速度了。

       在往后的模块调试中也经常涉及,是一个很常见并且很好用的协议。

二、STM8S103中手册对I2C简介

 看完中文资料手册,个人觉得比较浅显,具体使用在后面我会贴出来。

三、 I2C详细解析

I2C总共由五个核心函数,分别为:

①起始信号

②停止信号

③应答信号

④发送数据

⑤接收数据

通过这五个核心基本函数就能于大多数的传感进行通信了。

以下对各个部分进行详细介绍,附上部分主要代码,各位可以参考一下。

3.1 起始信号

当SCL为高电平期间,SDA由高电平到低电平的跳变过程;起始信号是一种电平跳变时序信号,而不是一个电平信号,如上图虚线框所。

void Start_Signal_IIC_(void){
  
  //起始信号:
  GPIO_WriteHigh(GPIOD, GPIO_PIN_2);//数据线
  IIC_Delay_4us();
  GPIO_WriteHigh(GPIOD, GPIO_PIN_3);//时钟线
  IIC_Delay_4us();
  GPIO_WriteLow(GPIOD, GPIO_PIN_2); //数据线
  IIC_Delay_4us();
  GPIO_WriteLow(GPIOD, GPIO_PIN_3); //时钟线
  IIC_Delay_4us();
}

  

3.2 停止信号

当SCL为高电平期间,SDA由低电平到高电平的跳变过程;停止信号也是一种电平跳变时序信号,而不是一个电平信号,如上图虚线框所。

void End_Data_IIC_()
  {
    GPIO_WriteLow(GPIOD, GPIO_PIN_2); //数据线拉低
    IIC_Delay_4us();
    GPIO_WriteHigh(GPIOD, GPIO_PIN_3);//时钟线拉高
    IIC_Delay_4us();
    GPIO_WriteHigh(GPIOD, GPIO_PIN_2);//数据线拉高
}

  

3.3 应答信号

应答信号有两种:分别是主动应答信号和主动不应答信号

①Ack(主动拉低SDA形成应答信号)

 I2C总线的数据都是以字节(8位)的方式传送的,发送器件每发送一个字节之后,在时钟的第9个脉冲期间释放数据总线,由接收器发送一个  ACK(把数据总线的电平拉低)来表示数据成功接收。

//主动应答信号
void vIIC_Ack() { GPIO_WriteLow(GPIOD, GPIO_PIN_2); IIC_Delay_4us(); GPIO_WriteHigh(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); GPIO_WriteLow(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); }

②NAck(主动不拉低SDA不形成应答信号)

在时钟的第9个脉冲期间发送器释放数据总线,接收器不拉低数据总线表示一个NACK,NACK有两种用途:

a. 一般表示接收器未成功接收数据字节;

b. 当接收器是主控器时,它收到最后一个字节后,应发送一个NACK信号,以通知被控发送器结束数据发送,并释放总线,以便主控接收器发送一个停止信号STOP。

//主动不应答
void vIIC_NAck()
{
  GPIO_WriteHigh(GPIOD, GPIO_PIN_2);
  IIC_Delay_4us();
  GPIO_WriteHigh(GPIOD, GPIO_PIN_3);
  IIC_Delay_4us();
  GPIO_WriteLow(GPIOD, GPIO_PIN_3);
  IIC_Delay_4us();
}

 ③ReadAck(等待应答信号)

    该信号在主机发送完数据后等待从机应答时候使用。

 u8 bIIC_ReadACK()
  {
    GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_IN_PU_IT);//将SDA改为输入模式。
    GPIO_WriteHigh(GPIOD, GPIO_PIN_3);               //拉高时钟线。
    IIC_Delay_4us();  
    if(IIC_SDA_R != 0)
       {
         //低 有应答
         GPIO_WriteLow(GPIOD, GPIO_PIN_3);
         IIC_Delay_4us();
         GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);//SDA
         return 1;
       }
     else
        //高 无应答
       {
        GPIO_WriteLow(GPIOD, GPIO_PIN_3);
        IIC_Delay_4us();
        GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);//SDA
        return 0;
       }
  }

  

3.4 发送数据

在发送起始信号后开始通信,主机发送一个8位数据。然后,主机释放SDA线并等待从从机发出得确认信号(ACK)。

void Send_Data_IIC_(uint8_t Data){
    int i;
//拉低数据线和时钟线 GPIO_WriteLow(GPIOD, GPIO_PIN_3); GPIO_WriteLow(GPIOD, GPIO_PIN_2); for(i=0;i<8;i++) { if(Data&0x80) GPIO_WriteHigh(GPIOD, GPIO_PIN_2); else GPIO_WriteLow(GPIOD, GPIO_PIN_2); Data= Data<<1; IIC_Delay_2us(); GPIO_WriteHigh(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); GPIO_WriteLow(GPIOD, GPIO_PIN_3); IIC_Delay_2us(); } }

  

3.5 接收数据

在发送起始信号后开始通信,主机发送一个8位数据。然后,从机收到数据返回一个确认信号(ACK)给主机,这时候主机才开始接收数据,待主机接收数据完成后,发送一个NACK信号给从机,以通知接收端结束数据接收。

//接收函数
uint8_t uIIC_RecvByte()
{
  uint8_t i,uReceiveByte = 0;
  GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_IN_PU_IT);
  for(i=0;i<8;i++)
  {
  
    uReceiveByte <<= 1;
    IIC_Delay_4us();
    GPIO_WriteHigh(GPIOD, GPIO_PIN_3);//高时钟线时读取数据电平
    IIC_Delay_4us();
    if(IIC_SDA_R !=0 )
    {
      uReceiveByte|=0x01;
    }
    IIC_Delay_4us();
    GPIO_WriteLow(GPIOD, GPIO_PIN_3);
    IIC_Delay_4us();
  }
  
   GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);
   return uReceiveByte;
}

  

3.6 I2C通信总过程

以下图完美地诠释了iic从接收到发送全过程中,SDA和SCL线的变化线。综合上面的解释和过程代码,这张图可以帮助记忆和理解。

四、例程

4.1 编译环境:

        这里用的是IAR进行编译,较为好用,后期使用STM32的开发板可以推荐使用CUBE直接生成初始化函数,与Keil5相互搭配使用,很是方便。

4.2 主芯片:

  我的主芯片是STM8S系列中的103,其中STM8S的003、005、和103、105,配置一样(外设和CPU频率,FLASH),在代码相同的情况下均可进行烧写。

4.3 代码&解析

       iic代码可以驱动几乎市面上的所有时钟模块,所以这里的代码可以与时钟模块的代码相互调用。每个函数我都有加以解释,可以详细了解一下。

      看了上面的代码也可以知道,这个协议是由数据线和时钟线,数据发送接收要求拉高数据线或拉低时钟线。所以这里推荐直接使用库函数的拉高低,如果要方便的话,再加个宏定义可以更加直观方便。

五、结尾

以上是iic的核心函数,对于每个函数我已经写的很清楚,下一篇博客我会将基于iic的时钟模块的传感通信博客贴出来,各位可以继续阅读下一篇博客做一下参考。

原文地址:https://www.cnblogs.com/shasha2019/p/12171728.html