DA14585墨水屏学习(2)
一、user_svc2_wr_ind_handler函数
void user_svc2_wr_ind_handler(ke_msg_id_t const msgid,struct custs1_val_write_ind const *param,ke_task_id_t const dest_id,ke_task_id_t const src_id)
{// sprintf(buf2,"HEX %d :",param->length);arch_printf("cmd HEX %d:", param->length);for (int i = 0; i < param->length; i++){arch_printf("%02X", param->value[i]);}arch_printf("\r\n");if ((param->value[0] == 0xDD) && (param->length >= 5)){current_unix_time = (param->value[1] << 24) + (param->value[2] << 16) + (param->value[3] << 8) + (param->value[4] & 0xff);tm_t tm = {0};transformTime(current_unix_time, &tm);app_easy_timer_cancel(timer_used_min);time_offset = 60 - tm.tm_sec;timer_used_min = app_easy_timer(time_offset * 100, do_min_work);arch_printf("%d-%02d-%02d %02d:%02d:%02d %d\n", tm.tm_year + YEAR0,tm.tm_mon + 1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec,tm.tm_wday);}else if (param->value[0] == 0xAA){platform_reset(RESET_NO_ERROR);}else if (param->value[0] == 0x101){do_rili_show();is_part = 0;step = 1;display();}else if (param->value[0] == 0xE2){do_time_show();is_part = 0;step = 1;display();}
}
这段代码实现了一个蓝牙服务写入指示处理函数 user_svc2_wr_ind_handler,用于解析来自客户端的命令并执行相应操作。以下是对代码的详细解释:
函数概述
该函数是一个事件处理回调,当接收到自定义蓝牙服务(custs1)的写请求时被触发。
它会解析命令数据并执行以下操作:
1. 打印接收到的原始数据(HEX 格式)
2. 根据命令类型(首字节)执行不同逻辑
◦ 0xDD:设置系统时间
◦ 0xAA:重启设备
◦ 0x101:显示日历
◦ 0xE2:显示时间
核心逻辑解析
1. 数据接收与打印
arch_printf("cmd HEX %d:", param->length);
for (int i = 0; i < param->length; i++)
{
arch_printf("%02X", param->value[i]);
}
arch_printf("\r\n");
• 功能:将接收到的字节流以 HEX 格式打印输出
• 参数:
◦ param->length:数据长度
◦ param->value[]:数据内容
2. 时间设置命令(0xDD)
if ((param->value[0] == 0xDD) && (param->length >= 5))
{
// 从字节流中解析Unix时间戳(大端格式)
current_unix_time = (param->value[1] << 24) + (param->value[2] << 16) +
(param->value[3] << 8) + (param->value[4] & 0xff);
// 转换为本地时间结构
tm_t tm = {0};
transformTime(current_unix_time, &tm);
// 重新同步定时器,确保整分钟触发
app_easy_timer_cancel(timer_used_min);
time_offset = 60 - tm.tm_sec;
timer_used_min = app_easy_timer(time_offset * 100, do_min_work);
// 打印格式化时间
arch_printf("%d-%02d-%02d %02d:%02d:%02d %d\n",
tm.tm_year + YEAR0, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_wday);
}
• 功能:通过蓝牙设置系统时间
• 数据格式:
◦ value[0]:命令头(0xDD)
◦ value[1-4]:Unix 时间戳(4 字节大端整数)
• 时间同步机制:
◦ 取消当前分钟定时器
◦ 计算距离下一个整分钟的剩余秒数(time_offset)
◦ 重新设置定时器,确保 do_min_work 在整分钟触发
3. 系统重启命令(0xAA)
else if (param->value[0] == 0xAA)
{
platform_reset(RESET_NO_ERROR);
}
• 功能:触发系统软复位
• 参数:RESET_NO_ERROR 表示正常重启(无错误)
4. 日历显示命令(0x101)
else if (param->value[0] == 0x101)
{
do_rili_show(); // 显示日历内容
is_part = 0;
step = 1;
display(); // 更新屏幕显示
}
• 功能:切换到日历显示模式
• 状态变量:
◦ is_part:可能表示部分更新标志
◦ step:状态机控制变量
5. 时间显示命令(0xE2)
else if (param->value[0] == 0xE2)
{
do_time_show(); // 显示时间内容
is_part = 0;
step = 1;
display(); // 更新屏幕显示
}
• 功能:切换到时间显示模式
• 与日历命令类似,但调用 do_time_show() 而非 do_rili_show()
潜在问题与优化建议
1. 命令格式检查:
◦ 对于 0x101 和 0xE2 命令,未检查 param->length 是否足够,可能导致越界访问。
2. 定时器精度: ◦ time_offset * 100 可能是笔误,应为 time_offset * 1000(毫秒转换)。
3. 状态管理: ◦ is_part 和 step 作为全局变量,多命令并发时可能引发状态混乱。
4. 错误处理:
◦ 未处理未知命令(首字节非 0xDD/0xAA/0x101/0xE2)的情况。
应用场景 该处理函数常见于蓝牙低功耗(BLE)设备中,用于接收手机 APP 发送的控制命令,实现:
• 时间同步(通过 NTP 或手机时间)
• 远程重启设备 • 界面显示切换(时钟 / 日历) 通过蓝牙协议栈的 GATT 服务,客户端可以向设备写入特定命令,触发相应功能。
二、app_easy_timer_cancel函数
void app_easy_timer_cancel(const timer_hnd timer_id)
{if APP_EASY_TIMER_HND_IS_VALID(timer_id){if ((timer_callbacks[APP_EASY_TIMER_HND_TO_IDX(timer_id)] != NULL) &&(timer_callbacks[APP_EASY_TIMER_HND_TO_IDX(timer_id)] != timer_canceled_handler)){// Remove the timer from the timer queueke_timer_clear(APP_EASY_TIMER_HND_TO_MSG_ID(timer_id), TASK_APP);timer_callbacks[APP_EASY_TIMER_HND_TO_IDX(timer_id)] = timer_canceled_handler;/*Send a message to the kernel in order to clear the timer callback function andfree the respective position in the timers callback array.The app_easy_timer_cancel() function cannot guarantee if a timer has enteredthe message queue or not. Therefore a message must be sent to the kernel andinform it about the requested cancel operation.*/struct cancel_timer_struct *req = KE_MSG_ALLOC(APP_CANCEL_TIMER, TASK_APP, TASK_APP,cancel_timer_struct);req->timer_id = timer_id;ke_msg_send(req);}else{ASSERT_WARNING(0);}}else{ASSERT_WARNING(0);}
}
相关文章:
DA14585墨水屏学习(2)
一、user_svc2_wr_ind_handler函数 void user_svc2_wr_ind_handler(ke_msg_id_t const msgid,struct custs1_val_write_ind const *param,ke_task_id_t const dest_id,ke_task_id_t const src_id) {// sprintf(buf2,"HEX %d :",param->length);arch_printf("…...

Linux系统下的延迟任务及定时任务
1、延迟任务 概念: 在系统中我们的维护工作大多数时在服务器行对闲置时进行 我们需要用延迟任务来解决自动进行的一次性的维护 延迟任务时一次性的,不会重复执行 当延迟任务产生输出后,这些输出会以邮件的形式发送给延迟任务发起者 在 RH…...
Spark 之 YarnCoarseGrainedExecutorBackend
YarnCoarseGrainedExecutorBackend executor ID , 在日志里也有体现。 25/05/06 12:41:58 INFO YarnCoarseGrainedExecutorBackend: Successfully registered with driver 25/05...

【网络原理】数据链路层
目录 一. 以太网 二. 以太网数据帧 三. MAC地址 四. MTU 五. ARP协议 六. DNS 一. 以太网 以太网是一种基于有线或无线介质的计算机网络技术,定义了物理层和数据链路层的协议,用于在局域网中传输数据帧。 二. 以太网数据帧 1)目标地址 …...

相或为K(位运算)蓝桥杯(JAVA)
这个题是相或为k,考察相或的性质,用俩个数举例子,011001和011101后面的数不管和哪个数相或都不可能变成前面的数,所以利用这个性质我们可以用相与运算来把和k对应位置的1都积累起来,看最后能不能拼起来k如果能拼起来k那…...

AI汽车时代的全面赋能者:德赛西威全栈能力再升级
AI汽车未来智慧出行场景正在描绘出巨大的商业图景,德赛西威已经抢先入局。 在2025年上海车展开幕前夕,德赛西威发布2030年全新使命愿景——“创领安全、愉悦和绿色的出行生活”,并推出全栈式智慧出行解决方案Smart Solution3.0、车路云一体式…...
Python函数:从基础到进阶的完整指南
在Python编程中,函数是构建高效、可维护代码的核心工具。无论是开发Web应用、数据分析还是人工智能模型,函数都能将复杂逻辑模块化,提升代码复用率与团队协作效率。本文将从函数基础语法出发,深入探讨参数传递机制、高阶特性及最佳实践,助你掌握这一编程基石。 一、函数基…...

学习Python的第四天之网络爬虫
30岁程序员学习Python的第四天之网络爬虫的Scrapy库 Scrapy库的基本信息 Scrapy库的安装 在windows系统中通过管理员权限打开cmd。运行pip install scrapy即可安装。 通过命令scrapy -h可查看scrapy库是否安装成功. Scrapy库的基础信息 scrapy库是一种爬虫框架库 爬虫框…...

5、开放式PLC梯形图编程组件 - /自动化与控制组件/open-plc-programming
76个工业组件库示例汇总 开放式PLC编程环境 这是一个开放式PLC编程环境的自定义组件,提供了一个面向智能仓储堆垛机控制的开放式PLC编程环境。该组件采用苹果科技风格设计,支持多厂商PLC硬件,具有直观的界面和丰富的功能。 功能特点 多语…...
数据指标和数据标签
数据指标和数据标签是数据管理与分析中的两个重要概念,它们在用途、形式和应用场景上有显著区别。以下是两者的详细对比: 1. 核心定义 维度数据指标(Data Metrics)数据标签(Data Tags/Labels)定义量化衡量…...

linux中常用的命令(三)
目录 1- ls(查看当前目录下的内容) 2- pwd (查看当前所在的文件夹) 3- cd [目录名](切换文件夹) 4- touch [文件名] (如果文件不存在,新建文件) 5- mkdir[目录名] (创建目录) 6-rm[文件名]&…...

Java 中 AQS 的实现原理
AQS 简介 AQS(全称AbstractQueuedSynchronizer)即抽象同步队列,它是实现同步器的基础组件,并发包中锁的底层就是使用AQS实现的。 由类图可以看到,AQS是一个FIFO的双向队列,其内部通过节点head和tail记录队首和队尾元素࿰…...

『Python学习笔记』ubuntu解决matplotlit中文乱码的问题!
ubuntu解决matplotlit中文乱码的问题! 文章目录 simhei.ttf字体下载链接:http://xiazaiziti.com/210356.html将字体放到合适的地方 sudo cp SimHei.ttf /usr/share/fonts/(base) zkfzkf:~$ fc-list | grep -i "SimHei" /usr/local/share/font…...
docker compose ps 命令
docker compose ps 命令用于列出与 Docker Compose 项目相关的容器及其状态。 docker compose ps 能显示当前项目中所有服务容器的运行状态、端口映射等信息。 语法 docker compose ps [OPTIONS] [SERVICE…] SERVICE(可选):指定要查看状态…...
redis数据结构-04 (HINCRBY、HDEL、HKEYS、HVALS)
哈希操作:HINCRBY、HDEL、HKEYS、HVALS Redis 中的哈希功能极其丰富,让您能够以类似于编程语言中对象的方式存储和检索数据。本课将深入探讨具体的哈希操作,这些操作为操作以下结构中的数据提供了强大的工具: HINCRBY 、 HDEL 、…...

鸿蒙知识总结
判断题 1、 在http模块中,多个请求可以使用同一个httpRequest对象,httpRequest对象可以复用。(错误) 2、订阅dataReceiverProgress响应事件是用来接收HTTP流式响应数据。(错误) 3、ArkTS中变量声明时不需要…...
Ubuntu 22虚拟机【网络故障】快速解决指南
Ubuntu22虚拟机突然无法连接网络了,以下是故障排除步骤记录。 Ubuntu 22虚拟机网络故障快速解决指南 当在虚拟机中安装的 Ubuntu 22 系统出现 ping: connect: 网络不可达 和 ping: www.baidu.com: 域名解析出现暂时性错误的报错时,通常意味着虚拟机无法…...

C++23 新特性:深入解析 std::views::join_with(P2441R2)
文章目录 std::views::join_with 基本用法处理字符串集合std::views::join_with 与其他视图的结合使用总结 随着C23标准的逐步推进,我们迎来了许多令人兴奋的新特性,其中之一就是 std::views::join_with。这个新特性是C23中引入的视图适配器,…...
购物车构件示例
通用购物车构件设计 注:代码仅用于演示原理,不可用于生产环境。 一、设计目标 设计一个高度可复用的购物车构件,具备以下特点: 与具体业务系统解耦支持多种应用场景(商城、积分系统等)提供标准化接口易于集成和扩展二、核心架构设计 1. 分层架构 ┌─────────…...

数据可视化大屏——智慧社区内网比对平台
综述分析: 智慧社区内网数据比对信息系统 这段代码实现了一个智慧社区内网数据比对信息系统的前端界面,采用三栏式布局展示各类社区安全相关数据。界面主要由左侧数据统计、中间地图展示和右侧数据分析三部分组成,使用了多种图表可视化技术…...
详解SLAM中的李群和李代数(中)
1 概述 在上一篇文章《详解SLAM中的李群和李代数(上)》中,我们已经通过对李群求导引出了李代数。在这篇文章中,我们就系统总结一下李代数的相关知识。 2 李代数 2.1 定义 李代数是一个向量空间 g \mathfrak{g} g与一个二元运算…...

Jenkins企业级实战
目标 在Windows操作系统上使用Jenkins完成代码的自动拉取、编译、打包、发布工作。 实施 1.安装Java开发工具包(JDK) Jenkins是基于Java的应用程序,因此需要先安装JDK。可以从Oracle官网或OpenJDK下载适合的JDK版本。推荐java17版本&#x…...

uniapp-商城-52-后台 商家信息(商家信息数据,云对象使用)
1、概述 已经通过好几个篇幅来说明商家信息,包括logo、商家名称,地址,电话以及商家简介。通过表单组件和标签,以及我们的文件上传标签,都做了说明。(logo上传,用的文件上传组件是上传到公共的数…...

MySQL 索引设计宝典:原理、原则与实战案例深度解析
目录 前言第一章:索引设计的基础原则 (知其然,更要知其所以然)第二章:实战案例:电商订单系统的索引设计第三章:索引设计的实践流程总结结语 🌟我的其他文章也讲解的比较有趣😁,如果喜…...

C#上传文件到腾讯云的COS
测试环境: vs2022 .net 6控制台应用程序 测试步骤如下: 1 添加子用户,目前是为了拿到secretId和secretKey,打开添加子用户界面链接:https://console.cloud.tencent.com/cam 并为子用户添加API 密钥 2 通过链接htt…...
java的Stream流处理
Java Stream 流处理详解 Stream 是 Java 8 引入的一个强大的数据处理抽象,它允许你以声明式方式处理数据集合(类似于 SQL 语句),支持并行操作,提高了代码的可读性和处理效率。 一、Stream 的核心概念 1. 什么是 Str…...

C PRIMER PLUS——第9节:动态内存分配、存储类别、链接和内存管理
目录 1.动态内存分配 1.1 malloc 函数 1.2 calloc 函数 1.3 realloc 函数 1.4 free 函数 1.5常见错误 1.6综合例题 2.C语言的内存结构 3.存储类别 3.1作用域(Scope) 3.2链接(Linkage) 3.3存储期(Storage Du…...

作业...
基础配置 RI R2 R3 R4 R5 例如R1 BGP配置 1,R1和R2之间使用直连接口IP地址来建立EBGP对等体关系 2、R2、R3、R4之间配置OSPF协议,保证各设备之间的网络互通,且通过重发布的方式发布路由 查看R2、R3、R4的OSPF路由表: \ R2、R3、R4使用环…...

IC ATE集成电路测试学习——电流测试的原理和方法
电流测试 我们可以通过电流来判断芯片的工作状态时,首先先了解下芯片的电流是如何产生的。 静态电流 理论上,CMOS结构的芯片静态时几乎不耗电 CMOS基本结构:Pmos Nmos 串联当逻辑电平稳定时: ➜ 要么Pmos导通,Nmo…...
redis数据结构-03 (HMSET、HGET、HGETALL)
Redis 哈希介绍:HMSET、HGET、HGETALL Redis 哈希是一种强大的数据结构,允许您在单个键内存储字段值对的集合。它们对于表示对象、配置或任何可以自然分组到字段中的数据非常有用。本课将向您介绍使用 Redis 哈希的基本命令: HMSET 、 HGET …...