有没有人成功地将此温度/湿度传感器与PIC18F连接?我一直在使用Sensirion's sample code provided
我使用的是Adafruit的SHT31分线板,它已经有10k上拉/下拉电阻。我想我已经接近获得阅读但我现在陷入困境并且不确定要走向哪个方向。我在示波器上获取SDA / SCL线路的波形。
我试图将温度和湿度读数输出到我的液晶显示屏,但我没有得到任何东西。
我正在使用错误处理程序来查看它被卡住的位置。特别是在主while循环中它停在这里:
//read status register
error |= SHT3X_ReadStatus(&status.u16);
if(error != NO_ERROR) {
LCDWriteStringXY(0,0,"Read Status Error");
}break;
我的初始化参数是否适用于i2c和SHT31?下面是主要的i2c和一部分sht3x源文件。整个项目可以在这里下载:https://ufile.io/fwrhp(允许使用外部链接吗?它太大了,无法在此发布)
我要注意的一件事是我有两个延迟功能。一个用于菜单和LCD文件,另一个用于sht31和i2c文件。我不确定这两件事是否可能导致问题。我将尝试探索下一步。任何帮助将不胜感激。
main.c
/******************************************************************************/
/* 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初始化
/*
* 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;
}
SHT初始化(部分)
/*
* 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;
}