Neptune w800点灯(中断)工程详解
目录
- 一、鸿蒙项目简介
-
- 1.1 项目构建
-
- 1.1.1 什么是 Ninja?
- 1.1.2 什么是gn?
- 1.2 项目结构
- 1.3 启动流程
- 二 、点灯工程详解
-
- 2.1 实现代码
- 2.2 相关配置
-
- 2.2.1 项目目录下BUILD.gn
- 2.2.2 app目录下BUILD.gn
- 2.2.3 makefile配置
- 2.3 效果展示
一、鸿蒙项目简介
1.1 项目构建
鸿蒙开发分为应用开发和设备开发,应用开发使用JS、Java、仓颉等语言,这里不展开谈。而设备开发一般使用 C/C++ 语言写,编译用 gcc(clang),项目构建上,没有用传统的 make,而是用的 GN。
1.1.1 什么是 Ninja?
ninjia是一个致力于速度的小型编译系统工具 (类似于Make编译工具)
其主要有两个特点:
1.可以通过其他高级的编译系统生产其输入文件。
2.它的设计就是为了更快的编译。
ninjia的核心是由C/C++编写的,同时有一部分辅助功能由和shell实现。
1.1.2 什么是gn?
gn 即 Generate ninjia ,是用来生成ninjia编译文件的工具,可以理解为cmake工具。
1.2 项目结构
目录名 | 描述 |
---|---|
applications | 应用程序样例,包括camera等 |
base | 基础软件服务子系统集&硬件服务子系统集 |
build | 组件化编译、构建和配置脚本 |
docs | 说明文档 |
domains | 增强软件服务子系统集 |
drivers | 驱动子系统 |
foundation | 系统基础能力子系统集 |
kernel | 内核子系统 |
prebuilts | 编译器及工具链子系统 |
test | 测试子系统 |
third_party | 开源第三方组件 |
utils | 常用的工具集 |
vendor | 厂商提供的软件 |
build.py | 编译脚本文件 |
jaychou@jaychou-pc:~/neptune-harmony-os1.1-iot-master$ tree -L 1.├── applications├── base├── build├── build.py -> build/lite/build.py├── developtools├── device├── docs├── domains├── drivers├── foundation├── kernel├── LICENSE├── ohos_config.json├── out├── prebuilts├── README.en.md├── README.md├── test├── third_party├── utils└── vendor
1.3 启动流程
示例代码结尾有:
SYS_RUN(GpioExampleEntry); // if test add it
SYS_RUN ()是ohos系统初始化的宏,系统启动将运行这里指定的任务
定义如下:
/*** @brief Identifies the entry for initializing and starting a system running phase by the* priority 2.** This macro is used to identify the entry called at the priority 2 in the system startup* phase of the startup process. n** @param func Indicates the entry function for initializing and starting a system running phase.* The type is void (*)(void).*/#define SYS_RUN(func) LAYER_INITCALL_DEF(func, run, "run")
定义了系统启动阶段的初始化和启动入口,类型必须是 void (*)(void),即不能有参数,也没有返回值。
一般任务都会通过一个轮询结构(如while循环+switch)来执行各项任务,最佳的方法是启动一个线程,这样入口函数不会阻塞导致一系列问题。
启动线程的方法如下:
osThreadAttr_t attr;attr.name = "Task_Name";attr.attr_bits = 0U;attr.cb_mem = NULL;attr.cb_size = 0U;attr.stack_mem = NULL;attr.stack_size = 10240;attr.priority = osPriorityNormal;if(osThreadNew(HelloTaskFunc, NULL, &attr) == NULL) {printf( "[HelloTaskDemo] Falied to create HelloTask!n");}
二 、点灯工程详解
2.1 实现代码
通过按键PB9控制(中断方式)开发版LED2的状态切换(亮、灭、闪烁),LED共阳。
代码已做详细注释。
/*GPIO、中断使用练习LED2和PB8相连,共阳,则PB8输出0点亮PB9按键改变LED状态(中断方式)使用了CMSIS实时操作系统,也可以修改为普通的轮询、中断等结构*/#include //基本输入输出函数的声明#include //unistd.h为Linux/Unix系统中内置头文件,包含了许多系统服务的函数原型,例如read函数、write函数和getpid函数等。 //其作用相当于windows操作系统的"windows.h",是操作系统为用户提供的统一API接口,方便调用系统提供的一些服务。#include "cmsis_os2.h" //CMSIS-RTOS2 是一个通用的 API ,不受底层 RTOS 内核的影响。应用程序员在用户代码中调用 CMSIS-RTOS2 API // 函数以确保从一个 RTOS 到另一个 RTOS 的最大可移植性。使用 CMSIS-RTOS2 API 的中间件可以避免不必要的移植工作。#include "ohos_init.h" //系统初始化启动服务、功能的头文件,SYS_RUN()这个宏就定义在其中#include "iot_gpio_neptune.h" //提供了操作设备的API:flash, GPIO, I2C, PWM, UART, and watchdog APIs.可进入查看函数简介、参数、返回等信息#include "iot_gpio_w800.h" //定义了w800引脚,例:IOT_GPIO_PA_00 为PA0#define LED_TASK_STACK_SIZE 512 //此处宏用于RTOS的设置。RTOS特点:1)多任务; 2)有线程优先级; 3)多种中断级别。#define LED_TASK_PRIO 25enum LedState {//枚举LED状态,凉、灭、闪烁 LED_ON = 0, LED_OFF, LED_SPARK,};enum LedState g_ledState = LED_SPARK; //初始为闪烁static void* GpioTask(const char* arg) //创建GPIO任务{ (void)arg; while (1) { switch (g_ledState) { //扫描led状态 case LED_ON: printf(" LED_ON! \n"); IoTGpioSetOutputVal(IOT_GPIO_PB_08,0); osDelay(1000); break; case LED_OFF: printf(" LED_OFF! \n"); IoTGpioSetOutputVal(IOT_GPIO_PB_08,1); osDelay(1000); break; case LED_SPARK: printf(" LED_SPARK! \n"); IoTGpioSetOutputVal(IOT_GPIO_PB_08,0); //闪烁,osDelay单位ms,他是CMSIS实时操作系统中的函数 osDelay(200); IoTGpioSetOutputVal(IOT_GPIO_PB_08, 1); osDelay(200); break; default: osDelay(500); break; } } return NULL;}static void GpioIsr(char* arg) //GPIO中断函数,PB9中断输入,进入一次中断状态改变一次{ (void)arg; enum LedState nextState = LED_SPARK; printf(" GpioIsr entry\n"); IoTGpioSetIsrMask(IOT_GPIO_PB_09, 0); //不屏蔽PB9的中断功能(因为用它的中断功能确定LED的状态) switch (g_ledState) { //初始状态为SPARK case LED_ON: nextState = LED_SPARK; break; case LED_OFF: nextState = LED_ON; break; case LED_SPARK: nextState = LED_OFF; break; default: break; } g_ledState = nextState;}static void GpioExampleEntry(void) //程序入口{ osThreadAttr_t attr; IoTGpioInit(IOT_GPIO_PB_08); //初始化PB8、9引脚 IoTGpioInit(IOT_GPIO_PB_09); IoTGpioSetDir(IOT_GPIO_PB_08, IOT_GPIO_DIR_OUT); //设置引脚输出输出方向, output is 0 PB08 to control led IoTGpioSetDir(IOT_GPIO_PB_09,IOT_GPIO_DIR_IN); // input is PB09 IoTIoSetPull(IOT_GPIO_PB_09,IOT_GPIO_PULLHIGH); //PB9上拉输入,上拉输入的好处就是输入的电平不会上下浮动而导致输入信号不稳定,在没有信号输入的情况下可以稳定在高电平。 IoTGpioRegisterIsrFunc(IOT_GPIO_PB_09,IOT_INT_TYPE_EDGE,IOT_GPIO_EDGE_FALL_LEVEL_LOW, GpioIsr, NULL); //中断使能,PB9,边缘触发、下降沿或低电平 attr.name = "GpioTask"; attr.attr_bits = 0U; attr.cb_mem = NULL; attr.cb_size = 0U; attr.stack_mem = NULL; attr.stack_size = LED_TASK_STACK_SIZE; attr.priority = LED_TASK_PRIO; if (osThreadNew((osThreadFunc_t)GpioTask, NULL, &attr) == NULL) { printf("[GpioExample] Falied to create GpioTask!\n"); }}SYS_RUN(GpioExampleEntry); // 系统将执行该服务(功能)
2.2 相关配置
一般工程都应做如下3步类似配置。我的application目录如下:
2.2.1 项目目录下BUILD.gn
static_library("my_test_gn") { #静态库的名称 #要编译的源代码 sources = [ "gpio_test.c", ] #头文件的路径 include_dirs = [ "//utils/native/lite/include", "//domains/iot/link/libbuild", "//base/iot_hardware/peripheral/interfaces/kits" ]}
2.2.2 app目录下BUILD.gn
import("//build/lite/config/component/lite_component.gni")lite_component("app") { features = [ #格式:文件夹名称:文件夹下面BUILD文件中静态库的名称 "my_test_gn:my_test_gn", # "demolink:example_demolink", # "iothardware:gpio_example", # "samgr:example_samgr", ]}
2.2.3 makefile配置
位置:device/winnermicro/neptune/sdk_liteos/Makefile
添加2.2.1中的静态库:
2.3 效果展示
烧录等步骤见我的其它文章。
串口助手:cutecom
按一次PB9,LED状态改变一次。