把读SHT30的历程改成度SHT20,在初始化的时候进入了死循环在问题
小白求大佬解答,把读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; //Uart1接收缓存
unsigned char xdata T_Buffer; //Uart1发送缓存
bit I2C_Busy;
unsigned char Temp;// 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);
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 = I2C_RecvData();// MSB
I2C_SendACK();
Temp = I2C_RecvData();// LSB
I2C_SendACK();
Temp = 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 = I2C_RecvData();// MSB
I2C_SendACK();
Temp = I2C_RecvData();// LSB
I2C_SendACK();
Temp = 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))
{
raw_data = (Temp << 8) | Temp;
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))
{
raw_data = (Temp << 8) | Temp;
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=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++;
}
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);
}
作为一名嵌入式开发者,针对您在将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状态检测逻辑:
c
void I2CStart(void) {
SDA = 1;
I2CDelay();
SCL = 1;
I2CDelay();
while(SCL == 0); // 检测时钟拉伸
SDA = 0;
I2CDelay();
}
若SCL被从机拉低超时(如SHT20未响应),将导致死循环。建议增加超时计数器:
c
unsigned char timeout = 0xFF;
while(SCL == 0 && timeout--) { I2CDelay(); }
if(timeout == 0) { / 总线错误处理 / }
2. 电平配置验证
确认硬件连接:
上拉电阻值需满足:Rpull-up > VDD/(3mA) 且 RC时间常数 < 100kHz周期
使用示波器测量SCL/SDA上升沿时间应
[本文内容由国芯人工智能辅助生成,仅供参考] 试一下这个例程
https://www.stcaimcu.com/thread-4612-1-1.html DebugLab 发表于 2025-10-15 22:44
试一下这个例程
https://www.stcaimcu.com/thread-4612-1-1.html
就是使用该例程进行修改的{:ciya:},你的意思是不做任何修改直接运行试一下还会不会进入死循环是嘛 这是没有进入到void I2C_Isr(void) interrupt 24,清除状态才导致的一直在while(I2C_Busy);死循环是嘛 简清 发表于 2025-10-15 22:50
就是使用该例程进行修改的,你的意思是不做任何修改直接运行试一下还会不会进入死循环是嘛 ...
需要看数据手册对比一下这两个型号传感器有哪些不同
页:
[1]