基于LiteOS与SLE的多任务无线控制器项目实战
前言
在《LiteOS与SLE透传实战案例》中,介绍了SLE通信协议与LiteOS实时操作系统的基础知识与开发方法。本文将以实际项目为例,讲解如何将SLE与LiteOS应用于多任务无线控制器的完整开发流程,包括架构设计、关键代码、软硬件协同、调试方法等,帮助理解相关技术。
文章目录
- 前言
- 一、项目简介
- 二、项目架构与功能特性
- 1. 系统架构概览
- 2. 主要功能特性
- 三、作者与开源信息
- 四、硬件要求
- 五、接口定义
- ADC 接口
- I2C 接口
- 六、项目结构
- 七、软件依赖
- 八、使用方法
- 九、开发方式
- 十、软件架构与主要模块
- 1. LiteOS 多任务架构
- 任务创建与优先级
- 2. 队列与互斥锁
- 3. 主要流程
- 4. 其他细节
- 5. 关键代码说明
- 5.1 系统初始化与任务创建
- 5.2 按键中断与校准流程
- 5.3 摇杆输入与数据采集
- 5.4 OLED 显示与内容切换
- 5.5 SLE 通信与数据上报
- 5.6 队列与互斥锁操作示例
- 十一. LiteOS 相关说明
- 十二. 按键说明
- 十三. 运行与调试
- 十四. 参考资料
一、项目简介
SLEController 是基于 Hispark ws63 核心板的多任务低延迟无线控制器项目,采用 C 语言开发,使用 LiteOS 实时操作系统。
项目支持多通道摇杆输入采集、OLED 实时数据显示、SLE 协议无线通信,适用于远程设备、无人机等场景。
二、项目架构与功能特性
1. 系统架构概览
项目采用多任务并发架构,任务间通过队列和互斥锁通信,确保数据采集、显示与传输的高效协同。
2. 主要功能特性
- 摇杆数据采集与显示:支持4通道摇杆数据实时采集,OLED屏幕显示控制数据和状态,支持校准和内容切换。
- SLE低延迟通信:支持Server模式,断开自动重连,实时上报数据,支持自定义设备名。
- 多任务系统架构:并行处理采集、显示、传输、协议等多种功能,任务间高效通信与同步。
- 异常处理与容错:外设初始化失败检测、队列读写失败提示、通信异常日志输出。
- OLED显示优化:提升显示实时性和准确性,支持内容切换。
- 测试模式切换:支持通过按键切换无人机测试模式,OLED显示当前模式编号。
三、作者与开源信息
- Lamonce(flashier) - 嵌入式软件开发
- 软件开源地址:SLEController - gitee/HiSpark/fbb_ws63
- silenirt - 硬件设计
- 硬件开源地址:星闪遥控器 - 立创开源硬件平台
四、硬件要求
- Hispark ws63 开发板
- SSD1306 OLED 显示屏(I2C 接口)
- 硬件平台
五、接口定义
ADC 接口
- ADC 通道 0-3:连接摇杆 X1、Y1、X2、Y2 轴
- ADC 通道 5:连接电池电压采集
I2C 接口
- 连接 SSD1306 OLED 显示屏
六、项目结构
SLEController/
├── sle_uart_server/ # SLE Server 相关驱动与头文件
│ ├── sle_uart_server_adv.c # Server 端广播驱动实现
│ ├── sle_uart_server_adv.h # Server 端广播头文件
│ ├── sle_uart_server.c # Server 端驱动实现
│ └── sle_uart_server.h # Server 端头文件
├── CMakeLists.txt # CMake 构建脚本
├── README.md # 项目说明文档
├── SLEController.c # 主程序入口
├── SSD1306_OLED.c # OLED 驱动实现
└── SSD1306_OLED.h # OLED 驱动头文件
七、软件依赖
- Hispark Studio
- 串口助手
八、使用方法
-
硬件连接
- 焊接元器件
- 将摇杆模块连接到 ADC 接口
- 将 OLED 显示屏连接到 I2C 接口
-
烧录文件
flash ws63-liteos-app_all.fwpkg / ws63-liteos-app_load_only.fwpkg
-
操作说明
- 开机后系统自动初始化并进入摇杆校准状态,同时启动 SLE Server
- SLE Server 端会自动广播设备信息,等待客户端连接
- Server 端和 Client 端通过
Local Name
进行连接,默认名称为NearLink
(代码参考sle_uart - gitee/bearpi/bearpi-pico_h3863) - 将摇杆向四个方向移动,系统会自动校准并显示当前摇杆状态,找到摇杆最大值(最小值默认为 0)
- 完成校准后按下 KEY3 以退出校准状态
- OLED 显示当前摇杆数据和状态信息,按 KEY3 切换显示内容
- 摇杆操作将直接反映在 OLED 屏幕上
- 控制数据会通过 SLE 框架实时传输
- 按下 KEY6 可切换测试模式(模式相应操作由用户自定义),OLED 显示当前模式编号
九、开发方式
本项目采用 C 语言开发,基于 Hispark Studio 、HUAWEI LiteOS 和 SLE 通信框架。
十、软件架构与主要模块
1. LiteOS 多任务架构
本项目基于 LiteOS,采用多任务并发设计。
主要任务如下:
-
JoystickInputTask:
- 初始化 ADC,采集 4 路摇杆原始数据和电池电压
- 校准阶段自动记录最大值,按下 KEY3 结束校准
- 数据写入
joystick_data_queueID
(摇杆数据队列)和battery_voltage_queueID
(电池电压队列) - 校准完成后,计算百分比数据写入
SLE_Transfer_QueueID
,并对中值做抖动校准
-
OLEDDisplayTask:
- 初始化 OLED 屏幕,显示内容包括摇杆原始数据、百分比、电池电压、SLE 连接状态、测试模式等
- 支持按下 KEY3 切换显示内容(摇杆/状态/测试模式)
- 通过互斥锁
g_mux_id
保证 OLED 与 ADC 初始化顺序,防止资源冲突
-
SELSendTask:
- 负责将摇杆百分比数据通过 SLE 框架实时发送给客户端
- 从
SLE_Transfer_QueueID
读取数据,判断连接状态后进行数据上报
-
sle_uart_server_task:
- 负责 SLE Server 端的消息队列管理、广播和连接状态维护
- 通过设备名
sle_local_name
进行连接,断开时自动重启广播
任务创建与优先级
系统初始化时,依次创建上述任务,并设置合理的优先级,确保数据采集、显示与传输的高效协同。
2. 队列与互斥锁
joystick_data_queueID
:摇杆原始数据队列,供 JoystickInputTask 写入,OLEDDisplayTask 读取battery_voltage_queueID
:电池电压数据队列,供 JoystickInputTask 写入,OLEDDisplayTask 读取SLE_Transfer_QueueID
:摇杆百分比数据队列,供 JoystickInputTask 写入,SELSendTask 读取g_sle_uart_server_msgqueue_id
:SLE Server 端内部消息队列g_mux_id
:互斥锁,保证 OLED 与 ADC 初始化顺序
3. 主要流程
- 系统启动:初始化 GPIO、队列、互斥锁,依次创建各任务
- 摇杆校准:上电后进入校准,移动摇杆采集最大值,按 KEY3 结束校准
- 数据采集与显示:ADC 任务持续采集数据,OLED 任务实时显示,支持内容切换
- 数据传输:SELSendTask 任务将百分比数据通过 SLE 实时上报,Server 端断开自动重连广播
- 异常处理:各任务均有错误检测与日志输出
4. 其他细节
- 支持通过修改
sle_local_name
更改 SLE 设备名。 - 电池电压采集采用分压方式,已在代码中做换算。
- 按键 KEY3 既用于校准结束,也用于显示切换。
- 按键 KEY6 用于切换无人机测试模式,OLED 显示当前模式编号。
- 所有任务均有详细日志输出,便于调试。
5. 关键代码说明
5.1 系统初始化与任务创建
系统初始化主要负责硬件引脚、消息队列、互斥锁的创建,并依次启动各功能任务。通过合理的任务划分与优先级设置,实现数据采集、显示、通信等功能的高效并发。
static void sysInit(void)
{pin_init(); // 初始化 GPIO 引脚osal_msg_queue_create("Joystick_Data_Queue", ...); // 创建摇杆数据队列osal_msg_queue_create("SLE_Transmit_Queue", ...); // 创建 SLE 传输队列osal_msg_queue_create("Battery_Voltage_Queue", ...); // 创建电池电压队列osal_mutex_init(&g_mux_id); // 初始化互斥锁// 创建各任务osal_kthread_create((osal_kthread_handler)JoystickInputTask, ...);osal_kthread_create((osal_kthread_handler)OLEDDisplayTask, ...);osal_kthread_create((osal_kthread_handler)SELSendTask, ...);osal_kthread_create((osal_kthread_handler)sle_uart_server_task, ...);
}
5.2 按键中断与校准流程
static void ButtonISR_KEY3(void)
{if (joystick_ready_index == false) // 校准阶段joystick_ready_index = true;else // 切换 OLED 显示内容OLED_display_index = (OLED_display_index + 1) % 3;
}static void ButtonISR_KEY6(void)
{test_flag = (test_flag + 1) % 3; // 切换测试模式
}
5.3 摇杆输入与数据采集
static void *JoystickInputTask(void)
{uapi_adc_init(ADC_CLOCK_NONE); // 初始化ADC// ...省略部分初始化...while (true) {adc_port_read(...); // 读取各通道ADC// 写入队列osal_msg_queue_write_copy(joystick_data_queueID, &joystick_data, sizeof(joystick_data), 0xff);// 校准后计算百分比if (joystick_ready_index == true) {sle_send_data.adc_ch0_percent = (joystick_data.adc_ch0 * 100) / joystick_adc_default_value0;// ...同理处理其它通道...sle_send_data.is_test_mode = test_flag;osal_msg_queue_write_copy(SLE_Transfer_QueueID, &sle_send_data, sizeof(sle_send_data), 0xff);}// 电池电压采集osal_msg_queue_write_copy(battery_voltage_queueID, &BAT_Vol, sizeof(BAT_Vol), 0xff);osal_msleep(ADC_DELAY_TIME);}
}
5.4 OLED 显示与内容切换
static void *OLEDDisplayTask(void)
{// ...初始化I2C和OLED...while (true) {// 读取队列数据osal_msg_queue_read_copy(joystick_data_queueID, &joystick_rcv_data, ...);osal_msg_queue_read_copy(battery_voltage_queueID, &battery_voltage, ...);if (OLED_display_index == 0) {// 显示摇杆百分比} else if (OLED_display_index == 1) {// 显示SLE连接状态、电池电压} else if (OLED_display_index == 2) {// 显示测试模式编号}}
}
5.5 SLE 通信与数据上报
static void *SELSendTask(void)
{while (true) {osal_msg_queue_read_copy(SLE_Transfer_QueueID, &sle_send_data, ...);if (sle_uart_client_is_connected()) {sle_uart_server_send_report_by_handle((uint8_t *)data_string, strlen(data_string));}}
}static void *sle_uart_server_task(const char *arg)
{sle_uart_server_create_msgqueue();sle_uart_server_register_msg(sle_uart_server_write_msgqueue);sle_uart_server_init(...);while (1) {sle_uart_server_receive_msgqueue(rx_buf, &rx_length);// 未连接则自动广播if (未连接) sle_start_announce(...);}
}
5.6 队列与互斥锁操作示例
// 创建队列
osal_msg_queue_create("QueueName", QUEUE_SIZE, &queueID, 0, NODE_SIZE);
// 写入队列
osal_msg_queue_write_copy(queueID, &data, sizeof(data), 0xff);
// 读取队列
osal_msg_queue_read_copy(queueID, &data, &msgSize, OSAL_WAIT_FOREVER);
// 互斥锁
osal_mutex_init(&g_mux_id);
osal_mutex_lock(&g_mux_id);
osal_mutex_unlock(&g_mux_id);
十一. LiteOS 相关说明
本项目基于 LiteOS,任务、队列、互斥锁等均采用 LiteOS API 实现。详细用法可参考:
- LiteOS与SLE透传实战案例
主要用到的 LiteOS API 包括:
osal_kthread_create
:创建任务osal_msg_queue_create
:创建消息队列osal_mutex_init
/osal_mutex_lock
/osal_mutex_unlock
:互斥锁操作osal_msg_queue_write_copy
/osal_msg_queue_read_copy
:队列读写osal_printk
:日志输出
十二. 按键说明
- KEY3:用于摇杆校准及切换 OLED 显示内容
- KEY6:切换无人机测试模式,OLED 显示当前模式编号
- 各按键功能可自定义
十三. 运行与调试
- 硬件连接:
- 摇杆模块连接 ADC 接口
- OLED 显示屏连接 I2C 接口
- 烧录固件:
flash ws63-liteos-app_all.fwpkg / ws63-liteos-app_load_only.fwpkg
- 上电后自动进入校准,按 KEY3 结束校准,OLED 实时显示数据
- 通过 SLE 框架无线传输数据,可用 QCOM 串口助手等工具调试
十四. 参考资料
- SLE 代码参考:https://gitee.com/bearpi/bearpi-pico_h3863/tree/master/application/samples/products/sle_uart
- ws63 开发板资料:https://gitee.com/HiSpark/fbb_ws63/tree/master
- SSD1306 OLED 驱动资料:https://item.szlcsc.com/datasheet/HS96L03W2C03/5960631.html?spm=sc.it.xds.a___sc.cidn.xh1.zy.n&lcsc_vid=FVlXAlZWFlUIX11XR1JXV11QTlNcUAFfFgdeU1EDRlgxVlNTRlhZX1JSQFlaUztW
如需进一步定制或移植,请参考源码注释与 LiteOS 官方文档。