百为STM32开发板教程之十——I2C数字温度传感器
参考资料:
百为stm32开发板光盘\其他参考资料\I2C协议-周立功.pdf
百为stm32开发板光盘\芯片数据手册\LM75A_2_cn.pdf
实验目的:读取I2C数字温度传感器LM75A的温度,并打印到串口上
主要内容:
一、了解I2C协议
二、了解STM32的I2C接口
三、研究LM75A的数据手册,了解LM75A工作原理及相关操作
四、通过STM32的I2C接口读取LM75A的温度并打印串口上
一、了解I2C协议
I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线。
1、这两线分别是串行数据线SDA和串行时钟线SCL。
2、I2C 总线上数据的传输速率在标准模式下可达100kbit/s, 在快速模式下可达400kbit/s。
3、任何连接到总线上的设备都有一个唯一的地址,主机访问从机设备之前要先发送地址选中从机。
4、I2C进行通信时由主机发送起始位开始,直到主机发送停止位时结束。
SCL 线是高电平时,SDA 线从高电平向低电平切换,这个情况表示起始条件。
SCL 线是高电平时,SDA 线由低电平向高电平切换,这个情况表示停止条件。
5、发送到SDA 线上的每个字节必须为8 位,每次传输可以发送的字节数量不受限制。每个字节后必须跟一个响应位。首先传输的是数据的最高位(MSB)。
6、I2C地址有7位地址和10位地址两种,我们这里只介绍7位地址的情况。主机发送完停止位后,发送的第一个字节包括7位地址,和1位读写标志位。
最后一位R/W为0时表示写,为1时表示读
二、了解STM32的I2C接口
STM32的I2C既可做主机也可做从机,我们这里只讨论STM32的I2C作为主机的情况。
STM32的I2C功能:
1、硬件产生起始位,停止位
2、状态寄存器中有“起始条件已发送”等状态标志,这些标志组合起来就成了I2C通信过程中的事件EV5,EV6,EV7,EV8等
STM32的I2C通信过程:
STM32的I2C主机发送数据过程(发送数据到LM75A):
STM32的I2C主机接收数据过程(从LM75A接收数据):
通信过程中的EV事件(仅用于STM32):
EV5:检查状态寄存器的这三位:SB:起始位(主模式),MSL:主从模式,BUSY:总线忙
EV6:主机发送时:检查状态寄存器的:BUSY:总线忙,MSL:主从模式,ADDR:地址已被发送,TxE:数据寄存器为空,TRA:发送/接收
主机接收时:检查状态寄存器的:BUSY:总线忙,MSL:主从模式,ADDR:地址已被发送
EV8:检查状态寄存器的:TRA:发送/接收,BUSY:总线忙,MSL:主从模式,TxE:数据寄存器为空,BTF:字节发送结束
EV7:检查状态寄存器的:BUSY:总线忙,MSL:主从模式,RxNE:数据寄存器非空
要用I2C接口,首先要初始化相关的GPIO及I2C的参数:
/* tsensor.c */
void I2C_LM75_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
/* GPIOB Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);
/* 打开I2C1时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
/* 配置I2C1管脚: SCL and SDA */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //设置I2C1管脚PB6,PB7
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //设置为复用开漏输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 配置PB5为上拉输入, 连接LM75A的INT管脚 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置为输入上拉
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_DeInit(I2C1); //xx_DeInit仅DEBUG时用
/* I2C1 参数初始化 */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //设置为I2C模式,区别于SMBus模式
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //设置I2C快速模式Tlow / Thigh = 2
I2C_InitStructure.I2C_OwnAddress1 = 0x00; //设置I2C自身设备地址,我们这里STM32的I2C做主机用,设为0
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //使能ACK应答位
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //响应7位地址,仅作从机时用
I2C_InitStructure.I2C_ClockSpeed = 200000; //设置I2C时钟频率
I2C_Init(I2C1, &I2C_InitStructure);
/*打开I2C1 */
I2C_Cmd(I2C1, ENABLE);
}
三、了解LM75A工作原理及相关操作
1、概述
LM75A是NXP半导体公司推出的I2C接口的数字温度传感器,它也是一个温度检测器,提供过热检测输出功能。
LM75A 可设置成工作在两种模式:正常工作模式或关断模式。我们这里只讨论正常模式。
2、LM75A管脚电路图:
百为STM32开发板上连接LM75A的电路图(STLM75M2E是另一个器件的名称,我们只要采用的是LM75A):
3、LM75A地址及寄存器
LM75A的7位地址:其中高4位固定为1001,低3位由管脚A2,A1,A0决定
LM75A 包含许多寄存器:
(1)指针寄存器,用来选择要操作的寄存器
其中最低两位B1,B0表示要操作的寄存器
(2)配置寄存器:8位寄存器,用来配置器件的工作模式
(3)温度寄存器:16位寄存器,只有其中高11位有效,存放以0.125℃为单位的温度值补码
(4)滞后寄存器(Thyst):当环境温度低于此温度的时候,LM75A将根据当前模式(比较、中断)控制OS引脚作出相应反应。
(5)过热关断阈值寄存器(Tos):当环境温度高于此温度的时候,LM75A将根据当前模式(比较、中断)控制OS引脚作出相应反应。
这两个寄存器的作用是控制OS管脚的输出。具体可以参考LM75A数据手册。
4、LM75A相关操作时序
(这里只介绍含指针字节的情况,预置指针的情况请参考LM75A数据手册)
写配置寄存器
读配置寄存器
写Tos 或Thyst 寄存器
读包含指针字节的Temp、Tos 或Thyst 寄存器
四、通过STM32的I2C接口读取LM75A的温度并打印到串口上
/* main.c */
TempReadValue = I2C_LM75_Temp_Read(); //读取LM75A温度寄存器值
temperature = TempReadValue*0.125; //转换成实际的温度值
printf("TempReadValue = %d\n\r", TempReadValue);
printf("temperature = %.3f\n\r", temperature);
/* tsensor.c */
u16 I2C_LM75_Temp_Read(void)
{
u32 RegValue = 0;
/* 使能I2C1 ACK应答位(如果ACK被其他功能模块取消的话)*/
I2C_AcknowledgeConfig(I2C1, ENABLE);
/*----- 发送阶段-----*/
/* 发送I2C起始条件 */
I2C_GenerateSTART(I2C1, ENABLE);
/* 等待EV5事件 */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) /* EV5 */
{
}
/* 发送LM75A从机地址,写操作 */
I2C_Send7bitAddress(I2C1, LM75_Addr, I2C_Direction_Transmitter);
/* 等待EV6事件 */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) /* EV6 */
{
}
/* 发送温度寄存器指针值 */
I2C_SendData(I2C1, LM75_TEMP_Reg);
/* 等待EV8事件*/
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) /* EV8 */
{
}
/*----- 接收阶段 -----*/
/* 发送重复起始条件 */
I2C_GenerateSTART(I2C1, ENABLE);
/* 等待EV5事件 */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) /* EV5 */
{
}
/* 发送LM75A从机地址,读操作 */
I2C_Send7bitAddress(I2C1, LM75_Addr, I2C_Direction_Receiver);
/* 等待EV6事件 */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) /* EV6 */
{
}
/* 等待EV7事件 */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) /* EV7 */
{
}
/* 接收LM75A温度值高8位 */
RegValue = I2C_ReceiveData(I2C1) << 8;
/* 取消应答位,LM75A读温度的第二个字节不需要应答位,参考LM75A的时序图 */
I2C_AcknowledgeConfig(I2C1, DISABLE);
/* 发送停止条件 */
I2C_GenerateSTOP(I2C1, ENABLE);
/* 等待EV7事件 */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) /* EV7 */
{
}
/* 接收LM75A温度值低8位 */
RegValue |= I2C_ReceiveData(I2C1);
/* 返回温度值高11位 */
return (RegValue >> 5);
}
|