目录
因项目需求,用DW_apb_i2c读写TMP75这个温度传感器,本文仅做个人使用记录。
1.TMP75介绍
TMP75器件属于数字温度传感器,片上12位模数转换器 (ADC) 具备低至 0.0625°C 的分辨率,TMP75功能总结如下:
(1)可以用i2c进行通信,主要是配置TMP75的工作模式以及获取温度信息;
(2)最多支持8个可配置的设备地址;
(3)支持SMBus Alert功能;
(4)支持广播功能(General Call)
以上常用功能是我个人的总结,更多详细介绍,清查阅TI官方文档,附上链接:TMP75 data sheet, product information and support | TI.com
2.引脚使用说明
截图来自官方文档,PIN脚使用不做太多赘述。这里需要注意A0、A1、A2这3个地址控制PIN脚,需要用户在硬件设计上选择拉高或拉低,一共有8种组合,故可以生成8个设备地址,具体见下表:
硬件电路原理图:
当前电路的A0、A1、A2都拉高,所以使用i2c或者smbus通信时,设备地址就是1001111,即0x4f。
3.寄存器使用说明
TMP75内部一共有5个寄存器,寄存器结构图如下:
(1)指针寄存器(Pointer Register)
首先介绍指针寄存器。因为在使用TMP75时,首先就要配置指针寄存器,其配置值表示接下来是读写另外4个寄存器中的哪一个。指针寄存器是一个8bit的寄存器,其低2bit用来指明接下来是读写哪一个寄存器。换句话说,其低2bit表示接下来哪一个寄存器要响应master的读写请求。
如上图所示,假如指针寄存器的低2bit是01时,即给指针寄存器配置0x01,说明接下来是Configuration register要响应master的读写请求,即表示后面是读写Configuration register,其他值依次类推。
(2)温度传感器(Temperature Register)
TMP上电时,指针寄存器默认值是0x00,即TMP75上电时默认是可以直接读取温度的。从文档可知,使用中需要连续读取2次温度传感器,才能获取温度值,并且温度传感器是一个12bit有效的只读传感器,有效位见下图:
从上图可知,T0到T11是温度有效数据位。在实际使用时,读回来的byte1和byte2组成16bit数据,其高12bit是有效温度数据,低4bit数据舍弃。温度计算公式(以0.0625分辨率为例):
Temperature =((byte1<<4) | (byte2>>4))*0.0625
(3)配置寄存器(Configuration Register)
这是一个8bit可读可写寄存器,用来控制TMP75的工作模式。bit位定义如下图:
当前只是读取温度的话,使用默认值就好,后面再研究一下其他模式的用法。
(4)THIGH and TLOW register
又叫 High and Low Limit Registers ,顾名思义,这2个寄存器是控制温度上限和下限,这里与alert功能的使用有关,当温度超过上限或低于下限时会触发Smbus alert警报。这2个寄存器是可读可写寄存器,读写的时候和上述的温度传感器一样,需要读写2次,高12bit为温度有效值。
4.TMP75寄存器读写流程
上图是写寄存器流程,Frame1,即第1个byte,是设备地址加写标志位,设备地址怎么设置前面已经说过了;第2个byte是给指针寄存器配置的值,表明接下来是写哪个寄存器;第3个和第4个byte就是给指定寄存器写的值。
上图是读寄存器流程,Frame1,即第1个byte,是设备地址加上写标志位;第2个byte还是给指针寄存器配置的值;第3个byte是设备地址加上读标志位,第4个和第5个byte就是读回来的值。
5.读取温度例程
截图上部分代码:
#define I2C1_ADDR (i2c_reg_s *)I2C1_BASE
/*
* i2c1 作为 master,采用轮询方式读写 TMP75
*/
void i2c1_master_test_case_for_TMP75(void)
{
i2c_reg_s *i2c_reg = NULL;
static i2c_handle_s i2c1_handle = {0};
unsigned char data[5] = {0};
unsigned int receive_fifo_empty = 0;
unsigned short temperature_data = 0;
unsigned int ic_state = 0;
i2c1_handle.instance = I2C1_ADDR;
i2c1_handle.irq_num = IRQ_NUM_I2C1;
i2c1_handle.i2c_mode = I2C_MODE_MASTER;
i2c1_handle.i2c_speed_mode = I2C_BUS_SPEED_STANDARD;
i2c1_handle.i2c_addr_mode = I2C_ADDRESS_7BIT;
i2c1_handle.i2c_general_cell = GENERAL_CELL_DISABLE;
i2c1_handle.i2c_restart = RESTART_DISABLE;
i2c1_handle.i2c_dma_mode = DMA_DISABLE;
i2c1_handle.i2c_notify_type = I2C_NOTIFY_TYPE_POLL;
i2c_init(&i2c1_handle);
dbg_uart_print("i2c1_master_test_case_for_TMP75 init end!!\r\n");
i2c_reg = i2c1_handle.instance;
i2c_set_transmit_fifo_threshold(i2c_reg, 2);
i2c_set_receive_fifo_threshold(i2c_reg, 2);
i2c_clear_all_irq(i2c_reg);
i2c_set_slave_address(i2c_reg,0x4f); // TMP75地址:100 1111
mdelay(1);
i2c_transmit_byte(i2c_reg, 0x00, WRITE_OPERATION, NO_STOP); //Pointer Register配置0x00,表示后面是操作Temperature register
mdelay(1);
i2c_transmit_byte(i2c_reg, 0x00, READ_OPERATION, NO_STOP); //read 0x00 to get the first byte
mdelay(1);
i2c_transmit_byte(i2c_reg, 0x00, READ_OPERATION, SEND_STOP); //read 0x00 again to get the second byte
mdelay(5);
ic_state = i2c_get_ic_status(i2c_reg); // get i2c irq status
if ((ic_state & I2C_STATUS_RFNE) == I2C_STATUS_RFNE) { // receive fifo not empty
data[0] = i2c_receive_byte(i2c_reg); // get receive data
dbg_uart_print("data[0]=0x%x\r\n",data[0]);
ic_state = 0;
}
ic_state = i2c_get_ic_status(i2c_reg); // get i2c irq status
if ((ic_state & I2C_STATUS_RFNE) == I2C_STATUS_RFNE) { // receive fifo not empty
data[1] = i2c_receive_byte(i2c_reg); // get receive data
dbg_uart_print("data[1]=0x%x\r\n",data[1]);
ic_state = 0;
}
temperature_data = (data[0]<<4 | data[1]>>4);
dbg_uart_print("temperature_data=0x%x\r\n",temperature_data);
dbg_uart_print("temperature_data=%f\r\n",(temperature_data*0.0625));
}
我用的是Synopsys的DW_apb_i2c控制器,上图是DW_apb_i2c的用法,不同产商的i2c使用方法有差异,这里不展开讲,我们的重点是要搞清楚TMP75使用方法。划重点:先配置指针寄存器为0x00,表示后续是读写温度寄存器;然后连续发送两次读请求,用来获取温度寄值;读回来第一个byte放在data[0],第二个byte放在data[1];拼接一下,按公式计算出当前测量出来的温度值。
串口打印结果:
逻辑分析仪抓取波形:
能看到这里,你可真是个狠人,相信已经很累了吧,那就扫个码吧,让你放松一下。