过往分享
下面是参加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上,当采集的光照在设定范围内就可以触发中断信号,本文不使用。
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
#include "hal_data.h"
#include "app_hw_i2c.h"
i2c_master_event_t sci3_i2c_event = I2C_MASTER_EVENT_ABORTED;
i2c_master_event_t sci0_i2c_event = I2C_MASTER_EVENT_ABORTED;
void I2c_Init(void)
{
fsp_err_t err;
err = R_SCI_I2C_Open(&g_sci3_i2c_ctrl, &g_sci3_i2c_cfg);
assert(FSP_SUCCESS == err);
err = R_SCI_I2C_Open(&g_sci0_i2c_ctrl, &g_sci0_i2c_cfg);
assert(FSP_SUCCESS == err);
}
void sci3_i2c_master_callback(i2c_master_callback_args_t *p_args)
{
sci3_i2c_event = I2C_MASTER_EVENT_ABORTED;
if (NULL != p_args)
{
sci3_i2c_event = p_args->event;
}
}
void sci0_i2c_master_callback(i2c_master_callback_args_t *p_args)
{
sci0_i2c_event = I2C_MASTER_EVENT_ABORTED;
if (NULL != p_args)
{
sci0_i2c_event = p_args->event;
}
}
app_hw_i2c.h
#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
ISL29035操作代码
app_isl29035.c
#include "hal_data.h"
#include "app_hw_i2c.h"
#include "app_isl29035.h"
#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)
#define ISL29035_COMMAND_1_INIT (0xA0U)
#define ISL29035_COMMAND_2_INIT (0x06U)
static int32_t Isl29035_Resolution = ISL29035_RES_8BIT;
static int32_t Isl29035_range = ISL29035_LUX_SCALE_4K;
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);
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);
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);
}
sci0_i2c_event = I2C_MASTER_EVENT_ABORTED;
}
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);
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);
}
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;
address = ISL29035_DATA_L_ADDR;
Isl29035_WriteToI2C(&address, 1);
Isl29035_ReadFromI2C(&data, 1);
read_adc = 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
#ifndef APP_ISL29035_H_
#define APP_ISL29035_H_
#include "app_common.h"
#define ISL29035_RES_16BIT (65536U)
#define ISL29035_RES_12BIT (4096U)
#define ISL29035_RES_8BIT (256U)
#define ISL29035_RES_4BIT (16U)
#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
读取数据
ISL29035的代码与HS300X写在了一起。
#define DISP_DEBUG
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多,移到光强的地方,会变到很大。