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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/80415.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

树莓派5+Ubuntu24.04 LTS串口通信 保姆级教程

【背景】 各位&#xff0c;除了树莓派4B之外&#xff0c;我又搞了个树莓派5, 装的也是Ubuntu24.04 LTS服务器版。装系统的方法跟树莓派4B一样&#xff0c;没什么好说的。装完了系统之后&#xff0c;我就想装个wiringPi来试试串口&#xff0c;却发现这个树莓派5的串口和树莓派4…

【QT】UDP通讯本地调试

qt已经写好了udp通讯代码&#xff0c;现在要进行测试。 1、终端输入ipconfig查看本机网卡的ipv4地址 2、 用udpBind函数&#xff0c;绑定到此ip和自定义的端口号。 3、 打开网络调试助手&#xff0c;自动检测到本机的ip地址&#xff0c;输入任意一个和程序里不一样的端口号。 …

在 Elasticsearch 中连接两个索引

作者&#xff1a;来自 Elastic Kofi Bartlett 解释如何使用 terms query 和 enrich processor 来连接 Elasticsearch 中的两个索引。 更多有关连接两个索引的查询&#xff0c;请参阅文章 “Elastic&#xff1a;开发者上手指南” 中的 “丰富数据及 lookup” 章节。 Elasticsea…

LabVIEW的PID参数自适应控制

在工业控制领域&#xff0c;PID 控制凭借结构简单、稳定性好、工作可靠等优点被广泛应用。然而&#xff0c;传统固定参数的 PID 控制在面对复杂多变的工况时&#xff0c;控制效果往往难以达到最优。基于 LabVIEW 实现 PID 控制根据情况选择参数&#xff08;即参数自适应调整&am…

[redis进阶四]分布式系统之哨兵(2)

目录 一 利用docker搭建环境 板书: 一)准备⼯作: 板书: 解读docker配置文件: 1)安装docker和docker-compose 2) 停⽌之前的redis-server 3) 使⽤docker获取redis镜像 二)编排redis主从节点 板书:​编辑 1) 编写docker-compose.yml 2) 启动所有容器 3) 查看运⾏⽇志 …

spark-Schema 定义字段强类型和弱类型

在数据处理和存储中&#xff0c;Schema&#xff08;模式&#xff09;定义了数据的结构和字段属性&#xff0c;其中字段的强类型和弱类型是重要的概念&#xff0c;直接影响数据的验证、存储和处理方式。以下是详细解释&#xff1a; 1. 强类型&#xff08;Strongly Typed&#x…

2024睿抗编程赛国赛-题解

2024睿抗编程赛国赛题解 RC-u1 大家一起查作弊 题目重述 我们需要从给定的多行字符串中提取出所有的关键词&#xff0c;并计算这些关键词的可疑分数总和、总长度以及关键词的数量。具体步骤如下&#xff1a; 关键词定义&#xff1a;由大写字母、小写字母、数字组成的字符串&a…

控制LED灯设备

本章分别使用C库和系统调用的文件操作方式控制开发板的LED灯&#xff0c;展示如何在应用层通过系统提供的设备文件控制相关硬件。 本章的示例代码目录为&#xff1a;base_code/linux_app/led/sys_class_leds。 9.1. LED子系统 在Linux系统中&#xff0c;绝大多数硬件设备都有…

SpringBoot学习(上) , SpringBoot项目的创建(IDEA2024版本)

目录 1. SpringBoot介绍 SpringBoot特点 2. SpringBoot入门 2.1 创建SpringBoot项目 Spring Initialize 第一步: 选择创建项目 第二步: 选择起步依赖 第三步: 查看启动类 2.2 springboot父项目 2.3 测试案例 2.3.1 数据库 2.3.2 生成代码 1. SpringBoot介绍 Spring B…

在 Ubuntu 中配置 Samba 实现「特定用户可写,其他用户只读」的共享目录

需求目标 所有认证用户可访问 Samba 共享目录 /path/to/home&#xff1b;**仅特定用户&#xff08;如 developer&#xff09;**拥有写权限&#xff1b;其他用户仅允许读取&#xff1b;禁止匿名访问。 配置步骤 1. 设置文件系统权限 将目录 /home3/guest 的所有权设为 develo…

ENSP-OSPF综合实验

AR4中通过ospf获取的其他区域路由信息&#xff0c;并且通过路由汇总后简化路由信息 实现全网通&#xff0c;以及单向重发布&#xff0c;以及通过缺省双向访问&#xff0c; 通过stub简化过滤四类五类lsa&#xff0c;简化ospf路由信息 通过nssa简化ospf信息 区域汇总简化R4路由信…

linux(centos)联网情况下部署

nginx部署 1.linux(centos)联网情况下部署 1.下载nginx所需依赖 # 安装开发工具组&#xff08;若未安装&#xff09; sudo yum groupinstall "Development Tools"# 安装 OpenSSL 开发包 sudo yum install openssl-devel# 安装 PCRE 开发包 sudo yum install pcre-…

LeetCode 1550.存在连续三个奇数的数组:遍历

【LetMeFly】1550.存在连续三个奇数的数组&#xff1a;遍历 力扣题目链接&#xff1a;https://leetcode.cn/problems/three-consecutive-odds/ 给你一个整数数组 arr&#xff0c;请你判断数组中是否存在连续三个元素都是奇数的情况&#xff1a;如果存在&#xff0c;请返回 tr…

Android Framework学习四:init进程实现

文章目录 init流程简介init源码执行顺序执行顺序 init进程的具体工作事项挂载文件系统设置 SELinuxSecondStageMaininit.rc启动zygote和serviceManager进程的重要性serviceManager工作原理 Framework学习之系列文章 init流程简介 下面图片主要围绕 Android 系统中init进程的运…

HTTP/3展望、我应该迁移到HTTP/2吗

1. HTTP/3展望 HTTP/3 基于 QUIC 协议&#xff0c;完全解决了“队头阻塞”问题&#xff0c;弱网环境下的表现会优于 HTTP/2&#xff1b;QUIC 是一个新的传输层协议&#xff0c;建立在 UDP 之上&#xff0c;实现了可靠传输&#xff1b;QUIC 内含了 TLS1.3&#xff0c;只能加密通…

【大模型面试每日一题】Day 15:流水线并行的Bubble问题及其缓解方法

【大模型面试每日一题】Day 15&#xff1a;流水线并行的Bubble问题及其缓解方法 &#x1f4cc; 题目重现 &#x1f31f;&#x1f31f; 面试官&#xff1a;解释流水线并行&#xff08;Pipeline Parallelism&#xff09;的bubble问题及其缓解方法。 #mermaid-svg-Uz7WGsO8akW5F…

Windows环境下maven的安装与配置

1.检查JAVA_HOME环境变量 Maven是使用java开发的&#xff0c;所以必须知道当前系统环境中的JDK的安装目录。 搜索栏直接输入“cmd” 或者 WinR 输入cmd 在打开的终端窗口输入“echo %JAVA_HOME”&#xff0c;就可以看到jdk的位置了。 如果没有的话&#xff0c;请参考我的文章&a…

Kubernetes 集群部署应用

部署 Nginx 应用 命令行的方式 1. 创建 deployment 控制器的 pod # --imagenginx&#xff1a;这个会从 docker.io 中拉取&#xff0c;这个网站拉不下来 # kubectl create deployment mynginx --imagenginx# 使用国内镜像源拉取 kubectl create deployment mynginx --imaged…

如何使用依赖注入来实现依赖倒置原则?

依赖注入(Dependency Injection, DI)是实现依赖倒置原则(DIP)的具体技术手段,它通过将依赖对象的创建和管理交给外部容器,从而实现高层模块与低层模块的解耦。下面从原理、实现方式、框架应用及最佳实践四个方面详细解析: 一、依赖倒置原则(DIP)的核心思想 高层模块不…

python使用AES进行加密和解密

如果需要加密和解密功能,可以使用AES算法。以下是使用Python实现AES加密和解密的示例: from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from Crypto.Random import get_random_bytesdef aes_encrypt(data,