Intel® Quark™ SE Microcontroller C1000 开发套件 - 加速计教程
使用 Intel® Quark™ 微控制器软件接口 (Intel® QMSI),此示例应用程序读取加速度计数据并将其输出到串行端口。
获取 Grove* IoT 商业开发套件,这是一个完整的硬件和软件解决方案,可让专业开发人员使用最新的 Intel® 板卡创建激动人心且可扩展的新型 IoT 解决方案。请访问 Intel® 物联网开发者中心。
Intel® System Studio for Microcontrollers 包含多个示例应用程序,可帮助您快速掌握其基本功能并熟悉 Intel® Quark™ 微控制器软件接口 (Intel® QMSI)。此示例应用程序读取加速度计数据并将其输出到串行端口。
要求
- 在按照本教程操作之前,请确保您已完成 入门指南 说明,您可以在此处找到:https://software.intel.com/en-us/iot/hardware/c1000/get-started
- Intel® Quark™ SE 微控制器 C1000 开发板和 USB 数据线
说明
-
将 USB 数据线连接到开发板和主机 PC
注意:这是连接到 FTDI 芯片的 USB 端口
- 启动 Intel® System Studio for Microcontrollers IDE。
-
使用“Accelerometer”示例项目文件创建一个项目
- 从“文件”菜单中,选择“新建”,然后选择“Intel Project for Microcontrollers”。
-
按照“创建新项目”屏幕进行操作
- 开发板:Intel® Quark™ SE C1000 开发板
- 项目类型:Intel® QMSI (1.1)
- 核心:传感器子系统
- 项目名称:Accelerometer,位于“Developer Board Sensors”文件夹中
-
单击完成。
注意:“Accelerometer”示例应用程序运行在传感器子系统核心上,该核心不支持 IPP 库。因此,无法使用 IPP 库构建此示例应用程序。
-
配置串行终端窗口以查看传感器输出。此窗口将通过串行电缆通过 UART 接口显示您的加速度计传感器数据。
-
在屏幕右下角选择“Serial Terminal”窗格,然后单击加号 + 图标以打开新的串行终端连接
-
确保选择了正确的串行端口;还可以单击“Custom configuration”菜单修改默认的串行连接设置
提示:端口将根据所使用的串行硬件而有所不同,并且可能会列出多个端口。有几种方法可以检查您的端口
- Linux*:使用 ‘dmesg’ 命令查看您的端口状态。
-
Windows*:打开设备管理器查看“端口 (COM & LPT)”状态。
使用以上任一方法,您可以将 USB 数据线从 PC 上拔下并重新连接,以查看板卡对应的 COM 端口。
-
单击“确定”,连接到串行终端即可建立。您应该在串行控制台中看到“Connected”状态。
注意:如果您关闭串行终端窗口,可以从以下位置重新打开:
Window › Show View › Other › Intel ISSM › Serial Terminal
-
-
构建并部署您的项目。
- 在“Project Explorer”中选择“Accelerometer”项目。
- 单击Build按钮编译项目。
-
从Run下拉列表中,选择“Accelerometer (flashing)”。
注意:您也可以进行部署和调试。从Debug下拉列表中,选择“Accelerometer (flashing)”。 -
现在您可以在串行终端窗口中查看加速度计的 X、Y 和 Z 值。
工作原理
加速度计示例使用板载 Bosch BMC160 加速度计,通过 I2C 接口连接到微控制器,以及 Intel® Quark™ 微控制器中集成的 RTC(实时时钟)。它还使用集成的 UART 模块通过串行端口输出数据。
该示例在 main 函数中开始,在 rtc 配置结构中设置 RTC 参数
/* Configure the RTC and request the IRQ. */
rtc.init_val = 0;
rtc.alarm_en = true;
rtc.alarm_val = INTERVAL;
rtc.callback = accel_callback;
rtc.callback_data = NULL;
此配置启用 RTC 闹钟,并将 `accel_callback` 设置为 RTC 闹钟的 `callback` 函数。它用于定期打印加速度计数据。
接下来,代码通过 QMSI API 调用请求 RTC 中断,并启用 RTC 时钟
qm_irq_request(QM_IRQ_RTC_0, qm_rtc_isr_0);
/* Enable the RTC. */
clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK);
之后,它根据加速度计类型(BMC150 或 BMI160)配置加速度计参数
/* Initialise the sensor config and set the mode. */
bmx1xx_init(cfg);
bmx1xx_accel_set_mode(BMX1XX_MODE_2G);
#if (BMC150_SENSOR)
bmx1xx_set_bandwidth(BMC150_BANDWIDTH_64MS); /* Set the bandwidth. */
#elif(BMI160_SENSOR)
bmx1xx_set_bandwidth(BMI160_BANDWIDTH_10MS); /* Set the bandwidth. */
#endif /* BMC150_SENSOR */
接下来设置 RTC 配置,从而启用 RTC 闹钟
/* Start the RTC. */
qm_rtc_set_config(QM_RTC_0, &rtc);
使用 while 循环等待读取并打印到串行控制台输出的定义数量的加速度计样本
/* Wait for the correct number of samples to be read. */
while (!complete)
每次达到 125 毫秒间隔且 RTC 闹钟触发时,都会调用以下 `accel_callback` 函数。函数开头定义的 accel 数据结构会传递给 `bmx1xx_read_accel` 函数,该函数会填充当前读取的加速度计数据。如果读取成功,则将加速度计数据打印到串行控制台输出;否则,将打印错误消息。
/* Accel callback will run every time the RTC alarm triggers. */
static void accel_callback(void *data)
{
bmx1xx_accel_t accel = {0};
if (0 == bmx1xx_read_accel(&accel)) {
QM_PRINTF("x %d y %d z %d\n", accel.x, accel.y, accel.z);
} else {
QM_PUTS("Error: unable to read from sensor");
}
`callback` 函数检查是否已读取定义的样本数量,如果未读取,则重置 RTC 闹钟并将计数器加一;否则,将 complete 变量设置为 true。
/* Reset the RTC alarm to fire again if necessary. */
if (cb_count < NUM_SAMPLES) {
qm_rtc_set_alarm(QM_RTC_0,
(QM_RTC[QM_RTC_0].rtc_ccvr + INTERVAL));
cb_count++;
} else {
complete = true;
}
请注意,该应用程序默认读取 500 个样本(`NUM_SAMPLES`)后退出。
最后,当 complete 变量设置为 true 时,while 循环退出,应用程序向串行控制台输出一条最终消息然后退出。
QM_PUTS("Finished: Accelerometer example app");
return 0;
}
加速度计示例应用程序代码
/*
* {% copyright %}
*/
/*
* QMSI Accelerometer app example.
*
* This app will read the accelerometer data from the onboard BMC150/160 sensor
* and print it to the console every 125 milliseconds. The app will complete
* once it has read 500 samples.
*
* If the app is compiled with the Intel(R) Integrated Performance Primitives
* (IPP) library enabled, it will also print the Root Mean Square (RMS),
* variance and mean of the last 15 samples each time.
*/
#include <unistd.h>
#if (__IPP_ENABLED__)
#include <dsp.h>
#endif
#include "clk.h"
#include "qm_interrupt.h"
#include "qm_isr.h"
#include "qm_rtc.h"
#include "qm_uart.h"
#include "bmx1xx/bmx1xx.h"
#define INTERVAL (QM_RTC_ALARM_SECOND >> 3) /* 125 milliseconds. */
#define NUM_SAMPLES (500)
#if (__IPP_ENABLED__)
/* Number of samples to use to generate the statistics from. */
#define SAMPLES_SIZE (15)
#endif /* __IPP_ENABLED__ */
static volatile uint32_t cb_count = 0;
static volatile bool complete = false;
#if (__IPP_ENABLED__)
static float32_t samples[SAMPLES_SIZE];
static void print_axis_stats(int16_t value)
{
static uint32_t index = 0;
static uint32_t count = 0;
float32_t mean, var, rms;
/* Overwrite the oldest sample in the array. */
samples[index] = value;
/* Move the index on the next position, wrap around if necessary. */
index = (index + 1) % SAMPLES_SIZE;
/* Store number of samples until it reaches SAMPLES_SIZE. */
count = count == SAMPLES_SIZE ? SAMPLES_SIZE : count + 1;
/* Get the root mean square (RMS), variance and mean. */
ippsq_rms_f32(samples, count, &rms);
ippsq_var_f32(samples, count, &var);
ippsq_mean_f32(samples, count, &mean);
QM_PRINTF("rms %d var %d mean %d\n", (int)rms, (int)var, (int)mean);
}
#endif /* __IPP_ENABLE__ */
/* Accel callback will run every time the RTC alarm triggers. */
static void accel_callback(void *data)
{
bmx1xx_accel_t accel = {0};
if (0 == bmx1xx_read_accel(&accel)) {
QM_PRINTF("x %d y %d z %d\n", accel.x, accel.y, accel.z);
} else {
QM_PUTS("Error: unable to read from sensor");
}
#if (__IPP_ENABLED__)
print_axis_stats(accel.z);
#endif /* __IPP_ENABLE__ */
/* Reset the RTC alarm to fire again if necessary. */
if (cb_count < NUM_SAMPLES) {
qm_rtc_set_alarm(QM_RTC_0,
(QM_RTC[QM_RTC_0].rtc_ccvr + INTERVAL));
cb_count++;
} else {
complete = true;
}
}
int main(void)
{
qm_rtc_config_t rtc;
bmx1xx_setup_config_t cfg;
QM_PUTS("Starting: Accelerometer example app");
/* Configure the RTC and request the IRQ. */
rtc.init_val = 0;
rtc.alarm_en = true;
rtc.alarm_val = INTERVAL;
rtc.callback = accel_callback;
rtc.callback_data = NULL;
qm_irq_request(QM_IRQ_RTC_0, qm_rtc_isr_0);
/* Enable the RTC. */
clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK);
#if (QUARK_D2000)
cfg.pos = BMC150_J14_POS_0;
#endif /* QUARK_D2000 */
/* Initialise the sensor config and set the mode. */
bmx1xx_init(cfg);
bmx1xx_accel_set_mode(BMX1XX_MODE_2G);
#if (BMC150_SENSOR)
bmx1xx_set_bandwidth(BMC150_BANDWIDTH_64MS); /* Set the bandwidth. */
#elif(BMI160_SENSOR)
bmx1xx_set_bandwidth(BMI160_BANDWIDTH_10MS); /* Set the bandwidth. */
#endif /* BMC150_SENSOR */
/* Start the RTC. */
qm_rtc_set_config(QM_RTC_0, &rtc);
/* Wait for the correct number of samples to be read. */
while (!complete)
;
QM_PUTS("Finished: Accelerometer example app");
return 0;
}
有关编译器优化的更完整信息,请参阅我们的 优化声明。