使用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);
};
}