Renesas R7FA8D1BH (Cortex®-M85)控制ISLS29035
目录
概述
1 ISL29035芯片介绍
1.1 ISL29035特征
1.2 ISL29035工作电路
1.3 ISL29035工作时序分析
1.4 ISL29035相关的寄存器
1.4.1 COMMAND-1( 0x00 )
1.4.2 COMMAND-11(0x01)
1.4.3 DATA寄存器(0x02和0x03)
1.4.4 中断报警寄存器(0x04和0x05)
1.4. 5 中断报警寄存器(0x06和0x07)
1.4. 6 ID寄存器(0x0f)
1.5 采样值到实际Lux值转换
2 I2C驱动实现
2.1 硬件接口
2.2 FSP配置I2C
2.3 I2C驱动程序实现
3 ISL29035驱动程序实现
3.1 驱动程序功能介绍
3.2 代码实现
4 测试功能
4.1 编写测试代码
4.2 测试
概述
本文主要介绍ISLS29035芯片驱动的相关内容,包括ISLS29035芯片的特性,其内部各个寄存器的功能,以及和MCU相连后其时序操作的注意点。还介绍了R7FA8D1BH上I2C模块的使用方法,包括FSP配置参数,I2C驱动代码,以及使用I2C接口驱动ISLS29035的功能实现方法等内容。
1 ISL29035芯片介绍
1.1 ISL29035特征
ISL29035 - Integrated Digital Light Sensor with Interrupt | Renesas
ISL29035是一款数字型光感传感器,采用通用I2C接口,可实时采集环境的光照强度。其主要特点如下:
关注几个核心参数:
1) 其采用16-bit ADC采样数据,所以,该传感器有这个极高的分辨率
2)数据采样区间: 1: 420 0000
3)采用标准的I2C协议,便于使用MCU驱动该芯片
1.2 ISL29035工作电路
下图是官方给的标准工作电路,采用标准的i2c通信电路,还额外增加一个INT中断IO,用于对外提供一个报警信号,其在低电平时有效。
sensor IO接口定义如下:
1.3 ISL29035工作时序分析
1) 写数据时序
2) 读数据时序
3) 连续读多个数据时序
1.4 ISL29035相关的寄存器
其主要寄存器如下表:
1.4.1 COMMAND-1( 0x00 )
其中:B7,B6,B5用于配置 采样方式,例如:配置为101则为连续采样模式
1.4.2 COMMAND-11(0x01)
在该寄存器中,B0和B1用于配置lux的范围
B3和B2用于配置ADC的采样精度:
1.4.3 DATA寄存器(0x02和0x03)
data寄存器的地址分别为0x02(数据低 8个 bit)和0x03(数据高8个bit)
1.4.4 中断报警寄存器(0x04和0x05)
该寄存器的值用于设置报警数据的下限值
1.4. 5 中断报警寄存器(0x06和0x07)
该寄存器的值用于设置报警数据的上限值
1.4. 6 ID寄存器(0x0f)
该寄存器用于存在sensor的ID值
1.5 采样值到实际Lux值转换
根据datasheet的资料可得:
Range 可取的值(Lux): 1000, 4000, 16000, 64000
Count( Max) 可取的值: 16, 256, 4096, 65536
举个例子:
配置 address = 0x01寄存器, B3B2 = 10, adc 采样为8bit, Count(max) = 256
B1B0 = 01, Lux的range = 4000
当前从DATA寄存器读取的值为: 120, 其对应的lux值为 val = (4000/256)* 120
2 I2C驱动实现
2.1 硬件接口
本系统采用野火瑞萨R7FA8D1BHECBD-BTB开发板,其与Sensor之间的接口关系如下:
2.2 FSP配置I2C
1) 在Pins面板上配置I2C IO port
2) 创建Stack对象
3)配置Stack的参数
2.3 I2C驱动程序实现
使用FSP完成参数配置后,生成硬件相关的配置代码,接下来需要实现I2C相关的驱动接口
1)创建bsp_i2c.c文件,编写如下代码
/*
FILE NAME : bsp_i2c.c
Description: user i2c interface
Author : tangmingfei2013@126.com
Date : 2024/06/03
*/
#include "bsp_i2c.h"
#include "hal_data.h"
#define TIME_OUT 10000
i2c_master_event_t g_i2c_callback_event;
void sci_b_i2c_master_callback (i2c_master_callback_args_t * p_args)
{
if (NULL != p_args)
{
g_i2c_callback_event = p_args->event;
}
}
void i2c2_init_para( uint32_t const slaveAddress )
{
fsp_err_t err;
err = R_SCI_B_I2C_Open(&g_i2c0_ctrl, &g_i2c0_cfg);
assert(FSP_SUCCESS == err);
err = R_SCI_B_I2C_SlaveAddressSet(&g_i2c0_ctrl, slaveAddress, I2C_MASTER_ADDR_MODE_7BIT);
assert(FSP_SUCCESS == err);
}
void i2c2_write_bytes(uint8_t *pbuff, uint16_t length )
{
unsigned int timeout_ms = TIME_OUT;
fsp_err_t err;
err = R_SCI_B_I2C_Write(&g_i2c0_ctrl, pbuff, length, false);
assert(FSP_SUCCESS == err);
g_i2c_callback_event = I2C_MASTER_EVENT_ABORTED;
/* Since there is nothing else to do, block until Callback triggers*/
while ((I2C_MASTER_EVENT_TX_COMPLETE != g_i2c_callback_event) && timeout_ms)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
timeout_ms--;;
}
}
void i2c2_read_bytes(uint8_t *pbuff, uint16_t length )
{
unsigned int timeout_ms = TIME_OUT;
fsp_err_t err;
g_i2c_callback_event = I2C_MASTER_EVENT_ABORTED;
err = R_SCI_B_I2C_Read(&g_i2c0_ctrl, pbuff, length, false);
assert(FSP_SUCCESS == err);
/* Since there is nothing else to do, block until Callback triggers*/
while ((I2C_MASTER_EVENT_RX_COMPLETE != g_i2c_callback_event) && timeout_ms)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
timeout_ms--;;
}
}
/* End of this file */
2)创建bsp_i2c.h文件,编写如下代码:
/*
FILE NAME : bsp_i2c.h
Description: user i2c interface
Author : tangmingfei2013@126.com
Date : 2024/06/03
*/
#ifndef BSP_I2C_H
#define BSP_I2C_H
#include "hal_data.h"
void i2c2_init_para( uint32_t const slaveAddress );
void i2c2_write_bytes(uint8_t *pbuff, uint16_t length );
void i2c2_read_bytes(uint8_t *pbuff, uint16_t length );
#endif /* BSP_I2C_H */
3 ISL29035驱动程序实现
3.1 驱动程序功能介绍
驱动程序分成两个层次,底层使用I2C接口,实现读写寄存器功能,在应用层中调用者两个函数接口实现ISL29035芯片的初始化功能,还实现一个接口:实时读取lux值功能。
3.2 代码实现
创建ISL29035_drv.c,编写如下代码:
/*
FILE NAME : ISL29035_drv.c
Description: user ISL29035 interface
Author : tangmingfei2013@126.com
Date : 2024/06/03
*/
/* isl29035 i2c address */
#include "bsp_i2c.h"
#include "hal_data.h"
#include "IsL29035_drv.h"
#include <string.h>
#define ISL29035_ADDR (0x44U)
/* isl29035 register */
#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)
/* 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)
static unsigned int convert_lux(unsigned int data)
{
return (unsigned int)((double)ISL29035_LUX_SCALE_4K / (double)ISL29035_RES_8BIT * data);
}
static uint8_t write_reg( uint8_t reg, uint8_t data)
{
fsp_err_t err;
unsigned char buff[2];
err = R_SCI_B_I2C_SlaveAddressSet( &g_i2c0_ctrl,
ISL29035_ADDR,
I2C_MASTER_ADDR_MODE_7BIT);
assert(FSP_SUCCESS == err);
buff[0] = reg;
buff[1] = data;
i2c2_write_bytes(buff, 2);
return 0;
}
static uint8_t read_regs(uint8_t reg, uint8_t len, uint8_t *buf)
{
fsp_err_t err;
uint8_t msgs[2];
err = R_SCI_B_I2C_SlaveAddressSet( &g_i2c0_ctrl,
ISL29035_ADDR,
I2C_MASTER_ADDR_MODE_7BIT);
assert(FSP_SUCCESS == err);
msgs[0] = reg;
i2c2_write_bytes(msgs, 1);
R_BSP_SoftwareDelay( 1, BSP_DELAY_UNITS_MILLISECONDS);
i2c2_read_bytes( buf, len);
return 0;
}
int IsL29035_read_lux(unsigned int *lux )
{
int ret;
unsigned char buff[1];
unsigned int tempval;
ret = read_regs(ISL29035_DATA_L_ADDR, 1, buff);
if( ret < 0 )
{
printf("get the lux value failure.\n");
return -1;
}
tempval = buff[0];
ret = read_regs(ISL29035_DATA_H_ADDR, 1, buff);
if( ret < 0 )
{
printf("get the lux value failure.\n");
return -1;
}
tempval |= (unsigned int)(buff[0]<<8);
*lux = convert_lux( tempval );
return 0;
}
void IsL29035_Init( void )
{
fsp_err_t err;
err = R_SCI_B_I2C_SlaveAddressSet( &g_i2c0_ctrl,
ISL29035_ADDR,
I2C_MASTER_ADDR_MODE_7BIT);
assert(FSP_SUCCESS == err);
write_reg(ISL29035_COMMAND_1_ADDR, ISL29035_COMMAND_1_INIT);
write_reg(ISL29035_COMMAND_2_ADDR, ISL29035_COMMAND_2_INIT);
}
创建ISL29035_drv.h,编写源代码的头文件:
/*
FILE NAME : ISL29035_drv.h
Description: user ISL29035 interface
Author : tangmingfei2013@126.com
Date : 2024/06/03
*/
#ifndef USER_ISL29035_DRV_H_
#define USER_ISL29035_DRV_H_
void IsL29035_Init( void );
int IsL29035_read_lux(unsigned int *lux );
#endif /* USER_ISL29035_DRV_H_ */
4 测试功能
4.1 编写测试代码
编写测试代码,其主要实时的从ISL29035中读取lux值,然后将该值显示在OLED屏幕上,其详细代码如下:
代码11行: 在主函数中调用IsL29035_Init,实现ISL29035的初始化功能
代码153行:调用IsL29035_read_lux接口,实时获取lux值
代码170~171行: 在OLED上显示数据
源代码如下:
void ui_disISL29035( void )
{
static int temp=0;
uint8_t dataBuff[32];
IsL29035_read_lux( &luxValue );
if( temp != timer0_get_tick( ))
{
if( (tick_cnt % 100) == 0 )
{
// ui DS18B20
// printf(" DS18B20 Temperature(C): %.02f \n", st_dsval.temperatureVal );
{
memset((char*)dataBuff, 0, sizeof(dataBuff));
sprintf((char*)dataBuff, "ISL29035(Lux): ");
oled_SetCharSize( FONT_16 );
oled_PrintfString(1,3, dataBuff);
}
// display ds18b20 value
{
memset((char*)dataBuff, 0, sizeof(dataBuff));
sprintf((char*)dataBuff, "%d ", luxValue);
oled_PrintfString(60,6, dataBuff);
}
LED2_TOGGLE;
}
temp = timer0_get_tick( );
tick_cnt++;
}
}
4.2 测试
编译代码,下载代码到板卡中
下载代码到板卡中,其运行结果如下:
OLED上显示数据