This post was last edited by Hot Ximixiu on 2020-12-2 20:29
This is an application of data transmission via the serial interface of msp430. The serial interface of SHTxx is not compatible with IIC, but its software implementation is similar to IIC.
Device model used: msp430F169/msp430F149, SHT70 @sensirion AG
Typical application circuit:
Code:
#include <msp430x16x.h>
#include "intrinsics.h"
#include <math.h>
typedef unsigned int uint;
typedef unsigned char uchar;
char write_byte(uchar value);
char read_byte(uchar ack);
void transstart(void);
void connectionreset(void);
char softreset(void);
char read_statusreg(uchar *p_value, uchar *p_checksum);
char write_statusreg(uchar *p_value );
char measure(unsigned short int*p_value, uchar *p_checksum, uchar mode);
void calc_sth(unsigned short int t, unsigned short int rh, float *p_temperature, float *p_humidity);
float calc_dewpoint(float h, float t) ;
void sht10_init(void);
void CLK_Init();
float humi_val_real=0.0;
float temp_val_real=0.0;
float dew_point=0.0;
#define noACK 0
#define ACK 1
#define DATA_OUT P5DIR |= BIT3
#define DATA_IN P5DIR &=~BIT3
#define DATA_RIN (P5IN & BIT3)
#define DATA_H P5OUT |= BIT3 //DATA <---> P5.1
#define DATA_L P5OUT &=~ BIT3
#define SCK_H P5OUT |= BIT4 //SCK <---> P5.2
#define SCK_L P5OUT &= ~ BIT4
#define REG_W 0x06 // 0000 0110
#define REG_R 0x07 // 0000 0111
#define TEMP 0x03 // 0000 0011
#define HUMI 0x05 // 0000 0101
#define RESET 0x1e // 0001 1111
#define CPU_F ((double)8000000)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/ 1000.0))
void delay();
char write_byte(uchar value)
//write a byte on the sensibus and checks the ackonwledge
{
uchar i,error = 0;
DATA_OUT;
for(i=0x80;i>0;i/=2)
{
if(i&value)
{DATA_OUT;DATA_H;}
else
{DATA_OUT; DATA_L;}
delay();
SCK_H;
delay ();//5ms
SCK_L;
delay();
}
DATA_IN;
SCK_H;
//delay_ms(800);
error = DATA_RIN;
SCK_L;
return error;
}
char read_byte(uchar ack)
// read a byte from sensibus and gives an ackowledge in case of 'ack =1'
{
uchar i,val=0;
DATA_IN;
for (i=0x80;i>0;i/=2) //shift bit for masking
{
delay();
SCK_H; //clk for SENSI-BUS
delay();
if (DATA_RIN)
val=(val | i); //read bit
SCK_L;
}
DATA_OUT;
if(ack)
DATA_L ;
else
DATA_H;
delay();
SCK_H; //clk #9 for ack
delay(); //pulswith approx. 5 us
SCK_L;
delay();
return val;
}
void transstart(void)
{
DATA_OUT;
DATA_H;SCK_L;
delay();
SCK_H;
delay();
DATA_L;
delay();
SCK_L;
delay();
SCK_H;
delay();
DATA_H;
delay();
SCK_L;
}
void connectionreset(void)
{
uchar i;
DATA_OUT;
DATA_H;
SCK_L;
for(i=0;i<9;i++)
{
SCK_H;
delay();
SCK_L;
delay();
}
transstart();
}
char softreset(void)
{
uchar error = 0;
connectionreset();
error += write_byte(RESET);
return error;
}
char read_statusreg(uchar *p_value, uchar *p_checksum)
//---------------------------------------- ---------------------------------------------
// reads the status register with checksum (8-bit)
{
uchar error=0;
transstart(); //transmission start
error=write_byte(REG_R); //send command to sensor
*p_value=read_byte(ACK); //read status register (8 -bit)
*p_checksum=read_byte(noACK); //read checksum (8-bit)
return error; //error=1 in case of no response form the sensor
}
//------------------------------------------------ ----------------------------------
char write_statusreg(uchar *p_value)
//------ -------------------------------------------------- --------------------------
// writes the status register with checksum (8-bit)
{
uchar error=0;
transstart(); // transmission start
error+=write_byte(REG_W);//send command to sensor
error+=write_byte(*p_value); //send value of status register
return error; //error>=1 in case of no response form the sensor
}
//------------------------------------------------ ----------------------------------
char measure(unsigned short int*p_value, uchar *p_checksum, uchar mode)
//------------------------------------------------ ----------------------------------
// makes a measurement (humidity/temperature) with checksum
{
uchar error= 0;
unsigned short int i;
uchar value_H = 0,value_L = 0;
transstart(); //transmission start
switch(mode){ //send command to sensor
case TEMP:
error+=write_byte(TEMP);
break;
case HUMI:
error+=write_byte(HUMI);
break;
default:
break;
}
DATA_IN;
for (i=0;i<250;i++)
{
delay();
delay();
delay();
delay();
if(DATA_RIN == 0)
break;
} //wait until sensor has finished the measurement
if(DATA_RIN == 1) error+=1; // or timeout (~2 sec.) is reached
value_H=read_byte(ACK); / /read the first byte (MSB)
value_L =read_byte(ACK); //read the second byte (LSB)
*p_checksum =read_byte(noACK); //read checksum
*p_value = (value_H << 8) | value_L;
return error ;
}
void calc_sth(unsigned short int t, unsigned short int rh, float *p_temperature, float *p_humidity)
{
const float d1 = -39.61; //@3.3V
const float d2 = +0.01; //for 14 bit
// for 12 bit
const float C1 = -2.0468;
const float C2 = +0.0367;
const float C3 = -0.0000015955;
//for 12 bit
const float T1 = +0.01;
const float T2 = +0.00008;
float RH_Lin;
float RH_Ture;
float temp_C;
temp_C = d1 + d2 * t;
RH_Lin = C1 + C2 * rh + C3 * rh * rh;
RH_Ture = (temp_C -25) * (T1 + T2 * rh) + RH_Lin;
if(RH_Ture > 100)
RH_Ture = 100;
if(RH_Ture < 0.1f)
RH_Ture = 0.1;
*p_humidity = RH_Ture;
*p_temperature = temp_C;
}
float calc_dewpoint(float t,float h)
{
float dew_point;
float m=17.62,Tn=243.12; //default
if(-40<=t && t<0)
{
m = 22.46;
Tn = 272.62;
}
dew_point = Tn *(log10(h)+m*t/(Tn+t))/(m-log10(h)-+m*t/(Tn+t));
return dew_point;
}
void sht10_init(void)
{
P5SEL = 0x00;
// P5SEL |=BIT2;
// P5SEL &=~ BIT1;
// P5DIR &=~BIT1;
//P5DIR |= BIT2;
//DATA_OUT;
P5DIR |= BIT3+BIT4;
}
void CLK_Init()
{
unsigned int iq0;
//BCSCTL1&=~0X00; //Turn on XT2 oscillator
BCSCTL1 &= ~XT2OFF; //Turn on XT oscillator
do
{
IFG1 &= ~OFIFG; // Clear oscillator failure flag
for (iq0 = 0xFF; iq0 > 0; iq0--); // Delay, wait for XT2 to start oscillating
}
while ((IFG1 & OFIFG) != 0); // Determine whether XT2 starts oscillating
//BCSCTL2 =SELM_2+SELS; //Select MCLK and SMCLK for XT2
BCSCTL2 |= SELM1+SELS; //MCLK is 8MHZ, SMCLK is 8MHZ
}
int main(void)
{
unsigned short int humi_val=0,temp_val=0;
uchar error=0,checksum=0;
WDTCTL=WDTPW+WDTHOLD;
//int i;
CLK_Init();
sht10_init();
connectionreset();
while(1)
{
error=0;
error+=measure(&temp_val,&checksum,TEMP); //measure temperature
error+=measure(&humi_val,&checksum,HUMI); //measure humidity
if(error!=0)
connectionreset();
else
{
calc_sth(temp_val,humi_val,&temp_val_real, &humi_val_real); //calculate humidity, temperature
dew_point = calc_dewpoint(temp_val_real, humi_val_real);
//printf("%2.1f℃ %2.1f%% %2.1f℃ \r\n", temp_val_real, humi_val_real, dew_point);
}
//----------wait approx. 0.8s to avoid heating up SHTxx-------------- ----------------
delay();
delay();
delay();
}
}
void delay()
{
for(int i=0;i<300;i++)
for(int j=0;j<2;j++);
}
|