手上有TMP102和TMP112,发现正常温度变化缓慢时,读取应答都正常,但是当某段时间温度变化剧烈(比如拿热吹风吹热风时)去读取内部温度寄存器时发送器件地址(0x48)会没有响应,稳定一会儿后又好了,换了很多片都是这个现象。单片机使用的msp430fr2433,有用其它单片机(AVR)试一下没有这个现象,SDA\SCL引脚都是通过10K电阻上拉的,频率大概100K
/* --COPYRIGHT--,BSD * Copyright (c) 2017, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --/COPYRIGHT--*/ #include <msp430.h> #include <stdint.h> #include <string.h> #include <i2c.h> #define TIMEOUT 60000 void i2c_init(void){ static char init=0; if(!init){ P1REN |= BIT2 | BIT3; P1OUT |= BIT2 | BIT3; // if the bus is stuck (SDA = low): clock until it recovers P1DIR |= BIT3; while(!(P1IN & BIT2)){ P1OUT |= BIT3; __delay_cycles(8*80); P1OUT &= ~BIT3; __delay_cycles(8*80); } P1SEL0 |= BIT2 | BIT3; // I2C pins // Configure USCI_B0 for I2C mode UCB0CTLW0 |= UCSWRST; // Software reset enabled UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC; // I2C mode, Master mode, sync // after UCB0TBCNT is reached UCB0BRW = 10; // baudrate = SMCLK / 10 = ~100K UCB0CTL1 &= ~UCSWRST; init = 1; } } int i2c_senddata(char *data, int len){ unsigned int timeout=0; unsigned int i; static int dummy=0; /*if(dummy){ UCB0TXBUF = 0; timeout = 0; while(!(UCB0IFG & UCTXIFG0)) if(timeout++ > TIMEOUT) return -1; } if(dummy == 0) dummy = 1; */ //__delay_cycles(5000); for(i=0;i<len;i++){ UCB0TXBUF = data[i]; timeout = 0; while(!(UCB0IFG & UCTXIFG0)) if(timeout++ > TIMEOUT) return 3; } return 0; } int i2c_readdata(char *data, int len){ unsigned int timeout=0; unsigned int i; memset(data, 0, len); for(i=0;i<len;i++){ data[i] = 0; timeout=0; while(!(UCB0IFG & UCRXIFG0)) if(timeout++ > TIMEOUT) return -1; data[i] = UCB0RXBUF; if(len > 1) if(i == len-2) UCB0CTLW0 |= UCTR | UCTXSTP; } //while(!(UCB0IFG & UCTXIFG0)); return 0; } int i2c_start(char addr, int read){ unsigned int timeout=0; UCB0I2CSA = addr; if(read) UCB0CTLW0 &= ~UCTR; else UCB0CTLW0 |= UCTR; while (UCB0CTL1 & UCTXSTP); UCB0CTLW0 |= UCTXSTT; // I2C TX, start condition while(!(UCB0IFG & UCTXIFG0)) if(timeout++ > TIMEOUT) return 1; if(UCB0IFG & UCNACKIFG) { UCB0CTL1 |= UCTXSTP; // I2C start condition UCB0IFG = 0; // Clear All USCI_B0 flags return 2; // check for NACK } if(!read){ UCB0TXBUF = 0; while(!(UCB0IFG & UCTXIFG0)); } return 0; } int i2c_start2(char addr, int read){ unsigned int timeout=0; UCB0I2CSA = addr; if(read) UCB0CTLW0 &= ~UCTR; else UCB0CTLW0 |= UCTR; while (UCB0CTL1 & UCTXSTP); UCB0CTLW0 |= UCTXSTT; // I2C TX, start condition while(!(UCB0IFG & UCTXIFG0)) { if(timeout++ > TIMEOUT) return 5; } if(UCB0IFG & UCNACKIFG) { UCB0CTL1 |= UCTXSTP; // I2C start condition UCB0IFG = 0; // Clear All USCI_B0 flags return 6; // check for NACK } /*if(!read){ UCB0TXBUF = d; while(!(UCB0IFG & UCTXIFG0)); }*/ return 0; } int i2c_stop(void){ unsigned int timeout=0; UCB0CTLW0 |= UCTR | UCTXSTP; // I2C TX, stop condition while(UCB0IFG & UCTXSTP) if(timeout++ > TIMEOUT) return 4; return 0; } int read_reg(int address, int reg){ int err; char buf[2] = {reg}; err = i2c_start2(address, 0); if(err != 0) return err; err = i2c_senddata(buf, 1); if(err != 0) return err; err = i2c_stop(); if(err != 0) return err; __delay_cycles(10000); //等待转换完成 err = i2c_start2(address, 1); if(err != 0) return err; err = i2c_readdata(buf, 2); if(err != 0) return err; return buf[0]<<8|buf[1]; } void write_reg(int address, int reg, int value){ char buf[2] = {reg, value}; i2c_start2(address, 0); i2c_senddata(buf, 2); i2c_stop(); }
void tmp117_init(void){ i2c_init(); } int tmp117_gettemp(void) { unsigned int tmp117_raw = 0; float t = 0; tmp117_raw = read_reg(0x48, 0); tmp117_raw >>= 4; if(tmp117_raw <= 0x7ff){ t= tmp117_raw * 6.25; } if(tmp117_raw>=0xc90) { tmp117_raw = ~tmp117_raw; tmp117_raw &=0x0fff; tmp117_raw +=1; t= tmp117_raw*6.25; t =-t; } return (int)t; }