- 打卡等级:以坛为家II
- 打卡总天数:423
- 最近打卡:2025-05-01 07:10:25
已绑定手机
超级版主
DebugLab
- 积分
- 8343
|
本程序实现SHT30读取温湿度从串口发送的功能,分为直接赋值和printf两个版本,使用CRC校验,使用数据手册“4.6 测量结果的读出周期模式”功能,使用数据手册“4.5 周期测量命令数据采集方式”周期测量,通过读报头响应的ACK/NACK判断是否有测量数据,如无测量数据则I2C停止,I2C是始终轮询的,发送频率由SHT30的寄存器控制,无延时函数,注意:在最高mps设置时,传感器可能会发生自热。
单片机STC8G1K08A-8PIN,时钟频率11.0592MHz,UART1 9600bps 8N1,SHT30使用成品模块。
SHT30模块长这样:
模块原理图:
SHT30地址设置:ADDR=0
串口和printf的使用见此连接:
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=4598
附带部分中文数据手册,重要部分已翻译。
直接赋值版本:
/*----------------------------分割线----------------------------*/
#include <STC8G.H>
#include "define.h"
#include <intrins.h>
#include <string.h>
#define RXD P30
#define TXD P31
#define SCL P32
#define SDA P33
#define FOSC 11059200UL
#define BAUD 9600UL
#define BRT (0x10000-FOSC/BAUD/4)
#define T_Buffer_Len 64 //Uart1发送缓存长度
#define R_Buffer_Len 64 //Uart1接收缓存长度
bit I2C_Busy;
bit Tem_Sign;
unsigned char RP; //Uart1接收指针
unsigned char TP; //Uart1发送指针
unsigned char Uart_Send_Lenth; //Uart1发送长度
unsigned char xdata R_Buffer[R_Buffer_Len]; //Uart1接收缓存
unsigned char xdata T_Buffer[T_Buffer_Len]; //Uart1发送缓存
unsigned char code Hex_to_Ascii[16]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};
signed long Tem,Hum;
/*----------------------------延时10us@STC-Y6@11.0592MHz----------------------------*/
void Delay_10us(void)
{
unsigned char i;
i=35;
while(--i);
}
/*----------------------------延时x10us----------------------------*/
void Delay_x10us(unsigned char x)
{
while(x--)
Delay_10us();
}
///*----------------------------延时10ms@STC-Y6@11.0592MHz----------------------------*/
//void Delay_10ms(void)
//{
// unsigned char i,j;
// _nop_();
// _nop_();
// i=144;
// j=157;
// do
// {
// while(--j);
// }while(--i);
//}
///*----------------------------延时x10ms----------------------------*/
//void Delay_x10ms(unsigned char x)
//{
// while(x--)
// Delay_10ms();
//}
void UART_Send(unsigned int x)
{
TP=0;
Uart_Send_Lenth=x;
TI=1;
}
void I2C_Start(void)
{
I2C_Busy=1;
I2CMSCR=0x81;
while(I2C_Busy);
}
void I2C_SendData(unsigned char dat)
{
I2CTXD=dat;
I2C_Busy=1;
I2CMSCR=0x82;
while(I2C_Busy);
}
void I2C_RecvACK(void)
{
I2C_Busy=1;
I2CMSCR=0x83;
while(I2C_Busy);
}
unsigned char I2C_RecvData(void)
{
I2C_Busy=1;
I2CMSCR=0x84;
while(I2C_Busy);
return I2CRXD;
}
void I2C_SendACK(void)
{
I2CMSST=0x00;
I2C_Busy=1;
I2CMSCR=0x85;
while(I2C_Busy);
}
void I2C_SendNAK(void)
{
I2CMSST=0x01;
I2C_Busy=1;
I2CMSCR=0x85;
while(I2C_Busy);
}
void I2C_Stop(void)
{
I2C_Busy=1;
I2CMSCR=0x86;
while(I2C_Busy);
}
unsigned char CRC8(unsigned char *p,unsigned char num)
{
unsigned char i,j;
unsigned char crc=0xFF;
for(j=0;j<num;j++)
{
crc^=(p[j]);
for(i=8;i>0;--i)
{
if(crc&0x80)
crc=(crc<<1)^0x31;
else
crc=(crc<<1);
}
}
return crc;
}
bit SHT30_CRC(unsigned char *p,unsigned char num,unsigned char dat)
{
unsigned char crc;
crc=CRC8(p,num);
if(crc!=dat)
{
return 0;
}
return 1;
}
bit SHT30_Read(void)
{
bit ok;
unsigned char temp_tem[3],temp_hum[3];
I2C_Start();
I2C_SendData(0x88);//写
I2C_RecvACK();
I2C_SendData(0xE0);
I2C_RecvACK();
I2C_SendData(0x00);
I2C_RecvACK();
I2C_Stop();
Delay_x10us(100);
I2C_Start();
I2C_SendData(0x89);//读
I2C_RecvACK();
ok=!(I2CMSST&MSACKI);
if(ok)
{
temp_tem[0]=I2C_RecvData();//温度高8位
I2C_SendACK();
temp_tem[1]=I2C_RecvData();//温度低8位
I2C_SendACK();
temp_tem[2]=I2C_RecvData();//温度CRC
I2C_SendACK();
temp_hum[0]=I2C_RecvData();//湿度高8位
I2C_SendACK();
temp_hum[1]=I2C_RecvData();//湿度低8位
I2C_SendACK();
temp_hum[2]=I2C_RecvData();//湿度CRC
I2C_SendNAK();
}
I2C_Stop();
if(ok)
{
if(SHT30_CRC(temp_tem,2,temp_tem[2]))
{
Tem=((unsigned long)temp_tem[0]<<8)|(unsigned long)temp_tem[1];
Tem=Tem*17500/0xFFFF-4500;
if(Tem<0)
{
Tem_Sign=1;
Tem=~Tem+1;
}
else
Tem_Sign=0;
}
if(SHT30_CRC(temp_hum,2,temp_hum[2]))
{
Hum=((unsigned long)temp_hum[0]<<8)|(unsigned long)temp_hum[1];
Hum=Hum*10000/0xFFFF;
}
}
return ok;
}
void SHT30_Init(void)
{
I2C_Start();
I2C_SendData(0x88);
I2C_RecvACK();
I2C_SendData(0x30);
I2C_RecvACK();
I2C_SendData(0xA2);
I2C_RecvACK();
I2C_Stop();
Delay_x10us(100);
I2C_Start();
I2C_SendData(0x88);
I2C_RecvACK();
I2C_SendData(0x21);
I2C_RecvACK();
I2C_SendData(0x30);
I2C_RecvACK();
I2C_Stop();
Delay_x10us(100);
}
void Init(void)
{
P_SW2|=EAXFR;
P3M0=0x00;
P3M1=0x00;
P5M0=0x00;
P5M1=0x00;
P3PU=0x0c;
AUXR=0x40; //设置定时器0时钟为12T模式,设置定时器1为1T模式,设置定时器1为波特率发生器
TMOD=0x01; //设置定时器0为16位不自动重装载模式,设置定时器1为16位自动重装载模式
TL0=0x00; //设置定时器0初始值(5ms)
TH0=0xEE; //设置定时器0初始值(5ms)
TF0=0; //清除TF0中断标志位
ET0=1; //启用定时器0中断
SCON=0x50; //设置UART1模式为8位数据可变波特率
TL1=BRT; //设置UART1波特率
TH1=BRT>>8; //设置UART1波特率
TR1=1; //打开定时器1
ES=1; //启用UART1中断
I2CCFG=0xC6; //345.6K@11.0592M
I2CMSCR=EMSI;
I2CMSST=0x00;
EA=1; //启用总中断
SHT30_Init();
}
void main(void)
{
Init();
while(1)
{
if(SHT30_Read())
{
if(!Tem_Sign)
{
T_Buffer[0]='T';
T_Buffer[1]='=';
T_Buffer[2]=Hex_to_Ascii[Tem%10000/1000];
T_Buffer[3]=Hex_to_Ascii[Tem%1000/100];
T_Buffer[4]='.';
T_Buffer[5]=Hex_to_Ascii[Tem%100/10];
T_Buffer[6]=Hex_to_Ascii[Tem%10];
T_Buffer[7]='C';
T_Buffer[8]=' ';
T_Buffer[9]='H';
T_Buffer[10]='=';
T_Buffer[11]=Hex_to_Ascii[Hum%10000/1000];
T_Buffer[12]=Hex_to_Ascii[Hum%1000/100];
T_Buffer[13]='.';
T_Buffer[14]=Hex_to_Ascii[Hum%100/10];
T_Buffer[15]=Hex_to_Ascii[Hum%10];
T_Buffer[16]='%';
T_Buffer[17]=0x0d;
T_Buffer[18]=0x0a;
UART_Send(19);
}
else
{
T_Buffer[0]='T';
T_Buffer[1]='=';
T_Buffer[2]='-';
T_Buffer[3]=Hex_to_Ascii[Tem%10000/1000];
T_Buffer[4]=Hex_to_Ascii[Tem%1000/100];
T_Buffer[5]='.';
T_Buffer[6]=Hex_to_Ascii[Tem%100/10];
T_Buffer[7]=Hex_to_Ascii[Tem%10];
T_Buffer[8]='C';
T_Buffer[9]=' ';
T_Buffer[10]='H';
T_Buffer[11]='=';
T_Buffer[12]=Hex_to_Ascii[Hum%10000/1000];
T_Buffer[13]=Hex_to_Ascii[Hum%1000/100];
T_Buffer[14]='.';
T_Buffer[15]=Hex_to_Ascii[Hum%100/10];
T_Buffer[16]=Hex_to_Ascii[Hum%10];
T_Buffer[17]='%';
T_Buffer[18]=0x0d;
T_Buffer[19]=0x0a;
UART_Send(20);
}
}
}
}
void Uart_Start(void)
{
TL0=0x00;
TH0=0xEE;
TR0=1;
}
void Uart_Stop(void)
{
TR0=0;
TL0=0x00;
TH0=0xEE;
RP=0;
memset(R_Buffer,0x00,sizeof R_Buffer);
}
void Timer0_Isr(void) interrupt 1
{
Uart_Stop();
}
void Uart_Isr(void) interrupt 4
{
if(RI)
{
RI=0;
Uart_Start();
R_Buffer[RP]=SBUF;
if(RP==R_Buffer_Len-1)
{
Uart_Stop();
}
else if(TR0)
{
RP++;
}
}
if(TI)
{
TI=0;
if(Uart_Send_Lenth!=0)
{
SBUF=(T_Buffer[TP]);
TP++;
}
if(TP==Uart_Send_Lenth)
{
TP=0;
Uart_Send_Lenth=0;
}
}
}
void I2C_Isr(void) interrupt 24
{
_push_(P_SW2);
P_SW2|=EAXFR;
if(I2CMSST&MSIF)
{
I2CMSST&=~MSIF;
I2C_Busy=0;
}
_pop_(P_SW2);
}
/*----------------------------分割线----------------------------*/
printf版本:
/*----------------------------分割线----------------------------*/
#include <STC8G.H>
#include "define.h"
#include <intrins.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#define RXD P30
#define TXD P31
#define SCL P32
#define SDA P33
#define FOSC 11059200UL
#define BAUD 9600UL
#define BRT (0x10000-FOSC/BAUD/4)
#define T_Buffer_Len 64 //Uart1发送缓存长度
#define R_Buffer_Len 64 //Uart1接收缓存长度
unsigned char RP; //Uart1接收指针
unsigned char TP; //Uart1发送指针
unsigned char Uart_Send_Lenth; //Uart1发送长度
unsigned char xdata R_Buffer[R_Buffer_Len]; //Uart1接收缓存
unsigned char xdata T_Buffer[T_Buffer_Len]; //Uart1发送缓存
bit I2C_Busy;
unsigned char Temp[6];
float Tem,Hum;
/*----------------------------延时10us@STC-Y6@11.0592MHz----------------------------*/
void Delay_10us(void)
{
unsigned char i;
i=35;
while(--i);
}
/*----------------------------延时x10us----------------------------*/
void Delay_x10us(unsigned char x)
{
while(x--)
Delay_10us();
}
///*----------------------------延时10ms@STC-Y6@11.0592MHz----------------------------*/
//void Delay_10ms(void)
//{
// unsigned char i,j;
// _nop_();
// _nop_();
// i=144;
// j=157;
// do
// {
// while(--j);
// }while(--i);
//}
///*----------------------------延时x10ms----------------------------*/
//void Delay_x10ms(unsigned char x)
//{
// while(x--)
// Delay_10ms();
//}
void UART_Send(unsigned int x)
{
TP=0;
Uart_Send_Lenth=x;
TI=1;
}
void Uart_Printf(unsigned char *v,...)
{
va_list ap;
va_start(ap,v);
UART_Send(vsprintf(T_Buffer,v,ap));
va_end(ap);
}
void I2C_Start(void)
{
I2C_Busy=1;
I2CMSCR=0x81;
while(I2C_Busy);
}
void I2C_SendData(unsigned char dat)
{
I2CTXD=dat;
I2C_Busy=1;
I2CMSCR=0x82;
while(I2C_Busy);
}
void I2C_RecvACK(void)
{
I2C_Busy=1;
I2CMSCR=0x83;
while(I2C_Busy);
}
unsigned char I2C_RecvData(void)
{
I2C_Busy=1;
I2CMSCR=0x84;
while(I2C_Busy);
return I2CRXD;
}
void I2C_SendACK(void)
{
I2CMSST=0x00;
I2C_Busy=1;
I2CMSCR=0x85;
while(I2C_Busy);
}
void I2C_SendNAK(void)
{
I2CMSST=0x01;
I2C_Busy=1;
I2CMSCR=0x85;
while(I2C_Busy);
}
void I2C_Stop(void)
{
I2C_Busy=1;
I2CMSCR=0x86;
while(I2C_Busy);
}
unsigned char CRC8(unsigned char *p,unsigned char num)
{
unsigned char i,j;
unsigned char crc=0xFF;
for(j=0;j<num;j++)
{
crc^=(p[j]);
for(i=8;i>0;--i)
{
if(crc&0x80)
crc=(crc<<1)^0x31;
else
crc=(crc<<1);
}
}
return crc;
}
bit SHT30_CRC(unsigned char *p,unsigned char num,unsigned char dat)
{
unsigned char crc;
crc=CRC8(p,num);
if(crc!=dat)
{
return 0;
}
return 1;
}
bit SHT30_Read(unsigned char *p,unsigned char i)
{
bit x;
I2C_Start();
I2C_SendData(0x88);
I2C_RecvACK();
I2C_SendData(0xE0);
I2C_RecvACK();
I2C_SendData(0x00);
I2C_RecvACK();
I2C_Stop();
Delay_x10us(100);
I2C_Start();
I2C_SendData(0x89);
I2C_RecvACK();
x=!(I2CMSST&MSACKI);
if(x)
{
do
{
*p=I2C_RecvData();
p++;
if(i!=1)
I2C_SendACK();
}
while(--i);
I2C_SendNAK();
}
I2C_Stop();
return x;
}
bit SHT30_Calc(void)
{
bit x;
unsigned char i;
unsigned char temp[3];
unsigned int tem,hum;
x=SHT30_Read(Temp,6);
if(x)
{
for(i=0;i<3;i++)
{
temp=Temp;
}
if(SHT30_CRC(temp,2,temp[2]))
{
tem=((temp[0]<<8)|temp[1]);
Tem=(175.0F*(float)tem/65535.0F-45.0F);//Tem=-45+175*tem/(2^16-1)
}
for(i=0;i<3;i++)
{
temp=Temp[i+3];
}
if(SHT30_CRC(temp,2,temp[2]))
{
hum=((temp[0]<<8)|temp[1]);
Hum=(100.0F*(float)hum/65535.0F);//Hum=hum*100/(2^16-1)
}
}
return x;
}
void SHT30_Init(void)
{
I2C_Start();
I2C_SendData(0x88);
I2C_RecvACK();
I2C_SendData(0x30);
I2C_RecvACK();
I2C_SendData(0xA2);
I2C_RecvACK();
I2C_Stop();
Delay_x10us(100);
I2C_Start();
I2C_SendData(0x88);
I2C_RecvACK();
I2C_SendData(0x21);
I2C_RecvACK();
I2C_SendData(0x30);
I2C_RecvACK();
I2C_Stop();
Delay_x10us(100);
}
void Init(void)
{
P_SW2|=EAXFR;
P3M0=0x00;
P3M1=0x00;
P5M0=0x00;
P5M1=0x00;
P3PU=0x0c;
AUXR=0x40; //设置定时器0时钟为12T模式,设置定时器1为1T模式,设置定时器1为波特率发生器
TMOD=0x01; //设置定时器0为16位不自动重装载模式,设置定时器1为16位自动重装载模式
TL0=0x00; //设置定时器0初始值(5ms)
TH0=0xEE; //设置定时器0初始值(5ms)
TF0=0; //清除TF0中断标志位
ET0=1; //启用定时器0中断
SCON=0x50; //设置UART1模式为8位数据可变波特率
TL1=BRT; //设置UART1波特率
TH1=BRT>>8; //设置UART1波特率
TR1=1; //打开定时器1
ES=1; //启用UART1中断
I2CCFG=0xC6; //345.6K@11.0592M
I2CMSCR=EMSI;
I2CMSST=0x00;
EA=1; //启用总中断
SHT30_Init();
}
void main(void)
{
Init();
while(1)
{
if(SHT30_Calc())
Uart_Printf("T=%2.2f℃ H=%2.2f%%\r\n",Tem,Hum);
}
}
void Uart_Start(void)
{
TL0=0x00;
TH0=0xEE;
TR0=1;
}
void Uart_Stop(void)
{
TR0=0;
TL0=0x00;
TH0=0xEE;
RP=0;
memset(R_Buffer,0x00,sizeof R_Buffer);
}
void Timer0_Isr(void) interrupt 1
{
Uart_Stop();
}
void Uart_Isr(void) interrupt 4
{
if(RI)
{
RI=0;
Uart_Start();
R_Buffer[RP]=SBUF;
if(RP==R_Buffer_Len-1)
{
Uart_Stop();
}
else if(TR0)
{
RP++;
}
}
if(TI)
{
TI=0;
if(Uart_Send_Lenth!=0)
{
SBUF=(T_Buffer[TP]);
TP++;
}
if(TP==Uart_Send_Lenth)
{
TP=0;
Uart_Send_Lenth=0;
}
}
}
void I2C_Isr(void) interrupt 24
{
_push_(P_SW2);
P_SW2|=EAXFR;
if(I2CMSST&MSIF)
{
I2CMSST&=~MSIF;
I2C_Busy=0;
}
_pop_(P_SW2);
}
/*----------------------------分割线----------------------------*/
完整工程见附件:
|
1
喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
-
+1
楼主威武~
|