[Mod] AHT10驱动 优化AHT10源码

1. 参考 devctl 使用方法;
2. 参考 QNX 文档,确认:i2c_send_t 后附加发送数据;
This commit is contained in:
gaoyang3513
2026-03-17 22:29:38 +08:00
parent fc8a1e6620
commit 0ded3c35eb
4 changed files with 153 additions and 88 deletions

16
.editorconfig Normal file
View File

@ -0,0 +1,16 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_size = 4
indent_style = space
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false
[*.c]
indent_size = 8
indent_style = tab

View File

@ -7,10 +7,6 @@
#include <stdbool.h>
#include "aht10_util.h"
int fd_i2c1 = -1;
extern bool aht1x_getEvent(sensors_event_t *humidity, sensors_event_t *temp);
int main() {
int ret = 0, fd_i2c_s = 0;
i2c_driver_info_t info = {0};
@ -22,39 +18,25 @@ int main() {
return -1;
}
ret = ioctl(fd_i2c_s, DCMD_I2C_DRIVER_INFO, &info);
ret = aht1x_begin(fd_i2c_s, AHTX0_I2CADDR_DEFAULT);
if (ret < 0) {
printf("ErrNo(%d) %s, failed to read from I2C device\n", errno, strerror(errno));
printf("[%12s|%4u] ErrNo(%d), failed to init AHT1x\n", __FILE_NAME__, __LINE__, ret);
close(fd_i2c_s);
return -1;
}
printf("I2C Driver Info:\n");
printf(" Speed : %#X\n", info.speed_mode); /* supported speeds: I2C_SPEED_* */
printf(" Mode-Addr: %#X\n", info.addr_mode); /* supported address fmts: I2C_ADDRFMT_* */
printf(" Verbosity: %#X\n", info.verbosity); /* Driver verbosity level */
Adafruit_AHTX0 aht;
Serial.begin(115200);
Serial.println("Adafruit AHT10/AHT20 demo!");
if (! aht.begin()) {
Serial.println("Could not find AHT? Check wiring");
while (1) delay(10);
}
Serial.println("AHT10 or AHT20 found");
while(1) {
sensors_event_t humidity, temp;
aht.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
Serial.print("Temperature: "); Serial.print(temp.temperature); Serial.println(" degrees C");
Serial.print("Humidity: "); Serial.print(humidity.relative_humidity); Serial.println("% rH");
float humidity, temp;
ret = aht1x_getEvent(fd_i2c_s, AHTX0_I2CADDR_DEFAULT, &humidity, &temp);
if (ret < 0) {
printf("[%12s|%4u] ErrNo(%d), failed to read data from AHT1x\n", __FILE_NAME__, __LINE__, ret);
return ret;
}
delay(500);
printf("Temperature: %2.3f degrees C\n", temp);
printf("Humidity : %2.3f %% rH\n", humidity);
usleep(500000); // wait 500ms before next read
}
close(fd_i2c_s);

View File

@ -1,3 +1,4 @@
#include <malloc.h>
#include <stdio.h>
#include <fcntl.h>
#include <hw/i2c.h>
@ -7,9 +8,90 @@
#include <stdbool.h>
#include "aht10_util.h"
float _humidity = 0, _temperature = 0;
static int fd_i2c;
extern int fd_i2c1;
static int _i2c_read(uint8_t address, uint8_t *data, size_t length, uint8_t stop)
{
int ret = 0;
char *data_recv = NULL;
unsigned int recv_lent = sizeof(i2c_recv_t) + length;
i2c_recv_t *data_msg = NULL, *data_buf = NULL;
data_recv = malloc(recv_lent);
if (data_recv == NULL) {
printf("Failed to allocate memory for I2C read\n");
return -1;
}
memset(data_recv, 0, recv_lent);
data_msg = (i2c_recv_t *)data_recv;
data_buf = (char *)data_recv + sizeof(*data_msg);
data_msg->slave.addr = address;
data_msg->slave.fmt = I2C_ADDRFMT_7BIT;
data_msg->len = length;
data_msg->stop = stop;
ret = devctl(fd_i2c, DCMD_I2C_RECV, data_msg, recv_lent, NULL);
if (ret < 0) {
printf("[%s|%u] ErrNo(%d) %s, failed to read I2C data\n", __FILE__, __LINE__, errno, strerror(errno));
return ret;
}
return ret;
}
static int _i2c_write(uint8_t address, const uint8_t *data, size_t length, uint8_t stop)
{
int ret = 0;
char *data_send = NULL;
i2c_send_t *data_msg = NULL;
unsigned int send_lent = sizeof(i2c_send_t) + length;
data_send = malloc (send_lent);
if (data_send == NULL) {
printf("Failed to allocate memory for I2C write\n");
return -ENOMEM;
}
memset(data_send, 0, send_lent);
data_msg = (i2c_send_t *)data_send;
data_msg->slave.addr = address;
data_msg->slave.fmt = I2C_ADDRFMT_7BIT;
data_msg->len = length;
data_msg->stop = stop;
memcpy ((char *)data_send + sizeof(*data_msg), data, length);
ret = devctl(fd_i2c, DCMD_I2C_SEND, data_send, send_lent, NULL);
if (ret < 0) {
printf("[%12s|%4u] ErrNo(%d) %s, failed to write I2C data\n", __FILE_NAME__, __LINE__, errno, strerror(errno));
return ret;
}
return ret;
}
/**
* @brief Gets the status (first byte) from AHT10/AHT20
*
* @returns 8 bits of status data, or 0xFF if failed
*/
static int aht1x_getStatus(uint8_t address)
{
int ret;
uint8_t recv_data[1] = {0};
ret = _i2c_read(address, recv_data, 1, 1);
if (ret < 0) {
printf("[%s|%4u] ErrNo(%d) %s, failed to read date from I2C Address[%#X]\n", __FILE_NAME__, __LINE__, ret, address);
return ret;
}
return recv_data[0];
}
/*!
* @brief Sets up the hardware and initializes I2C
@ -21,63 +103,47 @@ extern int fd_i2c1;
* The I2C address used to communicate with the sensor
* @return True if initialization was successful, otherwise false.
*/
bool aht1x_begin(TwoWire *wire, int32_t sensor_id, uint8_t i2c_address)
int aht1x_begin(int i2c_dev, uint8_t i2c_address)
{
delay(20); // 20 ms to power up
int ret = 0;
uint8_t cmd[3] = {0};
if (i2c_dev) {
delete i2c_dev; // remove old interface
if (i2c_dev < 0) {
printf("Error, invalid I2C device\n");
return -EINVAL;
}
i2c_dev = new Adafruit_I2CDevice(i2c_address, wire);
if (!i2c_dev->begin()) {
return false;
}
uint8_t cmd[3];
fd_i2c = i2c_dev;
cmd[0] = AHTX0_CMD_SOFTRESET;
if (!i2c_dev->write(cmd, 1)) {
return false;
ret = _i2c_write(i2c_address, cmd, 1, 0);
if (ret < 0) {
printf("[%12s|%4u] ErrNo(%d), failed to write SOFTRESET command\n", __FILE_NAME__, __LINE__, ret);
return ret;
}
delay(20);
while (getStatus() & AHTX0_STATUS_BUSY) {
delay(10);
usleep(20000); // 20ms delay
while (aht1x_getStatus(i2c_address) & AHTX0_STATUS_BUSY) {
usleep(10000);
}
cmd[0] = AHTX0_CMD_CALIBRATE;
cmd[1] = 0x08;
cmd[2] = 0x00;
i2c_dev->write(cmd, 3); // may not 'succeed' on newer AHT20s
while (getStatus() & AHTX0_STATUS_BUSY) {
delay(10);
}
if (!(getStatus() & AHTX0_STATUS_CALIBRATED)) {
ret = _i2c_write(i2c_address, cmd, 3, 1);
if (ret < 0) {
printf("ErrNo(%d) %s, failed to write CALIBRATE command\n", errno, strerror(errno));
return false;
}
delete humidity_sensor;
temp_sensor = new Adafruit_AHTX0_Temp(this);
return true;
}
/**
* @brief Gets the status (first byte) from AHT10/AHT20
*
* @returns 8 bits of status data, or 0xFF if failed
*/
uint8_t aht1x_getStatus(void)
{
uint8_t ret;
if (!i2c_dev->read(&ret, 1)) {
return 0xFF;
while (aht1x_getStatus(i2c_address) & AHTX0_STATUS_BUSY) {
delay(10);
}
return ret;
if (!(aht1x_getStatus(i2c_address) & AHTX0_STATUS_CALIBRATED)) {
return false;
}
return true;
}
/**************************************************************************/
@ -89,42 +155,42 @@ uint8_t aht1x_getStatus(void)
@returns true if the event data was read successfully
*/
/**************************************************************************/
bool aht1x_getEvent(sensors_event_t *humidity, sensors_event_t *temp)
int aht1x_getEvent(int i2c_dev, uint8_t i2c_address, float *_humidity, float *_temperature)
{
uint32_t t = millis();
int ret = 0;
// read the data and store it!
uint8_t cmd[3] = {AHTX0_CMD_TRIGGER, 0x33, 0};
if (!i2c_dev->write(cmd, 3)) {
return false;
ret = _i2c_write(i2c_address, cmd, 3, 1);
if (ret < 0) {
printf("[%s|%4u] ErrNo(%d) %s, failed to write TRIGGER command\n", __FILE_NAME__, __LINE__, ret);
return ret;
}
while (getStatus() & AHTX0_STATUS_BUSY) {
while (aht1x_getStatus(i2c_address) & AHTX0_STATUS_BUSY) {
delay(10);
}
uint8_t data[6];
if (!i2c_dev->read(data, 6)) {
return false;
ret = _i2c_read(i2c_address, data, 6, 1);
if (ret < 0) {
printf("[%s|%4u] ErrNo(%d) %s, failed to read date from I2C Address[%#X]\n", __FILE_NAME__, __LINE__, ret, i2c_address);
return ret;
}
uint32_t h = data[1];
h <<= 8;
h |= data[2];
h <<= 4;
h |= data[3] >> 4;
_humidity = ((float)h * 100) / 0x100000;
*_humidity = ((float)h * 100) / 0x100000;
uint32_t tdata = data[3] & 0x0F;
tdata <<= 8;
tdata |= data[4];
tdata <<= 8;
tdata |= data[5];
_temperature = ((float)tdata * 200 / 0x100000) - 50;
*_temperature = ((float)tdata * 200 / 0x100000) - 50;
// use helpers to fill in the events
if (temp)
fillTempEvent(temp, t);
if (humidity)
fillHumidityEvent(humidity, t);
return true;
}

View File

@ -9,6 +9,7 @@
#define AHTX0_STATUS_BUSY 0x80 ///< Status bit for busy
#define AHTX0_STATUS_CALIBRATED 0x08 ///< Status bit for calibrated
bool aht1x_getEvent(sensors_event_t *humidity, sensors_event_t *temp);
int aht1x_begin(int i2c_dev, uint8_t i2c_address);
int aht1x_getEvent(int i2c_dev, uint8_t i2c_address, float *_humidity, float *_temperature);
#endif