您当前的位置: 首页 >  物联网

txwtech

暂无认证

  • 3浏览

    0关注

    813博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Edison 物联网:使用MRAA发挥平台输入输出能力

txwtech 发布时间:2016-04-10 18:39:35 ,浏览量:3



https://software.intel.com/zh-cn/articles/internet-of-things-using-mraa-to-abstract-platform-io-capabilities?utm_source=CSDN.com&utm_medium=Syndication&utm_campaign=IoT_PRC_Q3-15

目录
  • 1. 摘要
  • 2. MRAA 概述
    • 2.1. 获取 MRAA API 和 API 文档
    • 2.2. GPIO 针脚名称
    • 2.3. MRAA 一般用途
    • 2.4. MRAA Include 文件
  • 3. 使用 MRAA 和模拟设备
    • 3.1. 电压基准
    • 3.2. 模拟数字转换器 (ADC) 分辨 率
    • 3.3. 解析数据
    • 3.4. 模拟示例
  • 4. 使用 MRAA 和数字设备
    • 4.1. 数字输入示例
    • 4.2. 中断处理程序
    • 4.3. 数字输出示例
  • 5. 使用 MRAA 和脉宽调制 (PWM) 与数字设备
    • 5.1. 一般使用规则
    • 5.2. PWM 示例
  • 6. 使用 MRAA 和 I2C
    • 6.1. I2C 示例
  • 7. 使用 MRAA 和通用异步收发器 (UART)
    • 7.1. UART 示例
  • 8. 结束语

1. 摘要

本白皮书将介绍 MRAA API 的一般用法,该 API 可大大简化各类设备的使用,例如:

  • 模拟输入
  • 数字输入与输出
  • 脉宽调制 (PWM)
  • 内部集成两线式总线 (I2C) 设备
  • 使用通用异步收发器 (UART) 硬件的设备

与完整程序示例不同,本文主要节选部分 C 代码来验证 MRAA API 的核心原则。 为 充分掌握本文的信息,您应:

  • 熟知 Linux 操作系统和 C 编程语言。
  • 基本了解数字电子学和 GPIO 的用法。
  • 拥有待使用设备的规格表。

注: 关于代码编译或链接,以及如何将软件安装于特定平台,本 文将不予介绍。

2. MRAA 概述

MRAA(读作 em-rah)是用 C 语言编写的低级别通用库。 MRAA 旨在提取与平台(比 如英特尔® Galileo 或英特尔® Edison 开发板)基本 I/O 功能访问和控制相关的详细信 息,并将其转化为单个、简洁的 API。 请参阅下文,了解详细信息:

  • MRAA 可作为 Linux 通用输入/输出 (GPIO) 设备顶端的转换层。 尽管 Linux 提供丰富的基础设施来控制 GPIO,其用于处理 GPIO 的通用指令也非常标准,但 使用难度相对较大。
  • 根据定义,平台之间各具差异。 他们拥有不同的功能、针脚编号和 GPIO 类型。 例如,更换平台后,GPIO 针脚可能无法支持相同类型的功能。 某个特定平台可 能根本没有针脚。 另外, GPIO 在平台上的配置方式也取决于不同因素。 例如,一种 GPIO 针脚使用模式可能会影响其他针脚的其他使用模式,或影响其他针脚的使用。 因此 ,MRAA 可降低程序开发的复杂度,因为它可与其他软件一起使用来创建独立于平台的代 码。
  • 注: 尽管 MRAA 可用于编写独立于平台的代码,开发人 员仍然负责确保代码足够耐用,以适应平台的各种局限性。

2.1. 获取 MRAA API 和 API 文档

MRAA 数据包已安装于英特尔 Galileo 和 Edison 硬件,可直接链接至您的代码,如 下所述。 您还可获取英特尔源代码库的最新版本。

如欲获取 API 文档,请访问: http://iotdk.intel.com/docs/ma ster/mraa/

2.2. GPIO 针脚名称

本白皮书中引用了各种不同的“针脚”。 这些硬件针脚通常以编号的形式 加以引用。 针脚编号还可加上前缀,比如 “D” 代表数字, “A” 代表模拟。 例如,“D0” 指数字针脚 0, “A3” 指模拟输入针脚 3。 针脚还能够以类似 GPIO6 的形式引用,它表示 GPIO 针脚 6,无需用 “D” 或 “A” 指代模拟或数字。

2.3. MRAA 一般用途

创建代码之前,需遵循下列指南:

  1. MRAA 库必须链接至您的软件。 通常情况下,您必须用语句初始化 MRAA, 比如:
       
    view source print ?
    1mraa_result_t rv;
    2rv = mraa_init();
    3if (rv != MRAA_SUCCESS)
    4    
    5    . . .
  2. 许多 MRAA 函数返回 mraa_result_t 值。 您 必须确认该特定函数是否成功运行。
  3. 本文中的示例不提供检错功能。 强烈推荐对所有函数进行错误检查。
  4. 初始化后,您应向 MRAA 说明特定针脚将用于特定目的。 本文后续使用的 代码示例将举例说明该行为。
  5. 完成后(退出程序之前),您应告知 MRAA 释放针脚,以便清除所有内部状 态。 本文后续使用的代码示例将举例说明该行为。

2.4. MRAA Include 文件

用于 MRAA 的主要 Include 文件为 mraa.h,以及所有 独立于设备的 Include 文件,例如:

  • 模拟设备包含:

#include #include

  • 数字设备添加:

#include

3. 使用 MRAA 和模拟设备

模拟设备提供数据的方法是将电压电平从 0 更改为支持的最高电压。 这种数据通常 被称为模拟基准电压 (AREF)。 例如,模拟压力传感器可提供一开始为 0 (表示无压力 ),然后随压力的增加而上升时的电压数据。 传感器的电压随后由名为模拟数字转换器 (ADC) 的设备进行解析并转换为数值。 然后,控制该传感器的软件读取由 ADC 生成的数 值。

解析模拟传感器的数据时,您需要了解以下信息。 下列几点将在下文逐一进行介绍。

  1. 电压基准 (AREF) 值
  2. ADC 的分辨率
  3. 如何解析数据(取决于传感器类型)

3.1. 电压基准

电压基准通常为直流电 3.3 伏或 5.0 伏。 然而,基准电压可能各有差异,因为有些 平台(比如英特尔® Edison开发板)支持您生成针对该平台的自定义 AREF,无需使用其 内置 AREF。 因此,在获取此类设备的有效数据前,您需要了解它的 AREF。

3.2. 模拟数字转换器 (ADC) 分辨率

ADC 分辨率非常重要,因为它决定了测量值的精准度。 英特尔平台使用的所有 ADC 均支持 1024 (10 比特)的分辨率,而且在英特尔® Edison 开发板的案例中分辨率高达 4096 (12 比特)。

您可以确定大概的电压“阶跃”,即 AREF 值除以 ADC 分辨率之后的数值 。 您的应用随后将使用该数值。 电压阶跃的确定方法是:AREF 5.0 伏除以 ADC 分辨 率 1024 。 相除后的结果即为 ADC 返回的阶跃,约为 4 毫伏。

5.0 / 1024.0 = 0.00488 伏

3.3. 解析数据

根据以上信息,您可确定设备的模拟输入针脚所显示的大概电压电平。 ADC 分辨率越 高,电压测量值将越精确。

3.4. 模拟示例

Grove 湿度传感器 (http://www.seeedstudio.com/depot/Grove-Moisture-Sensor-p- 955.html) 是典型的简单模拟设备。 从根本上来说,它是一个可根据检测到的湿度 改变模拟输入针脚的电压电平的电阻器。 下列示例展示了传感器连接 A0 针脚后的工作原理。 下列代码示例显示了如何初始化 MRAA 和 A0 针脚、读取和打印该值,然后发布针脚:

 
view source print ?
01int main()
02{
03    /* initialize MRAA */
04    mraa_init();
05    /* create an MRAA analog context */
06    mraa_aio_context m_aio;
07    /* initialize A0 for use as an analog input */
08    m_aio = mraa_aio_init(0);
09 
10    /* read the value, an integer */
11    int value;
12    value = mraa_aio_read(m_aio);
13 
14    /* print the value */
15    printf(“The value returned was: %d\n”, value);
16 
17    /* now release (close) the pin and exit */
18    mraa_aio_close(m_aio);
19    return(0)   ;
20}

如果 ADC 分辨率为 1024 (10 比特),返回值将介于 0-1023 之间。 该数值解析方 法取决于传感器的设计。 以 Grove 湿度传感器为例,假设 ADC 分辨率是 10 比特, 数 据表将针对干燥、半潮湿和潮湿等属性值提供下列数值范围:

  • 0-300 = 干燥
  • 300-700 = 半潮湿
  • 700+ = 潮湿

重点提示: 传感器各不相同,因此并非所有传感器都可轻松解码 。 请注意以下要点:

  1. 有些传感器“神经过敏”(其输出电压上下波动)。 如果是这 种情况,可能需要选取几个样本读数,然后计算平均值。
  2. 如果要编写用于不同平台的 MRAA 驱动程序,那么您必须在代码中列明准确 的 AREF 电压值,如果有可能,还需列明 ADC 分辨率,这在计算时将会用到。 否则,返 回的数据可能无法使用。 在上述示例中,我们无需知道 AREF 电压,但这点不适用其他 比较复杂的模拟设备。 部分设备要求具有精确的 AREF 电压和 ADC 分辨率数值,以便确 定传感器的输出。

4. 使用 MRAA 和数字设备

数字设备可用于处理高低电平值,低电平值表示较低的电压电平,而高电平值表示较 高的电压电平。 只能够表示两种状态。 例如,在 5.0v 的系统中,低电平可能表示 0v ,高电平可能表示 5.0v。 然而,高电平通常由 1 表示,低电平由 0 表示。

数字设备可设置为输入或输出设备。 如果用作输入设备,您可使用 MRAA 读取数字针 脚,并返回表示电压高低状态的值。 相反,写入数字设备将引发数字针脚跳变至低电平 状态或高电平状态。

MRAA 可提供 API 用于读写数字针脚的状态。 此外,还可将用户提供的中断处理程序 连接至数字输入设备。 中断处理程序将于第 9 页予以介绍。 如欲使用 MRAA 的数字输 入和输出设备,您需要创建头文件:

#include

4.1. 数字输入示例

选择简单的数字输入设备为例,比如按钮式开关。 当按下开关,针脚将显示高电压电 平,否则,显示低电压电平。

 
view source print ?
01int main()
02{
03    /* initialize MRAA */
04    mraa_init();
05 
06    /* create an MRAA digital context */
07    mraa_ai o_context m_aio;
08 
09    /* initialize D2 for use as a digital pin */
10    m_gpio = mraa_gpio_init(2);
11 
12    /* configure the digital pin as an input */
13    mraa_gpio_dir(m_gpio, MRAA_GPIO_IN);
14 
15    /* read the value into an integer */
16    int value = mraa_gpio_read(m_gpio);
17 
18    /* print the value */
19    if (value != 0)
20        printf(“The button is being pushed\n”);
21    else
22        printf(“The button is not being pushed\n”);
23 
24    /* now release (close) the pin and exit */
25    mraa_gpio_close(m_gpio);
26    return(0);
27}

如上所示,这相当简单明了。 还请注意如何使用 mraa_gpio_dir() 告知 MRAA 将针脚配置为输入。 数字针脚既可用于输入,也可 用于输出,这与仅能用于输入的模拟针脚不同。

4.2. 中断处理程序

在有些情况下,您不希望用重复读取数字针脚的方式确定其状态。 以发动机上的传感 器为例,该传感器用于计算发动机的转速 (RPM)。 在这种情况下,重复读取针脚(设备 )以不断检测其变化不仅耗费精力,而且容易犯错。

MRAA 可帮助创建中断处理程序,并将其连接至针脚。 此时,如果针脚的状态/转换发 生某种特定变化(从低电平跳变至高电平,或从高电平跳变至低电平),MRAA 可确保您 的中断处理程序得以调用。

有了这种功能,您可轻松编写简单的计数函数,并告知 MRAA 在出现特定转换时调用 这种函数。 下面举例说明如何计数从高电平到低电平的跳变,并将这些跳变保留在计数 器中。

 
view source print ?
01/* first, create our counting variable */
02volatile int counter = 0;
03 
04/* Now our simple counting function. */
05/* This will be our interrupt handler. */
06void intrHandler(void *arg)
07{
08    counter++;
09}
10 
11/* now in our main() function */
12 
13int main()
14{
15 
16    /* initialize MRAA */
17    mraa_init();
18 
19    /* create an MRAA digital context */
20    mraa_aio_context m_aio;
21 
22    /* initialize D2 for use as digital pin */
23    m_gpio = mraa_gpio_init(2);
24 
25    /* configure the digital pin as an input */
26    mraa_gpio_dir(m_gpio, MRAA_GPIO_IN);
27 
28    /* now, setup an interrupt handler. */
29    /* Our function (intrHandler()) above will */
30    /* be called whenever the pin goes from */
31    /* HIGH to LOW */
32     */
33    mraa_gpio_isr(m_gpio, MRAA_GPIO_EDGE_FALLING, intrHandler, NULL);
34 
35    /* sleep for 5 seconds, and then print out the current */
36    /* value of counter */
37    sleep(5);
38 
39    printf(“Counter = %d\n”, counter);
40 
41    /* now, stop the interrupt handler and cleanup */
42    mraa_gpio_isr_exit(m_gpio);
43 
44    /* now release (close) the pin and exit */
45    mraa_gpio_close(m_gpio);
46    return(0);

在上述示例中观察:

  • 以可变关键字重点标示的计数变量。 这一点非常重要。 可变关键字能够向 C 编译器说明,这种变量可在不通知编译器的情况下进行更改,以防 止编译器在处理变量时进行某种优化。 如果没有可变关键字,编译器可能会认为变量无 需进行更改,并进行优化,由此造成上述示例中的值为 ‘0’。 所有中断处 理程序所控制的或暴露在中断处理程序外部的变量均应标示为可变变量。
  • 除 MRAA_GPIO_EDGE_FALLING之外,mraa_gpio_isr() 还可支持 MRAA_GPIO_EDGE_RISING (以检测从低到高的跳变),以及 MRAA_GPIO_EDGE_BOTH(以检测两种跳变)。 注: 并非所有平台 都支持上述跳变。 如要确定支持哪种跳变,最常用的方法是检查 mraa_gpio_isr() 的返回值。
  • 传递给 mraa_gpio_isr() 的最后一个自变量 为可选用户提供的指针值。 该自变量将供应给中断处理程序 intrHandler (),作为其唯一的自变量。 我们在上述示例中不需要这项功能,因此仅 传递 NULL。
  • 调用 mraa_gpio_isr_exit() 将禁用中断处理 程序,强力推荐进行此项操作以清理和避免出现意外情况。
  • 仅一条中断处理程序对某个特定针脚有效。 针脚总数取决于中断处理程序 ,同时也是平台所特有的,尽管使用三种中断处理程序(MRAA_GPIO_EDGE_RISING、 MRAA_GPIO_EDGE_FALLING 或 MRAA_GPIO_EDGE_BOTH)。 这是需要经常对 MRAA 函数的返 回值进行错误检查的另一原因。

4.3. 数字输出示例

正如您所想象的,数字输出非常简单明了。 下列示例可使数字针脚在 1 秒钟的休眠 期间跳变于高 (1) 低 (0) 之间。 类似这种特性可用于连接至针脚时的 LED 闪烁。

 
view source print ?
01int main()
02{
03    /* initialize MRAA */
04    mraa_init();
05 
06    /* create an MRAA digital context */
07    mraa_aio_context m_aio;
08 
09    /* initialize D13 for use as a digital pin */
10    m_gpio = mraa_gpio_init(13);
11 
12    /* configure the digital pin as an output */
13    mraa_gpio_dir(m_gpio, MRAA_GPIO_OUT);
14 
15    /* now run in a loop 10 times, blinking the output each second */
16    int i;
17    for (i=0; i
关注
打赏
1665060526
查看更多评论
0.0680s