开发者学堂课程【HaaS 物联网应用开发课程:5_2_1_光照信息屏_软件详解】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/801/detail/13845
5_2_1_光照信息屏_软件详解
内容介绍:
一、软件介绍
1.流程图
2.主页面逻辑
3.AP3216C 驱动
4.AP3216C 驱动代码
一、软件介绍
光照信息屏的应用代码入口∶
appliciation/example/edu_demo/k1_apps/light_meter/light_meter.c
它是edu_demo应用的一个子页面。所有的子页面都需要实现 MENU_TYP 结构体。在 HaaS EDUK1上电之后,按K1或K2键左右切换应用的时候,lightmeter 下面的 API 会依此被呼叫
lightmeter_init-进入光照信息屏页面的时候
lightmeter_uninit-退出光照信息屏页面的时候
MENU_COVER_TYP lightmeter_cover = {MENU_COVER
_NONE};
MENU_TASK_TYP lightmeter_tasks = {
lightmeter_init,
lightmeter_uninit};
MENU
_LIST_TYp lightmeter_child_list = {NULL,0};
MENU_TYP lightmeter = {
"lightmeter",
&lightmeter_cover,
&lightmeter_tasks,
NULL,
&lightmeter_child_list} ;
接下来讲述这些函数里做了什么事情:
1. 流程图
在进入“光照信息屏”页面时,lightmeter_int 会对 AP3216C 进行初始化,之后清空 OLED 屏 幕,启动lightmeter_task,然后再task里面完成光强度值读取以及显示,之后 lightmeter_int 函数就会退出。
在 lightmeter_task 里,首先读取 ALS/PS/IR 数据生成屏幕显示数据并将 ALS/PS/IR 数据打印到 OLED,之后判断物体靠近标志并将物体接近标志及左右按键标志打印到 OLED 屏幕上。之后,对屏幕进行刷新,刷新完成后会休眠150毫秒,然后会去周期性的读取光亮度以及接近程度的数据并重复上述完整过程。
在退出光照信息屏后,结束 lightmeter_task的task。
2.主页面逻辑
进入光照信息屏页面时:
appliciation/example/edu_demo/k1_apps/light_meter/light_meter.c
/*页面初始化函数*/'
int lightmeter_init(void)
{
printf("lightmeter_init begin\n"");
/*AP3216C 初始化函数*/
ap3216c_init( );
printf("lightmeter_init done\n");
/*清空 OLED 屏幕*/
O
LED_Clear( );
O
LED_Refresh_GRAM( );
/*启动光照信息屏主任务*/
aos_task_new("lightmeter_task", lightmeter_task,NULL,1000);
printf("aos_task_new lightmeter_task \n");
return 0;
}
O
LED_Clear( );
O
LED_Refresh_GRAM( );
OLED_Refresh_GRAM——将 OLED 缓存的数据刷新到屏幕,因为清空屏幕,所以屏幕无显示
aos_task_new("lightmeter_task", lightmeter_task,NULL,1000)这个 API 中有四个参数:”lightmeter_task”是字符串;lightmeter_task 是创建 task 的入口函数,函数名为 lightmeter_task;
NULL 是启动 lightmeter_task 时,没有数据需要传送;1000是创建 lightmeter_task 的 step size。
光照信息屏主任务逻辑︰
void lightmeter_task(void)
{
uint16_t tmp [3];
uint8_t als [20];
uint8_t ps [20];
uint8_t ir[20];
while (1)
{
/*从 AP3216C 读取 ALS、PS、IR 数据*/
tmp[0] = ap3216c_read_ambient_light( );
tmp[1] = ap3216c_read_ir_data( );
tmp [2] = ap3216c_read_ps_data( );
/*打印 ALS/IR 信息字串*/
sprintf(als,"ALS: %d" , tmp[0]) ;
sprintf(ir,"IR : %d" , tmp[1] );
/*将 lightmeter 图标及 ALS/IR 信息输出到屏幕*/
OLED_Clear( );
OLED_Icon_Draw( 20,14,&icon_lighter_32_32,0);
OLED_Show_String(64, 6, als, 12
,
1);
OLED_Show_String(64, 20, ir, 12
,
1); }
/*判断是否有物体靠近,并显示在屏幕上*/
if ( ( tmp[2] >>15)& 1)
OLED_Show_String(64,36,"near !",16,
else
OLED_Show_String(64,40,"far !",16,1);
/*将左右按键标志输出到屏幕上*/
OLED_Icon_Draw(2,24,&icon_skip_left,0);
OLED_Icon_Draw( 122,24,&icon_skip_right,0);
/*刷新屏幕数据*/
OLED_Refresh_GRAM( );
/*休眠150ms*/
aos_msleep( 150);
}
退出光照信息屏页面时:
/*光照信息屏页面退出处理函数*/
int lightmeter_uninit(void)
{
/*删除光照信息屏主任务*/
aos_task_delete("lightmeter_task" );
printf("aos_task_delete lightmeter_task
\
n");
return 0;
}
3.AP3216C 驱动
写 AP3216C 寄存器操作典型I2C 数据发送逻辑
发起写操作,将要读取的目标寄存器地址发送给 AP3216C;紧接着依此发送要写入的数值给 AP3216C;当前面的过程完成之后,HaaS1000会发送一个I2C 传输结束的信号到总线。
下图为I2C 的波形图的示例:
我们可以看到一个寄存器写操作在一次I2C 传输中完成,一次I2C 传输是指发起I2C 传输到I2C 传输结束之间的过程。
读取 AP3216C 寄存器的值是如何操作的:
读取 AP3216C 寄存器操作典型I2C 数据收发逻辑
不论是写操作还是读操作都是由主设备发起,HaaS100发起开始I2C 传输的信号,之后将 AP3216C 地址写在I2C总线上;然后发起写操作将要读取的目标寄存器地址发送给 AP3216C,AP3216C 收到之后回复 A,接下来 HaaS1000发起 Repeated Startt 号表示重新发起I2C 读操作,之后将I2C 从设备地址填进去,告诉从设备进行的是读操作,之后从设备回复 A,然后从设备会将寄存器的值写到I2C 总线上;最后 HaaS1000回复 N、发起传输结束信号。
从上述过程中可以看出是经过两个步骤的,一是进行I2C 写操作,二是进行读操作。
两条I2C 总线操作之间采用 Repeated Start condition 信号连接
4.AP3216C 驱动代码
AliOS Things HAL I2C register read API
I2c master mem read
@param[in] i2c the i2c device
@param[in] dev _addr device address
@param[in] mem_addr mem address
@param[in] mem_addr_size mem address
@param[out] data i2c master send data
@param[in] size i2c master send data size
@param[in] timeout timeout in milisecond,set this value to HAL_WAIT_FOREVERif you want to wait forever
@return 0 : on success,EI0 : if an error occurred during initialisation
Int32_t hal_i2c_men_read(i2c_dev_t *i2c,uint16 t dev_addr, uint16_t mem_addr ,uint16_t mem_addr_size,uint_t *data,uint16_t size,uint32_t timeout);
hal_i2c_men_read 会将要读取的寄存器的地址、数据长度传给 HaaS1000的驱动,HaaS1000驱动在这个 API的实现里面严格按照先写操作后读操作,中间用 repeated start 信号做连接。
Ali0S Things HAL I2C register write API
I2c master mem read
@param[in] i2c the i2c device
@param[in] dev _addr device address
@param[in] mem_addr mem address
@param[in] mem_addr_size mem address
@param[out] data i2c master send data
@param[in] size i2c master send data size
@param[in] timeout timeout in milisecond,set this value to HAL_WAIT_FOREVERif you want to wait forever
@return 0 : on success,EI0 : if an error occurred during initialisation
Int32_t hal_i2c_men_write(i2c_dev_t *i2c,uint16 t dev_addr, uint16_t mem_addr ,uint16_t mem_addr_size,uint_t *data,uint16_t size,uint32_t timeout);
hal_i2c_men_write 和前面所讲的写 AP3216C 寄存器操作典型I2C 数据发送逻辑是一样的。
下面讲述 AP3216C 的驱动代码:
AP3216C 驱动代码:
components/peripherals/sensor/drv/drv_als_ps_ir_liteon_ap3216c.c
基础寄存器读写 APl:
/*写寄存器的值*/
static void write_reg(uint8_t reg,uint8_t data)
{
hal_i2c_mem_write(&i2c_dev,i2c_dev.config.dev_addr,reg,1,&data,1,100);
}
/*读寄存器的值*/
static void read_regs(uint8_t reg,uint8_t len,uint8_t *buf)
{
hal_i2c_mem_read(&i2c_dev,i2c_dev.config.dev_addr,reg,1,buf,len,100);
}
/**
*This function is convenient to getting data except including high and low data for this sensor.
*note:after reading lower register first,reading higher add one.
*/
static uint32_t read_low_and_high(uint8_t reg,uint8_t len
{
uint32_t data;
uint8_t buf =0;
read_regs( reg,len,&buf); //读低字节
data = buf;
read_regs( reg + 1,len,&buf); //读高字节
data=data + Cbuf << len * 8); //合并数据
return data;
}
AP3216C初始化过程:首先是呼叫 hal_i2c_int 对 HaaS1000的I2C 控制器进行初始化
void ap3216c_init(void)
{
I2c_dev.port =1
i2c_dev.config.address_width= I2C_HAL_ADDRESS_WIDTH_7BIT;
i2c_dev.config.freq = I2C_BUS_BIT_RATES_100K;
i2c_dev. config.mode = I2C_MODE_MASTER;
i2c_dev. config.dev_addr =AP3216C_ADDR;
hal_i2c_init(&i2c_dev);
/ *reset ap3216c*/
reset_sensor();
aos_msleep(100) ;
ap3216c_set_param(AP3216C_SYSTEM_MODEAP3216C_MODE_ALS_AND_PS);
aos_msleep(100); // delay at least100ms
/*配置中断脚和中断数据*/
ap3216c_int_Config();
ap3216c_int_init();
}
I2c_dev.port =1
指要初始化的是I2C 的通道1
i2c_dev.config.address_width是指要操作的I2C 从设备的地址类型,是7bit 模式的
i2c_dev.config.freq指实际进行I2C 传输时 sclk 上的频率值
i2c_dev. config.mode 指使用的I2C 控制器的模式,这个控制器是 HaaS100的控制器,因为 HaaS1000是工作在master上的,所以这里写的是I2C_MODE_MASTER,只要是通过I2C 总线读取外面传感器的数据,莫得都要填I2C_MODE_MASTER 参数。
i2c_dev. config.dev_addr 填的是从设备的地址
复位 AP2316C:
/ *软件复位传感器*/
static void reset_sensor(void)
{
write_reg(AP3216C_SYS_CONFIGURATION_REG,AP3216C_MODE_SW_RESET);//reset
}
初始化I2C 控制器之后会对 AP2316C 进行复位,呼叫的是 reset_sensor,它调用 write_reg 将SYS_CONFIGURATION_REG 寄存器写入 SW_RESET 的 flag。
通过 AP3216C 如何读取光强度:
* This function reads light by ap3216c sensor measurement
*@param no
*@return the ambient light converted to float data.
* /
int16_t ap3216c_read_ambient_light(void)
{
uint16_t brightness =0; // default error data
uint16_t read_data;
uint8_t range;
read_data= (uint16_t )read_low_and_high(AP3216C_ALS_DATAL_REG,1);
ap3216c_get_param(AP3216C_ALS_RANGE,&range);.
if (range == AP3216C_ALS_RANGE_20661)
{
Brightness = 0.35 * read_data; //lsensor ambient light converse to reality}
}
Else if (range == AP3216C_ALS_RANGE_5162)
{
brightness = 0.0788 * read_data;//sensor ambient light converse to reality}.
}
else if (range == AP3216C_ALS_RANGE_1291)
{
brightness = 0.0197 * read_data;//sensor ambient light converse to reality
}
else if (range == AP3216C_ALS_RANGE_323)
{
brightness = 0.0049 * read_data;//sensor ambient light converse to reality
}
return brightness;
}
主要有三步,第一通过 read_low_and_high 将 ALS_DATA 低地址传进,每次读取一个 byte。
第二,呼叫 A3216C_get_param 将 ALS_RANGE 寄存器获取 ALS Range 的级别。第三,根据 ALS Range 级别计算实际 ALS 值。