瑞萨单片机论坛
直播中

hehung

8年用户 659经验值
擅长:嵌入式技术
私信 关注

【RA4M2设计挑战赛】3. 硬件IIC读取ISL29035采集光照强度

过往分享

下面是参加RA4M2使用活动的分享:

【瑞萨RA4系列开发板体验】1. 新建工程+按键控制LED

【瑞萨RA4系列开发板体验】2. KEIL环境搭建+STLINK调试+FreeRTOS使用

【瑞萨RA4系列开发板体验】3. KEIL下UART实现printf与scanf重定向

【瑞萨RA4系列开发板体验】4. PWM驱动LED

【瑞萨RA4系列开发板体验】5. 硬件IIC驱动OLED显示汉字

【瑞萨RA4系列开发板体验】6. ADC测量摇杆模块偏移量

【瑞萨RA4系列开发板体验】7. 用DAC输出正弦波以及余弦波

【瑞萨RA4系列开发板体验】8. 超声波测距模块在RA4M2上的应用

【瑞萨RA4系列开发板体验】9. 用两路DAC在示波器上显示一个爱心

RA4M2挑战赛分享:

【RA4M2设计挑战赛】1. RASC配置FreeRTOS

【RA4M2设计挑战赛】2. 硬件IIC读取HS3003的温湿度数据

前言

上文讲解了对温湿度传感器HS300X的操作,本文将讲解对光照度传感器ISL29035的操作,通过IIC实现,基于FreeRTOS。

ISL29035的IIC地址也是0x44,与HS300X冲突,所以需要单独使用一条IIC总线,不能使用HS300X连接的sci3 i2c,最终选择了sci0 i2c。

硬件连接

不做过多说明,和HS300X类似,不能通过PMOD连接。

其中INT引脚为中断引脚,可以连接到单片机的中断pin上,当采集的光照在设定范围内就可以触发中断信号,本文不使用。

01.jpg

ISL29035操作方式

通过数据手册《REN_isl29035_DST_20100127.pdf》我们可以连接到ISL29035的操作方式,下面会详细说明。

IIC地址

见下图,地址为0x44(7bit)

寄存器总述

有两个命令寄存器,COMMAND-I以及COMMAND-II,主要就是配置这样两个寄出器。

  • 命令寄存器你地址分别为0x00以及0x01。

  • 读取数据会使用寄存器DATA,DATA为16bit,由两个寄存器组成,0x02表示数据低位,0x03表示数据高位。

  • 还有中断寄存器,当采样值在设定值范围内就出发中断信号输出到INT引脚,本文采集光照不涉及中断,所以不会操作这些寄存器。

COMMAND-I配置

使用这个传感器必须要初始化配置,因为传感器默认配置寄存器的值都是0,需要初始化为自己想要的配置以及功能才能正常采样。

寄存器详细描述见下图:

其中B0~B2为中断配置寄存器,本文采用默认,不进行设置。

配置操作模式

操作模式由寄存器0x00的B5~B7位来配置。

如下图,可以配置多种模式,可以采集光照或者红外光照,有单次采集模式或者连续采集模式。

本文采用了101b的配置,即0x05,连续采集自然光照强度。

COMMAND-II配置

COMMAND-II寄存器主要配置采样精度以及采样范围。

采样范围

采样范围由B0,B1配置。

本文使用了01b,即4000。

采样精度配置

主要是配置采样的ADC的精度,本文使用8bit精度,可以看到TABLE11中有关于采样精度与时间的关系,采样精度越高,时间越长,所以选择了8bit,只需要花费0.41ms既可以完成采样。

数据获取

数据获取本文不做过多介绍,熟悉IIC总线就会知道直接发送读取数据的寄存器地址既可以获取到数据了,即发送:

IIC地址+低位读+数据地址。

返回结果就是读取到的数据,详见代码实现逻辑。

数据低位地址为0x02,高位地址为0x03。

数据转化

参考下面,可以将采集到的数据转换为光照强度(Lux)。

根据我们的配置,光照强度 = 4000/256 * ADC采样值。

RASC配置

RASC需要对使用的IIC进行配置,如下:

代码实现逻辑

IIC初始化代码

IIC初始化与HS300X使用的IIC写到了一起,如下:

app_hw_i2c.c

/*
@hehung
2023-2-8
转载请注明出处,版权由@hehung所有
email: 1398660197qq.com
wechat: hehung95
*/

#include "hal_data.h"
#include "app_hw_i2c.h"

/* sci3 i2c */
i2c_master_event_t sci3_i2c_event = I2C_MASTER_EVENT_ABORTED;
i2c_master_event_t sci0_i2c_event = I2C_MASTER_EVENT_ABORTED;

/* Initialize for I2c driver */
void I2c_Init(void)
{
	fsp_err_t err;
	
	// initialize the sci3 i2c
	// scl - P408
	// sda - P409
	err = R_SCI_I2C_Open(&g_sci3_i2c_ctrl, &g_sci3_i2c_cfg);
	assert(FSP_SUCCESS == err);

    // initialize the sci1 i2c
	// scl - P100
	// sda - P101
	err = R_SCI_I2C_Open(&g_sci0_i2c_ctrl, &g_sci0_i2c_cfg);
	assert(FSP_SUCCESS == err);
}

/* SCI3 I2C interrupt callback */
void sci3_i2c_master_callback(i2c_master_callback_args_t *p_args)
{
    sci3_i2c_event = I2C_MASTER_EVENT_ABORTED;
	
    if (NULL != p_args)
    {
        /* capture callback event for validating the i2c transfer event*/
        sci3_i2c_event = p_args->event;
    }
}

/* SCI1 I2C interrupt callback */
void sci0_i2c_master_callback(i2c_master_callback_args_t *p_args)
{
    sci0_i2c_event = I2C_MASTER_EVENT_ABORTED;
	
    if (NULL != p_args)
    {
        /* capture callback event for validating the i2c transfer event*/
        sci0_i2c_event = p_args->event;
    }
}

app_hw_i2c.h

/*
@hehung
2023-2-8
转载请注明出处,版权由@hehung所有
email: 1398660197qq.com
wechat: hehung95
*/

#ifndef APP_HW_I2C_H_
#define APP_HW_I2C_H_

#include "app_common.h"

extern i2c_master_event_t sci3_i2c_event;
extern i2c_master_event_t sci0_i2c_event;

extern void I2c_Init(void);

#endif /* APP_HW_I2C_H_ */

ISL29035操作代码

app_isl29035.c

/*
@hehung
2023-2-8
转载请注明出处,版权由@hehung所有
email: 1398660197qq.com
wechat: hehung95
*/

/*******************************************************************************
* Header include
******************************************************************************/
#include "hal_data.h"
#include "app_hw_i2c.h"
#include "app_isl29035.h"

/*******************************************************************************
* Macro Definitions
******************************************************************************/
#define ISL29035_I2C_SLAVE_ADDR_7BIT           (0x44U)

#define ISL29035_COMMAND_1_ADDR                (0x00U)
#define ISL29035_COMMAND_2_ADDR                (0x01U)
#define ISL29035_DATA_L_ADDR                   (0x02U)
#define ISL29035_DATA_H_ADDR                   (0x03U)
#define ISL29035_INT_LT_LSB_ADDR               (0x04U)
#define ISL29035_INT_LT_MSB_ADDR               (0x05U)
#define ISL29035_INT_HT_LSB_ADDR               (0x06U)
#define ISL29035_INT_HT_MSB_ADDR               (0x07U)
#define ISL29035_ID_ADDR                       (0x0FU)

/* 10100000: enable ALS consinuously  */
#define ISL29035_COMMAND_1_INIT                (0xA0U)
/* 00000110: Lux full scale range is 4000 and ADC  */
#define ISL29035_COMMAND_2_INIT                (0x06U)

/*******************************************************************************
* Static Variables Definitions 
******************************************************************************/
static int32_t Isl29035_Resolution = ISL29035_RES_8BIT;
static int32_t Isl29035_range = ISL29035_LUX_SCALE_4K;

/*******************************************************************************
* Static Function Declarations 
******************************************************************************/
static void Isl29035_ReadFromI2C(uint8_t *data_buffer, uint8_t data_len);
static void Isl29035_WriteToI2C(uint8_t *data_buffer, uint8_t data_len);
static uint32_t Isl29035_DataConvert(uint32_t data);

/*******************************************************************************
* Function Definitions 
******************************************************************************/
/*********************Isl29035读数据函数************************************/
static void Isl29035_ReadFromI2C(uint8_t *data_buffer, uint8_t data_len)
{
	fsp_err_t err;
	uint32_t timeout_ms = 100;

   R_SCI_I2C_SlaveAddressSet(&g_sci0_i2c_ctrl, 
                            ISL29035_I2C_SLAVE_ADDR_7BIT, 
							I2C_MASTER_ADDR_MODE_7BIT);

	err = R_SCI_I2C_Read(&g_sci0_i2c_ctrl, data_buffer, data_len, true);
	assert(FSP_SUCCESS == err);
	
	/* Since there is nothing else to do, block until Callback triggers*/
	while ((I2C_MASTER_EVENT_TX_COMPLETE != sci0_i2c_event) && timeout_ms>0)
	{
		R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
		timeout_ms--;
	}
	
	if (I2C_MASTER_EVENT_ABORTED == sci0_i2c_event)
	{
		__BKPT(0);
	}
	/* Read data back from the I2C slave */
	sci0_i2c_event = I2C_MASTER_EVENT_ABORTED;
}

/*********************Isl29035写数据函数************************************/
static void Isl29035_WriteToI2C(uint8_t *data_buffer, uint8_t data_len)
{
	fsp_err_t err;
	uint32_t timeout_ms = 100;

   R_SCI_I2C_SlaveAddressSet(&g_sci0_i2c_ctrl, 
                             ISL29035_I2C_SLAVE_ADDR_7BIT, 
							 I2C_MASTER_ADDR_MODE_7BIT);

	err = R_SCI_I2C_Write(&g_sci0_i2c_ctrl, data_buffer, data_len, true);
	assert(FSP_SUCCESS == err);
	
	/* Since there is nothing else to do, block until Callback triggers*/
	while ((I2C_MASTER_EVENT_TX_COMPLETE != sci0_i2c_event) && timeout_ms>0)
	{
		R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
		timeout_ms--;
	}
	
	if (I2C_MASTER_EVENT_ABORTED == sci0_i2c_event)
	{
		__BKPT(0);
	}
	/* Read data back from the I2C slave */
	sci0_i2c_event = I2C_MASTER_EVENT_ABORTED;
}

static uint32_t Isl29035_DataConvert(uint32_t data)
{
   return (uint32_t)((double)Isl29035_range / (double)Isl29035_Resolution * data);
}

void Isl29035_Init(void)
{
   uint8_t command[2U];
   
   command[0] = ISL29035_COMMAND_1_ADDR;
   command[1] = ISL29035_COMMAND_1_INIT;
   Isl29035_WriteToI2C(command, 2);

   command[0] = ISL29035_COMMAND_2_ADDR;
   command[1] = ISL29035_COMMAND_2_INIT;
   Isl29035_WriteToI2C(command, 2);

   Isl29035_Resolution = ISL29035_RES_8BIT;
   Isl29035_range = ISL29035_LUX_SCALE_4K;
}

uint32_t Isl29035_ReadData(void)
{
   uint8_t data;
   uint8_t address;
   uint16_t read_adc;

   /* Read low byte of data */
   address = ISL29035_DATA_L_ADDR;
   Isl29035_WriteToI2C(&address, 1);
   Isl29035_ReadFromI2C(&data, 1);
   read_adc = data;

   /* Read high byte of data */ 
   address = ISL29035_DATA_H_ADDR;
   Isl29035_WriteToI2C(&address, 1);
   Isl29035_ReadFromI2C(&data, 1);
   read_adc |= (data << 8U);

   return Isl29035_DataConvert(read_adc);
}

app_isl29035.h

/*
@hehung
2023-2-8
转载请注明出处,版权由@hehung所有
email: 1398660197qq.com
wechat: hehung95
*/

#ifndef APP_ISL29035_H_
#define APP_ISL29035_H_

#include "app_common.h"

/* ISL29035 ADC resolution */
#define ISL29035_RES_16BIT        (65536U)
#define ISL29035_RES_12BIT        (4096U)
#define ISL29035_RES_8BIT         (256U)
#define ISL29035_RES_4BIT         (16U)

/* ISL29035 full scale lux range */
#define ISL29035_LUX_SCALE_1K     (1000U)
#define ISL29035_LUX_SCALE_4K     (4000U)
#define ISL29035_LUX_SCALE_16K    (16000U)
#define ISL29035_LUX_SCALE_64K    (64000U)


extern void Isl29035_Init(void);
extern uint32_t Isl29035_ReadData(void);

#endif /* APP_ISL29035_H_ */

读取数据

ISL29035的代码与HS300X写在了一起。

#define DISP_DEBUG

// Display sensor information: humidity/temperature/light strength
static void Disp_SensorMonitor(void)
{
    char text[16];
    s_Hs300xDataType humi_temp;
	uint32_t lux;

    humi_temp = Hs300x_ReadData();
#ifdef DISP_DEBUG
	printf("humidity: %.2f%%, temperature: %.2fC\n", humi_temp.humi, humi_temp.temp);
#endif
		
	lux = Isl29035_ReadData();
#ifdef DISP_DEBUG
	printf("Lux: %u\n", lux);
#endif

    sprintf(text, "Humi:%.2f%%   ", humi_temp.humi);
    OLED_ShowString(0, 0, (const uint8_t*)text, 16, 1);
    sprintf(text, "Temp:%.2f   ", humi_temp.temp);
    OLED_ShowString(0, 16, (const uint8_t*)text, 16, 1);
    sprintf(text, "Lux:%u   ", lux);
    OLED_ShowString(0, 32, (const uint8_t*)text, 16, 1);
    OLED_Refresh_Gram();
}

实现效果

由于我所在的位置光照比较暗,采集的强度只有70多,移到光强的地方,会变到很大。

12.jpg

更多回帖

发帖
×
20
完善资料,
赚取积分