diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/.keep" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/.keep" new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/4/main.c" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/4/main.c" new file mode 100644 index 0000000000000000000000000000000000000000..699a7945bf44577a61af12128309ebdde2202717 --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/4/main.c" @@ -0,0 +1,36 @@ +#include +#include "vir.h" + +static void my_printfinfo(struct rt_device *device, rt_uint8_t *str) +{ + rt_kprintf("Device info: %s\n", str); +} + +static void my_set_val(struct rt_device *device, rt_uint8_t *val) +{ + rt_kprintf("Set value: %d\n", *val); +} + +static void my_get_val(struct rt_device *device, rt_uint8_t *val) +{ + *val = 42; // 示例值 + rt_kprintf("Get value: %d\n", *val); +} + +static struct rt_vir_ops my_ops = { + my_printfinfo, + my_set_val, + my_get_val +}; + +int main(void) +{ + struct rt_vir_device my_device; + rt_hw_vir_register(&my_device, "vir0", &my_ops, RT_NULL); + + rt_uint8_t val = 10; + rt_device_write(&my_device.parent, 0, &val, sizeof(val)); + rt_device_read(&my_device.parent, 0, &val, sizeof(val)); + + return 0; +} \ No newline at end of file diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/4/vir.c" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/4/vir.c" new file mode 100644 index 0000000000000000000000000000000000000000..5a1424b9593b74d21e2a802c418461579867fc50 --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/4/vir.c" @@ -0,0 +1,63 @@ +#include +#include +rt_err_t rt_vir_init(void) +{ + rt_kprintf("vir init\n"); + return RT_EOK; +} +rt_err_t rt_vir_open(struct rt_device *dev, rt_uint16_t oflag) +{ + rt_kprintf("vir open\n"); + return RT_EOK; +} +rt_err_t rt_vir_close(struct rt_device *dev) +{ + rt_kprintf("vir close\n"); + return RT_EOK; +} +rt_ssize_t rt_vir_read(struct rt_device *dev, rt_off_t pos, void *buf, rt_size_t size) +{ + rt_vir_device_t device = (rt_vir_device_t)dev; + if (device->ops && device->ops->vir_get_val) + { + device->ops->vir_get_val(dev, (rt_uint8_t *)buf); + return size; /* Assume all requested size is read */ + } + return -RT_ERROR; +} +rt_ssize_t rt_vir_write(struct rt_device *dev, rt_off_t pos, const void *buf, rt_size_t size) +{ + rt_vir_device_t device = (rt_vir_device_t)dev; + if (device->ops && device->ops->vir_set_val) + { + device->ops->vir_set_val(dev, (rt_uint8_t *)buf); + return size; /* Assume all requested size is written */ + } + return -RT_ERROR; +} +rt_err_t rt_vir_control(struct rt_device *dev, rt_uint8_t cmd, void *args) +{ + rt_kprintf("vir control\n"); + return RT_EOK; +} +rt_err_t rt_hw_vir_register(rt_vir_device_t device, const char *name, const struct rt_vir_ops *ops, const void *user_data) +{ + rt_err_t result; + + device->parent.type = RT_Device_Class_Miscellaneous; + device->parent.init = rt_vir_init; + device->parent.open = rt_vir_open; + device->parent.close = rt_vir_close; + device->parent.read = rt_vir_read; + device->parent.write = rt_vir_write; + device->parent.control = rt_vir_control; + device->ops = ops; + device->user_data = (void *)user_data; + + result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR); + if (result != RT_EOK) + { + return result; + } + return RT_EOK; +} diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/4/vir.h" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/4/vir.h" new file mode 100644 index 0000000000000000000000000000000000000000..efe37e626df6bf42e043b589b0472abce9815e43 --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/4/vir.h" @@ -0,0 +1,15 @@ + +struct rt_vir_ops +{ + void (*printfinfo)(struct rt_device *device, rt_uint8_t *str); + void (*vir_set_val)(struct rt_device *device, rt_uint8_t *val); + void (*vir_get_val)(struct rt_device *device, rt_uint8_t *val); +}; + +struct rt_vir_device +{ + struct rt_device parent; + const struct rt_vir_ops *ops; + void *user_data; +}; +typedef struct rt_vir_device *rt_vir_device_t; \ No newline at end of file diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/day5\347\254\224\350\256\260" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/day5\347\254\224\350\256\260" new file mode 100644 index 0000000000000000000000000000000000000000..b71822460ccad897a0a25278dd5de2cd39f3e43d --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\351\273\204\347\233\270\346\275\274/day5\347\254\224\350\256\260" @@ -0,0 +1,123 @@ + + +#### **一、MQTT 协议基础** + +MQTT (消息队列遥测传输) 是一种基于 **发布/订阅(Publish/Subscribe)** 模式的轻量级物联网通信协议。 + + * **核心角色**: + + * **客户端 (Client)**: 信息的**发布者**或**订阅者**。可以是任何运行 MQTT 库的程序或设备(如你的 STM32 开发板)。 + * **服务端 (Server/Broker)**: 消息的**中介**,负责接收所有客户端发布的消息,并根据订阅关系将消息转发给相应的客户端。 + + * **服务质量 (QoS)**: 定义消息传递的可靠性等级。 + + * **QoS 0 (至多一次)**: "发后不理",消息可能丢失。 + * **QoS 1 (至少一次)**: "使命必达",保证消息到达,但可能重复。 + * **QoS 2 (确保只有一次)**: "精确送达",保证消息到达且仅到达一次,最可靠但开销最大。 + + * **数据包结构**: + + * **固定头 (Fixed header)**: 所有包都有,定义报文类型和标志。 + * **可变头 (Variable header)**: 部分报文有,内容随报文类型而变。 + * **有效载荷 (Payload)**: 核心数据,例如传感器读数或控制命令。 + +----- + +#### **二、RT-Thread 环境配置** + +要在 RTT 中使用 MQTT,需要通过 `menuconfig` 工具开启并配置必要的软件包。 + +1. **开启组件**: + * 进入 `RT-Thread IoT` 菜单。 + * 勾选 `Paho MQTT` 软件包,这是 Eclipse 基金会提供的 MQTT 客户端库。 + * 勾选 `cJSON` 软件包,这是一个轻量级的 JSON 解析库,用于处理服务器下发的数据。 +2. **更新与生成**: + * 在 `env` 环境中执行 `pkgs --update` 下载软件包。 + * 执行 `scons --target=mdk5` (或其他IDE) 重新生成工程。 + +----- + +#### **三、MQTT 客户端编程核心步骤** + +##### **1. 初始化与配置客户端** + +这是客户端运行前的准备工作。 + + * **定义连接参数**: 使用宏定义服务器地址、客户端 ID、用户名和密码。 + ```c + #define MQTT_Uri "tcp://xxx.xxx.xxx:1883" // 服务器地址与端口 + #define ClientId "YourUniqueClientId" // 必须是唯一的 + #define UserName "YourUsername" + #define PassWord "YourPassword" + ``` + * **声明客户端实例**: `static MQTTClient client;` + * **配置连接参数**: 设置心跳间隔、会话状态等,并将定义的宏填充到 `MQTTPacket_connectData` 结构体中。 + * **申请内存**: 为收发缓冲区申请内存 (`rt_calloc`),这是 MQTT 通信所必需的。 + +##### **2. 设置回调函数与订阅** + +回调函数是 MQTT 异步处理的关键,它定义了“当某事发生时,应该做什么”。 + + * **设置状态回调**: + * `connect_callback`: 连接成功时触发。 + * `online_callback`: 客户端上线后触发。 + * `offline_callback`: 客户端掉线时触发。 + * **设置消息回调与订阅**: + * 这是**最重要**的回调,用于处理收到的消息。 + * 通过 `client.messageHandlers[]` 数组,将一个**主题 (Topic)** 和一个**处理函数 (`mqtt_sub_callback`)** 绑定起来。 + * `client.defaultMessageHandler`:为未单独指定回调的 Topic 设置一个默认处理函数。 + +##### **3. 启动客户端** + +完成所有配置后,调用一个函数即可启动。 + + * `paho_mqtt_start(&client);` + +----- + +#### **四、消息的发布与订阅处理** + +##### **1. 发布消息 (向服务器推送数据)** + + * **调用函数**: 使用 RT-Thread 封装好的 `paho_mqtt_publish()` 函数。 + * **数据格式化**: 通常使用 `sprintf` 将传感器数据等变量拼装成一个 JSON 格式的字符串。 + ```c + // 示例:将温湿度数据打包成 JSON 字符串 + char r_buff[128]; + sprintf(r_buff, "{\"temperature\":%.2f,\"humidity\":%.2f}", 26.5, 55.8); + // 发布消息 + paho_mqtt_publish(&client, QOS1, "topic_pub", r_buff); + ``` + +##### **2. 订阅处理 (解析服务器下发的数据)** + + * **触发点**: 当服务器向客户端订阅的 Topic 推送消息时,之前设置的 `mqtt_sub_callback` 函数会自动被调用。 + + * **核心任务**: 在回调函数中,使用 `cJSON` 库解析收到的 JSON 格式数据。 + + * **cJSON 关键函数**: + + * `cJSON_Parse()`: 将原始的 JSON 字符串文本转换成一个 cJSON 对象,方便程序处理。 + * `cJSON_GetObjectItem()`: 从 cJSON 对象中根据键(Key)获取对应的值(Value)。 + * `cJSON_Delete()`: **必须调用!** 释放 `cJSON_Parse()` 创建的内存,防止内存泄漏。 + + + + ```c + // 在 mqtt_sub_callback 函数内 + void mqtt_sub_callback(MQTTClient *c, MessageData *msg_data) { + // 1. 将收到的 payload 解析为 cJSON 对象 + cJSON *root = cJSON_Parse((const char *)msg_data->message->payload); + if (!root) return; + + // 2. 根据键名 "led1" 获取其值 + cJSON *object = cJSON_GetObjectItem(root, "led1"); + if (object) { + int led_status = object->valueint; // 获取整型值 + // ... 根据 led_status 控制 LED 灯 + } + + // 3. 释放内存 + cJSON_Delete(root); + } + ``` \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..f6c26977bbb993b180afd759658dcf5ea6619cd0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,194 @@ +木兰宽松许可证,第2版 + +木兰宽松许可证,第2版 + +2020年1月 http://license.coscl.org.cn/MulanPSL2 + +您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: + +0. 定义 + +“软件” 是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 + +“贡献” 是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 + +“贡献者” 是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 + +“法人实体” 是指提交贡献的机构及其“关联实体”。 + +“关联实体” 是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是 +指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 + +1. 授予版权许可 + +每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可 +以复制、使用、修改、分发其“贡献”,不论修改与否。 + +2. 授予专利许可 + +每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定 +撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡 +献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软 +件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“ +关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或 +其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权 +行动之日终止。 + +3. 无商标许可 + +“本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定 +的声明义务而必须使用除外。 + +4. 分发限制 + +您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“ +本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 + +5. 免责声明与责任限制 + +“软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对 +任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于 +何种法律理论,即使其曾被建议有此种损失的可能性。 + +6. 语言 + +“本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文 +版为准。 + +条款结束 + +如何将木兰宽松许可证,第2版,应用到您的软件 + +如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: + +1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; + +2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; + +3, 请将如下声明文本放入每个源文件的头部注释中。 + +Copyright (c) [Year] [name of copyright holder] +[Software Name] is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan +PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details. + +Mulan Permissive Software License,Version 2 + +Mulan Permissive Software License,Version 2 (Mulan PSL v2) + +January 2020 http://license.coscl.org.cn/MulanPSL2 + +Your reproduction, use, modification and distribution of the Software shall +be subject to Mulan PSL v2 (this License) with the following terms and +conditions: + +0. Definition + +Software means the program and related documents which are licensed under +this License and comprise all Contribution(s). + +Contribution means the copyrightable work licensed by a particular +Contributor under this License. + +Contributor means the Individual or Legal Entity who licenses its +copyrightable work under this License. + +Legal Entity means the entity making a Contribution and all its +Affiliates. + +Affiliates means entities that control, are controlled by, or are under +common control with the acting entity under this License, ‘control’ means +direct or indirect ownership of at least fifty percent (50%) of the voting +power, capital or other securities of controlled or commonly controlled +entity. + +1. Grant of Copyright License + +Subject to the terms and conditions of this License, each Contributor hereby +grants to you a perpetual, worldwide, royalty-free, non-exclusive, +irrevocable copyright license to reproduce, use, modify, or distribute its +Contribution, with modification or not. + +2. Grant of Patent License + +Subject to the terms and conditions of this License, each Contributor hereby +grants to you a perpetual, worldwide, royalty-free, non-exclusive, +irrevocable (except for revocation under this Section) patent license to +make, have made, use, offer for sale, sell, import or otherwise transfer its +Contribution, where such patent license is only limited to the patent claims +owned or controlled by such Contributor now or in future which will be +necessarily infringed by its Contribution alone, or by combination of the +Contribution with the Software to which the Contribution was contributed. +The patent license shall not apply to any modification of the Contribution, +and any other combination which includes the Contribution. If you or your +Affiliates directly or indirectly institute patent litigation (including a +cross claim or counterclaim in a litigation) or other patent enforcement +activities against any individual or entity by alleging that the Software or +any Contribution in it infringes patents, then any patent license granted to +you under this License for the Software shall terminate as of the date such +litigation or activity is filed or taken. + +3. No Trademark License + +No trademark license is granted to use the trade names, trademarks, service +marks, or product names of Contributor, except as required to fulfill notice +requirements in section 4. + +4. Distribution Restriction + +You may distribute the Software in any medium with or without modification, +whether in source or executable forms, provided that you provide recipients +with a copy of this License and retain copyright, patent, trademark and +disclaimer statements in the Software. + +5. Disclaimer of Warranty and Limitation of Liability + +THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY +KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR +COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT +LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING +FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO +MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGES. + +6. Language + +THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION +AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF +DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION +SHALL PREVAIL. + +END OF THE TERMS AND CONDITIONS + +How to Apply the Mulan Permissive Software License,Version 2 +(Mulan PSL v2) to Your Software + +To apply the Mulan PSL v2 to your work, for easy identification by +recipients, you are suggested to complete following three steps: + +i. Fill in the blanks in following statement, including insert your software +name, the year of the first publication of your software, and your name +identified as the copyright owner; + +ii. Create a file named "LICENSE" which contains the whole context of this +License in the first directory of your software package; + +iii. Attach the statement to the appropriate annotated syntax at the +beginning of each source file. + +Copyright (c) [Year] [name of copyright holder] +[Software Name] is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan +PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details.