STM32F103单片机软件模拟IIC并读取TMP112数字温度传感器

本文利用STM32F103系列单片机读取TMP112数字温度传感器的温度信息,TMP112数字传感器采用IIC总线协议通信。STM32自身含有硬件IIC资源,分别是PB6-->SCL、PB7-->SDA,硬件IIC的操作在STM32开发板对应的资料上均有给出,在此不再赘述,本文使用软件模拟IIC来完成与TMP112传感器之间的通信。


图1:TMP112的管脚定义图

TMP112温度传感器的电路连接如下,TMP112的IIC设备地址由管脚ADD0决定,

设备地址的值如下:

SCL和SDA管脚需要上拉电阻。ADD0管脚连接地,地址为7位,最后一位为读写操作位,0为写,1为读。即0x90和0x91。

进入正题模拟IIC的操作,STM32管脚定义。

 #define SCL GPIO_Pin_6
#define SDA GPIO_Pin_7

#define SCL_H GPIO_SetBits(GPIOB,GPIO_Pin_6 )
#define SCL_L GPIO_ResetBits(GPIOB,GPIO_Pin_6 )

#define SDA_H GPIO_SetBits(GPIOB,GPIO_Pin_7 )
#define SDA_L GPIO_ResetBits(GPIOB,GPIO_Pin_7)

#define SDAread GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_7)

IIC协议开始和停止条件

SCL时钟电平为高:

SDA数据线由高 -> 低 为总线开始条件;SDA数据线由低 -> 高 为总线结束条件;

注意:开始之后将需要将SCL变为低电平;


SCL时钟电平为低,可以改换SDA数据线的电平,在SCL升沿的过程将数据发送出去。数据从高至低发送,SCL_L--->SDA数据--->SCL_H。

时序:



应答信号。STM32作为主机,TMP112为从机。主机读,主机产生应答信号。时序图:



STM32向TMP112传感器写数据的时序图如下:

程序如下:

void I2C_WriteByte(void)
{
u16 i;
u8 j;
I2C_Start();
I2C_delay();
I2C_SendByte(0x90); //设备地址--写操作
I2C_Ack();
I2C_SendByte(0x01); //寄存器
I2C_Ack();
I2C_SendByte(0x00); //数据
I2C_Ack();
I2C_Stop();
for(j=30;j>0;j--)
I2C_delay();
}

STM接收TMP112发送过来的数据时,I2C的读一字节函数,其实和“写一字节”类似,只是数据传输方向相反,应答的方向也是相反。
读完一字节(8位)之后,由主机产生应答(或非应答)位:若产生应答,表示可以继续读下一字节操作(从设备地址指向下一字节);
若产生非应答,表示不可以继续读下一字节操作;

时序:


程序:

u8 I2C_ReceiveByte(void)

    u8 i=8,j;
    u8 ReceiveByte=0;
    SDA_H;
    while(i--)
    {
      ReceiveByte<<=1;      
      SCL_H;
      I2C_delay(); 
      if(SDAread)
      {
       ReceiveByte|=0x01;
      }
for(j=30;j>0;j--)
//I2C_delay();
SCL_L;
    }
    return ReceiveByte;
}

STM32向TMP112读取数据,时序图如下:


程序:

u16 ReadTemp(void)
{
u8 TempH ,TempL;
I2C_Start();
I2C_SendByte(0x90);    //设备地址--写操作
I2C_Ack();
I2C_SendByte(0x00); //数据
I2C_Ack();

I2C_Start();
I2C_SendByte(0x91);  //设备地址--读操作
I2C_Ack();
TempH=I2C_ReceiveByte();
I2C_NoAck(); //无应答,接收低8位数据
TempL=I2C_ReceiveByte();
I2C_Stop();

return TempH*10+(int)(TempL*0.0625*0.0625*10);
}


你可能感兴趣的:(嵌入式开发)