本帖最后由 hejun96 于 2021-6-11 09:38 编辑
#申请原创# 在AT32F403A上使用模拟GPIO时序和SHT31A通信读温湿度
1.初始化GPIO
#define SCL PBout(6)
#define SDA_OUT PBout(7)
#define SDA_IN PBin(7)
//IO方向操作
#define IIC_INPUT_MODE_SET() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=0x40000000;}///GPIOB->CRL|=8<<28;}//IO设置输入模式
#define IIC_OUTPUT_MODE_SET() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=0X30000000;}///GPIOB->CRL|=3<<28;}//IO设置输出模式
float humiture[4];
u8 Refresh_SHT30_Data=0;
u8 humiture_buff1[20];
u8 humiture_buff2[20];
u8 Temperature_L=15;
u8 Humidity_L=50;
u8 Temperature_H=30;
u8 Humidity_H=80;
/*******************************************************************
函数:SHT30_Init
功能:
********************************************************************/
void SHT30_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PB端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //SCL端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //开漏输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //SDA端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //开漏输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15; //SDA端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //开漏输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);//SDA/SCL拉高
GPIO_SetBits(GPIOB,GPIO_Pin_13);
GPIO_ResetBits(GPIOB,GPIO_Pin_15);
}
/*******************************************************************
函数:IIC_ACK
功能:
********************************************************************/
void IIC_ACK(void)
{
IIC_OUTPUT_MODE_SET();
SCL=0;
delay_us(2);
SDA_OUT=0;
delay_us(2);
SCL=1;
delay_us(2);
SCL=0;
delay_us(1);
}
/*******************************************************************
函数:IIC_NACK
功能:
********************************************************************/
void IIC_NACK(void)
{
IIC_OUTPUT_MODE_SET();
SCL=0;
delay_us(2);
SDA_OUT=1;
delay_us(2);
SCL=1;
delay_us(2);
SCL=0;
delay_us(1);
}
/*******************************************************************
函数:IIC_wait_ACK
功能:
********************************************************************/
u8 IIC_wait_ACK(void)
{
u8 t = 200;
IIC_OUTPUT_MODE_SET();
SDA_OUT=1;
delay_us(1);
SCL=0;
delay_us(1);
IIC_INPUT_MODE_SET();
delay_us(1);
while(SDA_IN)//
{
t--;
delay_us(1);
if(t==0)
{
SCL=0;
return 1;
}
delay_us(1);
}
delay_us(1);
SCL=1;
delay_us(1);
SCL=0;
delay_us(1);
return 0;
}
/*******************************************************************
函数:IIC_Start
功能:
********************************************************************/
void IIC_Start(void)
{
IIC_OUTPUT_MODE_SET();
SDA_OUT=1;
SCL=1;
delay_us(4);
SDA_OUT=0;
delay_us(4);
SCL=0;
}
/*******************************************************************
函数:IIC_Stop
功能:
********************************************************************/
void IIC_Stop(void)
{
IIC_OUTPUT_MODE_SET();
SCL=0;
SDA_OUT=0;
delay_us(4);
SCL=1;
delay_us(4);
SDA_OUT=1;
delay_us(4);
}
/*******************************************************************
函数:IIC_SendByte
功能:发送字节
********************************************************************/
void IIC_SendByte(u8 byte)
{
u8 BitCnt;
IIC_OUTPUT_MODE_SET();
SCL=0;
for(BitCnt=0;BitCnt<8;BitCnt++)
{
if(byte&0x80) SDA_OUT=1;
else SDA_OUT=0;
byte<<=1;
delay_us(2);
SCL=1;
delay_us(2);
SCL=0;
delay_us(2);
}
}
/*******************************************************************
函数:IIC_RcvByte
功能:接收字节
********************************************************************/
u8 IIC_RcvByte(void)
{
u8 retc;
u8 BitCnt;
retc=0;
IIC_INPUT_MODE_SET();
delay_us(1);
for(BitCnt=0;BitCnt<8;BitCnt++)
{
SCL=0;
delay_us(2);
SCL=1;
retc=retc<<1;
if(SDA_IN) retc |=1;
delay_us(1);
}
SCL=0;
return(retc);
}
/*******************************************************************
函数:SHT30_read_result
功能:温湿度读取
********************************************************************/
void SHT30_read_result(u8 addr)
{
u16 tem,hum;
u16 buff[6];
float Temperature=0;
float Humidity=0;
IIC_Start();
IIC_SendByte(addr<<1 | write);
IIC_wait_ACK();
IIC_SendByte(0x2C);
IIC_wait_ACK();
IIC_SendByte(0x06);
IIC_wait_ACK();
IIC_Stop();
delay_ms(50);
IIC_Start();
IIC_SendByte(addr<<1 | read);
if(IIC_wait_ACK()==0)
{
buff[0]=IIC_RcvByte();
IIC_ACK();
buff[1]=IIC_RcvByte();
IIC_ACK();
buff[2]=IIC_RcvByte();
IIC_ACK();
buff[3]=IIC_RcvByte();
IIC_ACK();
buff[4]=IIC_RcvByte();
IIC_ACK();
buff[5]=IIC_RcvByte();
IIC_NACK();
IIC_Stop();
}
tem = ((buff[0]<<8) | buff[1]);
hum = ((buff[3]<<8) | buff[4]);
Temperature= (175.0*(float)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)
Humidity= (100.0*(float)hum/65535.0);// RH = hum*100 / (2^16-1)
if((Temperature>=-20)&&(Temperature<=125)&&(Humidity>=0)&&(Humidity<=100))
{
humiture[0]=Temperature;
humiture[2]=Humidity;
}
hum=0;
tem=0;
HMI1_SendNumber("x0.val=",7,Temperature*100,4);//温度,串口屏浮点型数据处理
HMI1_SendNumber("x1.val=",7,Humidity*100,4);//湿度,串口屏浮点型数据处理
currentDataPoint.valueTemperature =Temperature ;//Add Sensor Data Collection
currentDataPoint.valueHumidity = Humidity ;//Add Sensor Data Collection
}
void delay_us(u16 time)
{
u16 i=0;
while(time--)
{
i=10; //
while(i--) ;
}
}
//
void delay_ms(u16 time)
{
u16 i=0;
while(time--)
{
i=10200; //
while(i--) ;
}
}
延时函数可以用示波器抓,SHT31A发送完字节后在读字节前要延时久一点,我用了delay_ms(50);
建议在主循环中每2s调用SHT30_read_result,可用一个通用定时器的中断做2s中断一次 @21小跑堂 |
厉害