请教下HC32F460读SHT30,实在是搞不定了。
HC32F460模拟I2C 读SHT30,实在是搞不定了。那位大佬做过类似的,可以参考下吗?建议你先用Arduino搞通,然后对比时序信号。主要侧重于脉冲周期、ACK/NACK上。 你先试一下你的模拟IIC信号是否对?基本就是时序周期等一类的问题 要不我给你个SHT30的驱动 下边是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();
}
qinlu123 发表于 2024-11-19 16:01
下边是I2C.c
#include "I2C.h"
感谢,今天排查后解决了。确实是时序还有SDA转换成输入时的问题。
页:
[1]