// File: lm75a.cpp // Continously read the temperature from a lm75a and display it. // Author: Jim Merkle, 03/30/2017 #include #include #include #include #include #include #include #include #include #include #include #include #include // nanosleep #define PROG_NAME "lm75a" // I2C Address #define LM75A 0x48 #ifndef u8 typedef unsigned char u8; #endif #ifndef u16 typedef unsigned short u16; #endif // LM75A Registers #define LM75A_REG_TEMP 0 #define LM75A_REG_CONF 1 #define LM75A_REG_THYST 2 #define LM75A_REG_TOS 3 #define LM75A_REG_PROD_ID 7 /* only applicable for TI manufactured part */ // Power On Defaults: // 0: Read only temperature - 2 bytes // 1: 0x00 Configuration // 2: 0x4B THYST - 75 degrees C - 2 bytes // 3: 0x50 TOS - 80 degrees C - 2 bytes // 7: 0xA1 (TI only) void msleep(int milliseconds) { //usleep(milliseconds * 1000); // limited method struct timespec ts; ts.tv_sec = milliseconds / 1000; ts.tv_nsec = (milliseconds % 1000) * 1000000; nanosleep(&ts, NULL); } void printbinary16(u16 number) { u16 mask = 0x8000; // most significant bit set while (mask) { printf("%c",mask & number?'1':'0'); mask >>= 1; } } // Return number of i2c_msg's transferred, else negative value for error int i2cWriteRead(int fd, int i2cAddress, u8 * pWriteData, int writeBytes, u8 * pReadData, int readBytes) { struct i2c_msg msg[2]; // declare a two i2c_msg array struct i2c_rdwr_ioctl_data i2c_data; // declare our i2c_rdwr_ioctl_data structure int msgsUsed=0; // how many i2c_msg structures are used int result; // return value from ioctl() call // Assume the first i2c_msg is used for writing if(pWriteData && writeBytes) { msg[0].addr = i2cAddress; msg[0].flags = 0; msg[0].buf = pWriteData; msg[0].len = writeBytes; msgsUsed++; // Load the second i2c_msg for receiving if the first one is used if(pReadData && readBytes) { // Load up receive msg msg[1].addr = i2cAddress; msg[1].flags = I2C_M_RD; msg[1].buf = pReadData; msg[1].len = readBytes; msgsUsed++; } } else if(pReadData && readBytes) { // Load the first i2c_msg for receiving (no transmit data) msg[0].addr = i2cAddress; msg[0].flags = I2C_M_RD; msg[0].buf = pReadData; msg[0].len = readBytes; msgsUsed++; } // Continue if we have data to transfer if(msgsUsed) { // i2c_msg array is loaded up. Now load i2c_rdwr_ioctl_data structure. i2c_data.msgs = msg; i2c_data.nmsgs = msgsUsed; // With our open file descriptor, perform I2C message transfers // This function call returns the number of i2c_msg structures processed, // or a negative error value result = ioctl(fd,I2C_RDWR,&i2c_data); if(result < 0) { printf("ioctl error: %s\n", strerror(errno)); return -2; } } else { printf("i2cWriteRead: No i2c_msg's processed\n"); } return result; // return number of i2c_msg structures processed } int main(int argc, char * argv[]) { //printf("Content-type: text/html\n\n"); // Open the i2c bus device where the chip resides int file = open("/dev/i2c-1",O_RDWR); if(file<0) { printf("Failed to open the bus."); /* ERROR HANDLING; you can check errno to see what went wrong */ exit(1); } // By default, the LM75A configuration register is 0x00 // Program the device to alert us when the temperature exceeds a threshold // If it gets to 30C (86F), signal using the OS pin (pull low) u8 tos[3] = {LM75A_REG_TOS,30,0}; i2cWriteRead(file, LM75A, tos, sizeof(tos), NULL, 0); // Reset the OS pin (allow to go back high when temp goes down u8 thyst[3] = {LM75A_REG_THYST,29,0}; i2cWriteRead(file, LM75A, thyst, sizeof(thyst), NULL, 0); while (1) { u8 index = LM75A_REG_TEMP; // Read temperature register u8 temperatureRegs[2]; // The MSB (first byte) is degree C units, the LSB is fractional component i2cWriteRead(file, LM75A, &index, 1, temperatureRegs, 2); // The following printf() is only accurate for positive temperatures.. //printf("MSB: %d & %d/8ths C\n",temperatureRegs[0],temperatureRegs[1] >> 5); // shift fractional bits into position // This should be accurate for both positive and negative temperatures: u16 uTemp = (u16)temperatureRegs[0] << 8 | (u16)temperatureRegs[1]; // high byte followed by low byte float fTemp = (short)uTemp; fTemp /= 256; // The float will keep the remainder // Convert into Fahrenheit float fTempf = fTemp*9/5 + 32; //printf("\033cTemp %0.1fF\n",fTempf); printbinary16(uTemp); printf(" 0x%04X %0.3fC ",uTemp,fTemp); printf("%0.1fF\n",fTempf); sleep(1); } // clean up close(file); return 0; }