上一篇:使用线上的开发板做开发调试
下一篇:使用AliOS Things快速构建RGB灯应用
使用AliOS Things快速构建温度计应用
本文是基于AliOS Things 3.1快速构建温度计的应用场景。涉及AliOS Things组件开发,构建AliOS Things用户项目,AliOS Things HAL API使用,向AliOS Things中添加并使用组件。用到的硬件设备有半导体开发板、温度传感器、数码管显示器。
背景信息
- AliOS Things HAL API
AliOS Things向用户提供的统一硬件抽象API,为用户提供标准的对MCU片上硬件操作的能力。使得用户应用在多个不同平台之间迁移时,可以无需考虑硬件平台本身的区别,同时也使外设驱动类组件可以快速地在适配过AliOS Things的不同硬件之间复用,提高开发效率。
- AliOS Things 组件
AliOS Things提供的功能扩展能力。通过将外设驱动,通信协议,控制算法,数据算法等通用能力封装为符合AliOS Things标准的组件,是各种附加能力可以快速被用户复用于自己的应用中。同时,组件与OS分离设计,按需安装使用,可以有效地控制资源占用。
- I2C总线
I2C总线用于总线上的器件之间传送信息,是一种简单、双向二线制同步串行总线。发送数据一方称为主器件,被寻址的器件称为从器件,由主器件负责产生定时时钟和终止数据传送。
- TM1637芯片
TM1637 是一种带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路,内部集成有MCU 数字接口、数据锁存器、LED 高压驱动、键盘扫描等电路。主要应用于电磁炉、微波炉及小家电产品的显示屏驱动。
整体流程图如下:
- 物联网系统使用AliOS Things 3.1版本作为基础软件平台。
- 设备端开发使用AliOS Things的HAL(硬件抽象层) API及组件,实现片上外设的使用及外部传感器的数据采集。
- 开发板采用意法半导体NUCLEO-F103RB开发板,主控芯片为stm32f103RBT6。AliOS Things已完成对该主板的适配。
- 温度传感器采用LM75A数字温度传感器,该传感器通过I2C总线与主控MCU通信,可以提供0.125℃精度的温度输出。
- 数码管采用由TM1637驱动的6位数码管进行显示。
硬件连接图如下:
步骤一:创建AliOS Things用户项目
1.单击左下角+按钮。在弹窗的选项框中选择project。
2.选择helloworld_demo作为工程构建模板。
3.选择stm32f103rb-nucleo作为开发板。
4.输入应用名,按enter键,例如:myapp_wdj。
5.选择工程存储目录,按enter键生成项目工程。
6.开发工具Visual Studio Code自动打开生成的用户应用。
用户应用主入口位于appdemo.c文件中。
7.单击下面的编译图标进行编译。
在控制台中看到编译结果。
8.单击下面的烧录图标,将编译好的固件烧写到开发板中。
9.单击插头图标,可以打开串口调试工具进行观察。
开发板已在按照模板程序打印hello world字符及打印计数。
至此,用户应用工程建立完毕。
步骤二:加入温度采集
1.在工程appdemo.c文件中加入如下代码。
#include <aos/hal/i2c.h> // 包含需要用到的I2C HAL驱动
#define I2C1_PORT_NUM PORT_I2C_1 // 使用开发板的第一路I2C通道
#define I2C_RX_TIMEOUT 10 // 定义接收超时时间宏
i2c_dev_t i2c1; // 定义一个I2C设备结构体,用户后续操作具体的I2C接口
/* i2c初始化函数 */
void i2c1_init(void)
{
int ret = -1;
/* i2c attr config */
i2c1.port = PORT_I2C_1;
i2c1.config.address_width = I2C_HAL_ADDRESS_WIDTH_7BIT;
i2c1.config.freq = I2C_BUS_BIT_RATES_400K;
i2c1.config.mode = I2C_MODE_MASTER;
/* init i2c1 with the given settings */
ret = hal_i2c_init(&i2c1);
}
HAL的其他参数细节请参考文档。
2.在方法application_start
中加入I2C初始化。
int application_start(int argc, char *argv[])
{
int count = 0;
printf("nano entry here!\r\n");
//fd = board_lcd_create("name");
//board_lcd_write(fd,buffer,len);
i2c1_init(); // 调用I2C初始化
while(1) {
printf("hello world! count %d \r\n", count++);
aos_msleep(1000);
};
}
3.加入温度采集及相关数据处理部分到主循环中。
int application_start(int argc, char *argv[])
{
int count = 0;
int ret = -1;
float temp;
unsigned char
i2c_data_buf[10];
uint16_t TempAll;
int sig = 1;
int temp_int;
printf("nano entry here!\r\n");
i2c1_init(); // 调用I2C初始化
while(1) {
// printf("hello world! count %d \r\n", count++);
/*通过HAL读取 0x90地址设备的0x00寄存器,读取长度为2字节,返回数据放入i2c_data_buf中*/
ret = hal_i2c_mem_read(&i2c1, 0x90, 0x00, I2C_MEMADD_SIZE_8BIT,i2c_data_buf,2,I2C_RX_TIMEOUT);
if(ret != 0)
{
printf("read fail!\r\n");
// return;
}
TempAll = ((i2c_data_buf[0] << 8) + i2c_data_buf[1]); // 根据LM75自身特性拼接温度数据
printf("middle=%d\r\n",TempAll);
if ((i2c_data_buf[0] & 0x80) != 0) // 判断数据的符号
{
TempAll = ~(TempAll) + 1;
sig = -1;
}
TempAll >>=5; // 低5位无效数据除
printf("middle=%d\r\n",TempAll); // 打印中间数据用于调试
temp = TempAll * 0.125* sig; // 计算最终数据
printf("temp = %.2f\n",temp); // 打印最终数据
aos_msleep(1000);
};
}
4.再次编译、烧录、串口监控。
在串口调试框中看到数据已完成采集。至此,温度采集部分完成。
步骤三:加入本地显示
1.组件包安装。
在组件包所在目录,输入如下安装命令。
aos install comp -L aos_TM1637-1.0.3.zip
aos-cube工具会把组件安装到AliOS Things源码目录。
输入以下命令查看安装的组件。
aos list comp
2.在应用中加入组件。
- 在应用中进行组件的头文件引用。
加入的代码如下:
#include <aos_TM1637.h> // 包含组件头文件
- 在应用中加入组件提供的相关API,完成显示设备驱动输出。
加入的代码如下:
aos_drv_TM1637_init(1,0); // 组件初始化,PA1=clk;PA0=data
aos_drv_TM1637_SetBrightness(3); // 通过组件设置数码管亮度
temp_int = temp * 100; // 数码管不支持小数显示,先将温度转为整数
aos_drv_TM1637_DisplayDecimal(temp_int,2); // 通过组件API使数码管显示,并将小数点定到第二位以匹配真实数据
3.再次编译、烧录、进行串口监控。
看到温度数据显示到了数码管上,和串口输出一致。
appdemo.c文件的完整代码如下:
/*
* Copyright (C) 2015-2020 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <aos/kernel.h>
#include "aos/init.h"
#include "board.h"
#include <k_api.h>
#include <aos/hal/i2c.h> // 包含需要用到的I2C HAL驱动
#include <aos_TM1637.h> // 包含组件头文件
#define I2C1_PORT_NUM PORT_I2C_1 // 使用开发板的第一路I2C通道
#define I2C_RX_TIMEOUT 10 // 定义接收超时时间宏
i2c_dev_t i2c1; // 定义一个I2C设备结构体,用户后续操作具体的I2C接口
/* i2c初始化函数 */
void i2c1_init(void)
{
int ret = -1;
/* i2c attr config */
i2c1.port = PORT_I2C_1;
i2c1.config.address_width = I2C_HAL_ADDRESS_WIDTH_7BIT;
i2c1.config.freq = I2C_BUS_BIT_RATES_400K;
i2c1.config.mode = I2C_MODE_MASTER;
/* init i2c1 with the given settings */
ret = hal_i2c_init(&i2c1);
}
int application_start(int argc, char *argv[])
{
int count = 0;
int ret = -1;
float temp;
unsigned char i2c_data_buf[10];
uint16_t TempAll;
int sig = 1;
int temp_int;
printf("nano entry here!\r\n");
i2c1_init(); // 调用I2C初始化
aos_drv_TM1637_init(1,0); // 组件初始化,PA1=clk;PA0=data
aos_drv_TM1637_SetBrightness(3); // 通过组件设置数码管亮度
while(1) {
// printf("hello world! count %d \r\n", count++);
/*通过HAL读取 0x90地址设备的0x00寄存器,读取长度为2字节,返回数据放入i2c_data_buf中*/
ret = hal_i2c_mem_read(&i2c1, 0x90, 0x00, I2C_MEMADD_SIZE_8BIT,i2c_data_buf,2, I2C_RX_TIMEOUT);
if(ret != 0)
{
printf("read fail!\r\n");
// return;
}
TempAll = ((i2c_data_buf[0] << 8) + i2c_data_buf[1]); // 根据LM75自身特性拼接温度数据
printf("middle=%d\r\n",TempAll);
if ((i2c_data_buf[0] & 0x80) != 0) // 判断数据的符号
{
TempAll = ~(TempAll) + 1;
sig = -1;
}
TempAll >>= 5; // 低5位无效数据除
printf("middle=%d\r\n",TempAll); // 打印中间数据用于调试
temp = TempAll * 0.125 * sig; // 计算最终数据
printf("temp = %.2f\n",temp); // 打印最终数据
temp_int = temp * 100; // 数码管不支持小数显示,先将温度转为整数
aos_drv_TM1637_DisplayDecimal(temp_int,2); // 通过组件API使数码管显示,并将小数点定到第二位以匹配真实数据
aos_msleep(1000);
};
}