本帖最后由 火辣西米秀 于 2020-12-2 20:29 编辑
属于msp430的串行接口传输数据的应用。SHTxx的串行接口与IIC不兼容,但其软件实现与IIC类似。
使用器件型号:msp430F169/msp430F149,SHT70@sensirion AG
典型应用电路:
代码:
#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; //打开XT2振荡器
BCSCTL1 &= ~XT2OFF; //打开XT振荡器
do
{
IFG1 &= ~OFIFG; // 清除振荡器失效标志
for (iq0 = 0xFF; iq0 > 0; iq0--); // 延时,等待XT2起振
}
while ((IFG1 & OFIFG) != 0); // 判断XT2是否起振
//BCSCTL2 =SELM_2+SELS; //选择MCLK、SMCLK为XT2
BCSCTL2 |= SELM1+SELS; //MCLK为8MHZ,SMCLK为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++);
}
|