IIC调试学习
----------------------应用于TMP1XX等一系列IIC温度传感器--------------------------------
由于项目要用到温度传感器,所以就挑选了TI的一款温度传感器Tmp102,这款温度传感器和TI的很多温度传感器都类似,比如Tmp112,lm75,lm75a等。这款温度传感器所用到的通信方式为IIC,之前仅仅了解过IIC并没有进行实际的操作,借着这个机会进行实际的IIC运用和学习。
其中IIC的基础知识点就不详细说明了,想要进行IIC的编程和学习,首先学习的应该是他的基本知识,只有知道了他的基础知识才能够进行有条不紊的应用。
我用的单片机是STM32F103ZET6,IIC为软件的形式是实现
IIC协议软件实现
- 产生开始信号
void IIC_Start(void)
{
SDA_OUT(); //sdaÏßÊä³ö
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//ǯסI2C×ÜÏߣ¬×¼±¸·¢ËÍ»ò½ÓÊÕÊý¾Ý
}
2.产生停止信号
void IIC_Stop(void)
{
SDA_OUT();//SDA设置为输出
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//钳住IIC线准备发送或者接受数据
delay_us(4);
}
3.主机等待从机应答
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();
printf("device no ack\r\n");
return 1;
}
}
IIC_SCL=0;
return 0;
}
4.主机不产生应答
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
5.主机产生应答
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
6.IIC发送一个字节
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=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);
}
}
6.IIC读一个字节
u8 IIC_Read_Byte(void)
{
unsigned char i,receive=0;
SDA_IN();//SDAÉèÖÃΪÊäÈë
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA) receive|=0x01;
delay_us(1);
}
return receive;
}
温度传感器实现
1.温度传感器初始化
void Tmp102_Init(void)
{
IIC_Init();
}
2.温度传感器读取一个字节
u8 Tmp102_ReadOneByte(u8 DeviceAdd, u8 PointAddr)
{
u8 temp=0;
IIC_Start();
IIC_Send_Byte(DeviceAdd); //·¢ËÍÆ÷¼þµØÖ·0X92,дÊý¾Ý
IIC_Wait_Ack();
IIC_Send_Byte(PointAddr);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(DeviceAdd|0x01);
IIC_Wait_Ack();
temp=IIC_Read_Byte();
IIC_Stop();
return temp;
}
3.温度传感器读取一个字
u16 Tmp102_ReadOneWrite(u8 DeviceAdd, u8 PointAddr)
{
u16 tempH=0;
u16 tempL=0;
u16 temp=0;
IIC_Start();
IIC_Send_Byte(DeviceAdd); //·¢ËÍÆ÷¼þµØÖ·0X92,дÊý¾Ý
IIC_Wait_Ack();
IIC_Send_Byte(PointAddr);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(DeviceAdd|0x01);
IIC_Wait_Ack();
tempH=IIC_Read_Byte();
IIC_Ack();
IIC_SDA=1; //**如果不对信号线进行拉高则只能读取一次数据**
tempL=IIC_Read_Byte();
IIC_NAck();
IIC_Stop();//²úÉúÒ»¸öÍ£Ö¹Ìõ¼þ
temp = (tempH << 8) | tempL ;
temp = (temp >> 4); //ÓÉÓÚtmp102ºÍtmp112µÄÓÐЧλΪ12bit£¨¸ß12λÓÐЧ£©¡£ËùÒÔÐèÒªÓÒÒÆ4λ
return temp;
}
4.写入一个字节
void Tmp102_WriteOneByte(u8 DeviceAdd,u8 PointAddr,u8 DataToWrite)
{
IIC_Start();
IIC_Send_Byte(DeviceAdd);
IIC_Wait_Ack();
IIC_Send_Byte(PointAddr);
IIC_Wait_Ack();
IIC_SDA=1;
IIC_Send_Byte(DataToWrite);
IIC_Wait_Ack();
IIC_Stop();
delay_ms(30);
}
5.写入一个字
void Tmp102_WriteOneWrite(u8 DeviceAdd,u8 PointAddr,u16 DataToWrite)
{
u8 ack;
IIC_Start();
IIC_Send_Byte(DeviceAdd); //·¢ËÍÆ÷¼þµØÖ·0XA0,дÊý¾Ý
IIC_Wait_Ack();
IIC_Send_Byte(PointAddr); //·¢Ë͵͵ØÖ·
IIC_Wait_Ack();
IIC_SDA=1;
IIC_Send_Byte((DataToWrite>>8)&0xff);
ack = IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite&0xff);
ack = IIC_Wait_Ack();
IIC_Stop();//²úÉúÒ»¸öÍ£Ö¹Ìõ¼þ
delay_ms(30);
}
主函数
char a[5];
int main(void)
{
u16 recv_data;
double aa;
delay_init();
LCD_Init();
uart_init(9600);
Tmp102_Init();
POINT_COLOR=BLUE;
LCD_ShowString(60,70,200,16,16,"IIC TEST");
while(1)
{
Tmp102_WriteOneWrite(0X92,0X02,0X7640);
delay_ms(1000);
recv_data = Tmp102_ReadOneWrite(0X92,0X02);
printf("data = %02x\r\n",recv_data);
aa = recv_data*0.0625;
printf("rece_data = %f\r\n",aa);
sprintf(a,"%f",aa);
LCD_ShowString(60,190,200,16,16,(u8 *)a);
printf("IIC test\r\n");
LED1 = !LED1;
}
}
实际测试效果
图片: