Edison 物联网:使用MRAA发挥平台输入输出能力
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 一般用途
创建代码之前,需遵循下列指南:
- MRAA 库必须链接至您的软件。 通常情况下,您必须用语句初始化 MRAA, 比如:
view sourceprint?
1
mraa_result_t rv;
2
rv = mraa_init();
3
if
(rv != MRAA_SUCCESS)
4
<report the error, insert your own code below>
5
. . .
- 许多 MRAA 函数返回 mraa_result_t 值。 您 必须确认该特定函数是否成功运行。
- 本文中的示例不提供检错功能。 强烈推荐对所有函数进行错误检查。
- 初始化后,您应向 MRAA 说明特定针脚将用于特定目的。 本文后续使用的 代码示例将举例说明该行为。
- 完成后(退出程序之前),您应告知 MRAA 释放针脚,以便清除所有内部状 态。 本文后续使用的代码示例将举例说明该行为。
2.4. MRAA Include 文件
用于 MRAA 的主要 Include 文件为 mraa.h,以及所有 独立于设备的 Include 文件,例如:
- 模拟设备包含:
#include <mraa.h>
#include <mraa/aio.h>
- 数字设备添加:
#include <mraa/gpio.h>
3. 使用 MRAA 和模拟设备
模拟设备提供数据的方法是将电压电平从 0 更改为支持的最高电压。 这种数据通常 被称为模拟基准电压 (AREF)。 例如,模拟压力传感器可提供一开始为 0 (表示无压力 ),然后随压力的增加而上升时的电压数据。 传感器的电压随后由名为模拟数字转换器 (ADC) 的设备进行解析并转换为数值。 然后,控制该传感器的软件读取由 ADC 生成的数 值。
解析模拟传感器的数据时,您需要了解以下信息。 下列几点将在下文逐一进行介绍。
- 电压基准 (AREF) 值
- ADC 的分辨率
- 如何解析数据(取决于传感器类型)
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 针脚、读取和打印该值,然后发布针脚:
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 比特, 数 据表将针对干燥、半潮湿和潮湿等属性值提供下列数值范围:
- 0-300 = 干燥
- 300-700 = 半潮湿
- 700+ = 潮湿
重点提示: 传感器各不相同,因此并非所有传感器都可轻松解码 。 请注意以下要点:
- 有些传感器“神经过敏”(其输出电压上下波动)。 如果是这 种情况,可能需要选取几个样本读数,然后计算平均值。
- 如果要编写用于不同平台的 MRAA 驱动程序,那么您必须在代码中列明准确 的 AREF 电压值,如果有可能,还需列明 ADC 分辨率,这在计算时将会用到。 否则,返 回的数据可能无法使用。 在上述示例中,我们无需知道 AREF 电压,但这点不适用其他 比较复杂的模拟设备。 部分设备要求具有精确的 AREF 电压和 ADC 分辨率数值,以便确 定传感器的输出。
4. 使用 MRAA 和数字设备
数字设备可用于处理高低电平值,低电平值表示较低的电压电平,而高电平值表示较 高的电压电平。 只能够表示两种状态。 例如,在 5.0v 的系统中,低电平可能表示 0v ,高电平可能表示 5.0v。 然而,高电平通常由 1 表示,低电平由 0 表示。
数字设备可设置为输入或输出设备。 如果用作输入设备,您可使用 MRAA 读取数字针 脚,并返回表示电压高低状态的值。 相反,写入数字设备将引发数字针脚跳变至低电平 状态或高电平状态。
MRAA 可提供 API 用于读写数字针脚的状态。 此外,还可将用户提供的中断处理程序 连接至数字输入设备。 中断处理程序将于第 9 页予以介绍。 如欲使用 MRAA 的数字输 入和输出设备,您需要创建头文件:
#include <mraa/gpio.h>
4.1. 数字输入示例
选择简单的数字输入设备为例,比如按钮式开关。 当按下开关,针脚将显示高电压电 平,否则,显示低电压电平。
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 将针脚配置为输入。 数字针脚既可用于输入,也可 用于输出,这与仅能用于输入的模拟针脚不同。
4.2. 中断处理程序
在有些情况下,您不希望用重复读取数字针脚的方式确定其状态。 以发动机上的传感 器为例,该传感器用于计算发动机的转速 (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);
|
在上述示例中观察:
- 以可变关键字重点标示的计数变量。 这一点非常重要。 可变关键字能够向 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 闪烁。
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 非常简单。 中断处理稍微复杂一些,不过只要 您注意合理使用共享于中断处理程序外部的变量的可变关键字,其在多种应用中的使用也 会非常简单和方便。
5. 使用 MRAA 和脉宽调制 (PWM) 与数字设备
脉宽调制 (PWM) 是一种数字输出。 PWM 针脚的输出由两部分组成,分别为周期和占 空比:
- 周期指脉冲产生的频率。
- 占空比表示该周期在高电平状态中所占的比例。
例如,如果您将周期和占空比分别设置为 2 毫秒和 50%,那么您的重复模式将为 1 毫秒高电平和 1 毫秒低电平电平,然后该周期会不断重复。 这可用于完成各种不同的功 能,比如可通过调节占空比调暗 LED 或控制发动机的速度。
5.1. 一般使用规则
- MRAA 能够将数字输出配置为 PWM 输出。 检查您的平台并找出可用作 PWM 输出的 GPIO,这一点非常重要。 具体可用作 PWM 输出的 GPIO 将因平台而异。
- 平台所容许的周期长度各不相同,因此,必须对 MRAA 调用进行错误检查。
- 有些设备在使用时会对周期长度提出一些要求。 例如,伺服发动机通常要 求周期长达 20 毫秒。
- 使用 MRAA 的 PWM 设施所需的标题为:
#include <mraa/pwm.h>
5.2. PWM 示例
我们将在下列示例中脉冲调节 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
|
}
|
在上述示例中观察:
- 我们使用了mraa_pwm_write(),它可接受 0.0 (关闭,占空比 0%) - 1.0(开启,占空比 100%)之间的浮点值。
- MRAA 还可提供一套函数支持您直接指定脉宽,无需通过时间比例(占空比 )。 对于某些在周期以及输出必须为高电平的周期内的时间量方面有特殊要求的传感器 来说,这一功能可发挥巨大作用。
- MRAA 可提供各种不同的函数,并使用秒、(上述示例中使用的)毫秒和微 秒为单位设置周期。 MRAA 还可提供函数支持您用一个函数调用同时设置周期和占空比。
- 您可能会遇到一个常见问题,即平台是否支持设备要求的周期。 如果基础 硬件不支持您设置的周期,MRAA 将返回相应的错误代码。
6. 使用 MRAA 和 I2C
使用 I2C 时,请牢记以下几点:
- I2C 为两线式双向总线,运行频率为 100Khz、400Khz,和 3.4Mhz。
- I2C 由 2 条信号线组成: SCL(时钟)和 SDA(数据)。
- I2C 设备的地址必须是特定 I2C 总线上的唯一地址。多台设备可同时连接 至一条特定总线,但每台设备必须有唯一的地址,一次只允许一台设备进行通信。
- 除地址外,I2C 设备通常有一套可进行读写的寄存器(有时称为指令) 通 信和控制就是通过这些可读写特定设备的寄存器来进行。
- 使用 MRAA 的 I2C 设备所需的标题为:
#include <mraa/i2c.h>
6.1. I2C 示例
在下列示例中,我们将查询实时时钟 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
|
}
|
在上述示例中观察:
- 我们使用了 mraa_i2c_read(),从寄存器 0x00 开始读取。 如需更高级的使用模式,MRAA 可提供更多可在特定寄存器中进行读写 或读/写字(16 比特)数据的函数。 使用方法的选择取决于您的设备和软件要求。
- 读取字数据时,您可能需要调换返回的字节(取决于您的设备)。
- 设备所适用的访问方式各不相同。 例如,我们试用过的一台设备无法正常 使用 mraa_i2c_read(),而要求 mraa_i2c_read_byte_data()。 可能需要进行进一步试验。
7. 使用 MRAA 和通用异步收发器 (UART)
请回顾:
- 基于 UART 的设备基本上都是标准串口设备,比如我们过去采用 COM 端口 连接计算机时所使用的设备。 通常情况下,这种连接为全双工连接,并以特定的速度( 波特率)运行。 许多传感器常见的波特率为 9600(每秒 9600 比特)。
- 实际上,您有两根线: TX(用于发送数据)和 RX(用于接收数据)。 然 而使用大多数传感器时,您可以使用不同的电压电平,而非根据 RS232 标准编译的 COM 端口所使用的电压电平。 这些电压通常为 5.0v 或 3.3v,而 RS232 COM 端口使用的电 压通常在 -15v - +15v 之间。 请勿将这种低压传感器直接连接至 COM 端口,除非为传 感器厂商特别支持的传感器, 否则会造成设备损坏。
- MRAA 可提供一种机制,即数字针脚 D0 和 D1(基于英特尔® Galileo 或英 特尔® Edison 开发板)可路由至硬件辅助的 UART,从而支持软件轻松读取或将数据写入 UART 可访问的设备。 MRAA 设置合适的针脚路由后,您可以使用标准 Linux 读 () 写 () 通过 /dev/ttyX 端口与该设备进行通信。
注: MRAA 将仅安排合适的针脚路由以连接硬件 UART;您的软件 负责打开和设置正确的 TTY 设备并开始通信。
- 使用 MRAA 的 UART 设备所需的标题为:
#include <mraa/uart.h>
7.1. UART 示例
在下列示例中,我们将使用连接至针脚 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
|
}
|
在上述示例中观察:
- 使用基于 UART 的设备大体包括使 MRAA 正确设置针脚、向 MRAA 请求设备 路径、打开并初始化设备路径,然后使用标准 Unix* 读 () 写 () 调用。
- 如果没有可供读取的内容,直接使用读 () 写 () 将会受阻。 为避免出现 这种现象,在大多数情况下,您希望创建一种函数,可在读取前检查是否有数据提供。 使用 select() 系统调用可实现这一点。 以 UPM wt5001 驱动程序为例。 这项功能可作为 dataAvailable() 的方法 实施。
- 在本示例中,我们假设波特率为最常见的 9600。 Linux 系统头文件定义了 'B9600' 常量,当然,也可提供其他波特率。 您需要根据所使用的设备选择 正确的波特率。
- 本示例中所使用的 setupTTY() 函数假定最常 见的情况。 通常您不会运行对此有其他要求的设备,不过这点需要注意。
8. 结束语
MRAA 可简化英特尔® Galileo 或英特尔® Edison 开发板等平台的基本 I/O 功能的访 问与控制流程。 MRAA 是一个功能强大的通用库,可为这类平台提供一致的用法来 使用模拟、数字、PWM、I2C 和 UART 设备。 对于任何人的物联网工具箱来说,这都是一 款关键的补充产品。
关于 ICS
基于对驱动程序、操作系统以及物联网传感器的深入了解,Integrated Computer Solutions (ICS) 融合了全面的专业知识和工程经验,可开发出能够满足消费者期望并包 含创新、易用接口的定制型嵌入式系统。 ICS 可在应对工程设计挑战的同时,降低复杂 性、成本和冗余,并缩短开发时间。
Edison 物联网:使用MRAA发挥平台输入输出能力相关推荐
- 【毕业设计】基于云平台的火灾报警器 - stm32 物联网 单片机 OneNET云平台
文章目录 0 简介 1 项目简介 2 开发环境 3 火焰传感器 4 连接OneNET云平台 5 演示效果 6 最后 0 简介 Hi,大家好,这里是丹成学长,今天向大家介绍一个 单片机项目 基于云平台的 ...
- 毕业设计 基于云平台的火灾报警系统设计与实现 - stm32 物联网 单片机 OneNET云平台
文章目录 0 简介 1 项目简介 2 开发环境 3 火焰传感器 4 连接OneNET云平台 5 演示效果 6 最后 0 简介 Hi,大家好,学长今天向大家介绍一个 单片机项目 基于云平台的火灾报警器 ...
- 输变电设备物联网节点设备无线组网协议_U-Link 物联网(工业互联网)服务平台
原标题:U-Link 物联网(工业互联网)服务平台 智慧硬件物联云平台U-Link,即U-Link 物联网(工业互联网)服务平台是由公司自主研发的产品,面向生产制造业.智慧城市.气象环保.农业水利.智 ...
- 物联网iot私有云平台搭建
物联网iot私有云平台搭建 物联网的平台有多种,把其中的一些列出一个开源平台比照表. IoT 软件平台 设备管理? 集成 安全 数据收集协议 分析 支持可视化? 数据库 Kaa IoT Platfor ...
- 一款SpringBoot轻量级物联网综合业务支撑平台,附源码
SpringBoot轻量级物联网综合业务支撑平台源码 开发语言 : JAVA 数据库 : MySQL 开发工具 : IDEA 源码类型:全开源免费分享,需要学习可私信. 一.系统概述: 物联网综合业务 ...
- 物联网开发和管理平台 - shifu 了解与学习
今天知道的一个物联网开发和管理平台,算是边缘计算中应用层的框架 这个我之前也了解过一些,但是其他的平台基本都会有出自己的硬件,因为从物联网开发来看,确实底层和硬件开发占了大部分时间,但是创造效益却主要 ...
- 智慧养殖物联网远程管控系统平台
前言 养殖业是现代农业的发展标志,近些年养殖业发展的非常迅速,养殖也从以数量增长为主逐步向数量质量并重.优化结构和增加效益为主转变,主要特点是养殖开始向优势区域集中,产业整合速度加快,更加注重质量安全 ...
- 物联网综合实训平台-物联网实训系统-物联网实训室设备
物联网综合实训平台 产品型号和技术规格 产品特点: 1) 物联网实训工位:设备主体结构必须采用全钢结构,坚固耐用,实训台中央内留显示器安装位置,使整个实训台成为一个整体.外观尺寸1700X1800X3 ...
- 虹科Vdoo物联网设备安全防护平台:现在正是物联网安全部署的最佳时机
连接革命的爆发 连接革命正在改变我们的生活.它允许我们与我们拥有的许多设备进行交互,从使用中学习,提高效率并节省资源. 作为这场革命的一部分,制造商能够充满动力地去探索他们以前没有经验的新领域:从将新 ...
- 天创与阿里云合作 推出“易联”物联网设备运营管理云平台
日前,天创集团与阿里云签署合作协议,并携手推出新一代的智能管控系统--易联物联网设备运营管理云平台,针对专业音视频行业云服务应用场景展开创新探索. 7月20日香港发布会 天创集团是国内专业音视频领域的 ...
最新文章
- 华山论剑之浅谈iOS的生产线 工厂模式
- 如何用python创建一个下载网站-用Python下载一个网页保存为本地的HTML文件实例...
- EXP1 PC平台逆向破解
- hsi转rgb公式matlab,rgb与hsi模型转换matlab程序
- 陈慧琳的10招不节食瘦身法 - 健康程序员,至尚生活!
- 掌握Python爬虫基础,仅需1小时!
- 设计模式之单例模式8种实现方式,其七:静态内部类
- mysql索引优化面试题_mysql索引优化面试题
- github 仓库中文名_Github仓库重命名
- 常用 EPSG 编号对应的投影信息
- 法线贴图及其用法详解
- 打地鼠游戏(使用Qt)
- ONF解决方案与合作伙伴副主席Aseem Parikh:CORD的社区增长概况及全球发展趋势
- 由Sensor光谱响应曲线联想到的白平衡增益计算
- 2010-04-20 代码复用、使用率情况分析
- 多元回归分析(分类与运用)
- DDR4时序标准规范(二)
- ps还原上一步快捷键,ps还原上一步快捷键_photoshop恢复上一步操作的快捷键是什么...
- Knockout JS 示例
- 怎么用dos命令进入指定的文件夹
热门文章
- 苹果 iOS 15.5更新了哪些功能 苹果 iOS 15.5值得更新吗
- Win10 清除 PowerShell 命令行历史记录的方法
- 二进制运算法则、负数的二进制补码表示与进制转换(短除法)
- 湖南师范大学2018年大学生程序设计竞赛新生赛 F 小名的回答
- JNIEXPORT void JNICALL Java_testdll_set(JNIEnv *, jclass, jint j) //i = j;
- Mac Brew安装及换源教程
- 供应链金融业务信息化平台搭建要点分享
- win10进程太多怎么优化_你应该这样用win10(优化篇)
- 三人表决器逻辑表达式与非_数电实验 | 组合逻辑电路(半加器全加器及逻辑运算)...
- java web 测试要点记录