<br><strong> 1. 摘要</strong> </br>
本白皮书将介绍 MRAA API 的一般用法,该 API 可大大简化各类设备的使用,例如:
<li>模拟输入</li>
<li>数字输入与输出</li>
<li>脉宽调制 (PWM)</li>
<li>内部集成两线式总线 (I2C) 设备</li>
<li>使用通用异步收发器 (UART) 硬件的设备</li>
<br>与完整程序示例不同,本文主要节选部分 C 代码来验证 MRAA API 的核心原则。 为充分掌握本文的信息,您应:</br>
<li>熟知 Linux 操作系统和 C 编程语言。</li>
<li>基本了解数字电子学和 GPIO 的用法。</li>
拥有待使用设备的规格表。</li>
注: 关于代码编译或链接,以及如何将软件安装于特定平台,本文将不予介绍。
<strong> 2. MRAA 概述</strong>
<li>MRAA(读作 em-rah)是用 C 语言编写的低级别通用库。 MRAA 旨在提取与平台(比如英特尔® Galileo 或英特尔® Edison 开发板)基本 I/O 功能访问和控制相关的详细信息,并将其转化为单个、简洁的 API。 请参阅下文,了解详细信息:</li>
<li>MRAA 可作为 Linux 通用输入/输出 (GPIO) 设备顶端的转换层。 尽管 Linux 提供丰富的基础设施来控制 GPIO,其用于处理 GPIO 的通用指令也非常标准,但使用难度相对较大。</li>
<li>根据定义,平台之间各具差异。 他们拥有不同的功能、针脚编号和 GPIO 类型。 例如,更换平台后,GPIO 针脚可能无法支持相同类型的功能。 某个特定平台可能根本没有针脚。 另外, GPIO 在平台上的配置方式也取决于不同因素。 例如,一种 GPIO 针脚使用模式可能会影响其他针脚的其他使用模式,或影响其他针脚的使用。 因此 ,MRAA 可降低程序开发的复杂度,因为它可与其他软件一起使用来创建独立于平台的代 码。</li>
注: 尽管 MRAA 可用于编写独立于平台的代码,开发人员仍然负责确保代码足够耐用,以适应平台的各种局限性。
<strong>2.1. 获取 MRAA API 和 API 文档</strong>
MRAA 数据包已安装于英特尔 Galileo 和 Edison 硬件,可直接链接至您的代码,如下所述。 您还可获取英特尔源代码库的最新版本。
如欲获取 API 文档,请访问: http://iotdk.intel.com/docs/ma ster/mraa/
<strong>2.2. GPIO 针脚名称</strong>
本白皮书中引用了各种不同的“针脚”。 这些硬件针脚通常以编号的形式 加以引用。 针脚编号还可加上前缀,比如 “D” 代表数字, “A” 代表模拟。 例如,“D0” 指数字针脚 0, “A3” 指模拟输入针脚 3。 针脚还能够以类似 GPIO6 的形式引用,它表示 GPIO 针脚 6,无需用 “D” 或 “A” 指代模拟或数字。
<strong>2.3. MRAA 一般用途</strong>
创建代码之前,需遵循下列指南:
1、MRAA 库必须链接至您的软件。 通常情况下,您必须用语句初始化 MRAA, 比如:
1 mraa_result_t rv;
2 rv = mraa_init();
3 if (rv != MRAA_SUCCESS)
4 <report the error, insert your own code below>
5 . . .
2、许多 MRAA 函数返回 mraa_result_t 值。 您必须确认该特定函数是否成功运行。
3、本文中的示例不提供检错功能。 强烈推荐对所有函数进行错误检查。
4、初始化后,您应向 MRAA 说明特定针脚将用于特定目的。 本文后续使用的代码示例将举例说明该行为。
5、完成后(退出程序之前),您应告知 MRAA 释放针脚,以便清除所有内部状 态。 本文后续使用的代码示例将举例说明该行为。
<strong>2.4. MRAA Include 文件</strong>
用于 MRAA 的主要 Include 文件为 mraa.h,以及所有独立于设备的 Include 文件,例如:
<li>模拟设备包含:</li>
#include <mraa.h>
#include <mraa/aio.h>
<li>数字设备添加:</li>
#include <mraa/gpio.h>
<strong>3. 使用 MRAA 和模拟设备</strong>
模拟设备提供数据的方法是将电压电平从 0 更改为支持的最高电压。 这种数据通常被称为模拟基准电压 (AREF)。 例如,模拟压力传感器可提供一开始为 0 (表示无压力 ),然后随压力的增加而上升时的电压数据。 传感器的电压随后由名为模拟数字转换器 (ADC) 的设备进行解析并转换为数值。 然后,控制该传感器的软件读取由 ADC 生成的数值。
解析模拟传感器的数据时,您需要了解以下信息。 下列几点将在下文逐一进行介绍。
1、电压基准 (AREF) 值
2、ADC 的分辨率
3、如何解析数据(取决于传感器类型)
<strong>3.1. 电压基准</strong>
电压基准通常为直流电 3.3 伏或 5.0 伏。 然而,基准电压可能各有差异,因为有些平台(比如英特尔® Edison开发板)支持您生成针对该平台的自定义 AREF,无需使用其 内置 AREF。 因此,在获取此类设备的有效数据前,您需要了解它的 AREF。
<strong>3.2. 模拟数字转换器 (ADC) 分辨率</strong>
ADC 分辨率非常重要,因为它决定了测量值的精准度。 英特尔平台使用的所有 ADC 均支持 1024 (10 比特)的分辨率,而且在英特尔® Edison 开发板的案例中分辨率高达 4096 (12 比特)。
您可以确定大概的电压“阶跃”,即 AREF 值除以 ADC 分辨率之后的数值 。 您的应用随后将使用该数值。 电压阶跃的确定方法是:AREF 5.0 伏除以 ADC 分辨 率1024 。 相除后的结果即为 ADC 返回的阶跃,约为 4 毫伏。
5.0 / 1024.0 = 0.00488 伏
<strong>3.3. 解析数据</strong>
根据以上信息,您可确定设备的模拟输入针脚所显示的大概电压电平。 ADC 分辨率越高,电压测量值将越精确。
<strong>3.4. 模拟示例</strong>
Grove 湿度传感器 (http://www.seeedstudio.com/depot/Grove-Moisture-Sensor-p- 955.html) 是典型的简单模拟设备。 从根本上来说,它是一个可根据检测到的湿度 改变模拟输入针脚的电压电平的电阻器。 下列示例展示了传感器连接 A0 针脚后的工作原理。 下列代码示例显示了如何初始化 MRAA 和 A0 针脚、读取和打印该值,然后发布针脚:
01 int 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 比特, 数 据表将针对干燥、半潮湿和潮湿等属性值提供下列数值范围:
<li>0-300 = 干燥</li>
<li>300-700 = 半潮湿</li>
<li>700+ = 潮湿</li>
重点提示: 传感器各不相同,因此并非所有传感器都可轻松解码 。 请注意以下要点:
1、有些传感器“神经过敏”(其输出电压上下波动)。 如果是这种情况,可能需要选取几个样本读数,然后计算平均值。
2、如果要编写用于不同平台的 MRAA 驱动程序,那么您必须在代码中列明准确的 AREF 电压值,如果有可能,还需列明 ADC 分辨率,这在计算时将会用到。 否则,返回的数据可能无法使用。 在上述示例中,我们无需知道 AREF 电压,但这点不适用其他 比较复杂的模拟设备。 部分设备要求具有精确的 AREF 电压和 ADC 分辨率数值,以便确 定传感器的输出。
<strong>4. 使用 MRAA 和数字设备</strong>
数字设备可用于处理高低电平值,低电平值表示较低的电压电平,而高电平值表示较高的电压电平。 只能够表示两种状态。 例如,在 5.0v 的系统中,低电平可能表示 0v ,高电平可能表示 5.0v。 然而,高电平通常由 1 表示,低电平由 0 表示。
数字设备可设置为输入或输出设备。 如果用作输入设备,您可使用 MRAA 读取数字针脚,并返回表示电压高低状态的值。 相反,写入数字设备将引发数字针脚跳变至低电平 状态或高电平状态。
MRAA 可提供 API 用于读写数字针脚的状态。 此外,还可将用户提供的中断处理程序连接至数字输入设备。 中断处理程序将于下文予以介绍。 如欲使用 MRAA 的数字输入和输出设备,您需要创建头文件:
#include <mraa/gpio.h>
<strong>4.1. 数字输入示例</strong>
选择简单的数字输入设备为例,比如按钮式开关。 当按下开关,针脚将显示高电压电 平,否则,显示低电压电平。
01 int 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 将针脚配置为输入。 数字针脚既可用于输入,也可 用于输出,这与仅能用于输入的模拟针脚不同。
<strong>4.2. 中断处理程序 </strong>
在有些情况下,您不希望用重复读取数字针脚的方式确定其状态。 以发动机上的传感 器为例,该传感器用于计算发动机的转速 (RPM)。 在这种情况下,重复读取针脚(设备 )以不断检测其变化不仅耗费精力,而且容易犯错。
MRAA 可帮助创建中断处理程序,并将其连接至针脚。 此时,如果针脚的状态/转换发生某种特定变化(从低电平跳变至高电平,或从高电平跳变至低电平),MRAA 可确保您 的中断处理程序得以调用。
有了这种功能,您可轻松编写简单的计数函数,并告知 MRAA 在出现特定转换时调用这种函数。 下面举例说明如何计数从高电平到低电平的跳变,并将这些跳变保留在计数 器中。
01 /* first, create our counting variable */
02 volatile int counter = 0;
03
04 /* Now our simple counting function. */
05 /* This will be our interrupt handler. */
06 void intrHandler(void *arg)
07 {
08 counter++;
09 }
10
11 /* now in our main() function */
12
13 int 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);
在上述示例中观察:
<li>以可变关键字重点标示的计数变量。 这一点非常重要。 可变关键字能够向 C 编译器说明,这种变量可在不通知编译器的情况下进行更改,以防止编译器在处理变量时进行某种优化。 如果没有可变关键字,编译器可能会认为变量无 需进行更改,并进行优化,由此造成上述示例中的值为 ‘0’。 所有中断处 理程序所控制的或暴露在中断处理程序外部的变量均应标示为可变变量。</li>
<li>除 MRAA_GPIO_EDGE_FALLING之外,mraa_gpio_isr() 还可支持 MRAA_GPIO_EDGE_RISING (以检测从低到高的跳变),以及 MRAA_GPIO_EDGE_BOTH(以检测两种跳变)。注: 并非所有平台 都支持上述跳变。 如要确定支持哪种跳变,最常用的方法是检查 mraa_gpio_isr() 的返回值。</li>
<li>传递给 mraa_gpio_isr() 的最后一个自变量为可选用户提供的指针值。 该自变量将供应给中断处理程序 intrHandler (),作为其唯一的自变量。 我们在上述示例中不需要这项功能,因此仅 传递 NULL。</li>
<li>调用 mraa_gpio_isr_exit() 将禁用中断处理程序,强力推荐进行此项操作以清理和避免出现意外情况。</li>
<li>仅一条中断处理程序对某个特定针脚有效。 针脚总数取决于中断处理程序 ,同时也是平台所特有的,尽管使用三种中断处理程序(MRAA_GPIO_EDGE_RISING、 MRAA_GPIO_EDGE_FALLING 或 MRAA_GPIO_EDGE_BOTH)。 这是需要经常对 MRAA 函数的返 回值进行错误检查的另一原因。</li>
<br><strong>4.3. 数字输出示例</strong></br>
正如您所想象的,数字输出非常简单明了。 下列示例可使数字针脚在 1 秒钟的休眠 期间跳变于高 (1) 低 (0) 之间。 类似这种特性可用于连接至针脚时的 LED 闪烁。
01 int 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<10; i++)
18 {
19 /* turn output on (HIGH) */
20 mraa_gpio_write(m_gpio, 1);
21 sleep(1);
22 /* turn output off (LOW) */
23 mraa_gpio_write(m_gpio, 0);
24 sleep(1);
25 }
26
27
28 /* now release (close) the pin and exit */
29 mraa_gpio_close(m_gpio);
30 return(0);
31 }
正如您所见,将 MRAA 用于数字 I/O 非常简单。 中断处理稍微复杂一些,不过只要您注意合理使用共享于中断处理程序外部的变量的可变关键字,其在多种应用中的使用也 会非常简单和方便。
<strong>5. 使用 MRAA 和脉宽调制 (PWM) 与数字设备</strong>
脉宽调制 (PWM) 是一种数字输出。 PWM 针脚的输出由两部分组成,分别为周期和占空比:
<li>周期指脉冲产生的频率。</li>
<li>占空比表示该周期在高电平状态中所占的比例。</li>
例如,如果您将周期和占空比分别设置为 2 毫秒和 50%,那么您的重复模式将为 1 毫秒高电平和 1 毫秒低电平电平,然后该周期会不断重复。 这可用于完成各种不同的功 能,比如可通过调节占空比调暗 LED 或控制发动机的速度。
<strong>5.1. 一般使用规则</strong>
<li>MRAA 能够将数字输出配置为 PWM 输出。 检查您的平台并找出可用作 PWM 输出的 GPIO,这一点非常重要。 具体可用作 PWM 输出的 GPIO 将因平台而异。</li>
<li>平台所容许的周期长度各不相同,因此,必须对 MRAA 调用进行错误检查。</li>
<li>有些设备在使用时会对周期长度提出一些要求。 例如,伺服发动机通常要求周期长达 20 毫秒。</li>
<li>使用 MRAA 的 PWM 设施所需的标题为:</li>
#include <mraa/pwm.h>
<strong>5.2. PWM 示例</strong>
我们将在下列示例中脉冲调节 LED 的亮度。 我们所采用的做法是:将周期设置为 10 毫秒,每隔 100 毫秒增加或降低占空比。
01 int main()
02 {
03 /* initialize MRAA */
04 mraa_init();
05
06 /* create an MRAA PWM context */
07 mraa_pwm_context m_pwm;
08
09 /* initialize D3 for use as a digital pin */
10 m_pwm = mraa_gpio_init(3);
11
12 /* set the period to 10ms */
13 mraa_pwm_period_ms(m_pwm, 10);
14
15 /* set the initial duty cycle to 0 */
16 mraa_pwm_write(m_pwm, 0.0);
17
18 /* enable PWM output */
19 mraa_pwm_enable(m_pwm, 1);
20 /* now run in a loop 10 times, dimming or brightening /*
21 /* the LED every 100ms */
22 int i;
23 float duty = 0.0;
24 for (i=0; i<10; i++)
25 {
26 /* first, start at 0% duty cycle and increase to 100% */
27 for (duty= 0.0; duty < 1.0; duty+=0.1)
28 {
29 mraa_pwm_write(m_pwm, duty);
30 usleep(100000);
31 }
32 sleep(1);
33 /* now decrease it to 0% */
34 for (duty= 1.0; duty > 0.0; duty-=0.1)
35 {
36 mraa_pwm_write(m_pwm, duty);
37 usleep(100000);
38 }
39 sleep(1);
40 }
41
42 /* disable PWM output and clean up */
43 mraa_pwm_enable(m_pwm, 0);
44
45 mraa_pwm_close(m_pwm);
46 return(0);
47 }
在上述示例中观察:
<li>我们使用了mraa_pwm_write(),它可接受 0.0 (关闭,占空比 0%) - 1.0(开启,占空比 100%)之间的浮点值。</li>
<li>MRAA 还可提供一套函数支持您直接指定脉宽,无需通过时间比例(占空比 )。 对于某些在周期以及输出必须为高电平的周期内的时间量方面有特殊要求的传感器 来说,这一功能可发挥巨大作用。</li>
<li>MRAA 可提供各种不同的函数,并使用秒、(上述示例中使用的)毫秒和微秒为单位设置周期。 MRAA 还可提供函数支持您用一个函数调用同时设置周期和占空比。</li>
<li>您可能会遇到一个常见问题,即平台是否支持设备要求的周期。 如果基础硬件不支持您设置的周期,MRAA 将返回相应的错误代码。</li>
<br><strong> 6. 使用 MRAA 和 I2C</strong> </br>
使用 I2C 时,请牢记以下几点:
<li>I2C 为两线式双向总线,运行频率为 100Khz、400Khz,和 3.4Mhz。</li>
<li>I2C 由 2 条信号线组成: SCL(时钟)和 SDA(数据)。</li>
<li>I2C 设备的地址必须是特定 I2C 总线上的唯一地址。多台设备可同时连接至一条特定总线,但每台设备必须有唯一的地址,一次只允许一台设备进行通信。</li>
<li>除地址外,I2C 设备通常有一套可进行读写的寄存器(有时称为指令) 通 信和控制就是通过这些可读写特定设备的寄存器来进行。</li>
<li>使用 MRAA 的 I2C 设备所需的标题为:</li>
#include <mraa/i2c.h>
<strong> 6.1. I2C 示例</strong>
在下列示例中,我们将查询实时时钟 I2C 设备模块 (DS1307),并以秒为单位读取寄存器 (0x00)。 我们将 MRAA I2C 环境设置为 I2C 总线 0,使用 0x68 的 I2C 地址,然 后以秒为单位读取寄存器,并每隔一秒输入 10 秒。
重点提示: 许多 I2C 设备对如何读写设备的数据提出了不同的要求。 请参阅设备规格,了解更多信息。
01 int main()
02 {
03 /* initialize MRAA */
04 mraa_init();
05
06 /* create an MRAA I2C context */
07 mraa_i2c_context m_i2c;
08
09 /* initialize I2C on bus 0 */
10 m_i2c = mraa_i2c_init(0);
11
12 /* now run in a loop 10 times, reading the seconds */
13 /* register and printing it.*/
14 int i;
15 for (i=0; i<10; i++)
16 {
17 char buf;
18
19 /* always specify the address */
20 mraa_i2c_address(m_i2c, 0x68);
21 /* read in 1 byte. mraa_i2c_read() always reads */
22 /* starting at register 0x00 */
23 mraa_i2c_read(m_i2c, &buf, 1);
24
25 printf(“The seconds returned was: %d\n”, buf);
26 sleep(1);
27 }
28 mraa_i2c_stop(m_pwm);
29 return(0);
30 }
在上述示例中观察:
<li>我们使用了 mraa_i2c_read(),从寄存器 0x00 开始读取。 如需更高级的使用模式,MRAA 可提供更多可在特定寄存器中进行读写 或读/写字(16 比特)数据的函数。 使用方法的选择取决于您的设备和软件要求。</li>
<li>读取字数据时,您可能需要调换返回的字节(取决于您的设备)。</li>
<li>设备所适用的访问方式各不相同。 例如,我们试用过的一台设备无法正常 使用 mraa_i2c_read(),而要求 mraa_i2c_read_byte_data()。 可能需要进行进一步试验。</li>
<br><strong>7. 使用 MRAA 和通用异步收发器 (UART)</strong></br>
请回顾:
<li>基于 UART 的设备基本上都是标准串口设备,比如我们过去采用 COM 端口 连接计算机时所使用的设备。 通常情况下,这种连接为全双工连接,并以特定的速度( 波特率)运行。 许多传感器常见的波特率为 9600(每秒 9600 比特)。</li>
<li>实际上,您有两根线: TX(用于发送数据)和 RX(用于接收数据)。 然而使用大多数传感器时,您可以使用不同的电压电平,而非根据 RS232 标准编译的 COM 端口所使用的电压电平。 这些电压通常为 5.0v 或 3.3v,而 RS232 COM 端口使用的电 压通常在 -15v - +15v 之间。 请勿将这种低压传感器直接连接至 COM 端口,除非为传 感器厂商特别支持的传感器, 否则会造成设备损坏。</li>
<li>MRAA 可提供一种机制,即数字针脚 D0 和 D1(基于英特尔® Galileo 或英特尔® Edison 开发板)可路由至硬件辅助的 UART,从而支持软件轻松读取或将数据写入 UART 可访问的设备。 MRAA 设置合适的针脚路由后,您可以使用标准 Linux 读 () 写 () 通过 /dev/ttyX 端口与该设备进行通信。</li>
注: MRAA 将仅安排合适的针脚路由以连接硬件 UART;您的软件负责打开和设置正确的 TTY 设备并开始通信。
<li>使用 MRAA 的 UART 设备所需的标题为:</li>
#include <mraa/uart.h>
<strong>7.1. UART 示例</strong>
在下列示例中,我们将使用连接至针脚 D0 和 D1 的基于虚构 UART 的传感器。 在 MRAA 中对 UART 进行编号,即 UART 0。
打开设备后,您要正确地启用和禁用不同的行规则(Linux 内核自动将其应用于串行 设备),这一点非常重要。 为此,我们可包含名为 setupTTY() 的函数,然后打开 TTY 设备。
01 int setupTTY(int fd, speed_t baud)
02 {
03 if (fd < 0)
04 return 0;
05
06 struct termios termio;
07
08 /* get current modes */
09 tcgetattr(fd, &termio);
10
11 /* setup for a 'raw' mode. 8bit, 1 stop bit, no parity, */
12 /* no echo or special character handling, */
13 /* no flow control or line editing semantics. */
14
15 cfmakeraw(&termio);
16
17 // set our baud rates
18 cfsetispeed(&termio, baud);
19 cfsetospeed(&termio, baud);
20
21 // make it so
22 if (tcsetattr(fd, TCSAFLUSH, &termio) < 0)
23 {
24 fprintf(stderr, “%s\n”, “tcsetattr failed”);
25 return 0;
26 }
27
28 return 1;
29 }
30
31 /* now our main function */
32 ¬
33 int main()
34 {
35 /* initialize MRAA */
36 mraa_init();
37
38 /* create an MRAA UART context */
39 mraa_uart_context m_uart;
40
41 /* initialize UART 0 (pins D0 and D1 used for TX and RX) */
42 m_uart = mraa_uart_init(0);
43
44 /* now that we have our context, query MRAA */
45 /* to get the file name of the TTY device we need to open. */
46
47 char *devPath = mraa_uart_get_dev_path(m_uart);
48
49 /* if this fails, we can go no further */
50 if (!devPath)
51 {
52 fprintf(stderr, “%s\n”, “Could not get device path”);
53 return 0;
54 }
55
56 /* now that we have a device path, open it and set it up */
57 int fd;
58 if ((fd = open(devPath, O_RDWR)) == -1)
59 {
60 fprintf(stderr, “%s\n”, “Could not open device path”);
61 return 0;
62 }
63
64 /* now we are almost ready, call setupTTY() and from then on */
65 /* we can read/write to the device normally. */
66 /* We assume a baud rate of 9600/ */
67 if (!setupTTY(fd, B9600))
68 {
69 fprintf(stderr, “%s\n”, “Could not setup TTY port”);
70 return 0;
71 }
72
73 /* now we can use standard read and write calls */
74 /* read(fd, ...) or write(fd, …) */
75
76 /* when we are done, close the device and exit */
77 close(fd);
78
79 return(0);
80 }
在上述示例中观察:
<li>使用基于 UART 的设备大体包括使 MRAA 正确设置针脚、向 MRAA 请求设备路径、打开并初始化设备路径,然后使用标准 Unix* 读 () 写 () 调用。</li>
<li>如果没有可供读取的内容,直接使用读 () 写 () 将会受阻。 为避免出现 这种现象,在大多数情况下,您希望创建一种函数,可在读取前检查是否有数据提供。 使用 select() 系统调用可实现这一点。 以 UPM wt5001 驱动程序为例。 这项功能可作为 dataAvailable() 的方法实施。</li>
<li>在本示例中,我们假设波特率为最常见的 9600。 Linux 系统头文件定义了 'B9600' 常量,当然,也可提供其他波特率。 您需要根据所使用的设备选择 正确的波特率。</li>
<li>本示例中所使用的 setupTTY() 函数假定最常见的情况。 通常您不会运行对此有其他要求的设备,不过这点需要注意。</li>
<br><strong> 8. 结束语</strong> </br>
MRAA 可简化英特尔® Galileo 或英特尔® Edison 开发板等平台的基本 I/O 功能的访 问与控制流程。 MRAA 是一个功能强大的通用库,可为这类平台提供一致的用法来 使用模拟、数字、PWM、I2C 和 UART 设备。 对于任何人的物联网工具箱来说,这都是一 款关键的补充产品。
<strong> 关于 ICS</strong>
基于对驱动程序、操作系统以及物联网传感器的深入了解,Integrated Computer Solutions (ICS) 融合了全面的专业知识和工程经验,可开发出能够满足消费者期望并包 含创新、易用接口的定制型嵌入式系统。 ICS 可在应对工程设计挑战的同时,降低复杂 性、成本和冗余,并缩短开发时间。
点击下载附件:<font color="#0000C6"><font size="4"><a href="http://intel.eetrend.com/files/2016-05/wen_zhang_/100001577-3489-icsusi…;