AI8051U AHT25 温湿度传感器 偶遇问题
本帖最后由 DebugLab 于 2024-8-19 00:21 编辑AHT25 温湿度传感器 采用I2C通信
时序如下图所示:
如何使用IO模拟I2C
关键是起始,停止和应答
代码如下:
void aht_sleep_us(unsigned int n) //24mhz
{
while (n--)
{
NOP24();
}
}
void aht_sleep_ms(unsigned intn)
{
while (n--)
aht_sleep_us(1000);
}
#define I2C_TIMEOUT_TIMES 100 //超时倍数
//延时 用于等待应答时的超时判断 移植时需修改
void i2c_timeout_delay(void)
{
aht_sleep_ms(1);
}
void i2c_delay() //每步的间隔 用于等待电平稳定和控制通讯速率
{
aht_sleep_us(5);
}
//SCL拉高 移植时需修改
void I2C_SCL_H(void)
{
I2C_SCL = 1;
}
//SCL拉低 移植时需修改
void I2C_SCL_L(void)
{
I2C_SCL = 0;
}
//SDA拉高 移植时需修改
void I2C_SDA_H(void)
{
I2C_SDA = 1;
}
//SDA拉低 移植时需修改
void I2C_SDA_L(void)
{
I2C_SDA = 0;
}
//读取SDA 移植时需修改
unsigned char I2C_SDA_Read(void)
{
return I2C_SDA;
}
/*******************************************************************************
* 函 数 名 : i2c_start
* 函数功能 : 产生I2C起始信号
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void i2c_start(void)
{
I2C_SDA_H();
I2C_SCL_H();
i2c_delay();
I2C_SDA_L(); //当SCL为高电平时,SDA由高变为低
i2c_delay();
I2C_SCL_L(); //钳住I2C总线,准备发送或接收数据
}
/*******************************************************************************
* 函 数 名 : i2c_stop
* 函数功能 : 产生I2C停止信号
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void i2c_stop(void)
{
I2C_SDA_L();
I2C_SCL_H();
i2c_delay();
I2C_SDA_H(); //当SCL为高电平时,SDA由低变为高
i2c_delay();
}
/*******************************************************************************
* 函 数 名 : i2c_ack
* 函数功能 : 产生ACK应答
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void i2c_ack(void)
{
I2C_SCL_L();
I2C_SDA_L(); //SDA为低电平
i2c_delay();
I2C_SCL_H();
i2c_delay();
I2C_SCL_L();
I2C_SDA_H();
}
/*******************************************************************************
* 函 数 名 : i2c_nack
* 函数功能 : 产生NACK非应答
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void i2c_nack(void)
{
I2C_SCL_L();
I2C_SDA_H(); //SDA为高电平
i2c_delay();
I2C_SCL_H();
i2c_delay();
I2C_SCL_L();
}
/*******************************************************************************
* 函 数 名 : i2c_wait_ack
* 函数功能 : 等待应答信号到来
* 输 入 : 无
* 输 出 : 1,接收应答失败
0,接收应答成功
*******************************************************************************/
unsigned char i2c_wait_ack(void)
{
unsigned int time_temp = 0;
I2C_SCL_H();
i2c_delay();
while(I2C_SDA_Read()) //等待SDA为低电平
{
time_temp++;
i2c_timeout_delay();
if(time_temp > I2C_TIMEOUT_TIMES) //超时则强制结束I2C通信
{
i2c_stop();
return 1;
}
}
I2C_SCL_L();
return 0;
}
/*******************************************************************************
* 函 数 名 : i2c_write_byte
* 函数功能 : I2C发送一个字节
* 输 入 : dat:发送一个字节
* 输 出 : 无
*******************************************************************************/
void i2c_write_byte(unsigned char dat)
{
unsigned char i = 0;
I2C_SCL_L();
for(i = 0; i<8; i++) //循环8次将一个字节传出,先传高再传低位
{
if((dat & 0x80) > 0)
I2C_SDA_H();
else
I2C_SDA_L();
dat <<= 1;
i2c_delay();
I2C_SCL_H();
i2c_delay();
I2C_SCL_L();
i2c_delay();
}
}
/*******************************************************************************
* 函 数 名 : i2c_read_byte
* 函数功能 : I2C读一个字节
* 输 入 : ack = 1时,发送ACK,ack = 0,发送nACK
* 输 出 : 应答或非应答
*******************************************************************************/
unsigned char i2c_read_byte(unsigned char ack)
{
unsigned char i = 0, receive = 0;
for(i = 0; i < 8; i++ ) //循环8次将一个字节读出,先读高再传低位
{
I2C_SCL_L();
i2c_delay();
I2C_SCL_H();
receive <<= 1;
if(I2C_SDA_Read())
receive++;
i2c_delay();
}
if (!ack)
i2c_nack();
else
i2c_ack();
return receive;
}
/*******************************************************************************
* 函 数 名 : i2c_mem_write
* 函数功能 : I2C对指定器件、指定寄存器连续写入
* 输 入 : 器件地址、器件寄存器地址、待输入数据首地址、待输入数据长度
* 输 出 : 0: 成功 1:失败
*******************************************************************************/
unsigned char i2c_mem_write(unsigned char DevAddress, unsigned char MemAddress, unsigned char *pData, unsigned int Len)
{
i2c_start();
i2c_write_byte(DevAddress << 1);
if(i2c_wait_ack())
return 1;
i2c_write_byte(MemAddress);
if(i2c_wait_ack())
return 1;
while(Len--)
{
i2c_write_byte(*pData++);
if(i2c_wait_ack())
return 1;
}
i2c_stop();
return 0;
}
/*******************************************************************************
* 函 数 名 : i2c_mem_read
* 函数功能 : I2C对指定器件、指定寄存器连续读取
* 输 入 : 器件地址、器件寄存器地址、数据缓冲区首地址、数据长度
* 输 出 : 0: 成功 1:失败
*******************************************************************************/
unsigned char i2c_mem_read(unsigned char DevAddress, unsigned char MemAddress, unsigned char *pBuffer, unsigned int Len)
{
i2c_start();
i2c_write_byte(DevAddress << 1); //发送写命令
if(i2c_wait_ack())
return 1;
i2c_write_byte(MemAddress); //发送字地址
if(i2c_wait_ack())
return 1;
i2c_start();
i2c_write_byte(DevAddress << 1 | 1); //进入接收模式
if(i2c_wait_ack())
return 1;
while(Len--)
{
*pBuffer++ = i2c_read_byte(Len!=0); //读取字节
}
i2c_stop(); //产生一个停止条件
return 0;
}然后直接读数据,看数据手册写
void AHT10_Read(unsigned int t,unsigned int h)
{
char timeout = 0;
unsigned char buff = {0};
volatile unsigned long int dat = 0;
unsigned char cmd;
cmd = 0x33;
cmd = 0x00;
i2c_mem_write(ATH20_SLAVE_ADDRESS,AHT20_TrigMeasure_REG,cmd,2);
i2c_mem_read(ATH20_SLAVE_ADDRESS,AHT20_STATUS_REG,buff,7);
//高位在前
dat = buff;dat = dat<<8;dat+=buff;dat=dat<<8;dat+=buff;dat=dat>>4;
hum = dat * 100 / rate;
dat = buff&0x0F;dat = dat<<8;dat+=buff;dat=dat<<8;dat+=buff;
tem = dat * 200 / rate - 50;
}坑
正常写数据处理这样写
//高位在前
dat = (((buff<<12) | (buff<<4)) | (buff>>4));
Humidity = dat / 1048576.0 * 100.0;
dat = 0;
dat = ((buff &0x0F) << 16 ) | ( buff << 8) | buff;
Temperature = (dat/1048576.0) * 200 - 50;感觉没错,就是结果不对
立马想到 是不是位移超出范围了
改成如下代码
dat = ((unsigned long int)buff << 8) | ((unsigned long int)buff) | ((unsigned long int)(buff >> 4));不行,没变化
这都不能转换?
我直接打开AHT25的官网,下载官网的例子
官网这样写:
dat = buff;dat = dat<<8;dat+=buff;dat=dat<<8;dat+=buff;dat=dat>>4;我修改代码,试了一下,温度湿度立马正确了
但是,我再32里直接用位移可以使用,为啥这里不行了?
我也发现了,我的流水灯必须要这样写,写成P1=_crol_(P1,1)不好使
可以试试硬件I2C,效率高很多,代码也非常简单。 晓飛飛 发表于 2024-8-19 00:46
可以试试硬件I2C,效率高很多,代码也非常简单。
正在学习中{:4_188:} wnagming 发表于 2024-8-19 06:35
为什么会这个样子?
编译器的锅 什么数据类型 soma 发表于 2024-8-19 14:58
什么数据类型
hum tem 都是long
页:
[1]