Interfacing sensirion SHT31 with PIC18F2420

(instructions, reset, WDT, specifications...) PIC17Cxx, PIC18Fxxx

Interfacing sensirion SHT31 with PIC18F2420

Postby zfeng » Mon Oct 09, 2017 7:56 pm

Hey folks,

Has anyone successfully interfaced this temp/humidity sensor with a PIC18F? I've been using Sensirion's sample code provided.

I'm using Adafruit's SHT31 breakout board which already has the 10k pull up/down resistors. I think I'm getting close to getting readings but I am stuck at the moment and not sure which direction to go. I am getting waveforms on my oscilloscope for SDA/SCL lines (see attached image). I'm trying to output the temperature and humidity readings to my LCD but I'm not getting anything.

I'm using error handlers to see where it's getting stuck. Specifically in the main while loop it stops here:
Code: Select all
 //read status register
error |= SHT3X_ReadStatus(&status.u16);
if(error != NO_ERROR) {
LCDWriteStringXY(0,0,"Read Status Error");
}break;


Are my initializing parameters correct for the i2c and SHT31? Below are the main, i2c and sht3x source files. The project can be downloaded here (are external links allowed? The size was too large to attach here)

One thing I'd like to note is I have two delay functions. One is used for the menu and LCD files and the other is for sht31 and i2c files. I'm not sure if these two things might be causing a problem. I'll try to explore that next. Any help would be appreciated.

main.c
Code: Select all
/******************************************************************************/
/* Files to Include */
/******************************************************************************/
#if defined(__XC)
#include <xc.h> /* XC8 General Include File */
#elif defined(HI_TECH_C)
#include <htc.h> /* HiTech General Include File */
#elif defined(__18CXX)
#include <p18cxxx.h> /* C18 General Include File */
#endif
#if defined(__XC) || defined(HI_TECH_C)
#include <stdint.h> /* For uint8_t definition */
#include <stdbool.h> /* For true/false definition */
#endif
#include "system.h" /* System funct/params, like osc/peripheral config */
#include "user.h" /* User funct/params, such as InitApp */
#include "lcd.h"
#include "config.h"
#include "port.h"
#include "damper.h"
#include "sht3x.h"
/******************************************************************************/
/* User Global Variable Declaration */
/******************************************************************************/
/* i.e. uint8_t <variable_name>; */
#define MSB(x) (((x)>>8)&0xFF)
#define LSB(x) ((x)&0xFF)
unsigned int sensor;
unsigned int CAL = 128;
float PressureVal;
int startup = TRUE;
int LCDWait;
int MEM;
/******************************************************************************/
/* Main Program */
/******************************************************************************/
// Delay Routine
void delay(unsigned int delay)
{
for(;delay;delay--)
__delay_us(100);
}
void mainScreen(void)
{
LCDWriteStringXY(0,0,"Temp: ");
LCDWriteStringXY(0,1,"RH% : ");
}
void main()
{
etError error; // error code
u32t serialNumber;// serial number
regStatus status; // sensor status
ft temperature; // temperature [°C]
ft humidity; // relative humidity [%RH]
bt heater; // heater, false: off, true: on
if(startup == TRUE)
{
ConfigureOscillator();
InitApp();
LCDBoot(); // call boot function for initializing LCD and startup screen
MemReadConfig();
KeyPadInit();
Counter();
GIE = 0;
LCDWait = TRUE;
GIE = 1;
GIEL = 1;
TMR0ON = 0;
startup = FALSE;
SHT3X_Init(0x44); // initialize SHT31 sensor on default 0x44 address
// wait 50ms after power on
DelayMicroSeconds(50000);
error = SHT3x_ReadSerialNumber(&serialNumber);
if(error == NO_ERROR){} // do error handling here
// demonstrate a single shot measurement with clock-stretching
error = SHT3X_GetTempAndHumi(&temperature, &humidity, REPEATAB_HIGH, MODE_CLKSTRETCH, 50);
if(error != NO_ERROR){} // do error handling here
// demonstrate a single shot measurement with polling and 50ms timeout
error = SHT3X_GetTempAndHumi(&temperature, &humidity, REPEATAB_HIGH, MODE_POLLING, 50);
if(error != NO_ERROR){} // do error handling here
}
while(1)
{
error = NO_ERROR;
// loop while no error
while(error == NO_ERROR)
{
if(LCDWait == TRUE)
{
write();

//read status register
error |= SHT3X_ReadStatus(&status.u16);
if(error != NO_ERROR) {
LCDWriteStringXY(0,0,"Read Status Error");
}break;

//check if the reset bit is set after a reset or power-up
// if(status.bits.ResetDetected)
// {
// // override default temperature and humidity alert limits
// error = SHT3X_SetAlertLimits( 70.0f, 50.0f, // high set: RH [%], T [°C]
// 68.0f, 48.0f, // high clear: RH [%], T [°C]
// 32.0f, -2.0f, // low clear: RH [%], T [°C]
// 30.0f, -4.0f); // low set: RH [%], T [°C]
// if(error != NO_ERROR) break;
//
// // clear reset and alert flags
// error = SHT3X_ClearAllAlertFlags();
// if(error != NO_ERROR) break;
//
// //start periodic measurement, with high repeatability and 1 measurements per second
// error = SHT3X_StartPeriodicMeasurment(REPEATAB_HIGH, FREQUENCY_1HZ);
// if(error != NO_ERROR) break;
//
// }

// read measurement buffer
error = SHT3X_ReadMeasurementBuffer(&temperature, &humidity);
if(error == ACK_ERROR)
{
error = NO_ERROR;
}
// else break;

if(LCDWait == TRUE) //If the LCD Menu is active then
{
mainScreen();
LCDWriteIntXY(6,0,temperature,2);
LCDWriteIntXY(6,1,humidity,2);
LCDTImer1();
}
}
// else {
// Modulate();
// }
}

// if(error != NO_ERROR)
// {
// LCDWriteStringXY(0,0,"Soft Resetting...");
// DelayMicroSeconds(1000);
// SHT3X_SoftReset();
// }
}
}



i2c initialization

Code: Select all
/*
* File: i2c_hal.c
* Author: Johan.Andrade
*
* Created on September 22, 2017, 10:46 AM
* Brief : I2C hardware abstraction layer
============================================================================
*/
/******************************************************************************/
/* Files to Include */
/******************************************************************************/
#if defined(__XC)
#include <xc.h> /* XC8 General Include File */
#elif defined(HI_TECH_C)
#include <htc.h> /* HiTech General Include File */
#elif defined(__18CXX)
#include <p18cxxx.h> /* C18 General Include File */
#endif
#include "i2c_hal.h"
//-- Defines ------------------------------------------------------------------
#define MCUCLK 4000000 // 4MHz ( same as OSCCON)
#define I2C_SPEED 100000 // 100kHz
#define I2C_SSPADD ( ( MCUCLK / ( 4 * I2C_SPEED ) ) - 1 )
#if I2C_SSPADD > 255
#error "I2C_SPPED can not be greater that 255 ! Please adjust MCUCLK and I2C_SPEED"
#endif
// I2C IO-Pins /* -- adapt the defines for your uC -- */
// SDA on port B, bit 14
//#define SDA_LOW() (GPIOB->BSRR = 0x40000000) // set SDA to low
//#define SDA_OPEN() (GPIOB->BSRR = 0x00004000) // set SDA to open-drain
//#define SDA_READ (GPIOB->IDR & 0x4000) // read SDA
// PIC18F2420 SDA on PORTC RC4
#define SDA TRISCbits.TRISC4
#define SDA_IN PORTCbits.RC4
// SCL on port B, bit 13 /* -- adapt the defines for your uC -- */
//#define SCL_LOW() (GPIOB->BSRR = 0x20000000) // set SCL to low
//#define SCL_OPEN() (GPIOB->BSRR = 0x00002000) // set SCL to open-drain
//#define SCL_READ (GPIOB->IDR & 0x2000) // read SCL
// PIC18F2420 SCL on PORTC RC3
#define SCL TRISCbits.TRISC3
#define SCL_IN PORTCbits.RC3
//-- Static function prototypes -----------------------------------------------
static etError I2c_WaitWhileClockStreching(u8t timeout);
//-----------------------------------------------------------------------------
void I2c_Init(void) /* -- adapt the init for your uC -- */
{
//SSPCON1 = 0;
PIE1bits.SSPIE = 0; // Disable interrupt from I2C module
TRISC = 0b00011000; // Make SCL (RC3) SDA (RC4) to be inputs
SSPSTATbits.SMP = 1; // enable 100KHz & 1MHz
SSPSTATbits.CKE = 0; // I2C specification
SSPCON2bits.GCEN = 0; // disable interrupt when detect general call address on the i2c bus.
SSPADD = I2C_SSPADD;
SSPCON1 = 0x28; // Master mode, SSPEN enabled, I2C_Clock = ( Fosc / ( 4 * SSPADD ) ) - 1;
PIR1bits.SSPIF = 0;
}
//-----------------------------------------------------------------------------
void I2c_StartCondition(void)
{
// SDA_OPEN();
SDA = 1;
DelayMicroSeconds(1);
// SCL_OPEN();
SCL = 1;
DelayMicroSeconds(1);
// SDA_LOW();
SDA = 0;
DelayMicroSeconds(10); // hold time start condition (t_HD;STA)
// SCL_LOW();
SCL = 0;
DelayMicroSeconds(10);
}
//-----------------------------------------------------------------------------
void I2c_StopCondition(void)
{
// SCL_LOW();
SCL = 0;
DelayMicroSeconds(1);
// SDA_LOW();
SDA = 0;
DelayMicroSeconds(1);
// SCL_OPEN();
SCL = 1;
DelayMicroSeconds(10); // set-up time stop condition (t_SU;STO)
// SDA_OPEN();
SDA = 1;
DelayMicroSeconds(10);
}
//-----------------------------------------------------------------------------
etError I2c_WriteByte(u8t txByte)
{
etError error = NO_ERROR;
u8t mask;
for(mask = 0x80; mask > 0; mask >>= 1) // shift bit for masking (8 times)
{
if((mask & txByte) == 0)
// SDA_LOW(); // masking txByte, write bit to SDA-Line
SDA = 0;
else
// SDA_OPEN();
SDA = 1;
DelayMicroSeconds(1); // data set-up time (t_SU;DAT)
//SCL_OPEN(); // generate clock pulse on SCL
SCL = 1;
DelayMicroSeconds(5); // SCL high time (t_HIGH)
//SCL_LOW();
SCL = 0;
DelayMicroSeconds(1); // data hold time(t_HD;DAT)
}
//SDA_OPEN(); // release SDA-line
SDA = 1;
//SCL_OPEN(); // clk #9 for ack
SCL = 1;
DelayMicroSeconds(1); // data set-up time (t_SU;DAT)
//if(SDA_READ)
if(SDA_IN)
error = ACK_ERROR; // check ack from i2c slave

//SCL_LOW();
SCL = 0;
DelayMicroSeconds(20); // wait to see byte package on scope
return error; // return error code
}
//-----------------------------------------------------------------------------
etError I2c_ReadByte(u8t *rxByte, etI2cAck ack, u8t timeout)
{
etError error = NO_ERROR;
u8t mask;
*rxByte = 0x00;
//SDA_OPEN(); // release SDA-line
SDA = 1;
for(mask = 0x80; mask > 0; mask >>= 1) // shift bit for masking (8 times)
{
//SCL_OPEN(); // start clock on SCL-line
SCL = 1;
DelayMicroSeconds(1); // clock set-up time (t_SU;CLK)
error = I2c_WaitWhileClockStreching(timeout);// wait while clock stretching
DelayMicroSeconds(3); // SCL high time (t_HIGH)

//if(SDA_READ)
if(SDA_IN)
*rxByte |= mask; // read bit

//SCL_LOW();
SCL = 0;
DelayMicroSeconds(1); // data hold time(t_HD;DAT)
}

if(ack == ACK)
//SDA_LOW(); // send acknowledge if necessary
SDA = 0;
else
//SDA_OPEN();
SDA = 1;

DelayMicroSeconds(1); // data set-up time (t_SU;DAT)
//SCL_OPEN(); // clk #9 for ack
SCL = 1;
DelayMicroSeconds(5); // SCL high time (t_HIGH)
//SCL_LOW();
SCL = 0;
//SDA_OPEN(); // release SDA-line
SDA = 1;
DelayMicroSeconds(20); // wait to see byte package on scope
return error; // return with no error
}
//-----------------------------------------------------------------------------
etError I2c_GeneralCallReset(void)
{
etError error;
I2c_StartCondition();
error = I2c_WriteByte(0x00);

if(error == NO_ERROR)
error = I2c_WriteByte(0x06);

return error;
}
//-----------------------------------------------------------------------------
static etError I2c_WaitWhileClockStreching(u8t timeout)
{
etError error = NO_ERROR;
//while(SCL_READ == 0)
while(SCL_IN == 0)
{
if(timeout-- == 0)
return TIMEOUT_ERROR;
DelayMicroSeconds(1000);
}
return error;
}


SHT31 source code
Code: Select all
/*
* File: sht3x.c
* Author: Johan.Andrade
*
* Created on September 22, 2017, 10:46 AM
* Brief : I2C hardware abstraction layer
============================================================================
*/
/******************************************************************************/
/* Files to Include */
/******************************************************************************/
#if defined(__XC)
#include <xc.h> /* XC8 General Include File */
#elif defined(HI_TECH_C)
#include <htc.h> /* HiTech General Include File */
#elif defined(__18CXX)
#include <p18cxxx.h> /* C18 General Include File */
#endif
#include "sht3x.h"
#include "i2c_hal.h"
//-- Defines ------------------------------------------------------------------
// Generator polynomial for CRC
#define POLYNOMIAL 0x131 // P(x) = x^8 + x^5 + x^4 + 1 = 100110001
//=============================================================================
// IO-Pins /* -- adapt the defines for your uC -- */
//-----------------------------------------------------------------------------
// Reset on port B, bit 12
//#define RESET_LOW() (GPIOB->BSRR = 0x10000000) // set Reset to low
//#define RESET_HIGH() (GPIOB->BSRR = 0x00001000) // set Reset to high
// Alert on port B, bit 10
//#define ALERT_READ (GPIOB->IDR & 0x0400) // read Alert
//=============================================================================
//-- Global variables ---------------------------------------------------------
static u8t _i2cAddress; // I2C Address
//-- Static function prototypes -----------------------------------------------
static etError SHT3X_WriteAlertLimitData(ft humidity, ft temperature);
static etError SHT3X_ReadAlertLimitData(ft* humidity, ft* temperature);
static etError SHT3X_StartWriteAccess(void);
static etError SHT3X_StartReadAccess(void);
static void SHT3X_StopAccess(void);
static etError SHT3X_WriteCommand(etCommands command);
static etError SHT3X_Read2BytesAndCrc(u16t* data, etI2cAck finaleAckNack,
u8t timeout);
static etError SHT3X_Write2BytesAndCrc(u16t data);
static u8t SHT3X_CalcCrc(u8t data[], u8t nbrOfBytes);
static etError SHT3X_CheckCrc(u8t data[], u8t nbrOfBytes, u8t checksum);
static ft SHT3X_CalcTemperature(u16t rawValue);
static ft SHT3X_CalcHumidity(u16t rawValue);
static u16t SHT3X_CalcRawTemperature(ft temperature);
static u16t SHT3X_CalcRawHumidity(ft humidity);
//-----------------------------------------------------------------------------
void SHT3X_Init(u8t i2cAddress) /* -- adapt the init for your uC -- */
{
// init I/O-pins
// RCC->APB2ENR |= 0x00000008; // I/O port B clock enabled
//
// // Alert on port B, bit 10
// GPIOB->CRH &= 0xFFFFF0FF; // set floating input for Alert-Pin
// GPIOB->CRH |= 0x00000400; //
//
// // Reset on port B, bit 12
// GPIOB->CRH &= 0xFFF0FFFF; // set push-pull output for Reset pin
// GPIOB->CRH |= 0x00010000; //
// RESET_LOW();
//
I2c_Init(); // init I2C
SHT3X_SetI2cAdr(i2cAddress);
//
// // release reset
// RESET_HIGH();
}
//-----------------------------------------------------------------------------
void SHT3X_SetI2cAdr(u8t i2cAddress)
{
_i2cAddress = i2cAddress;
}
//-----------------------------------------------------------------------------
etError SHT3x_ReadSerialNumber(u32t* serialNumber)
{
etError error; // error code
u16t serialNumWords[2];

error = SHT3X_StartWriteAccess();

// write "read serial number" command
error |= SHT3X_WriteCommand(CMD_READ_SERIALNBR);
// if no error, start read access
if(error == NO_ERROR) error = SHT3X_StartReadAccess();
// if no error, read first serial number word
if(error == NO_ERROR) error = SHT3X_Read2BytesAndCrc(&serialNumWords[0], ACK, 100);
// if no error, read second serial number word
if(error == NO_ERROR) error = SHT3X_Read2BytesAndCrc(&serialNumWords[1], NACK, 0);

SHT3X_StopAccess();

// if no error, calc serial number as 32-bit integer
if(error == NO_ERROR)
{
*serialNumber = (serialNumWords[0] << 16) | serialNumWords[1];
}

return error;
}
//-----------------------------------------------------------------------------
etError SHT3X_ReadStatus(u16t* status)
{
etError error; // error code

error = SHT3X_StartWriteAccess();

// if no error, write "read status" command
if(error == NO_ERROR) error = SHT3X_WriteCommand(CMD_READ_STATUS);
// if no error, start read access
if(error == NO_ERROR) error = SHT3X_StartReadAccess();
// if no error, read status
if(error == NO_ERROR) error = SHT3X_Read2BytesAndCrc(status, NACK, 0);

SHT3X_StopAccess();

return error;
}
//-----------------------------------------------------------------------------
etError SHT3X_ClearAllAlertFlags(void)
{
etError error; // error code

error = SHT3X_StartWriteAccess();

// if no error, write clear status register command
if(error == NO_ERROR) error = SHT3X_WriteCommand(CMD_CLEAR_STATUS);

SHT3X_StopAccess();

return error;
}
//-----------------------------------------------------------------------------
etError SHT3X_GetTempAndHumi(ft* temperature, ft* humidity,
etRepeatability repeatability, etMode mode,
u8t timeout)
{
etError error;
switch(mode)
{
case MODE_CLKSTRETCH: // get temperature with clock stretching mode
error = SHT3X_GetTempAndHumiClkStretch(temperature, humidity,
repeatability, timeout);
break;
case MODE_POLLING: // get temperature with polling mode
error = SHT3X_GetTempAndHumiPolling(temperature, humidity,
repeatability, timeout);
break;
default:
error = PARM_ERROR;
break;
}

return error;
}
//-----------------------------------------------------------------------------
etError SHT3X_GetTempAndHumiClkStretch(ft* temperature, ft* humidity,
etRepeatability repeatability,
u8t timeout)
{
etError error; // error code
u16t rawValueTemp; // temperature raw value from sensor
u16t rawValueHumi; // humidity raw value from sensor

error = SHT3X_StartWriteAccess();

// if no error ...
if(error == NO_ERROR)
{
// start measurement in clock stretching mode
// use depending on the required repeatability, the corresponding command
switch(repeatability)
{
case REPEATAB_LOW:
error = SHT3X_WriteCommand(CMD_MEAS_CLOCKSTR_L);
break;
case REPEATAB_MEDIUM:
error = SHT3X_WriteCommand(CMD_MEAS_CLOCKSTR_M);
break;
case REPEATAB_HIGH:
error = SHT3X_WriteCommand(CMD_MEAS_CLOCKSTR_H);
break;
default:
error = PARM_ERROR;
break;
}
}
// if no error, start read access
if(error == NO_ERROR) error = SHT3X_StartReadAccess();
// if no error, read temperature raw values
if(error == NO_ERROR) error = SHT3X_Read2BytesAndCrc(&rawValueTemp, ACK, timeout);
// if no error, read humidity raw values
if(error == NO_ERROR) error = SHT3X_Read2BytesAndCrc(&rawValueHumi, NACK, 0);

SHT3X_StopAccess();

// if no error, calculate temperature in °C and humidity in %RH
if(error == NO_ERROR)
{
*temperature = SHT3X_CalcTemperature(rawValueTemp);
*humidity = SHT3X_CalcHumidity(rawValueHumi);
}

return error;
}
//-----------------------------------------------------------------------------
etError SHT3X_GetTempAndHumiPolling(ft* temperature, ft* humidity,
etRepeatability repeatability,
u8t timeout)
{
etError error; // error code
u16t rawValueTemp; // temperature raw value from sensor
u16t rawValueHumi; // humidity raw value from sensor

error = SHT3X_StartWriteAccess();

// if no error ...
if(error == NO_ERROR)
{
// start measurement in polling mode
// use depending on the required repeatability, the corresponding command
switch(repeatability)
{
case REPEATAB_LOW:
error = SHT3X_WriteCommand(CMD_MEAS_POLLING_L);
break;
case REPEATAB_MEDIUM:
error = SHT3X_WriteCommand(CMD_MEAS_POLLING_M);
break;
case REPEATAB_HIGH:
error = SHT3X_WriteCommand(CMD_MEAS_POLLING_H);
break;
default:
error = PARM_ERROR;
break;
}
}

// if no error, wait until measurement ready
if(error == NO_ERROR)
{
// poll every 1ms for measurement ready until timeout
while(timeout--)
{
// check if the measurement has finished
error = SHT3X_StartReadAccess();

// if measurement has finished -> exit loop
if(error == NO_ERROR) break;

// delay 1ms
DelayMicroSeconds(1000);
}

// check for timeout error
if(timeout == 0) error = TIMEOUT_ERROR;
}

// if no error, read temperature and humidity raw values
if(error == NO_ERROR)
{
error |= SHT3X_Read2BytesAndCrc(&rawValueTemp, ACK, 0);
error |= SHT3X_Read2BytesAndCrc(&rawValueHumi, NACK, 0);
}

SHT3X_StopAccess();

// if no error, calculate temperature in °C and humidity in %RH
if(error == NO_ERROR)
{
*temperature = SHT3X_CalcTemperature(rawValueTemp);
*humidity = SHT3X_CalcHumidity(rawValueHumi);
}

return error;
}
//-----------------------------------------------------------------------------
etError SHT3X_StartPeriodicMeasurment(etRepeatability repeatability,
etFrequency frequency)
{
etError error; // error code

error = SHT3X_StartWriteAccess();

// if no error, start periodic measurement
if(error == NO_ERROR)
{
// use depending on the required repeatability and frequency,
// the corresponding command
switch(repeatability)
{
case REPEATAB_LOW: // low repeatability
switch(frequency)
{
case FREQUENCY_HZ5: // low repeatability, 0.5 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_05_L);
break;
case FREQUENCY_1HZ: // low repeatability, 1.0 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_1_L);
break;
case FREQUENCY_2HZ: // low repeatability, 2.0 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_2_L);
break;
case FREQUENCY_4HZ: // low repeatability, 4.0 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_4_L);
break;
case FREQUENCY_10HZ: // low repeatability, 10.0 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_10_L);
break;
default:
error |= PARM_ERROR;
break;
}
break;

case REPEATAB_MEDIUM: // medium repeatability
switch(frequency)
{
case FREQUENCY_HZ5: // medium repeatability, 0.5 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_05_M);
break;
case FREQUENCY_1HZ: // medium repeatability, 1.0 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_1_M);
break;
case FREQUENCY_2HZ: // medium repeatability, 2.0 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_2_M);
break;
case FREQUENCY_4HZ: // medium repeatability, 4.0 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_4_M);
break;
case FREQUENCY_10HZ: // medium repeatability, 10.0 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_10_M);
break;
default:
error |= PARM_ERROR;
break;
}
break;

case REPEATAB_HIGH: // high repeatability
switch(frequency)
{
case FREQUENCY_HZ5: // high repeatability, 0.5 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_05_H);
break;
case FREQUENCY_1HZ: // high repeatability, 1.0 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_1_H);
break;
case FREQUENCY_2HZ: // high repeatability, 2.0 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_2_H);
break;
case FREQUENCY_4HZ: // high repeatability, 4.0 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_4_H);
break;
case FREQUENCY_10HZ: // high repeatability, 10.0 Hz
error |= SHT3X_WriteCommand(CMD_MEAS_PERI_10_H);
break;
default:
error |= PARM_ERROR;
break;
}
break;
default:
error |= PARM_ERROR;
break;
}
}
SHT3X_StopAccess();
return error;
}
//-----------------------------------------------------------------------------
etError SHT3X_ReadMeasurementBuffer(ft* temperature, ft* humidity)
{
etError error; // error code
u16t rawValueTemp; // temperature raw value from sensor
u16t rawValueHumi; // humidity raw value from sensor
error = SHT3X_StartWriteAccess();
// if no error, read measurements
if(error == NO_ERROR) error = SHT3X_WriteCommand(CMD_FETCH_DATA);
if(error == NO_ERROR) error = SHT3X_StartReadAccess();
if(error == NO_ERROR) error = SHT3X_Read2BytesAndCrc(&rawValueTemp, ACK, 0);
if(error == NO_ERROR) error = SHT3X_Read2BytesAndCrc(&rawValueHumi, NACK, 0);
// if no error, calculate temperature in °C and humidity in %RH
if(error == NO_ERROR)
{
*temperature = SHT3X_CalcTemperature(rawValueTemp);
*humidity = SHT3X_CalcHumidity(rawValueHumi);
}
SHT3X_StopAccess();
return error;
}
//-----------------------------------------------------------------------------
etError SHT3X_EnableHeater(void)
{
etError error; // error code
error = SHT3X_StartWriteAccess();
// if no error, write heater enable command
if(error == NO_ERROR) error = SHT3X_WriteCommand(CMD_HEATER_ENABLE);
SHT3X_StopAccess();
return error;
}
//-----------------------------------------------------------------------------
etError SHT3X_DisableHeater(void)
{
etError error; // error code
error = SHT3X_StartWriteAccess();
// if no error, write heater disable command
if(error == NO_ERROR) error = SHT3X_WriteCommand(CMD_HEATER_DISABLE);
SHT3X_StopAccess();
return error;
}
//-----------------------------------------------------------------------------
etError SHT3X_SetAlertLimits(ft humidityHighSet, ft temperatureHighSet,
ft humidityHighClear, ft temperatureHighClear,
ft humidityLowClear, ft temperatureLowClear,
ft humidityLowSet, ft temperatureLowSet)
{
etError error; // error code
// write humidity & temperature alter limits, high set
error = SHT3X_StartWriteAccess();
if(error == NO_ERROR) error = SHT3X_WriteCommand(CMD_W_AL_LIM_HS);
if(error == NO_ERROR) error = SHT3X_WriteAlertLimitData(humidityHighSet,
temperatureHighSet);
SHT3X_StopAccess();
if(error == NO_ERROR)
{
// write humidity & temperature alter limits, high clear
error = SHT3X_StartWriteAccess();
if(error == NO_ERROR) error = SHT3X_WriteCommand(CMD_W_AL_LIM_HC);
if(error == NO_ERROR) error = SHT3X_WriteAlertLimitData(humidityHighClear,
temperatureHighClear);
SHT3X_StopAccess();
}
if(error == NO_ERROR)
{
// write humidity & temperature alter limits, low clear
error = SHT3X_StartWriteAccess();
if(error == NO_ERROR) error = SHT3X_WriteCommand(CMD_W_AL_LIM_LC);
if(error == NO_ERROR) error = SHT3X_WriteAlertLimitData(humidityLowClear,
temperatureLowClear);
SHT3X_StopAccess();
}

if(error == NO_ERROR)
{
// write humidity & temperature alter limits, low set
error = SHT3X_StartWriteAccess();
if(error == NO_ERROR) error = SHT3X_WriteCommand(CMD_W_AL_LIM_LS);
if(error == NO_ERROR) error = SHT3X_WriteAlertLimitData(humidityLowSet,
temperatureLowSet);
SHT3X_StopAccess();
}
return error;
}
//-----------------------------------------------------------------------------
etError SHT3X_GetAlertLimits(ft* humidityHighSet, ft* temperatureHighSet,
ft* humidityHighClear, ft* temperatureHighClear,
ft* humidityLowClear, ft* temperatureLowClear,
ft* humidityLowSet, ft* temperatureLowSet)
{
etError error; // error code

// read humidity & temperature alter limits, high set
error = SHT3X_StartWriteAccess();
if(error == NO_ERROR) error = SHT3X_WriteCommand(CMD_R_AL_LIM_HS);
if(error == NO_ERROR) error = SHT3X_StartReadAccess();
if(error == NO_ERROR) error = SHT3X_ReadAlertLimitData(humidityHighSet,
temperatureHighSet);
SHT3X_StopAccess();
if(error == NO_ERROR)
{
// read humidity & temperature alter limits, high clear
error = SHT3X_StartWriteAccess();
if(error == NO_ERROR) error = SHT3X_WriteCommand(CMD_R_AL_LIM_HC);
if(error == NO_ERROR) error = SHT3X_StartReadAccess();
if(error == NO_ERROR) error = SHT3X_ReadAlertLimitData(humidityHighClear,
temperatureHighClear);
SHT3X_StopAccess();
}
if(error == NO_ERROR)
{
// read humidity & temperature alter limits, low clear
error = SHT3X_StartWriteAccess();
if(error == NO_ERROR) error = SHT3X_WriteCommand(CMD_R_AL_LIM_LC);
if(error == NO_ERROR) error = SHT3X_StartReadAccess();
if(error == NO_ERROR) error = SHT3X_ReadAlertLimitData(humidityLowClear,
temperatureLowClear);
SHT3X_StopAccess();
}
if(error == NO_ERROR)
{
// read humidity & temperature alter limits, low set
error = SHT3X_StartWriteAccess();
if(error == NO_ERROR) error = SHT3X_WriteCommand(CMD_R_AL_LIM_LS);
if(error == NO_ERROR) error = SHT3X_StartReadAccess();
if(error == NO_ERROR) error = SHT3X_ReadAlertLimitData(humidityLowSet,
temperatureLowSet);
SHT3X_StopAccess();
}

return error;
}
//-----------------------------------------------------------------------------
bt SHT3X_ReadAlert(void)
{
// read alert pin
// return (ALERT_READ != 0) ? TRUE : FALSE;
}
//-----------------------------------------------------------------------------
etError SHT3X_SoftReset(void)
{
etError error; // error code
error = SHT3X_StartWriteAccess();
// write reset command
error |= SHT3X_WriteCommand(CMD_SOFT_RESET);
SHT3X_StopAccess();

// if no error, wait 50 ms after reset
if(error == NO_ERROR) DelayMicroSeconds(50000);
return error;
}
//-----------------------------------------------------------------------------
void SHT3X_HardReset(void)
{
// set reset low
// RESET_LOW();
// wait 100 ms
DelayMicroSeconds(100000);

// release reset
// RESET_HIGH();

// wait 50 ms after reset
DelayMicroSeconds(50000);
}
//-----------------------------------------------------------------------------
static etError SHT3X_WriteAlertLimitData(ft humidity, ft temperature)
{
etError error; // error code

i16t rawHumidity;
i16t rawTemperature;

if((humidity < 0.0f) || (humidity > 100.0f)
|| (temperature < -45.0f) || (temperature > 130.0f))
{
error = PARM_ERROR;
}
else
{
rawHumidity = SHT3X_CalcRawHumidity(humidity);
rawTemperature = SHT3X_CalcRawTemperature(temperature);
error = SHT3X_Write2BytesAndCrc((rawHumidity & 0xFE00) | ((rawTemperature >> 7) & 0x001FF));
}

return error;
}
//-----------------------------------------------------------------------------
static etError SHT3X_ReadAlertLimitData(ft* humidity, ft* temperature)
{
etError error; // error code
u16t data;

error = SHT3X_Read2BytesAndCrc(&data, NACK, 0);

if(error == NO_ERROR)
{
*humidity = SHT3X_CalcHumidity(data & 0xFE00);
*temperature = SHT3X_CalcTemperature(data << 7);
}

return error;
}
//-----------------------------------------------------------------------------
static etError SHT3X_StartWriteAccess(void)
{
etError error; // error code
// write a start condition
I2c_StartCondition();
// write the sensor I2C address with the write flag
error = I2c_WriteByte(_i2cAddress << 1);
return error;
}
//-----------------------------------------------------------------------------
static etError SHT3X_StartReadAccess(void)
{
etError error; // error code
// write a start condition
I2c_StartCondition();
// write the sensor I2C address with the read flag
error = I2c_WriteByte(_i2cAddress << 1 | 0x01);
return error;
}
//-----------------------------------------------------------------------------
static void SHT3X_StopAccess(void)
{
// write a stop condition
I2c_StopCondition();
}
//-----------------------------------------------------------------------------
static etError SHT3X_WriteCommand(etCommands command)
{
etError error; // error code
// write the upper 8 bits of the command to the sensor
error = I2c_WriteByte(command >> 8);
// write the lower 8 bits of the command to the sensor
error |= I2c_WriteByte(command & 0xFF);
return error;
}
//-----------------------------------------------------------------------------
static etError SHT3X_Read2BytesAndCrc(u16t* data, etI2cAck finaleAckNack,
u8t timeout)
{
etError error; // error code
u8t bytes[2]; // read data array
u8t checksum; // checksum byte
// read two data bytes and one checksum byte
error = I2c_ReadByte(&bytes[0], ACK, timeout);
if(error == NO_ERROR) error = I2c_ReadByte(&bytes[1], ACK, 0);
if(error == NO_ERROR) error = I2c_ReadByte(&checksum, finaleAckNack, 0);
// verify checksum
if(error == NO_ERROR) error = SHT3X_CheckCrc(bytes, 2, checksum);
// combine the two bytes to a 16-bit value
*data = (bytes[0] << 8) | bytes[1];
return error;
}
//-----------------------------------------------------------------------------
static etError SHT3X_Write2BytesAndCrc(u16t data)
{
etError error; // error code
u8t bytes[2]; // read data array
u8t checksum; // checksum byte
bytes[0] = data >> 8;
bytes[1] = data & 0xFF;
checksum = SHT3X_CalcCrc(bytes, 2);
// write two data bytes and one checksum byte
error = I2c_WriteByte(bytes[0]); // write data MSB
if(error == NO_ERROR) error = I2c_WriteByte(bytes[1]); // write data LSB
if(error == NO_ERROR) error = I2c_WriteByte(checksum); // write checksum
return error;
}
//-----------------------------------------------------------------------------
static u8t SHT3X_CalcCrc(u8t data[], u8t nbrOfBytes)
{
u8t bits; // bit mask
u8t crc = 0xFF; // calculated checksum
u8t byteCtr; // byte counter
// calculates 8-Bit checksum with given polynomial
for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++)
{
crc ^= (data[byteCtr]);
for(bits = 8; bits > 0; --bits)
{
if(crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;
else crc = (crc << 1);
}
}
return crc;
}
//-----------------------------------------------------------------------------
static etError SHT3X_CheckCrc(u8t data[], u8t nbrOfBytes, u8t checksum)
{
u8t crc; // calculated checksum

// calculates 8-Bit checksum
crc = SHT3X_CalcCrc(data, nbrOfBytes);

// verify checksum
if(crc != checksum) return CHECKSUM_ERROR;
else return NO_ERROR;
}
//-----------------------------------------------------------------------------
static ft SHT3X_CalcTemperature(u16t rawValue)
{
// calculate temperature [°C]
// T = -45 + 175 * rawValue / (2^16-1)
return 175.0f * (ft)rawValue / 65535.0f - 45.0f;
}
//-----------------------------------------------------------------------------
static ft SHT3X_CalcHumidity(u16t rawValue)
{
// calculate relative humidity [%RH]
// RH = rawValue / (2^16-1) * 100
return 100.0f * (ft)rawValue / 65535.0f;
}
//-----------------------------------------------------------------------------
static u16t SHT3X_CalcRawTemperature(ft temperature)
{
// calculate raw temperature [ticks]
// rawT = (temperature + 45) / 175 * (2^16-1)
return (temperature + 45.0f) / 175.0f * 65535.0f;
}
//-----------------------------------------------------------------------------
static u16t SHT3X_CalcRawHumidity(ft humidity)
{
// calculate raw relative humidity [ticks]
// rawRH = humidity / 100 * (2^16-1)
return humidity / 100.0f * 65535.0f;
}
Attachments
I2C.jpg
I2C.jpg (222.58 KiB) Viewed 3825 times
zfeng
 
Posts: 1
Joined: Mon Oct 09, 2017 7:35 pm
PIC experience: Professional 1+ years with MCHP products

Return to 16-Bit Core

Who is online

Users browsing this forum: No registered users and 8 guests

cron