0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

AWorks对常见的外部通用设备接口应用

UtFs_Zlgmcu7890 来源:互联网 作者:佚名 2018-05-24 09:44 次阅读
AWorks对常见的外部设备进行了统一的抽象,定义了访问外部设备的通用接口。比如,LED、蜂鸣器、数码管、按键等。应用程序基于通用接口编程,将使应用程序不与具体的硬件设备绑定,换句话说,应用程序可以跨平台复用,在任何运行AWorks的硬件平台上运行。

6.1 通用LED接口

AWorks提供了操作LED的通用接口,详见表6.1。

表6.1 通用LED接口(aw_led.h)

1. 设置LED的状态

设置LED状态的函数原型为:

其中,id为LED编号,系统为每个LED都分配了一个唯一ID,通常都是从0开始顺序为各个LED编号。如有2个LED,则LED的编号为0~1。布尔类型on参数表明是否点亮LED,若其值为AW_TRUE,则表示点亮LED;若其值为AW_FALSE,则表示熄灭LED。

aw_bool_t类型是AWorks在aw_types.h文件中自定义的布尔类型,使用该类型定义的数据,其值只能为真(AW_TRUE)或假(AW_FALSE)。

点亮编号为0的LED范例程序详见程序清单6.1。

程序清单6.1 使用aw_led_set()点亮LED的范例程序

熄灭编号为0的LED范例程序详见程序清单6.2。

程序清单6.2 使用aw_led_set()熄灭LED范例程序

函数的返回值表示本次操作的结果,其类型为aw_err_t,该类型在aw_errno.h文件中定义的一个有符号的整数类型。若接口返回值的类型为aw_err_t,则具有通用的含义:

  • 若返回值为AW_OK(常量宏,值为0),则表示操作成功;

  • 若返回值为负值,则表示操作失败,失败的原因通过返回值确定;

  • 若返回值为正数,则具体含义由接口定义,无特殊说明时,表明不会返回正数。

实际上AW_OK是在aw_common.h文件中定义的常量宏,其值为0,定义如下:

当返回负值时,则表示操作失败,具体失败的原因可根据返回值查找aw_errno.h文件中定义的错误号,通过错误号的含义即可确定失败的原因,详见表6.2。

表6.2 常见错误号的含义(aw_errno.h)

假设硬件只有两个LED,其操作编号为100的LED,由于LED不存在,将返回-AW_ENODEV,表示设备不存在。注意:AW_ENODEV的前面有一个负号,操作无效ID的范例程序详见程序清单6.3。

程序清单6.3 操作无效ID的范例程序

通常操作LED,只要LED编号是有效的,这操作均会成功,其返回值为AW_OK。

2. 点亮LED

点亮LED的函数原型为:

其中,id为LED编号,函数的返回值为标准错误号,点亮编号为0的LED范例程序详见程序清单6.4。

程序清单6.4 aw_led_on()范例程序

3. 熄灭LED

熄灭LED的函数原型为:

其中,id为LED编号,函数的返回值为标准错误号,熄灭编号为0的LED范例程序详见程序清单6.5。

程序清单6.5 aw_led_off()范例程序

4. 翻转LED的状态

翻转LED的状态就是使LED由点亮状态转变为熄灭状态或由熄灭状态转变为点亮状态,其函数原型为:

其中,id为LED编号,函数的返回值为标准错误号,通过翻转LED状态的接口可以实现LED闪烁,其范例程序详见程序清单6.6。

程序清单6.6 aw_led_toggle()范例程序

为了展示接口的使用方法,该程序使用了3种方式实现LED的闪烁,详见程序清单6.7。

程序清单6.7 LED闪烁范例程序

6.2 通用键盘接口

AWorks实现了一个输入子系统架构,可以统一管理按键、鼠标、触摸屏等外部输入事件。这里以使用按键为例,讲述输入系统的使用方法。

对于键盘,无论是独立键盘、矩阵键盘还是外接的外围键盘管理芯片(如ZLG72128),均可以使用输入系统进行管理。

对于用户来讲,要使用按键,即需要对外部输入的按键事件进行处理,为此,需要向系统中注册一个输入事件处理器,该处理器中,包含了用户自定义的事件处理函数,当有按键事件发生时,系统将自动回调事件处理器中的用户函数。

AWorks提供了注册输入事件处理器的接口,其函数原型为:

其中,p_input_handler为指向输入事件处理器的指针,pfn_cb为指向用户自定义的输入事件处理函数的指针,p_usr_data为按键处理函数的用户参数。当输入事件发生时,系统会回调pfn_cb指向的用户处理函数,并将p_usr_data作为参数传递给用户处理函数。

1. 输入事件处理器

p_input_handler指向输入事件处理器,其类型为:aw_input_handler_t,在

aw_input.h文件中定义,用户无需关心该类型的具体定义,仅需使用该类型定义一个输入事件处理器的实例。即:

其中,key_handler为用户自定义的输入事件处理器,其地址可以作为p_input_handler的实参传递。

2. 用户自定义事件处理函数

pfn_cb指向用户自定义的输入事件处理函数,其类型aw_input_cb_t为事件处理函数的类型,其在aw_input.h文件中定义如下:

当输入事件发生时,无论是按键事件,还是其它坐标事件,比如:鼠标、触摸屏等。均会调用pfn_cb指针指向的函数,当该函数被调用时,p_input_data为输入事件相关的数据,包含事件类型(区分按键事件或坐标事件,比如:鼠标、触摸屏等)、按键编码、坐标等信息,用户可以根据这些数据作出相应的处理动作。p_usr_data为用户自定义的参数,其值与注册事件处理器时传递的p_usr_data参数一致,若不使用该参数,则可以在注册事件处理器时,将p_usr_data参数的值设置为NULL。

p_input_data的类型为aw_input_event_t指针类型,该类型在aw_input.h文件中定义如下:

其本质上是一个结构体类型,仅包含一个数据成员,用于表示事件的类型,若为按键事件,则该值为AW_INPUT_EV_KEY;若为绝对事件(比如,触摸屏),则该值为AW_INPUT_EV_ABS。

若p_input_data指向的数据中,ev_type的值为AW_INPUT_EV_KEY,则表示其指向的数据本质上是一个完整的按键事件数据,其类型为aw_input_key_data_t,该类型在aw_input.h文件中定义如下:

该类型的第一个数据成员为input_ev,其中包含了事件的具体类型。也正因为其第一个数据成员的类型为aw_input_event_t,系统才可以在回调用户自定义的函数时,将aw_input_key_data_t类型的指针转换为指向aw_input_event_t类型的指针使用。

key_code为按键编码,用于区分系统中多个不同的按键。例如,系统中存在4个按键,则各个按键对应的编码可能分别为:KEY_0、KEY_1、KEY_2、KEY_3。这些编码都是在aw_input_code.h文件中使用宏的形式定义的。

key_state表示本次按键事件具体对应的按键状态,用以区分按键事件是按下事件还是释放事件。若该值不为0,则表示按键按下;否则,表示按键释放。

基于此,为了获取到更多的按键相关信息,比如:按键编码、按键状态(按下还是释放)等。可以将p_input_data强制转换为aw_input_key_data_t指针类型使用,详见程序清单6.8。

程序清单6.8 根据输入事件的类型使用数据

实际上,不同类型的输入事件,其需要包含的数据是不同的,例如,对于触摸屏事件,则需要包含横坐标和纵坐标。为了统一各种不同类型的事件处理函数类型,将aw_input_event_t类型的数据作为所有事件实际数据类型的第一个成员。这样,可以统一使用aw_input_event_t类型的指针指向实际的数据,以此统一事件处理函数的类型,用户在事件处理函数中,通过查看事件类型,即可进一步将该指针强制转换为指向实际数据类型的指针,使用其中更多的信息。

如图6.1所示的类图表示了这种关系,实际数据类型均是从基类派生而来的,aw_input_prt_data_t是指针型输入事件,比如触摸屏触摸事件等,其包含了具体坐标信息。

图6.1 各种类型的输入事件对应的实际数据类图

例如,使用一个按键(按键编码为KEY_0)控制LED0,当按键按下时,则LED0点亮;当按键释放后,则LED0熄灭,相应的按键处理函数详见程序清单6.9。

程序清单6.9 按键处理函数范例程序

完成按键处理函数的定义后,函数名可作为参数传递给aw_input_handler_register()函数的pfn_cb形参。综合范例程序详见程序清单6.10。

程序清单6.10 注册事件处理器范例程序

注册按键处理器后,当按键按下或释放时,均会调用注册按键处理器时指定的回调函数,即程序清单6.10中的__key_process()函数。

若系统中存在多个按键,且各个按键的处理动作毫不相关,为了分离各个按键的处理代码,可以注册多个按键事件处理器,每个处理器负责处理一个或多个按键,范例程序详见程序清单6.11。

程序清单6.11 注册多个按键处理器范例程序

6.3 通用蜂鸣器接口

AWorks提供了操作蜂鸣器的通用接口,详见表6.3。

表6.3 通用蜂鸣器接口(aw_buzzer.h)

1. 设置蜂鸣器的响度

该函数用于设置蜂鸣器鸣叫的响度,即控制蜂鸣器发声的音量。其函数原型为:

beep_level即为鸣叫的响度,其值被量化为百分比,有效值为0 ~ 100。为0时表示静音,为100时表示声音最大。设置响度为80%的范例程序详见程序清单6.12。

程序清单6.12 aw_buzzer_loud_set()范例程序

该接口仅用于设置蜂鸣器的响度,并不会使蜂鸣器立即发声,必须调用aw_buzzer_on()或aw_buzzer_beep()接口,才能使蜂鸣器发声。默认情况下,响度为0,因此,在调用相关接口使蜂鸣器鸣叫前,必须正确设置响度。

特别地,部分硬件不支持响度设置,响度是固定的,这种情况下,调用该接口是无效的,返回值为-AW_ENOTSUP(错误号,表示不支持)。

2. 打开蜂鸣器

打开蜂鸣器的函数原型为:

打开蜂鸣器,使蜂鸣器开始鸣叫的范例程序详见程序清单6.13。

程序清单6.13 aw_buzzer_on()范例程序

打开蜂鸣器后,蜂鸣器开始鸣叫,若响度为0,将听不到声音。

3. 关闭蜂鸣器

关闭蜂鸣器的函数原型为:

关闭蜂鸣器,使蜂鸣器停止鸣叫的范例程序详见程序清单6.14。

程序清单6.14 aw_buzzer_off()范例程序

4. 蜂鸣器鸣叫指定时间(同步)

该函数用于打开蜂鸣器,使蜂鸣器鸣叫指定时间后自动关闭,该函数会一直等到蜂鸣器鸣叫结束后返回。其函数原型为:

使蜂鸣器鸣叫50毫秒(“嘀”一声)的范例程序详见程序清单6.15。

程序清单6.15 aw_buzzer_beep()范例程序

注意,由于该函数会一直等到蜂鸣器鸣叫结束后才会返回,因此主程序调用该函数后,会阻塞50ms。

5.蜂鸣器鸣叫指定时间(异步)

该函数用于打开蜂鸣器,使蜂鸣器鸣叫指定时间后自动关闭,与aw_buzzer_beep()函数不同的是,该函数会立即返回,不会等待蜂鸣器鸣叫结束。其函数原型为:

使蜂鸣器鸣叫50毫秒(“嘀”一声)的范例程序详见程序清单6.16。

程序清单6.16 aw_buzzer_beep_async()范例程序

注意,由于该函数不会等待蜂鸣器鸣叫结束,因此,当调用该函数后,会立即返回,不会被阻塞。这是其与aw_buzzer_beep()接口的本质区别。

基于蜂鸣器通用接口,可以编写一个简易测试程序,按键按下,蜂鸣器鸣叫;按键释放,蜂鸣器停止鸣叫。范例程序详见程序清单6.17。

程序清单6.17 蜂鸣器使用范例程序

基于此,若需要实现一个按键按下,蜂鸣器“嘀”一声的效果,按照上述示例,可以简单修改事件处理函数,使用aw_buzzer_beep()函数实现“嘀”一声的效果,范例程序详见程序清单6.18.

程序清单6.18 事件处理函数修改(1)

实际测试会发现,上述程序并不能正常工作,不能观察到预期的现象。这是由于aw_buzzer_beep()函数会阻塞调用者一定的时间,而按键事件回调函数是在中断环境中运行的,中断上下文不能被阻塞,因此,aw_buzzer_beep()接口不能够直接在按键事件回调函数中使用。为了实现该应用,可以使用不阻塞的蜂鸣器鸣叫接口aw_buzzer_beep_async()替代,范例程序详见程序清单6.19。

程序清单6.19 事件处理函数修改(2)

6.4 通用数码管接口

AWorks提供了操作数码管的通用接口,详见表6.4。

表6.4 通用数码管接口(aw_digitron_disp.h)

1. 设置段码解码函数

数码管的各个段可以组合显示出多种图形,使用该函数可以自定义字符的解码函数,其函数原型为:

其中,id表示设置数码管显示器的编号,这里的id指的是显示器的编号,而不是数码管的位索引,一个数码管显示器可以包含多位数码管,比如,MiniPort-View显示器,其包含两位数码管。系统中的数码管显示器通常从0开始编号,例如,系统中共计有3个数码管显示器,则id为0 ~ 2。绝大部分情况下,系统中仅有一个数码管显示器,此时,其id为0。

pfn_decode为函数指针,其指向的函数即为设置的解码函数,解码函数的参数为uint16_t类型的字符,返回值为uint16_t类型的编码。

实际应用中,对于8段数码管,字符'0' ~ '9'等都是有默认编码的,为此,AWorks提供了默认的8段数码管解码函数,可以支持常见的字符'0' ~ '9'以及 'A' 、'B'、 'C' 、'D'、 'E'、 'F'等字符的解码。其在aw_digitron_disp.h文件中声明:

如无特殊需求,可以直接将该函数作为相应数码管显示器的字符解码函数,将该函数作为pfn_decode的实参传递,范例程序详见程序清单6.20。

程序清单6.20 aw_digitron_disp_decode_set()范例程序

若由于应用特殊需求,要求字符使用自定义的特殊编码,例如,要使字符'O'的编码为 0xFC,则可以自定义如下解码函数:

然后将该函数作为pfn_decode的实参传递即可:

注意,对于一个数码管显示器,只能设置一个解码函数。

2. 设置数码管闪烁

该函数可以指定数码管显示器的某一位数码管闪烁,其函数原型为:

其中,id为数码管显示器编号;index为数码管索引,当一个数码管显示器存在多位数码管时,使用index参数指定具体操作的数码管的位置。如MiniPort-View有两位数码管,则两个数码管的索引分别为0和1;blink表示该位是否闪烁,若其值为AW_TRUE,则闪烁,反之,则不闪烁,默认情况下,所有数码管均处于未闪烁状态。如设置1号数码管闪烁的范例程序详见程序清单6.21。

程序清单6.21 aw_digitron_disp_blink_set()范例程序

3. 显示指定的段码图形

该函数用于不经过解码函数解码,直接显示段码指定的图形,可以灵活的显示任意特殊图形,其函数原型为:

其中,id为数码管显示器编号;index为数码管索引;seg为显示的段码。如在8段数码管上显示字符'-',即需要g段点亮,对应的段码为0x02(即:0000 0010),范例程序详见程序清单6.22。

程序清单6.22 aw_digitron_disp_at()范例程序

4. 显示单个字符

该函数用于在指定位置显示一个字符,字符经过解码函数解码后显示,若解码函数不支持该字符,则不显示任何内容,其函数原型为:

其中,id为数码管显示器编号,index为数码管索引,ch为显示的字符。比如,显示字符'H'的范例程序详见程序清单6.23。

程序清单6.23 aw_digitron_disp_char_at()范例程序

5. 显示字符串

该函数用于从指定位置开始显示一个字符串,其函数原型为:

其中,id为数码管显示器编号,index为显示字符串的数码管起始索引,即从该索引指定的数码管开始显示字符串,len指定显示的长度,p_str指向需要显示的字符串。

实际显示的长度是len和字符串长度的较小值,若数码管位数不够,则多余字符不显示。

如显示字符"HELLO"的范例程序详见程序清单6.24。

程序清单6.24 aw_digitron_disp_str()范例程序

若使用的是MiniPort-View,由于只存在两个数码管,因此最终只会显示"HE"。

通常情况下,需要显示一些数字,如显示变量的值,此时,可以先将变量通过格式化字符串函数输出到字符串缓冲区中,然后再使用aw_digitron_disp_str()函数显示该字符串。比如,显示一个变量i的值,范例程序详见程序清单6.25。

程序清单6.25 使用aw_digitron_disp_str()显示整数变量值的范例程序

其中,aw_snprintf()与标准C函数snprintf()函数功能相同,均用于格式化字符串到指定的缓冲区中,其函数原型为(aw_vdebug.h):

其与aw_kprintf()函数的区别是,aw_kprintf()将信息直接通过调试串口打印输出,而aw_snprintf()函数将信息输出到大小为sz的buf缓冲区中。

6. 显示清屏

该函数用于显示清屏,清除数码管显示器中的所有内容,其函数原型为:

其中,id为数码管显示器编号,范例程序详见程序清单6.26。

程序清单6.26 aw_digitron_disp_clr()范例程序

7. 使能数码管显示

数码管默认是处于使能状态的,只有当被禁能后,才需要使用该函数重新使能。数码管仅在使能状态下才可以正常显示。

该函数用于显示清屏,清除数码管显示器中的所有内容,其函数原型为:

其中,id为数码管显示器编号,范例程序详见程序清单6.27。

程序清单6.27 aw_digitron_disp_enable()范例程序

8. 禁能数码管实现

数码管默认处于使能状态,可以正常显示。清屏状态下只是清空了数码管显示的内容,数码管实际上还是处于工作状态,对于动态扫描类数码管,依然处于动态扫描状态,需要消耗CPU资源。若长时间不使用数码管显示器,可以彻底关闭数码管显示器,关闭数码管扫描,节省CPU资源,甚至是关闭数码管的电源,降低系统功耗。关闭数码管显示器的函数原型为:

其中,id为数码管显示器编号,范例程序详见程序清单6.28。

程序清单6.28 aw_digitron_disp_disable()范例程序

数码管被禁能后,将不能再正常显示,若需正常显示,必须使用aw_digitron_disp_enable()接口重新使能数码管。

基于数码管通用接口,可以编写一个简易的60s倒计时程序,当倒计时还剩5s时,数码管闪烁。范例程序详见程序清单6.29。

程序清单6.29 倒计时应用程序实现

程序中,将应用程序使用的数码管显示器编号使用宏__DIGITRON_ID进行了定义,若一个系统中存在多个数码管显示器,则仅需修改该宏对应的宏值,就可以使该倒计时应用程序在不同的数码管显示器上运行。

6.5 通用传感器接口

AWorks提供了通用的传感器接口,适用于各式各样的传感器,例如,温度、湿度、电压、电流、压强、加速度、角速度、光照传感器等等。

在一个系统中,可能存在多种类型的传感器,例如,温度、湿度、电流、压强等。同时,还可能存在多个同种类型的传感器,例如,可能连接10个温度传感器以测试10个温度检测点的温度。此外,部分传感器可以采集多路信号,例如,温湿度传感器SHT11可以同时采集温度和湿度。

为了实现对各式各样的传感器进行统一管理,在AWorks中,定义了“传感器通道”的抽象概念,一个传感器通道用于完成一路物理信号的采集。对于只能采集单一信号的传感器,每个传感器只能为系统提供一路传感器通道,例如,LM75温度传感器仅能采集一路温度信号;对于可以采集多路信号的传感器,则每个传感器可以为系统提供多路传感器通道,例如,SHT11可以同时采集温度和湿度,其可以为系统提供一路温度传感器通道和一路湿度传感器通道。此外,也可能存在多个相同的传感器,以便为系统提供多个同类型的的传感器通道。

如此一来,一个系统中可能存在多个传感器通道,为了区分各个传感器通道,在AWorks中,为每个传感器通道分配了一个唯一 id。例如,某一系统中存在温度、加速度、角速度等多种传感器,各传感器通道对应的id分配范例详见表6.5。

表6.5 传感器通道id分配(仅作示意)

实际中,id 与具体硬件平台相关,用户应查看SDK中的用户手册,获知系统中可用的传感器通道资源,以正确使用各个传感器通道。

对于应用程序来讲,仅需通过id使用各个传感器通道即可,无需关心这些通道具体是由哪个传感器提供的。例如,某一应用需要采集一路温度和一路湿度,底层硬件可以是一个SHT11温湿度传感器,也可以是一个温度传感器和一个湿度传感器。

常用的传感器接口详见表6.6。

表6.6 通用传感器接口(aw_sensor.h)

1. 获取传感器通道类型

传感器通道有类型之分,不同的类型的传感器通道采集的物理信号不同,不同物理信号具有不同的基本单位不同。例如,电压的基本单位为伏特(V);电流的基本单位为安培(A);温度的基本单位为℃。为便于使用,在AWorks中,将传感器类型使用宏的形式进行了定义,常用的传感器类型详见表6.7。

表6.7 常用的传感器类型定义(aw_sensor.h)

在AWorks中,提供了获取传感器通道类型的接口,其函数原型为:

其中,id为传感器通道的编号。若函数返回值为非负数(>=0),则表示获取传感器类型成功,此时,返回值即为以AW_SENSOR_TYPE_ 为前缀的宏值;否则,表示获取传感器类型失败,此时,返回值为标准错误码,表示了获取类型失败的原因。例如,返回值为-AW_ENODEV时,表示id对应的传感器通道不存在,没有与之对应的传感器设备。例如,判断通道0是否为温度传感器的范例程序详见程序清单6.30。

程序清单6.30 获取传感器通道类型的范例程序

2. 使能传感器通道

在AWorks中,使用一个传感器通道采集数据的一般流程为:

(1)使能通道;

(2)获取数据(可以多次获取);

(3)禁能通道,不再使用时可以禁能通道,以使传感器进入最佳的低功耗状态(若支持)。

AWorks为每一个步骤都提供了两类接口:一类接口用于操作单个传感器通道,该类接口适用于仅使用单个传感器通道的应用程序;一类接口用于操作一组(多个)传感器通道,该类接口适用于需要使用多个传感器通道的应用程序。当应用需要使用多个传感器通道时,建议使用操作一组(多个)传感器通道的接口,而不是多次使用操作单个传感器通道的接口,后者效率较低,影响系统性能。

在获取数据前,必须使能传感器通道,AWorks提供了两类接口,分别用于使能单个传感器通道和使能一组(多个)传感器通道。

  • 使能单个传感器通道

使能单个传感器通道的函数原型为:

其中,id为传感器通道的编号。若函数返回值为AW_OK,则表示通道使能成功;否则,表示通道使能失败,返回值为标准错误码,可以据此判定失败的原因。例如,返回值为-AW_ENODEV时,表示id对应的传感器通道不存在。例如,使能通道0的范例程序详见程序清单6.31。

程序清单6.31 使能单个传感器通道的范例程序

  • 使能一组(多个)传感器通道

使能一组(多个)传感器通道的函数原型为:

其中,p_ids为指向传感器通道id列表的指针;num表示通道的数目,即id列表的大小;p_result指向用于存储各个通道使能结果的缓存,缓存大小应该与num一致。其类型aw_sensor_val_t 为传感器数据类型,其详细定义详见程序清单6.32。

程序清单6.32 aw_sensor_val_t类型定义(aw_sensor.h)

该类型的本意是表示一个传感器数据,如电压、电流、温度等,当表示一个传感器数据时,val和unit都有着特殊的含义,具体含义将在数据获取接口中详细介绍。当该类型使用于此时,unit的值无效,仅使用val值表示各个通道使能的结果,此时,val值即为标准错误码,若其值为AW_OK,则表示相应的通道使能成功;否则,表示相应的通道使能失败,例如,值为-AW_ENODEV时,表示对应通道不存在。

aw_sensor_group_enable()函数的返回值同样为标准错误码,若其值为AW_OK,则表示所有通道使能成功,此时,p_result中所有数据的val值均为AW_OK,因此,当返回值为AW_OK时,无需判断p_result中的值即可断定所有通道使能成功;否则,表示存在使能失败的通道,此时,可以逐一检查p_result中的值来判断具体哪些通道使能成功,哪些通道使能失败。使能一组通道(通道0、3、5、6、8、9)的范例程序详见程序清单6.33。

程序清单6.33 使能一组(多个)传感器通道的范例程序

3. 获取传感器数据

通道使能后,可以获取传感器中的数据, AWorks提供了两类接口,分别用于获取单个传感器通道的数据和获取一组(多个)传感器通道的数据。

  • 获取单个传感器通道的数据

该函数用于获取单个传感器通道的数据,其函数原型为:

其中,id为传感器通道的编号,p_val为输出参数,用以返回获取到的传感器值。函数返回值为标准错误码,若其值为AW_OK,则表示数据获取成功;否则,表示数据获取失败。

aw_sensor_val_t表示传感器数据类型,回顾(首次定义详见程序清单6.32)其定义如下:

其中,val为传感器数值,unit表示了数据单位。

例如:

"M"(106,“兆”)、"k"(103,“千”),"m"(10-6,“毫”)等等,unit使用10的幂进行表示,例如,单位为"m",则unit的值为-3。

为了规范unit的使用,unit不可以为任意值,AWorks根据国际单位制(SI)定义的词头(比如:"m"、"μ"、"p"、"n"等等)对其可用取值进行了定义,详见表6.8。

表6.8 uint可用取值

表中的最后一列即为unit的值,其值表示了10的幂,比如,-9表示的是10-9。单位符号区分大小写,例如,"m"表示“毫”,对应10-3;而"M"表示“兆”,对应106。英文前缀表示在英文单词中,通常可以在计量单位的单词前增加该前缀形成新的单词,例如,长度单位米的英文单词为:meter;而千米对应的单词为:kilometer,这里列出英文单词前缀,可以方便读者理解宏值和单位符号的定义。中文读音为该单位符号的一般读法,括号内的字在不致混淆的情况下可以省略(通常均省略)。

传感器val值的实际单位为将表中所示“单位符号”作为基本单位(基本单位与传感器类型相关,详见表6.7)的前缀形成的单位。例如,电压传感器的基本单位为V,若一个电压传感器数据的val为1234,unit为AW_SENSOR_UNIT_MILLI(即:-3),由于-3对应的单位符号为"m",因此,该传感器数据的单位为"mV",对应的电压值即为1234mV。

如需将传感器数据的单位转换为基本单位,可以使用如下公式:

data值的数据单位即为基本单位,比如,安培(A)、伏特(V)等。

使用一个“整数”和一个“单位”来对传感器数据进行表示,可以有效的避免使用浮点数(为了保证系统性能,AWorks内部不直接使用浮点数,当然,应用程序依然可以使用浮点数)。

例如,电压传感器采集到的电压可能为1.234V,为了避免使用小数,可以缩小单位至mV("m"表示“毫”,10-3),此时,1.234V即可表示为1234mV。若使用aw_sensor_val_t类型的数据表示该电压值,则val值为1234,unit为-3(表示10-3,对应了单位前缀:"m",即“毫”)。

由此可见, unit为负数时可以表示一个小数。此外,val值的类型为有符号32位整数,其可以表示的数据范围为:-2147483648 ~ 2147483647。若数据超过该范围,则也可以将unit设置为正数,例如,若传感器数据为2147483647000,则可以将val的值设置为2147483647,unit的值设置为AW_SENSOR_UNIT_KILO(即:3,表示103,对应了符号:"k",即“千”)。

假设传感器通道0为一个温度传感器通道,则获取温度的范例程序详见程序清单6.34。

程序清单6.34 获取单通道传感器数据的范例程序

其中,pow()函数为标准C库提供的数学运算函数(在math.h文件中声明),用于求取一个数的幂,其函数原型为:

其返回值即为x的y次方,即:xy。该函数的操作数均为double类型的双精度浮点数,运算效率较低。通常情况下,如非必要,都不建议引入浮点运算。例如,一个传感器数据仅仅只需要打印显示,则不需要将其转换为浮点数,仅需将小数点显示至合适的位置即可。例如,对于一个温度传感器数据,若其unit为-3,则以基本单位℃为单位进行数值的打印显示时,应显示3位小数,比如,45087应显示为45.087℃,基于此,分别显示整数部分和小数部分即可:

程序中,将val值整除1000作为了整数部分,对1000取余作为了小数部分(打印小数部分时,位宽固定为3位,且不足3位时,应在前面补0,比如45087对1000取余的结果为87,但应显示为"087")。

由此可见,打印显示时,完全可以避免浮点运算。需要注意的是,unit的值不一定为-3,也可能为-6或其它值。这种情况下,就要分别处理,例如,为-6时,应打印显示6位小数:

显然,这样处理起来略显复杂,需要分别为不同的unit值打印不同的小数位数。但在实际应用中,显示的小数位数往往是固定的,其通常由实际显示器(比如:数码管位数,显示器位宽等)或具体应用需求决定,不难想象,如果一个显示器一会儿显示3位小数,一会儿显示6位小数,用户体验将很难得到保证。

如果应用需要将显示的小数位数固定为3,那么当unit为-6时,可以将unit转换为-3后再按照3位小数进行显示,例如:

程序中,首先将unit的值增加了3,即表示将数据扩大了103,即1000倍。为了使数据保持不变,需要将val值缩小1000倍。如此一来,temp_val中的unit值又变为-3了,而后即可按照3位小数进行打印显示。由于val值整除了1000,那么原来低三位的数据均会丢失,也就意味着,精度会存在损失,实际上, 6位小数仅显示3位,本身就是一种精度的舍弃。例如,原val值为25234167,unit为-6,表示了25.234167℃。经过转换后,val值为25234,unit为-3,表示了25.234℃,即完成了由6位小数精度到3位小数精度的转换。

如果一个系统中固定温度显示的精度为3位小数,那么可以将所有温度数据的unit转换为-3。为便于用户使用,AWorks提供了传感器数据单位转换函数,其转换原理如下。

若是扩大单位(增加unit的值),假定unit增加的值为n,则会将val的值整除10n,由于存在整除,将会使原val值的精度减小。精度减小时,遵循四舍五入法则。例如,原数据为1860mV,若将单位转换为V,则转换的结果为2V;原数据为1245mV,若将单位转换为V,则转换的结果为1V。由于存在精度的损失,单位的扩大应该谨慎使用。

若是缩小单位(减小unit的值),假定unit减小的值为n,则会将val的值乘以10n,但应特别注意,val值的类型为32位有符号数,其能够表示的数据范围为:-2147483648 ~ 2147483647。不应使val值扩大10n后超过该范围。缩小单位不存在精度的损失,但应注意数据的溢出,不应将一个数据缩小至太小的单位。若数据可能溢出,则转换会失败,原数据的值和单位均会保持不变。

特别地,若转换前后的单位没有发生变化,则整个传感器的值保持不变。

传感器数据单位转换的函数原型为:

其中,p_buf为传感器数据缓存,num为缓存大小,表示需要转换单位的数据个数,to_unit表示目标单位,其值为AW_SENSOR_UNIT_* (比如: AW_SENSOR_UNIT_MILLI)。若返回值为AW_OK,表示所有数据转换成功;否则,表明存在转换失败的数据,转换失败可能是由于在缩小单位时,val值无法完成扩大,即扩大10n后会超过有符号32位数所能够表示的范围。转换失败的数据val值和unit值将保持不变,用户可以根据数据转换结束后的单位是否为目标单位来判断某一数据是否转换成功。

例如,从传感器中获取数据,并按照3位小数进行打印显示的范例程序详见程序清单6.35。

程序清单6.35 传感器数据单位转换的范例程序

程序中,假定了通道0为温度传感器通道,由于val值能够表示的数据范围为-2147483648 ~ 2147483647,当unit为-3时,其可以表示的温度范围为:-2147483.648 ~ 2147483.647℃。在一般应用环境中,温度不会超过该范围,因此,单位转换必然会成功,当能够确定数据不会超过表示范围时,可以不用判断单位转换函数的返回值。

  • 获取一组(多个)传感器通道的数据

该函数用于获取一组(多个)传感器通道的数据,其函数原型为:

其中,p_ids为指向传感器通道id列表的指针;num表示通道的数目,即id列表的大小;p_buf指向用于存储各通道数据的缓存,缓存大小应该与num一致,函数执行结束后,其中将包含各个通道的数据。

若返回值为AW_OK,则表示所有通道的数据均获取成功,p_buf所指缓存中存放了有效的数据;否则,表示存在数据获取失败的通道,此时,p_buf所指缓存中,这些失败的通道对应的数据将为无效值,即:使用 AW_SENSOR_VAL_IS_VALID()宏判断数据有效性时,将返回FALSE,用户可以使用AW_SENSOR_VAL_IS_VALID()宏逐一检查各个通道的数据,以判断哪些通道的数据获取成功,哪些通道的数据获取失败。特别注意,当数据为无效值时,val值将为标准错误码,用户可以根据val值判断该通道失败的原因,例如,值为-AW_ENODEV时,表示对应通道不存在。

AW_SENSOR_VAL_IS_VALID()宏用于判断一个数据的有效性,其原型(aw_sensor.h)为:

其中,data为aw_sensor_val_t类型的数据,仅当该宏返回TRUE时,才表示data为有效的传感器数据。否则,data为无效值,此时,unit值无效,val值表示标准错误码,其反应了数据无效(即某种操作失败)的原因。

获取一组通道(通道0、3、5、6、8、9)数据的范例程序详见程序清单6.36。

程序清单6.36 获取一组(多个)通道数据的范例程序(1)

通常情况下,为了使程序更加简洁,也可以不判断函数的返回值,仅需在最后使用传感器数据前,判断传感器数据是否有效即可,范例程序详见程序清单6.37。

程序清单6.37 获取一组(多个)通道数据的范例程序(2)

4.禁能传感器通道

当某些传感器通道使用完毕,暂时不需要从其中获取数据时,可以禁能相应的通道,使其进入一种最佳的低功耗状态(若支持)。AWorks提供了两类禁能接口,分别用于禁能单个传感器通道和禁能一组(多个)传感器通道。

  • 禁能单个传感器通道

禁能单个传感器通道的函数原型为:

其中,id为传感器通道的编号。若函数返回值为AW_OK,则表示通道禁能成功;否则,表示通道禁能失败,返回值为标准错误码,可以据此判定失败的原因。例如,返回值为-AW_ENODEV时,表示id对应的传感器通道不存在。禁能通道0的范例程序详见程序清单6.38。

程序清单6.38 禁能单个传感器通道的范例程序

  • 禁能一组(多个)传感器通道

禁能一组(多个)传感器通道的函数原型为:

其中,p_ids为指向传感器通道id列表的指针;num表示通道的数目,即id列表的大小;p_result指向用于存储各个通道禁能结果的缓存,缓存大小应该与num一致。函数执行结束后,其中将包含各个通道禁能的结果,其数据含义与使能通道时的数据含义一致,即:unit的值无效,仅使用val值表示各个通道禁能的结果。此时,val值即为标准错误码,若其值为AW_OK,则表示相应的通道禁能成功;否则,表示相应的通道禁能失败,例如,值为-AW_ENODEV时,表示对应通道不存在。

aw_sensor_group_disable()函数的返回值同样为标准错误码,若其值为AW_OK,则表示所有通道禁能成功,此时,p_result中所有数据的val值均为AW_OK,因此,当返回值为AW_OK时,无需判断p_result中的值即可断定所有通道禁能成功;否则,表示存在禁能失败的通道,此时,可以逐一检查p_result中的值来判断具体哪些通道禁能成功,哪些通道禁能失败。禁能一组通道(通道0、3、5、6、8、9)的范例程序详见程序清单6.39。

程序清单6.39 禁能一组(多个)传感器通道的范例程序

基于数码管接口和通用传感器接口,可以实现一个简单的应用:使用数码管实时显示当前温度值。范例程序详见程序清单6.40。

程序清单6.40 使用数码管实时显示温度的范例程序

应用程序中,将需要使用到的传感器通道id和数码管显示器id使用宏的形式在程序前进行了定义(详见程序清单6.40的第7 ~ 8行),当前id均定义为0,若实际使用的id发生变化,仅需修改这两个宏值即可。

6.6 温控器

下面将结合此前介绍的接口,使用LED、蜂鸣器、数码管、矩阵键盘和温度采集,实现一个简易的温控器。

1. 功能简介

使用标准I2C接口的LM75B温度传感器采集温度并在数码管上显示,由于只有两位数码管,因此只显示整数部分;当温度为负数时,也不显示负,仅显示温度值。

可设置温度上限值和温度下限值,当温度高于上限值或低于下限值时,则蜂鸣器鸣叫。

2. 状态指示

在调节过程中,使用LED0和LED1两个LED用于状态指示:

  • LED0亮:表明当前值为上限值,数码管显示上限值;

  • LED1亮:表明当前值为下限值,数码管显示下限值;

  • 两灯闪烁:表明正常运行状态,数码管显示环境温度值。

3. 操作说明

设置上下限值时,共计使用4个按键。即:

  • SET键:用于进入设置状态。点击后首先进入温度上限值设定,再次点击可进入温度下限值设定,再次点击回到正常运行状态;

  • 左移/右移键:用于切换当前调节的位(个位/十位)。当进入设置状态后,当前调节的位会不断的闪烁;点击该键可以切换当前调节的位,由个位切换到十位,或由十位切换到个位;

  • 加1键:当进入设置状态后,当前调节的位会不断的闪烁,按该键可以使该位上的数值增加1;

  • 减1键:当进入设置状态后,当前调节的位会不断的闪烁,按该键可以使该位上的数值增减1。

(1)设置上限值

首次按下SET键进入上限值设置,此时LED0点亮,数码管显示上限值温度,个位不停闪烁。按“加1键”或“减1键”可以对当前闪烁位上得值进行调整,按下“左移/右移键”可以切换当前调节的位。

(2)设置下限值

在设置上限值的基础上,再次点击SET键即可进入下限值的设定,此时LED1点亮,数码管显示下限值温度,个位不停闪烁。按“加1键”或“减1键”可以对当前闪烁位上的值进行调整,按“左移/右移键”可以切换当前调节的位。

4. 功能实现

温控器的实现范例程序详见程序清单6.41。程序中比较繁琐的是按键的处理程序。为了使程序结构更加清晰,分别对3种按键:切换状态(KEY0)、切换当前调节位(KEY2)、调节当前位的值(KEY1和KEY3)写了3个函数,各个函数直接在__key_callback()按键回调函数中调用。其它部分均在while(1)主循环中完成,主要完成3件事情:温度值的采集,每隔500ms进行一次;温度值的判断,判断是否过高或过低,以便报警;正常状态下LED0和LED1的闪烁。

程序清单6.41 使用通用接口实现温控器代码

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    8601

    浏览量

    151167
  • 周立功
    +关注

    关注

    38

    文章

    130

    浏览量

    37632

原文标题:AWorks软件篇 — 通用设备接口

文章出处:【微信号:Zlgmcu7890,微信公众号:周立功单片机】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Micro USB接口常见故障及解决方法

    常见故障 接触不良 描述:设备无法通过Micro USB接口充电或数据传输。 原因:接口接触不良,可能是由于接口氧化、灰尘积累或物理损伤。
    的头像 发表于 11-27 09:57 724次阅读

    dp接口转换的常见问题

    DP接口(DisplayPort接口)转换过程中可能会遇到一些常见问题,这些问题通常与兼容性、线缆质量、连接稳定性、设置配置以及硬件故障等因素有关。 一、兼容性问题 设备不支持 :不是
    的头像 发表于 10-30 14:03 521次阅读

    TMS320C6000 EMIF至外部SDRAM接口

    电子发烧友网站提供《TMS320C6000 EMIF至外部SDRAM接口.pdf》资料免费下载
    发表于 10-26 10:06 0次下载
    TMS320C6000 EMIF至<b class='flag-5'>外部</b>SDRAM<b class='flag-5'>接口</b>

    USB接口常见的类型有哪些

    USB(通用串行总线)接口是一种广泛使用的连接技术,用于连接计算机与外部设备。自1996年推出以来,USB接口已经经历了多次迭代,以满足不断增长的数据传输速度和电源需求。以下是一些
    的头像 发表于 10-21 13:45 470次阅读

    工控机 — 兼具工业设备的可用性和电脑的灵活性

    向工业应用的通用设备通用操作系统过渡作为工业应用硬件平台的工业设备正在从专用设计的设备通用设备通用
    的头像 发表于 10-10 16:26 259次阅读
    工控机 — 兼具工业<b class='flag-5'>设备</b>的可用性和电脑的灵活性

    gpio接口是干什么的 gpio四种输入输出模式怎么选择

    GPIO接口的作用 GPIO(General Purpose Input/Output)接口,即通用输入输出接口,是一种用于连接和控制各种外部设备
    的头像 发表于 10-06 16:07 2767次阅读

    数字输出接口有哪些,数字输出接口的作用

    数字输出接口是电子设备中用于传输数字信号到外部设备的关键部分。这些接口种类繁多,各有特点,适用于不同的应用场景。以下是一些常见的数字输出
    的头像 发表于 10-01 15:55 681次阅读

    外部设备必须通过什么与主机

    外部设备(外设)必须通过特定的接口与主机进行连接和通信。这些接口可以是物理的,也可以是逻辑的,它们确保了数据、控制信号和状态信息能够在主机和外设之间有效传输。 物理接口 : 串行
    的头像 发表于 09-30 14:16 638次阅读

    使用USB接口的注意事项

    USB接口作为现代电子设备中最为常见接口之一,因其便捷性和通用性而广受用户欢迎。然而,为了确保USB
    的头像 发表于 09-30 14:13 788次阅读

    外部存储器有哪些

    外部存储器是指用于存储数据的独立设备,它们通常与计算机或其他电子设备连接,并提供额外的存储空间,允许用户在不改变主设备内部存储的情况下保存和访问大量数据。
    的头像 发表于 09-05 10:42 2278次阅读

    LED显示屏中什么是USB接口

    USB,全称是Universal Serial Bus,即通用串行总线。它是一种用于连接计算机与外部设备接口标准,具有广泛的应用范围。在LED显示屏中,USB接口就像是一个桥梁,连接
    的头像 发表于 08-11 01:51 384次阅读

    HDMI常见接口类型及应用领域

    易用等特点,成为了数字娱乐、信息传递和多媒体设备连接的重要接口。本文将详细介绍HDMI常见接口类型及其在不同领域的应用,以期为读者提供全面而深入的理解。
    的头像 发表于 05-29 16:48 3066次阅读

    常见的光纤接口介绍

    在现代通信和网络技术中,光纤接口扮演着至关重要的角色。它们不仅是连接光纤线缆和设备的桥梁,还承载着高速、大容量数据传输的重要任务。本文将详细介绍几种常见的光纤接口类型,包括它们的特点、
    的头像 发表于 05-29 16:08 2045次阅读

    常见的网络接口介绍

    在现今的数字化时代,网络接口作为连接各种设备和网络的桥梁,其重要性不言而喻。网络接口不仅关系到数据传输的速率和质量,还影响着整个网络的稳定性和安全性。因此,了解和选择合适的网络接口对于
    的头像 发表于 05-29 16:07 1866次阅读

    output接口和PHONES接口的区别

    输出接口和PHONES接口是两个不同的概念,接下来我将详细介绍它们的定义、特点和用途。 输出接口: 输出接口(output interface)是计算机系统用于向
    的头像 发表于 02-23 11:40 1.4w次阅读