starry1028 发表于 2024-11-18 18:42

请教下HC32F460读SHT30,实在是搞不定了。

HC32F460模拟I2C 读SHT30,实在是搞不定了。那位大佬做过类似的,可以参考下吗?

suncat0504 发表于 2024-11-19 10:18

建议你先用Arduino搞通,然后对比时序信号。主要侧重于脉冲周期、ACK/NACK上。

wang369 发表于 2024-11-19 13:42

你先试一下你的模拟IIC信号是否对?基本就是时序周期等一类的问题

qinlu123 发表于 2024-11-19 15:51

要不我给你个SHT30的驱动

qinlu123 发表于 2024-11-19 16:01

下边是I2C.c
#include "I2C.h"

#define Delay_Time 2

void I2C_delay_nus(uint16_t time)
{   
   uint8_t i=0;   
   while(time--)
   {
      i=1;
      while(i--) ;   
   }
}
static void Set_I2C1_SCL(uint8_t a)
{
    if(a!=0)
    {
      PHout(5)=1;
    }
    else
    {
      PHout(5)=0;
    }
}
static void Set_I2C1_SDA(uint8_t a)
{
    if(a!=0)
    {
      PAout(4)=1;
    }
    else
    {
      PAout(4)=0;
    }
}
static uint8_t Get_I2C1_SDA(void)
{
    return PAin(4);
}
static void Set_I2C2_SCL(uint8_t a)
{
    if(a!=0)
    {
      PBout(7)=1;
    }
    else
    {
      PBout(7)=0;
    }
}
static void Set_I2C2_SDA(uint8_t a)
{
    if(a!=0)
    {
      PBout(8)=1;
    }
    else
    {
      PBout(8)=0;
    }
}
static uint8_t Get_I2C2_SDA(void)
{
    return PBin(8);
}
static void Set_I2C3_SCL(uint8_t a)
{
    if(a!=0)
    {
      PEout(2)=1;
    }
    else
    {
      PEout(2)=0;
    }
}
static void Set_I2C3_SDA(uint8_t a)
{
    if(a!=0)
    {
      PEout(3)=1;
    }
    else
    {
      PEout(3)=0;
    }
}
static uint8_t Get_I2C3_SDA(void)
{
    return PEin(3);
}

struct I2C_Device I2C_1=
{
    .Set_SDA = Set_I2C1_SDA,
    .Set_SCL = Set_I2C1_SCL,
    .Get_SDA = Get_I2C1_SDA,
    .delayus = I2C_delay_nus
};
struct I2C_Device I2C_2=
{
    .Set_SDA = Set_I2C2_SDA,
    .Set_SCL = Set_I2C2_SCL,
    .Get_SDA = Get_I2C2_SDA,
    .delayus = I2C_delay_nus
};
struct I2C_Device I2C_3=
{
    .Set_SDA = Set_I2C3_SDA,
    .Set_SCL = Set_I2C3_SCL,
    .Get_SDA = Get_I2C3_SDA,
    .delayus = I2C_delay_nus
};
/*
    IIC Driver
*/
void I2C_Start(struct I2C_Device *IIcBus)
{
    IIcBus->Set_SDA(1);
    IIcBus->delayus(Delay_Time);
    IIcBus->Set_SCL(1);
    IIcBus->delayus(Delay_Time);
    IIcBus->Set_SDA(0);
    IIcBus->delayus(Delay_Time);
    IIcBus->Set_SCL(0);
}
void I2C_Stop(struct I2C_Device *IIcBus)
{
    IIcBus->Set_SDA(0);
    IIcBus->delayus(Delay_Time);
    IIcBus->Set_SCL(1);
    IIcBus->delayus(Delay_Time);
    IIcBus->Set_SDA(1);
}
uint8_t Receive_ACK(struct I2C_Device *IIcBus)
{
    uint32_t i;
   
    IIcBus->Set_SCL(0);//一定把时钟设为低电平再释放总线等待ACK
    IIcBus->delayus(Delay_Time);
    IIcBus->Set_SDA(1);//释放总线
    IIcBus->delayus(Delay_Time);
    while(IIcBus->Get_SDA()!=0)
    {
      i++;
      if(i>10)
      {
            return 0;
      }
      IIcBus->delayus(Delay_Time);
    }
    IIcBus->Set_SCL(1);
    IIcBus->delayus(Delay_Time);
    IIcBus->Set_SCL(0);
    return 1;
}
void I2C_WriteOneByte(struct I2C_Device *IIcBus,uint8_t Write_Data)
{
    uint8_t i;
    uint8_t Data=0;
    Data=Write_Data;
    for(i=0;i<8;i++)
    {
      IIcBus->Set_SDA(Data & 0x80);
      IIcBus->delayus(Delay_Time);
      IIcBus->Set_SCL(1);
      IIcBus->delayus(Delay_Time);
      IIcBus->Set_SCL(0);
      IIcBus->delayus(Delay_Time);
      Data <<= 1;
    }
}
/**************Send ACK**************/
void I2C_SendACK(struct I2C_Device *IIcBus)
{
    IIcBus->Set_SCL(0);
    IIcBus->delayus(Delay_Time);
    IIcBus->Set_SDA(0);//发送ACK
    IIcBus->delayus(Delay_Time);
    IIcBus->Set_SCL(1);//拉高时钟线再拉低时钟线完成一个读周期
    IIcBus->delayus(Delay_Time);
    IIcBus->Set_SCL(0);//空闲时保证时钟线为低
    IIcBus->delayus(Delay_Time);
    IIcBus->Set_SDA(1);//发送完ACK后释放总线
}
void I2C_SendNACK(struct I2C_Device *IIcBus)
{
    IIcBus->Set_SCL(0);
    IIcBus->delayus(Delay_Time);
    IIcBus->Set_SCL(1);
    IIcBus->delayus(Delay_Time);
    IIcBus->Set_SCL(0);
}

uint8_t I2C_ReadOneByte(struct I2C_Device *IIcBus,uint8_t Ack)
{
    uint8_t i;
    uint8_t Data=0;

    IIcBus->Set_SDA(1);//释放总线
    IIcBus->delayus(Delay_Time);
    for(i=0;i<8;i++)
    {
      Data <<= 1;
      IIcBus->Set_SCL(0);
      IIcBus->delayus(Delay_Time);
      IIcBus->Set_SCL(1);
      IIcBus->delayus(Delay_Time);
      if(IIcBus->Get_SDA())
      {
            Data++;
      }
    }
    IIcBus->Set_SCL(0);
    if(Ack)
    {
      I2C_SendACK(IIcBus);
    }
    else
    {
      I2C_SendNACK(IIcBus);
    }
    return Data;
}
下边是I2C.h
#ifndef __IIC_H
#define __IIC_H

#include "Header.h"

struct I2C_Device
{
    void (*Set_SDA)(uint8_t a);
    void (*Set_SCL)(uint8_t a);
    uint8_t (*Get_SDA)(void);
    void (*delayus)(uint16_t us);
};

extern struct I2C_Device I2C_1,I2C_2,I2C_3;

void I2C_delay_nus(uint16_t time);
void I2C_Start(struct I2C_Device *IIcBus);
void I2C_Stop(struct I2C_Device *IIcBus);
uint8_t Receive_ACK(struct I2C_Device *IIcBus);
void I2C_WriteOneByte(struct I2C_Device *IIcBus,uint8_t Write_Data);
void I2C_SendACK(struct I2C_Device *IIcBus);
void I2C_SendNACK(struct I2C_Device *IIcBus);
uint8_t I2C_ReadOneByte(struct I2C_Device *IIcBus,uint8_t Ack);

#endif
下边是SHT3x.c
#include "Sht3x.h"

struct sht3xObj sht31_1 =
{
    .HardWare = &I2C_1
};
struct sht3xObj sht31_2 =
{
    .HardWare = &I2C_2
};

static uint8_t sht31_mode_set(struct sht3xObj *PARA, uint8_t mode_h,uint8_t mode_l)
{
    I2C_Start(PARA->HardWare);
    I2C_WriteOneByte(PARA->HardWare,SHT31_RHT_W);
    if(Receive_ACK(PARA->HardWare)!=1)
    {
      return 0;
    }
    I2C_WriteOneByte(PARA->HardWare,Mode_Set_H);
    if(Receive_ACK(PARA->HardWare)!=1)
    {
      return 0;
    }
    I2C_WriteOneByte(PARA->HardWare,Mode_Set_L);
    if(Receive_ACK(PARA->HardWare)!=1)
    {
      return 0;
    }   
    I2C_Stop(PARA->HardWare);
    return 1;
}

uint8_t soft_reset_sensor(struct sht3xObj *PARA)
{
I2C_Start(PARA->HardWare);
I2C_WriteOneByte(PARA->HardWare,SHT31_RHT_W);
if(Receive_ACK(PARA->HardWare)!=1)
    {
      return 0;
    }
I2C_WriteOneByte(PARA->HardWare,RESET_SET_H);
if(Receive_ACK(PARA->HardWare)!=1)
{
    return 0;
}
I2C_WriteOneByte(PARA->HardWare,RESET_SET_L);
if(Receive_ACK(PARA->HardWare)!=1)
{
    return 0;
}
I2C_Stop(PARA->HardWare);
return 1;
}

uint8_t StartReadRHTemperature(struct sht3xObj *PARA)
{
    I2C_Start(PARA->HardWare);
    I2C_WriteOneByte(PARA->HardWare,SHT31_RHT_W);
    if(Receive_ACK(PARA->HardWare)!=1)
    {
      return 0;
    }
    I2C_WriteOneByte(PARA->HardWare,0xE0);
    if(Receive_ACK(PARA->HardWare)!=1)
    {
      return 0;
    }
    I2C_WriteOneByte(PARA->HardWare,0x00);
    if(Receive_ACK(PARA->HardWare)!=1)
    {
      return 0;
    }
    return 1;
}


uint8_t sht31ReadRHTemperature(struct sht3xObj *PARA)
{
    uint8_t   T_Data_MSB, T_Data_LSB, RH_Data_MSB, RH_Data_LSB;
    uint8_t   CRC8_1, CRC8_2;
    uint16_tdata_t, data_rh;
      
    I2C_Start(PARA->HardWare);
    I2C_WriteOneByte(PARA->HardWare,SHT31_RHT_R);
    if(Receive_ACK(PARA->HardWare)!=1)
    {
      return 0;
    }
      
    T_Data_MSB = I2C_ReadOneByte(PARA->HardWare,ACK);
    T_Data_LSB = I2C_ReadOneByte(PARA->HardWare,ACK);
    CRC8_1 = I2C_ReadOneByte(PARA->HardWare,ACK);

    RH_Data_MSB = I2C_ReadOneByte(PARA->HardWare,ACK);
    RH_Data_LSB = I2C_ReadOneByte(PARA->HardWare,ACK);
    CRC8_2 = I2C_ReadOneByte(PARA->HardWare,NACK);
    I2C_Stop(PARA->HardWare);

    data_rh = (RH_Data_MSB<<8)|(RH_Data_LSB);
    PARA->Humidty = 100*((float)data_rh/65535);

    data_t = (T_Data_MSB<<8)|(T_Data_LSB);
    PARA->Temperture = -45 + 175*((float)data_t/65535);
   
    return 1;
}
void sht31_thread(struct sht3xObj *PARA)
{
    switch(PARA->RH_Status)
    {
    case 0:
    {
            if(CheckDelay(&PARA->Delay_Time)==0)
            {
                if(sht31_mode_set(PARA,Mode_Set_H,Mode_Set_L) != 0)
                {
                  PARA->RH_Status++;
                }
                else
                {
                  Set_Delay_Time(1500,&PARA->Delay_Time);
                }
            }
    }break;
      case 1://启动温湿度检测
      {
      if(CheckDelay(&PARA->Delay_Time)==0)
      {
      if(StartReadRHTemperature(PARA)!=0)
      {
                  Set_Delay_Time(1000,&PARA->Delay_Time);
                  PARA->RH_Read_Time = 0;
                  PARA->RH_Status++;
      }
      else
      {
          I2C_Stop(PARA->HardWare);
          PARA->RH_Read_Time++;
                  Set_Delay_Time(100,&PARA->Delay_Time);
          if(PARA->RH_Read_Time > 5)
          {
            PARA->RH_Read_Time = 0;
            PARA->RH_Status = 0;
          }
      }
      }
      }break;
      case 2:
      {
            if(CheckDelay(&PARA->Delay_Time)==0)
            {
                if(sht31ReadRHTemperature(PARA) != 0)
                {
                  PARA->RH_Status = 1;
                }
                else
                {
                  PARA->RH_Status = 0;
                }
            }
      }break;
      default:
      {
            PARA->RH_Status = 0;
      }break;
    }
}
下边是sht3x.h
#ifndef __SHT3X__H__
#define __SHT3X__H__

#include "I2C.h"
#include "Header.h"
#include "Delay.h"

#define ACK 1
#define NACK 0

#define SHT31_RHT_W   0X88
#define SHT31_RHT_R   0X89

//#define SHT31_RHT_W   0X8C
//#define SHT31_RHT_R   0X8D

//MODE COMMAND
#define Mode_Set_H    0x21   
#define Mode_Set_L    0x2D

//SOFTRESET COMMAND
#define RESET_SET_H   0x30
#define RESET_SET_L   0xA2

struct sht3xObj
{
    uint16_t Delay_Time;//别忘了需要被DelayTimeCount_ms
    struct I2C_Device *HardWare;

uint16_t   adc_t;
uint16_t   adc_rh;
    float   Temperture;
    float   Humidty;   
    uint8_t Status;
    uint8_t RH_Status;
    uint8_t RH_Read_Time;
};

extern struct sht3xObj sht31_1,sht31_2;

void sht31_thread(struct sht3xObj *PARA);


#endif
下边是用到的延时函数
void DelayTimeCount_ms(uint16_t *DelayTime_Count)
{
    if(*DelayTime_Count==0)
    {
      *DelayTime_Count=0;
    }
    else
    {
      *DelayTime_Count-=1;
    }
}
void Set_Delay_Time(uint16_t Time,uint16_t *DelayTime_Count)
{
    *DelayTime_Count=Time;
}
uint8_t CheckDelay(uint16_t *DelayTime_Count)
{
    if(*DelayTime_Count==0)
    {
      return 0;
    }
    else
    {
      return 1;
    }
}
下边是函数调用
#include "TaskMgr.h"

uint8_t Sys_Status=0;
uint16_t Item_OverTime_Count=0;
uint16_t TimeTick_Count=0;
uint8_t Task_1ms_EN=0,Task_2ms_EN=0,Task_5ms_EN=0,Task_10ms_EN=0,Task_20ms_EN=0,Task_50ms_EN=0,Task_100ms_EN=0,Task_500ms_EN=0,Task_1000ms_EN=0,Task_5000ms_EN=0;
uint8_t TCL=0;

static void SysTimeTikeCounting(void)
{
    TCL = 1;
    if(TimeTick_Count>60000)
    {
      TimeTick_Count=1;
    }
    else
    {
      TimeTick_Count++;
    }
}
static void Task_1ms(void)
{
    TimeCountReceive(&U_D_Uart1);
    DelayTimeCount_ms(&MS8607_Para_1.PT_Thread_Time);
    DelayTimeCount_ms(&MS8607_Para_2.PT_Thread_Time);
    DelayTimeCount_ms(&RS485BusSilentTime1);
    DelayTimeCount_ms(&MMDPort1.DelayTime);
    DelayTimeCount_ms(&PTQ3040.DelayTime);
    DelayTimeCount_ms(&sht31_1.Delay_Time);
    DelayTimeCount_ms(&sht31_2.Delay_Time);
    SmiTimeCount();
}
static void Task_2ms(void)
{
   
}
static void Task_5ms(void)
{
   
}
static void Task_10ms(void)
{
   
}
static void Task_20ms(void)
{
   
}
static void Task_50ms(void)
{
    ReadEleSensorInformationWhenBooting();
}
static void Task_100ms(void)
{

}
static void Task_500ms(void)
{

}
static void Task_1000ms(void)
{
    GetDS18B20Data(&DS18B20_1);
//GetDS18B20Data(&DS18B20_2);
//GetDS18B20Data(&DS18B20_3);
//GetDS18B20Data(&DS18B20_4);
    ReadEleSensorValueEnable();
    ReadLSPMValueEnable();
    ReadWSEnable();
    ReadWDEnable();
    PTQModeSetEnable();
    PTQReadEnable();
}
static void Task_5000ms(void)
{

}
static void TaskPolls(void)
{
    if(TCL)
    {
      TCL = 0;
      
      if((TimeTick_Count%1)==0)
      {
            Task_1ms_EN=1;
      }
      if((TimeTick_Count%2)==0)
      {
            Task_2ms_EN=1;
      }
      if((TimeTick_Count%5)==0)
      {
            Task_5ms_EN=1;
      }
      if((TimeTick_Count%10)==0)
      {
            Task_10ms_EN=1;
      }
      if((TimeTick_Count%20)==0)
      {
            Task_20ms_EN=1;
      }
      if((TimeTick_Count%50)==0)
      {
            Task_50ms_EN=1;
      }
      if((TimeTick_Count%100)==0)
      {
            Task_100ms_EN=1;
      }
      if((TimeTick_Count%500)==0)
      {
            Task_500ms_EN=1;
      }
      if((TimeTick_Count%1000)==0)
      {
            Task_1000ms_EN=1;
      }
      if((TimeTick_Count%5000)==0)
      {
            Task_5000ms_EN=1;
      }
    }
   
    if(Task_1ms_EN)
    {
      Task_1ms_EN=0;
      Task_1ms();
    }
    if(Task_2ms_EN)
    {
      Task_2ms_EN=0;
      Task_2ms();
    }
    if(Task_5ms_EN)
    {
      Task_5ms_EN=0;
      Task_5ms();
    }
    if(Task_10ms_EN)
    {
      Task_10ms_EN=0;
      Task_10ms();
    }
    if(Task_20ms_EN)
    {
      Task_20ms_EN=0;
      Task_20ms();
    }
    if(Task_50ms_EN)
    {
      Task_50ms_EN=0;
      Task_50ms();
    }
    if(Task_100ms_EN)
    {
      Task_100ms_EN=0;
      Task_100ms();
    }
    if(Task_500ms_EN)
    {
      Task_500ms_EN=0;
      Task_500ms();
    }
    if(Task_1000ms_EN)
    {
      Task_1000ms_EN=0;
      Task_1000ms();
    }
    if(Task_5000ms_EN)
    {
      Task_5000ms_EN=0;
      Task_5000ms();
    }
}
void Sys_INIT(void)
{
//MX_GPIO_Init();
//MX_TIM1_Init();
//MX_TIM2_Init();
//MX_TIM3_Init();
//MX_USART1_UART_Init();
    UartDebugInit();
    HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
    PTQModeSetEnable();
}
void SYSTICK_Callback(void)
{
    SysTimeTikeCounting();
}
void SystemRun(void)
{   
    TaskPolls();
//FlowControl(&FlowDust);

    MS8607_PT_Thread(&MS8607_Para_1);
    sht31_thread(&sht31_1);
    MS8607_PT_Thread(&MS8607_Para_2);
    sht31_thread(&sht31_2);
//
//SmiRuning(&SM9541_1);
   
    RS485Device1Handle();
}









starry1028 发表于 2024-11-19 17:43

qinlu123 发表于 2024-11-19 16:01
下边是I2C.c
#include "I2C.h"



感谢,今天排查后解决了。确实是时序还有SDA转换成输入时的问题。
页: [1]
查看完整版本: 请教下HC32F460读SHT30,实在是搞不定了。