找回密码
 立即注册
查看: 20|回复: 3

把读SHT30的历程改成度SHT20,在初始化的时候进入了死循环在问题

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:11
  • 最近打卡:2025-10-15 10:33:32
已绑定手机

8

主题

28

回帖

136

积分

注册会员

积分
136
发表于 昨天 17:05 | 显示全部楼层 |阅读模式
小白求大佬解答,把读SHT30的例程改成度SHT20,在初始化SHT20_Init();的时候进入到了I2C_Start();的死循环在问题,使用的是uvproj_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[3];  // SHT20只需要3个字节(2个数据+1个CRC)
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();
}

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 SHT20_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 SHT20_ReadTemperature(void)
{
        bit x;
        I2C_Start();
        I2C_SendData(0x80);  // SHT20写地址
        I2C_RecvACK();
        I2C_SendData(0xE3);  // 读取温度命令(保持主设备)
        I2C_RecvACK();
        I2C_Stop();
       
        Delay_x10us(100);    // 等待测量完成
       
        I2C_Start();
        I2C_SendData(0x81);  // SHT20读地址
        I2C_RecvACK();
        x=!(I2CMSST&MSACKI);
        if(x)
        {
                Temp[0] = I2C_RecvData();  // MSB
                I2C_SendACK();
                Temp[1] = I2C_RecvData();  // LSB
                I2C_SendACK();
                Temp[2] = I2C_RecvData();  // CRC
                I2C_SendNAK();
        }
        I2C_Stop();
        return x;
}

// 读取湿度
bit SHT20_ReadHumidity(void)
{
        bit x;
        I2C_Start();
        I2C_SendData(0x80);  // SHT20写地址
        I2C_RecvACK();
        I2C_SendData(0xE5);  // 读取湿度命令(保持主设备)
        I2C_RecvACK();
        I2C_Stop();
       
        Delay_x10us(100);    // 等待测量完成
       
        I2C_Start();
        I2C_SendData(0x81);  // SHT20读地址
        I2C_RecvACK();
        x=!(I2CMSST&MSACKI);
        if(x)
        {
                Temp[0] = I2C_RecvData();  // MSB
                I2C_SendACK();
                Temp[1] = I2C_RecvData();  // LSB
                I2C_SendACK();
                Temp[2] = I2C_RecvData();  // CRC
                I2C_SendNAK();
        }
        I2C_Stop();
        return x;
}

bit SHT20_Calc(void)
{
        bit x;
        unsigned int raw_data;
       
        // 读取温度
        x = SHT20_ReadTemperature();
        if(x && SHT20_CRC(Temp, 2, Temp[2]))
        {
                raw_data = (Temp[0] << 8) | Temp[1];
                raw_data &= 0xFFFC;  // 清除状态位
                Tem = -46.85 + 175.72 * (float)raw_data / 65536.0;
        }
        else
        {
                return 0;
        }
       
        // 读取湿度
        x = SHT20_ReadHumidity();
        if(x && SHT20_CRC(Temp, 2, Temp[2]))
        {
                raw_data = (Temp[0] << 8) | Temp[1];
                raw_data &= 0xFFFC;  // 清除状态位
                Hum = -6.0 + 125.0 * (float)raw_data / 65536.0;
                if(Hum > 100) Hum = 100;
                if(Hum < 0) Hum = 0;
        }
        else
        {
                return 0;
        }
       
        return x;
}

void SHT20_Init(void)
{
        // SHT20软复位
        I2C_Start();
        I2C_SendData(0x80);  // SHT20写地址
        I2C_RecvACK();
        I2C_SendData(0xFE);  // 软复位命令
        I2C_RecvACK();
        I2C_Stop();
        Delay_x10us(200);    // 等待复位完成
}

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;                        //启用总中断
       
        SHT20_Init();
}

void main(void)
{
        Init();
        while(1)
        {
                if(SHT20_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);
}


截图202510151702147629.jpg

sth20.zip

2.88 MB, 下载次数: 1

回复

使用道具 举报 送花

3

主题

1880

回帖

608

积分

等待验证会员

积分
608
发表于 昨天 17:23 | 显示全部楼层
作为一名嵌入式开发者,针对您在将SHT30驱动修改为SHT20过程中遇到的初始化死循环问题,我将从硬件通信协议、代码逻辑及调试方法三个维度进行专业分析。

一、问题定位分析
您在调用SHT20Init()时卡死在I2CStart()函数内,说明I²C总线状态检测机制存在异常。根据SHT20数据手册,其与SHT30的关键差异体现在:
1. 器件地址:SHT20为0x40(7位地址),需确认代码中I2CWriteByte(0x80)是否正确转换为7位地址左移
2. 初始化时序:SHT20通过写入0xFE进行软复位(持续>15ms),而SHT30使用0x30A3等特定命令
3. 响应机制:SHT20在测量命令后需等待16ms(RH 12bit/Temp 14bit模式),需检查延时函数精度

二、I²C通信异常排查
1. 总线仲裁异常
检查I2CStart()中SDA/SCL状态检测逻辑:
  1. c
  2. void I2CStart(void) {
  3.     SDA = 1;
  4.     I2CDelay();
  5.     SCL = 1;
  6.     I2CDelay();
  7.     while(SCL == 0); // 检测时钟拉伸
  8.     SDA = 0;
  9.     I2CDelay();
  10. }
复制代码
若SCL被从机拉低超时(如SHT20未响应),将导致死循环。建议增加超时计数器:
  1. c
  2. unsigned char timeout = 0xFF;
  3. while(SCL == 0 && timeout--) { I2CDelay(); }
  4. if(timeout == 0) { / 总线错误处理 / }
复制代码

2. 电平配置验证
确认硬件连接:
上拉电阻值需满足:Rpull-up > VDD/(3mA) 且 RC时间常数 < 100kHz周期
使用示波器测量SCL/SDA上升沿时间应

[本文内容由国芯人工智能辅助生成,仅供参考]
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:584
  • 最近打卡:2025-10-15 08:26:15
已绑定手机

86

主题

6274

回帖

1万

积分

超级版主

积分
11734
发表于 昨天 22:44 | 显示全部楼层
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:11
  • 最近打卡:2025-10-15 10:33:32
已绑定手机

8

主题

28

回帖

136

积分

注册会员

积分
136
发表于 昨天 22:50 | 显示全部楼层
Debu*** 发表于 2025-10-15 22:44
试一下这个例程
https://www.stcaimcu.com/thread-4612-1-1.html

就是使用该例程进行修改的,你的意思是不做任何修改直接运行试一下还会不会进入死循环是嘛
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-10-16 03:30 , Processed in 0.114678 second(s), 65 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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