8 changed files with 273 additions and 8 deletions
@ -0,0 +1,226 @@ |
|||||
|
/*
|
||||
|
* Copyright (c) 2025, Your Name |
||||
|
* |
||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||
|
* |
||||
|
* Change Logs: |
||||
|
* Date Author Notes |
||||
|
* 2025-12-27 Developer First version for ADS1115 on RT-Thread |
||||
|
*/ |
||||
|
|
||||
|
#include <rtthread.h> |
||||
|
#include <rtdevice.h> |
||||
|
#include <board.h> |
||||
|
#include "Variable.h" |
||||
|
|
||||
|
#define DBG_TAG "sensor.ads1115" |
||||
|
#define DBG_LVL DBG_LOG |
||||
|
#include <rtdbg.h> |
||||
|
|
||||
|
/* ADS1115 I2C 地址(A0 引脚接地时为 0x48) */ |
||||
|
#define ADS1115_I2C_ADDR 0x48 |
||||
|
/* 使用的 I2C 总线设备名 */ |
||||
|
#define ADS1115_I2C_BUS_NAME "i2c2" // 根据你的板子修改,如 "i2c1"
|
||||
|
|
||||
|
/* ADS1115 寄存器地址 */ |
||||
|
#define ADS1115_REG_CONVERT 0x00 |
||||
|
#define ADS1115_REG_CONFIG 0x01 |
||||
|
|
||||
|
static struct rt_i2c_bus_device *i2c_bus = RT_NULL; |
||||
|
|
||||
|
/**
|
||||
|
* 向 ADS1115 写入配置寄存器 |
||||
|
*/ |
||||
|
static rt_err_t ads1115_write_config(rt_uint16_t config) |
||||
|
{ |
||||
|
rt_uint8_t buf[3] = { |
||||
|
ADS1115_REG_CONFIG, |
||||
|
(rt_uint8_t)(config >> 8), |
||||
|
(rt_uint8_t)(config & 0xFF) |
||||
|
}; |
||||
|
|
||||
|
struct rt_i2c_msg msgs[1] = { |
||||
|
{ |
||||
|
.addr = ADS1115_I2C_ADDR, |
||||
|
.flags = RT_I2C_WR, |
||||
|
.buf = buf, |
||||
|
.len = 3, |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
if (rt_i2c_transfer(i2c_bus, msgs, 1) != 1) |
||||
|
{ |
||||
|
LOG_E("Failed to write config register."); |
||||
|
return -RT_ERROR; |
||||
|
} |
||||
|
return RT_EOK; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* 从 ADS1115 读取转换结果 |
||||
|
*/ |
||||
|
static rt_err_t ads1115_read_conversion(rt_int16_t *value) |
||||
|
{ |
||||
|
rt_uint8_t buf[2] = {0}; |
||||
|
|
||||
|
struct rt_i2c_msg msgs[2] = { |
||||
|
{ |
||||
|
.addr = ADS1115_I2C_ADDR, |
||||
|
.flags = RT_I2C_WR, |
||||
|
.buf = (rt_uint8_t[]){ADS1115_REG_CONVERT}, |
||||
|
.len = 1, |
||||
|
}, |
||||
|
{ |
||||
|
.addr = ADS1115_I2C_ADDR, |
||||
|
.flags = RT_I2C_RD, |
||||
|
.buf = buf, |
||||
|
.len = 2, |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
if (rt_i2c_transfer(i2c_bus, msgs, 2) != 2) |
||||
|
{ |
||||
|
LOG_E("Failed to read conversion register."); |
||||
|
return -RT_ERROR; |
||||
|
} |
||||
|
|
||||
|
*value = (rt_int16_t)((buf[0] << 8) | buf[1]); |
||||
|
return RT_EOK; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* 读取指定通道的 ADC 值(单端输入) |
||||
|
* channel: 0 ~ 3 (对应 AIN0~AIN3 对 GND) |
||||
|
* 返回:RT_EOK 或错误码 |
||||
|
*/ |
||||
|
static rt_err_t ads1115_read_channel(rt_uint8_t channel, rt_int16_t *raw_value) |
||||
|
{ |
||||
|
if (channel > 3) |
||||
|
{ |
||||
|
LOG_E("Invalid channel: %d", channel); |
||||
|
return -RT_EINVAL; |
||||
|
} |
||||
|
|
||||
|
// 配置:OS=1, MUX=100+ch (单端), PGA=001 (±4.096V), MODE=1 (single), DR=100 (128SPS)
|
||||
|
rt_uint16_t config = 0x8000 | // OS = 1
|
||||
|
((0x04 | channel) << 12) | // MUX: AINx vs GND
|
||||
|
(0x01 << 9) | // PGA = ±4.096V
|
||||
|
(0x01 << 8) | // MODE = single-shot
|
||||
|
(0x04 << 5); // DR = 128 SPS
|
||||
|
|
||||
|
if (ads1115_write_config(config) != RT_EOK) |
||||
|
{ |
||||
|
return -RT_ERROR; |
||||
|
} |
||||
|
|
||||
|
rt_thread_mdelay(10); // 等待转换完成(128SPS ≈ 8ms)
|
||||
|
|
||||
|
return ads1115_read_conversion(raw_value); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
* 将原始 ADC 值转换为毫伏(mV) |
||||
|
* 假设使用 ±2.048V 量程(PGA=1),则 LSB = 2.048V / 32768 ≈ 0.0625 mV/LSB |
||||
|
* 但因为是单端且参考地,实际范围 0~2.048V → 满量程 2.048V = 32768 LSB |
||||
|
* 所以:Voltage(mV) = raw * (2048 / 32768) = raw * 0.0625 |
||||
|
*/ |
||||
|
static rt_int32_t ads1115_raw_to_mv(rt_int16_t raw) |
||||
|
{ |
||||
|
/* 注意:单端模式下,raw 应为正数(0 ~ 32767)*/ |
||||
|
return (rt_int32_t)(((rt_int64_t)raw * 125) / 1000); // 等价于 raw * 0.0625 * 1000
|
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* ADS1115 读取线程(示例:读取 AIN0) |
||||
|
*/ |
||||
|
static void ads1115_thread_entry(void *parameter) |
||||
|
{ |
||||
|
rt_int16_t raw = 0 ,mt = 3600; |
||||
|
|
||||
|
while (1) |
||||
|
{ |
||||
|
if(mt>3600) |
||||
|
{ |
||||
|
if (ads1115_read_channel(0, &raw) == RT_EOK) |
||||
|
{ |
||||
|
pow_bat = ads1115_raw_to_mv(raw); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
LOG_E("Failed to read ADS1115 P_BAT"); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
mt = 0; |
||||
|
} |
||||
|
|
||||
|
if (ads1115_read_channel(1, &raw) == RT_EOK) |
||||
|
{ |
||||
|
pow_code = ads1115_raw_to_mv(raw); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
LOG_E("Failed to read ADS1115 P_CODE"); |
||||
|
} |
||||
|
|
||||
|
if (ads1115_read_channel(2, &raw) == RT_EOK) |
||||
|
{ |
||||
|
pow_dev1 = ads1115_raw_to_mv(raw); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
LOG_E("Failed to read ADS1115 P_DEV1"); |
||||
|
} |
||||
|
|
||||
|
if (ads1115_read_channel(3, &raw) == RT_EOK) |
||||
|
{ |
||||
|
pow_dev2 = ads1115_raw_to_mv(raw); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
LOG_E("Failed to read ADS1115 P_DEV2"); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
rt_thread_mdelay(1000); // 每 秒读取一次
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* ADS1115 驱动初始化函数 |
||||
|
*/ |
||||
|
static int rt_hw_ads1115_init(void) |
||||
|
{ |
||||
|
i2c_bus = rt_i2c_bus_device_find(ADS1115_I2C_BUS_NAME); |
||||
|
if (i2c_bus == RT_NULL) |
||||
|
{ |
||||
|
LOG_E("Failed to find I2C bus: %s", ADS1115_I2C_BUS_NAME); |
||||
|
return -RT_ENOSYS; |
||||
|
} |
||||
|
|
||||
|
LOG_I("Found I2C bus: %s", ADS1115_I2C_BUS_NAME); |
||||
|
|
||||
|
/* 创建读取线程 */ |
||||
|
rt_thread_t tid = rt_thread_create("ads1115", |
||||
|
ads1115_thread_entry, |
||||
|
RT_NULL, |
||||
|
512, |
||||
|
RT_THREAD_PRIORITY_MAX - 2, |
||||
|
10); |
||||
|
if (tid != RT_NULL) |
||||
|
{ |
||||
|
rt_thread_startup(tid); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
LOG_E("Failed to create ADS1115 thread."); |
||||
|
return -RT_ERROR; |
||||
|
} |
||||
|
|
||||
|
return RT_EOK; |
||||
|
} |
||||
|
|
||||
|
/* 自动初始化 */ |
||||
|
INIT_APP_EXPORT(rt_hw_ads1115_init); |
||||
Binary file not shown.
Loading…
Reference in new issue