本文利用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);
}