eefocus_4062187 发表于 2026-7-20 21:57:50

【RA-Eco-RA6M4开发板评测】光照强度监测仪

# 【RA-Eco-RA6M4开发板评测】光照强度监测仪

本文介绍了 RA-Eco-RA6M4-100PIN-V2.0 开发板通过 IIC 协议驱动 ADS1115 模块,并连接 TEMT6000 传感器模块,实现环境光照强度监测仪的项目设计,包括项目介绍、工程创建、参数配置、工程调试以及效果演示等。

## 项目介绍

- 模块设计:TEMT6000 传感器、ADS1115 模块、模块 PCB 设计、原理图;
- 准备工作:硬件连接、环境搭建;
- 工程测试:工程创建、工程配置、流程图、代码、编译上传、效果演示。

!(//m.qjumbo.com/forum/data/attachment/forum/202607/20/215726iujx7lmpqyf6xzju.jpg)



## ADS1115 模块

ADS1115是一款由德州仪器推出的16位模拟数字转换器(ADC),支持I2C接口。工作电流仅为20μA,转换速率可在 8SPS 到 860SPS 之间自定义;支持 2.0V 到 5.5V 的宽电压输入。

!(//m.qjumbo.com/forum/data/attachment/forum/202607/20/215440hb2cib520br243i2.jpg)



更多参数详见:(https://www.ti.com.cn/product/cn/ADS1115) .

原理图

!(//m.qjumbo.com/forum/data/attachment/forum/202607/20/215415o60eeg0jgcw5lgeh.jpg)



PCB 项目详见:(https://oshwhub.com/jinleili/project_pemhgfob) .

### TEMT6000

TEMT6000是一个三极管类型的光敏传感器,其光照强度和基极的电流成正比。

!(//m.qjumbo.com/forum/data/attachment/forum/202607/20/215353mzjdozi57r9srsg0.jpg)



详见:(https://www.vishay.com/en/product/81579/) .

## 硬件连接

使用杜邦线连接 ADS1115 模块与 RA6M4-Eco 开发板,接线方式如下

| ADS1115 | RA6M4 | Note         |
| ------- | ----- | ------------ |
| SDA   | P400| Serial Data|
| SCL   | P401| Serial Clock |
| GND   | GND   | Ground       |
| VCC   | 3V3   | Power      |

使用杜邦线连接 ADS1115 模块和 TEMT6000 传感器模块,接线方式如下

| TEMT6000 | ADS1115 | Note   |
| -------- | ------- | ------ |
| S      | A0      | Signal |
| G      | A-      | Ground |
| V      | A+      | Power|

使用杜邦线连接 JLINK-OB 和 RA6M4,实现工程调试、固件上传、串口通信,接线方式如下

| Jlink-OB | RA6M4      | Note      |
| :------- | :--------- | :-------- |
| DIO      | SWDIO      | Data I/O|
| CLK      | SWCLK      | Clock   |
| RXD      | TXD (P109) | Transmite |
| TXD      | RXD (P110) | Receive   |
| GND      | GND      | Ground    |
| 3V3      | VCC      | Power   |

实物图

!(//m.qjumbo.com/forum/data/attachment/forum/202607/20/215458p0upb4muvhz6iybv.jpg)



自制 JLINK-OB 工程详见:(https://oshwhub.com/jinleili/j-link-ob-gai-jin-ban) .

## 环境搭建

搭建和使用 e^2^ studio IDE 开发环境。

- 下载并安装 [瑞萨FSP (flexible software package) 灵活配置软件包](https://www.renesas.cn/zh/software-tool/flexible-software-package-fsp) ;
- 安装时注意选择 GNU ARM 工具链;

## 工程创建

- 文件 - 新建 - 瑞萨 C/C++ 项目 - `Renesas RA ` ;
- 自定义设备选择 `R7FA6M4AF3CFP` ,调试器选择 J-Link ;
- 项目创建完成后,选择进入透视图模式;

## 工程配置

工程配置包括引脚时钟配置、串口配置、IIC 配置。

### 时钟配置

根据原理图可知,板载 XTAL 晶振频率为 12MHz,需要重新配置 IDE 时钟树。

!(//m.qjumbo.com/forum/data/attachment/forum/202607/20/215514c0kx107dl8llz0pn.jpg)



### 串口配置

- 进入 FSP 配置界面,打开 Pins 标签页,根据原理图,板载 CH340 对应串口引脚为 P109 和 P110,因此将 SCI9 配置为异步串口模式;

!(//m.qjumbo.com/forum/data/attachment/forum/202607/20/215533ke401ejl1yq6gllj.jpg)



- 打开 `Stacks` 标签页,新建串口通信堆栈 `New Stack` - `Connectivity` - `UART (r_sci_uart)` ;
- 串口属性配置,General 标签下的 Channel 改为 9,名称改为 `g_uart9`,中断回调函数命名为 `user_uart9_callback`;
- 进入 BSP 标签页,配置 RA Common 属性,RA Common 标签下的 Heap size 改为 `0x2000`;

详见:[瑞萨RA-Eco-RA6M4评测 - 介绍、环境搭建、工程测试](//m.qjumbo.com/forum/thread-235881-1-1.html) .

### IIC 配置

- 打开 `Stacks` 标签页,新建硬件 IIC 总线堆栈 `New Stack` - `Connectivity` - `IIC Master (r_iic_master)` ;
- IIC 属性配置,Module 标签下的 Channel 设置为 0,名称为 `g_i2c_master0`,地址 `0x48`,中断回调函数命名为 `IIC_master_callback`;
- 检查引脚定义 SCL0 对应 P400,SDA0 对应 P401 ;
- 由原理图可知,P400 和 P401 引脚位于 PMOD1 接口,且 P400 需要将 SB13 短接,或使用 0603 封装的 0Ω 电阻焊接;

!(//m.qjumbo.com/forum/data/attachment/forum/202607/20/215552iy36ydmlm6tgdgy3.jpg)



- 点击 `Generate Project Content` ;
- 右键项目文件夹,构建工程,确认无报错;

## 流程图

!(//m.qjumbo.com/forum/data/attachment/forum/202607/20/215611ojf0c55000ee9am5.jpg)




## 工程代码

包括主程序和 ADS1115 传感器驱动程序。

### 主程序

打开 `./src/hal_entry.c` 文件,添加如下代码

```c++
#include "hal_data.h"
#include "ads1115.h"
#include <stdio.h>

/********************************
* UART Configurations
* see
* //m.qjumbo.com/forum/thread-235881-1-1.html
* for details
********************************/

/* 全局ADS1115句柄 */
static ads1115_handle_t g_ads1115;

// I2C Callback
i2c_master_event_t i2c_event = I2C_MASTER_EVENT_ABORTED;
void IIC_master_callback(i2c_master_callback_args_t *p_args)
{
    i2c_event = I2C_MASTER_EVENT_ABORTED;
    if (NULL != p_args)
    {
      i2c_event = p_args->event;
    }
}

void hal_entry(void)
{
    /* TODO: add your own code here */
    err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
    assert(FSP_SUCCESS == err);

    float voltage;

    /* 初始化ADS1115,使用I2C0实例 */
    err = ads1115_init(&g_ads1115, &g_i2c_master0, ADS1115_ADDR);
    if (err != FSP_SUCCESS)
    {
      printf("ADS1115 init failed: %d\r\n", err);
      while(1);
    }

    printf("RA6M4 + ADS1115 Module Driver Test\r\n");
    printf("==================================\r\n");

#if 1/* 单次转换模式示例 */

    printf("\r\n");

    while (1)
    {
      /* 读取A0通道电压,PGA=±4.096V,128SPS */
      err = ads1115_read_voltage(&g_ads1115, ADS1115_MUX_AIN0_GND, &voltage);
      if (err == FSP_SUCCESS)
      {
            printf("A0 = %.4f V\r\n", voltage);
      }
      else
      {
            printf("Read error: %d\r\n", err);
      }

      R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS);
    }
}
```

保存文件。

### 驱动程序

在 `./src` 文件夹新建 `ads1115.h` 驱动头文件,添加如下代码

```c++
#ifndef ADS1115_H
#define ADS1115_H

#include "hal_data.h"
#include <stdint.h>
#include <stdbool.h>

/* ADS1115 I2C地址(ADDR引脚接GND) */
#define ADS1115_ADDR            0x48

/* ADS1115寄存器地址 */
#define ADS1115_REG_CONVERSION0x00
#define ADS1115_REG_CONFIG      0x01
#define ADS1115_REG_LO_THRESH   0x02
#define ADS1115_REG_HI_THRESH   0x03

/* 输入通道选择(MUX位) */
typedef enum
{
    ADS1115_MUX_AIN0_AIN1 = 0x00,// 差分:A0 - A1
    ADS1115_MUX_AIN0_AIN3 = 0x01,// 差分:A0 - A3
    ADS1115_MUX_AIN1_AIN3 = 0x02,// 差分:A1 - A3
    ADS1115_MUX_AIN2_AIN3 = 0x03,// 差分:A2 - A3
    ADS1115_MUX_AIN0_GND= 0x04,// 单端:A0
    ADS1115_MUX_AIN1_GND= 0x05,// 单端:A1
    ADS1115_MUX_AIN2_GND= 0x06,// 单端:A2
    ADS1115_MUX_AIN3_GND= 0x07,// 单端:A3
} ads1115_mux_t;

/* PGA量程配置 */
typedef enum
{
    ADS1115_PGA_6_144V = 0x00,// ±6.144V, LSB = 187.5uV
    ADS1115_PGA_4_096V = 0x01,// ±4.096V, LSB = 125uV
    ADS1115_PGA_2_048V = 0x02,// ±2.048V, LSB = 62.5uV (默认)
    ADS1115_PGA_1_024V = 0x03,// ±1.024V, LSB = 31.25uV
    ADS1115_PGA_0_512V = 0x04,// ±0.512V, LSB = 15.625uV
    ADS1115_PGA_0_256V = 0x05,// ±0.256V, LSB = 7.8125uV
} ads1115_pga_t;

/* 数据速率 */
typedef enum
{
    ADS1115_DR_8SPS   = 0x00,
    ADS1115_DR_16SPS= 0x01,
    ADS1115_DR_32SPS= 0x02,
    ADS1115_DR_64SPS= 0x03,
    ADS1115_DR_128SPS = 0x04,// 默认
    ADS1115_DR_250SPS = 0x05,
    ADS1115_DR_475SPS = 0x06,
    ADS1115_DR_860SPS = 0x07,
} ads1115_dr_t;

/* 工作模式 */
typedef enum
{
    ADS1115_MODE_CONTINUOUS = 0x00,
    ADS1115_MODE_SINGLE   = 0x01,
} ads1115_mode_t;

/* 设备句柄 */
typedef struct
{
    i2c_master_instance_t const * p_i2c;    // I2C实例指针
    uint8_t                     addr;   // I2C地址
    ads1115_pga_t               pga;      // 当前PGA配置
    ads1115_dr_t                  dr;       // 当前数据速率
} ads1115_handle_t;

/* 初始化与反初始化 */
fsp_err_t ads1115_init(ads1115_handle_t * p_handle, i2c_master_instance_t const * p_i2c, uint8_t addr);
fsp_err_t ads1115_deinit(ads1115_handle_t * p_handle);

/* 配置 */
fsp_err_t ads1115_set_config(ads1115_handle_t * p_handle, ads1115_mux_t mux, ads1115_pga_t pga,
                              ads1115_dr_t dr, ads1115_mode_t mode);

/* 单次转换读取 */
fsp_err_t ads1115_read_single(ads1115_handle_t * p_handle, ads1115_mux_t channel, int16_t * p_raw);
fsp_err_t ads1115_read_voltage(ads1115_handle_t * p_handle, ads1115_mux_t channel, float * p_voltage);

/* 连续转换模式 */
fsp_err_t ads1115_start_continuous(ads1115_handle_t * p_handle, ads1115_mux_t channel);
fsp_err_t ads1115_read_continuous(ads1115_handle_t * p_handle, int16_t * p_raw);
fsp_err_t ads1115_read_continuous_voltage(ads1115_handle_t * p_handle, float * p_voltage);

/* 原始值转电压 */
float ads1115_raw_to_voltage(int16_t raw, ads1115_pga_t pga);

/* 获取转换时间(ms) */
uint16_t ads1115_get_conversion_time_ms(ads1115_dr_t dr);

#endif /* ADS1115_H */
```

保存文件。

#### 源文件

在 `./src` 文件夹新建 `ads1115.c` 驱动源文件,并添加如下代码

```c++
#include "ads1115.h"
#include <string.h>

/* 内部缓冲区 */
static uint8_tg_tx_buffer;
static uint8_tg_rx_buffer;
static volatile bool g_i2c_complete = false;
static i2c_master_event_t g_i2c_event;

/* 内部I2C回调 */
static void ads1115_i2c_callback(i2c_master_callback_args_t *p_args)
{
    g_i2c_event = p_args->event;
    g_i2c_complete = true;
}

/* 等待I2C传输完成 */
static fsp_err_t ads1115_wait_complete(uint32_t timeout_us)
{
    uint32_t timeout = timeout_us;
    while (!g_i2c_complete)
    {
      if (--timeout == 0)
      {
            return FSP_ERR_TIMEOUT;
      }
    }
    g_i2c_complete = false;
    return FSP_SUCCESS;
}

/* 写寄存器 */
static fsp_err_t ads1115_write_reg(ads1115_handle_t * p_handle, uint8_t reg, uint16_t value)
{
    fsp_err_t err;

    g_tx_buffer = reg;
    g_tx_buffer = (uint8_t)(value >> 8);    // MSB first
    g_tx_buffer = (uint8_t)(value & 0xFF);// LSB

    err = p_handle->p_i2c->p_api->write(p_handle->p_i2c->p_ctrl, g_tx_buffer, 3, false);
    if (err != FSP_SUCCESS) return err;

    err = ads1115_wait_complete(100000);
    if (err != FSP_SUCCESS) return err;

    return (g_i2c_event == I2C_MASTER_EVENT_TX_COMPLETE) ? FSP_SUCCESS : FSP_ERR_ABORTED;
}

/* 读寄存器 */
static fsp_err_t ads1115_read_reg(ads1115_handle_t * p_handle, uint8_t reg, uint16_t * p_value)
{
    fsp_err_t err;

    /* 写寄存器地址(带restart) */
    g_tx_buffer = reg;
    err = p_handle->p_i2c->p_api->write(p_handle->p_i2c->p_ctrl, g_tx_buffer, 1, true);
    if (err != FSP_SUCCESS) return err;

    err = ads1115_wait_complete(100000);
    if (err != FSP_SUCCESS) return err;

    /* 读2字节数据 */
    err = p_handle->p_i2c->p_api->read(p_handle->p_i2c->p_ctrl, g_rx_buffer, 2, false);
    if (err != FSP_SUCCESS) return err;

    err = ads1115_wait_complete(100000);
    if (err != FSP_SUCCESS) return err;

    if (g_i2c_event != I2C_MASTER_EVENT_RX_COMPLETE)
    {
      return FSP_ERR_ABORTED;
    }

    *p_value = ((uint16_t)g_rx_buffer << 8) | g_rx_buffer;
    return FSP_SUCCESS;
}

/* 构建配置寄存器值 */
static uint16_t ads1115_build_config(ads1115_mux_t mux, ads1115_pga_t pga, ads1115_dr_t dr,
                                    ads1115_mode_t mode, bool start_conversion)
{
    uint16_t config = 0;

    if (start_conversion)
    {
      config |= (1U << 15);// OS = 1, 启动单次转换
    }

    config |= ((uint16_t)mux & 0x07) << 12;   // MUX
    config |= ((uint16_t)pga & 0x07) << 9;    // PGA
    config |= ((uint16_t)mode & 0x01) << 8;   // MODE
    config |= ((uint16_t)dr & 0x07) << 5;   // DR
    config |= (0x03U << 0);                  // CQUE = 11, 禁用比较器

    return config;
}

/* 初始化 */
fsp_err_t ads1115_init(ads1115_handle_t * p_handle, i2c_master_instance_t const * p_i2c, uint8_t addr)
{
    fsp_err_t err;

    if (p_handle == NULL || p_i2c == NULL)
    {
      return FSP_ERR_INVALID_ARGUMENT;
    }

    memset(p_handle, 0, sizeof(ads1115_handle_t));
    p_handle->p_i2c = p_i2c;
    p_handle->addr= addr;
    p_handle->pga   = ADS1115_PGA_2_048V;// 默认
    p_handle->dr    = ADS1115_DR_128SPS;   // 默认

    /* 打开I2C */
    err = p_i2c->p_api->open(p_i2c->p_ctrl, p_i2c->p_cfg);
    if (err != FSP_SUCCESS) return err;

    /* 设置回调 */
    err = p_i2c->p_api->callbackSet(p_i2c->p_ctrl, ads1115_i2c_callback, NULL, NULL);
    if (err != FSP_SUCCESS) return err;

    return FSP_SUCCESS;
}

/* 反初始化 */
fsp_err_t ads1115_deinit(ads1115_handle_t * p_handle)
{
    if (p_handle == NULL || p_handle->p_i2c == NULL)
    {
      return FSP_ERR_INVALID_ARGUMENT;
    }

    return p_handle->p_i2c->p_api->close(p_handle->p_i2c->p_ctrl);
}

/* 设置配置 */
fsp_err_t ads1115_set_config(ads1115_handle_t * p_handle, ads1115_mux_t mux, ads1115_pga_t pga,
                              ads1115_dr_t dr, ads1115_mode_t mode)
{
    fsp_err_t err;
    uint16_t config;

    if (p_handle == NULL)
    {
      return FSP_ERR_INVALID_ARGUMENT;
    }

    p_handle->pga = pga;
    p_handle->dr= dr;

    config = ads1115_build_config(mux, pga, dr, mode, false);
    err = ads1115_write_reg(p_handle, ADS1115_REG_CONFIG, config);

    return err;
}

/* 单次转换读取原始值 */
fsp_err_t ads1115_read_single(ads1115_handle_t * p_handle, ads1115_mux_t channel, int16_t * p_raw)
{
    fsp_err_t err;
    uint16_t config;
    uint16_t raw_u16;

    if (p_handle == NULL || p_raw == NULL)
    {
      return FSP_ERR_INVALID_ARGUMENT;
    }

    /* 构建配置并启动转换 */
    config = ads1115_build_config(channel, p_handle->pga, p_handle->dr, ADS1115_MODE_SINGLE, true);
    err = ads1115_write_reg(p_handle, ADS1115_REG_CONFIG, config);
    if (err != FSP_SUCCESS) return err;

    /* 等待转换完成 */
    R_BSP_SoftwareDelay(ads1115_get_conversion_time_ms(p_handle->dr), BSP_DELAY_UNITS_MILLISECONDS);

    /* 读取结果 */
    err = ads1115_read_reg(p_handle, ADS1115_REG_CONVERSION, &raw_u16);
    if (err != FSP_SUCCESS) return err;

    *p_raw = (int16_t)raw_u16;
    return FSP_SUCCESS;
}

/* 单次转换读取电压 */
fsp_err_t ads1115_read_voltage(ads1115_handle_t * p_handle, ads1115_mux_t channel, float * p_voltage)
{
    fsp_err_t err;
    int16_t raw;

    err = ads1115_read_single(p_handle, channel, &raw);
    if (err != FSP_SUCCESS) return err;

    *p_voltage = ads1115_raw_to_voltage(raw, p_handle->pga);
    return FSP_SUCCESS;
}

/* 启动连续转换模式 */
fsp_err_t ads1115_start_continuous(ads1115_handle_t * p_handle, ads1115_mux_t channel)
{
    uint16_t config;

    if (p_handle == NULL)
    {
      return FSP_ERR_INVALID_ARGUMENT;
    }

    config = ads1115_build_config(channel, p_handle->pga, p_handle->dr, ADS1115_MODE_CONTINUOUS, false);
    return ads1115_write_reg(p_handle, ADS1115_REG_CONFIG, config);
}

/* 连续模式读取原始值 */
fsp_err_t ads1115_read_continuous(ads1115_handle_t * p_handle, int16_t * p_raw)
{
    fsp_err_t err;
    uint16_t raw_u16;

    if (p_handle == NULL || p_raw == NULL)
    {
      return FSP_ERR_INVALID_ARGUMENT;
    }

    err = ads1115_read_reg(p_handle, ADS1115_REG_CONVERSION, &raw_u16);
    if (err != FSP_SUCCESS) return err;

    *p_raw = (int16_t)raw_u16;
    return FSP_SUCCESS;
}

/* 连续模式读取电压 */
fsp_err_t ads1115_read_continuous_voltage(ads1115_handle_t * p_handle, float * p_voltage)
{
    fsp_err_t err;
    int16_t raw;

    err = ads1115_read_continuous(p_handle, &raw);
    if (err != FSP_SUCCESS) return err;

    *p_voltage = ads1115_raw_to_voltage(raw, p_handle->pga);
    return FSP_SUCCESS;
}

/* 原始值转电压 */
float ads1115_raw_to_voltage(int16_t raw, ads1115_pga_t pga)
{
    float lsb;

    switch (pga)
    {
      case ADS1115_PGA_6_144V: lsb = 0.0001875f; break;
      case ADS1115_PGA_4_096V: lsb = 0.000125f;   break;
      case ADS1115_PGA_2_048V: lsb = 0.0000625f;break;
      case ADS1115_PGA_1_024V: lsb = 0.00003125f; break;
      case ADS1115_PGA_0_512V: lsb = 0.000015625f; break;
      case ADS1115_PGA_0_256V: lsb = 0.0000078125f; break;
      default:               lsb = 0.0000625f;break;
    }

    return (float)raw * lsb;
}

/* 获取转换时间(ms),留有余量 */
uint16_t ads1115_get_conversion_time_ms(ads1115_dr_t dr)
{
    switch (dr)
    {
      case ADS1115_DR_8SPS:   return 130;
      case ADS1115_DR_16SPS:return 70;
      case ADS1115_DR_32SPS:return 35;
      case ADS1115_DR_64SPS:return 20;
      case ADS1115_DR_128SPS: return 12;
      case ADS1115_DR_250SPS: return 6;
      case ADS1115_DR_475SPS: return 4;
      case ADS1115_DR_860SPS: return 3;
      default:                return 12;
    }
}
```

保存文件。

## 工程编译

- 右键项目文件夹,选择 `属性` ,进入 `C/C++ 构建` - `设置` 选项;
- 进入 `GNU Arm Cross Create Flash Image - General` 选项;
- 在输出格式中选择 `Intel HEX` ,应用并关闭;
- 右键项目文件夹,构建工程,确认无报错;
- 查看工程目录下的 `Debug` 文件夹,生成相应的 HEX 格式的固件;

## 固件上传

开发板支持串口烧录、J-Link、EZ-Cube 调试器烧录等,这里使用 JLINK-OB 调试工程。

- 点击工具栏的小虫子 Debug 按钮,进入调试界面;
- 或右键项目文件夹,选择调试配置,选中当前项目对应的 elf 文件,调试工具为 JLINK,开始调试;
- 进入调试界面,点击菜单栏的运行按钮,程序开始执行;

!(//m.qjumbo.com/forum/data/attachment/forum/202607/20/215639nl60wz1z1o0szguz.jpg)



使用 USB 烧录固件的方案详见:[瑞萨RA-Eco-RA6M4评测 - 介绍、环境搭建、工程测试](//m.qjumbo.com/forum/thread-235881-1-1.html) .

## 效果演示

- 运行串口调试助手软件,连接 Jlink CDC 虚拟串口,配置波特率等参数;
- 打开串口,接收 A0 电压数据;

!(//m.qjumbo.com/forum/data/attachment/forum/202607/20/215653upmyhxhsvmzmp1yb.gif)



- 串口打印 A0 电压和 TEMT6000 光照强度数据;

!(//m.qjumbo.com/forum/data/attachment/forum/202607/20/215708f1uxzl323lx5llx8.jpg)



## 总结

本文介绍了 RA-Eco-RA6M4-100PIN-V2.0 开发板通过 IIC 协议驱动 ADS1115 模块,并连接 TEMT6000 传感器模块,实现环境光照强度监测仪的项目设计,包括项目介绍、工程创建、参数配置、工程调试以及效果演示等,为相关产品的快速开发和应用设计提供了参考。

页: [1]
查看完整版本: 【RA-Eco-RA6M4开发板评测】光照强度监测仪

Baidu
map