#include <MSP430X14X.h>
unsigned int FlagSHT11,TimerSHT11,TempSHT11,HumiSHT11;
unsigned char StateSHT11;
#define S_SCL (P5OUT |= BIT4)
#define C_SCL (P5OUT &= ~BIT4) // P5.4 时钟
#define S_SDA (P5DIR &= ~BIT5) // P5.5 数据
#define C_SDA (P5DIR |= BIT5)
#define SDA P5IN
#define CRC8_CHECK_INIT 0x00
const unsigned char CRC8_TABLE_SHT11[256];
#define SHT11_TEMP_CODE 0x03
#define SHT11_HUMI_CODE 0x05
#define TEMP_SHT11_SAMPLE_DELAY 350
#define HUMI_SHT11_SAMPLE_DELAY 100
#define CRC8_CHECK_INIT 0x00
#define D1_TEMP_SHT11 -40.1
#define D2_TEMP_SHT11 0.01
#define C1_HUMI_SHT11 -2.0468
#define C2_HUMI_SHT11 0.0367
#define C3_HUMI_SHT11 -1.5955e-6
#define T1_HUMI_SHT11 0.01
#define T2_HUMI_SHT11 0.00008
#define uchar unsigned char
#define uint unsigned int
#define FrameLenth 8 // 数据帧长度为 8
#define LocalAddr 0x01 // 地址为0x01
#define RS485_EN BIT3 // P3.3,接收(低有效)、发送(高有效)使能控制
#define RS485_R_EN P3DIR |= RS485_EN; P3OUT &= ~RS485_EN // 485接收使能
#define RS485_T_EN P3DIR |= RS485_EN; P3OUT |= RS485_EN
unsigned char RX_BUFF[FrameLenth];
unsigned char TX_BUFF[8]={0};
uint value;
void Init_UART0_9600(void)
{
U0CTL = CHAR;
ME1 |= UTXE0+URXE0;
U0TCTL|=SSEL1;
UBR0_0 = 0x00; // 7.3728Mhz @ 9600 = 768
UBR1_0 = 0x03;
UMCTL_0 = 0x00; // 波特率调整因子
P3SEL |= BIT4 + BIT5;
RS485_R_EN;
//IE1 |= URXIE0 +UTXIE0;
// _EINT();
}
void clk_ini(void) //配置主时钟函数
{
unsigned int i;
BCSCTL1 = 0X00;
do
{
IFG1 &= ~OFIFG; // Clear oscillator fault flag
for (i = 0x20; i > 0; i--); // Delay
}
while ((IFG1 & OFIFG) == OFIFG); // Test osc fault flag
BCSCTL1 &= ~(XT2OFF + XTS); // Select SMCLK source as XT2CLK
BCSCTL1 |= RSEL0 + RSEL1 + RSEL2; //DCO Rsel=7(Freq=3200k/25摄氏度)
BCSCTL1 |= 0x07;
BCSCTL2 += SELM1; //MCLK的时钟源为TX2CLK,分频因子为1
BCSCTL2 += SELS; //SMCLK的时钟源为TX2CLK,分频因子为1
}
void INIT(void)
{
FlagSHT11=1;
StateSHT11=0x01;
}
void UART0_PutFrame(unsigned int Lenth)
{
unsigned int loop;
RS485_T_EN;
//while((IFG1&UTXIFG0)==0);
for(loop=0;loop<Lenth;loop++)
{
TXBUF0 = TX_BUFF[loop];
while((IFG1&UTXIFG0)==0);
IFG1 &= ~UTXIFG0;
}
while((U0TCTL&TXEPT)==0);
RS485_R_EN;
}
void wait(void) //短延时函数
{
uchar i=3;
while(i--);
_NOP();
}
void start(void) //产生起始信号(在时钟线为1时,数据线要有下降沿)
{
S_SDA; //数据线拉高
wait();
S_SCL; //时钟线拉高
wait();
C_SDA; //数据线拉低(数据线下降沿)
wait();
C_SCL; //时钟线拉低
wait();
}
void stop(void) //产生停止信号(在时钟线为1时,数据线要有上升沿)
{
C_SCL; //时钟线为低
wait();
C_SDA; //数据线为低
wait();
S_SCL; //时钟线为高
wait();
S_SDA; //数据线为高(数据线上升沿)
}
void ack(void) //发送ACK
{
C_SDA; //数据线为低
wait();
C_SCL; //时钟线为低
wait();
S_SCL; //时钟线为高
wait();
C_SCL; //时钟线为低
}
void NoAck(void) //发送NO ACK
{
S_SDA ; //数据线为高
wait();
C_SCL; //时钟线拉低
wait();
S_SCL; //时钟线拉高
wait();
C_SCL; //时钟线拉低
}
uchar check_ack(void) //检I2C应答
{
uchar ack;
C_SCL; //时钟线为低
S_SDA; //数据线为高
wait();
S_SCL; //时钟线为高
wait();
ack=SDA & 0x80;
C_SCL; //时钟线为低
_NOP();
if(ack) return 1; //无应答
else return 0; //有应答
}
void write_byte(uchar byte) //发送一个8位数据
{
uchar i;
C_SCL; //拉低时钟线
for(i=0;i<8;i++) //连续发送8位数据
{
if(byte & 0x80) S_SDA; //变数据(为1发送高电平,为0发送低电平)
else C_SDA; //先从最高位发送
wait();
S_SCL; //拉高时钟线,送数据
wait();
C_SCL; //再把时钟拉低
byte <<= 1; //准备下一位
}
}
uchar read_byte(void) //读数据
{
uchar byte=0,i;
P5DIR &= ~BIT5; //输入模式
wait();
for(i=0;i<8;i++)
{ byte <<= 1;
C_SCL; // 时钟线为低
wait();
S_SCL; //拉高时钟线
wait();
if(SDA & 0X10) byte |= 0x01; //判断P5.5是高电平还是低电平
C_SCL; //拉低时钟线
wait();
}
return byte;
}
unsigned int I2CReadDataSHT11(unsigned char command)
{
unsigned int TempHumi;
unsigned char TempHumiH,TempHumiL,CheckData,CheckCompute,i,ComputeCheck;
if(!(SDA & 0X10))
{
TempHumiH = read_byte();
ack();
TempHumiL = read_byte();
ack();
CheckData = read_byte();
NoAck();
stop();
CheckCompute=command^CRC8_CHECK_INIT;
CheckCompute=TempHumiH^CRC8_TABLE_SHT11[CheckCompute];
CheckCompute=TempHumiL^CRC8_TABLE_SHT11[CheckCompute];
CheckCompute=CRC8_TABLE_SHT11[CheckCompute];
ComputeCheck=0;
for(i=8;i>0;i--)
{
ComputeCheck=ComputeCheck>>1;
if(CheckCompute&0x80)
{
ComputeCheck=ComputeCheck | 0x80;
}
else
{
ComputeCheck=ComputeCheck | 0x00;
}
CheckCompute=CheckCompute<<1;
}
if(ComputeCheck==CheckData)
{
TempHumi=(TempHumiH<<8)|TempHumiL;
}
else
{
TempHumi=0xffff;
}
}
else
{
TempHumi=0xffff;
}
return TempHumi;
}
void TempHumiSampleSHT11(void)
{
unsigned int TempHumi;
float tempdata;
if(FlagSHT11)
{
switch(StateSHT11)
{
case 0x01:
{
start();
stop();
start();
write_byte(SHT11_TEMP_CODE);
check_ack();
TimerSHT11=TEMP_SHT11_SAMPLE_DELAY;
StateSHT11=0x02;
}
break ;
case 0x02:
{
if(0==TimerSHT11)
{
TempHumi=I2CReadDataSHT11(SHT11_TEMP_CODE);
if(TempHumi==0xffff)
{
TempSHT11=TempSHT11;
StateSHT11=0x21;
break ;
}
tempdata=D1_TEMP_SHT11+D2_TEMP_SHT11*TempHumi;
if(tempdata<=-1000)
{
TempSHT11 = -1000;
}
if(tempdata>=1500)
{
TempSHT11 = 1500;
}
if(tempdata>-1000 && tempdata<1500)
{
TempSHT11 = (int) ceil(tempdata);
}
StateSHT11=0x21;
}
}
break;
case 0x21:
{
start();
stop();
start();
write_byte(SHT11_HUMI_CODE);
check_ack();
TimerSHT11=HUMI_SHT11_SAMPLE_DELAY;
StateSHT11=0x22;
}
break;
case 0x22:
{
if(0==TimerSHT11)
{
TempHumi=I2CReadDataSHT11(SHT11_HUMI_CODE);
if(TempHumi==0xffff)
{
HumiSHT11=HumiSHT11;
FlagSHT11=0;
StateSHT11=0x01;
break;
}
tempdata=C1_HUMI_SHT11+C2_HUMI_SHT11*TempHumi+C3_HUMI_SHT11*TempHumi*TempHumi;
tempdata=(TempSHT11-250)*(T1_HUMI_SHT11+T2_HUMI_SHT11*TempHumi) + tempdata*10;
if(tempdata<=0)
{
HumiSHT11 = 0;
}
if(tempdata>=1000)
{
HumiSHT11 = 1000;
}
if(tempdata>0 && tempdata<1000)
{
HumiSHT11 = (unsigned int) ceil(tempdata);
}
FlagSHT11=0;
StateSHT11=0x01;
}
}
break;
default:
StateSHT11=0x01;
}
}
}
void TX_Send()
{
TX_BUFF[0] = TempSHT11 ;
TX_BUFF[1] = TempSHT11>>8 ;
TX_BUFF[2] = HumiSHT11;
TX_BUFF[3] = HumiSHT11>>8;
UART0_PutFrame(4);
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
clk_ini(); //配置主时钟
INIT();
Init_UART0_9600();
while(1)
{
TempHumiSampleSHT11();
TX_Send();
}
}
全部代码,串口直接输出温度与湿度,可是全是0,是模拟IIC,时序应该没有错误,求大神指点一二...
此帖出自
小平头技术问答
一周热门 更多>