找回密码
 立即注册
查看: 571|回复: 0

SHT30读取温湿度从串口发送程序

[复制链接]
  • TA的每日心情
    开心
    8 小时前
  • 签到天数: 109 天

    [LV.6]常住居民II

    25

    主题

    304

    回帖

    1025

    积分

    荣誉版主

    Cyber Hamster

    积分
    1025
    发表于 2023-10-11 20:20:18 | 显示全部楼层 |阅读模式
    本程序实现SHT30读取温湿度从串口发送的功能,分为直接赋值和printf两个版本,使用CRC校验,使用数据手册“4.6 测量结果的读出周期模式”功能,使用数据手册“4.5 周期测量命令数据采集方式”周期测量,通过读报头响应的ACK/NACK判断是否有测量数据,如无测量数据则I2C停止,I2C是始终轮询的,发送频率由SHT30的寄存器控制,无延时函数,注意:在最高mps设置时,传感器可能会发生自热。

    单片机STC8G1K08A-8PIN,时钟频率11.0592MHz,UART1 9600bps 8N1,SHT30使用成品模块。

    SHT30模块长这样:

    O1CN01VZKIfr2KxOAUywLpk_!!1910689623.avif.jpg

    模块原理图:

    截图202310111939579885.jpg



    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);
    }

    /*----------------------------分割线----------------------------*/

    完整工程见附件:




    O1CN01zdQbBa2KxOAM8akQc_!!1910689623.avif.jpg

    SHT30.zip

    2.82 MB, 下载次数: 35

    1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
    (=・ω・=)
    回复 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-5-2 23:21 , Processed in 0.058117 second(s), 32 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表