Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
2024-RSOC
【2024-RSOC】day5-mqtt链接-文件挂载
发布于 2024-07-29 21:22:05 浏览:122
订阅该版
[tocm] # 【2024-RSOC】day5-mqtt链接-文件挂载 ## 一、软件包与组件 ### 软件包(Software Package) #### 定义 具有特定的功能,用来完成特定任务的一个程序或一组程序。 ### 组件(Component) #### 定义 组件是一个可以独立开发、测试、部署和维护的软件单元。它们通常具有明确的功能边界,可以在不同的项目中重复使用。组件不仅可以封装应用层逻辑,还可以封装底层驱动、协议栈等。 ## 二、温湿度传感器——AHT21(I2C设备) ### AHT外设驱动 ### 任务代码编写 以下代码演示了如何编写任务代码来读取AHT21传感器的温湿度数据,并将数据存储在消息队列中。 ```c #include
#include
#include
#include
#include "aht10.h" static float humidity, temperature; static aht10_device_t dev; static int count; /* 总线名称 */ static const char *i2c_bus_name = "i2c3"; // 新建一个线程专门用于读取传感器温湿度数据并将数据分别放入两个消息队列中 static rt_thread_t thread1 = RT_NULL; rt_mq_t mq_hum = RT_NULL; rt_mq_t mq_tem = RT_NULL; /* 定义一个线程入口 */ static void thread1_entry(void *parameter) { while (1) { /* 读取湿度 */ humidity = aht10_read_humidity(dev); rt_kprintf("humidity : %d.%d %%\n", (int)humidity, (int)(humidity * 10) % 10); rt_mq_send(mq_hum, &humidity, sizeof(humidity)); /* 读取温度 */ temperature = aht10_read_temperature(dev); rt_kprintf("temperature: %d.%d\n", (int)temperature, (int)(temperature * 10) % 10); rt_mq_send(mq_tem, &temperature, sizeof(temperature)); rt_thread_mdelay(500); } } static int aht21_example(void) { /* 初始化 aht10 */ dev = aht10_init(i2c_bus_name); if (dev == RT_NULL) { rt_kprintf(" The sensor initializes failure"); return 0; } // 初始化消息队列 mq_hum = rt_mq_create("mq_hum", 10, sizeof(humidity), RT_IPC_FLAG_FIFO); mq_tem = rt_mq_create("mq_tem", 10, sizeof(temperature), RT_IPC_FLAG_FIFO); // 创建线程 thread1 = rt_thread_create("thread1", thread1_entry, RT_NULL, 1024, 25, 10); if (thread1 != RT_NULL) { rt_thread_startup(thread1); } return RT_EOK; } /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(aht21_example, aht21_example); ``` ## 三、RW007 WIFI 连接(SPI设备) ### RW007外设驱动 ``` (90) RW007 CS pin index (29) RW007 BOOT0 pin index (same as spi clk pin) (90) RW007 BOOT1 pin index (same as spi cs pin) (107) RW007 INT/BUSY pin index (111) RW007 RESET pin index ``` 烧录上电后就可以使用如下命令对wifi进行操作了。 ```shell msh />help wifi wifi help wifi scan [SSID] wifi join [SSID] [PASSWORD] wifi ap SSID [PASSWORD] wifi disc wifi ap_stop wifi status wifi smartconfig ``` 可以使用如下命令来连接wifi ```c msh />wifi join **** ******** [I/WLAN.mgnt] wifi connect success ssid:**** ``` ### 任务代码编写 ```c // #include
#include
#define WIFI_SSID "****" #define WIFI_PASSWORD "********" rt_err_t rt_wlan_connect(const char *ssid, const char *password); static void wifi_connect(void) { rt_err_t result; result = rt_wlan_connect(WIFI_SSID, WIFI_PASSWORD); if (result != RT_EOK) { rt_kprintf("wifi connect failed\n"); } else { rt_kprintf("wifi connect success\n"); } } MSH_CMD_EXPORT(wifi_connect, wifi_connect); ``` ## 四、mqtt ### MQTT协议(搭配阿里云平台) #### 原理 MQTT(Message Queuing Telemetry Transport)是一种轻量级、基于发布-订阅模式的消息传输协议,适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境。它在物联网应用中广受欢迎,能够实现传感器、执行器和其它设备之间的高效通信。 特点: - **轻量级:**物联网设备通常在处理能力、内存和能耗方面受到限制。MQTT 开销低、报文小的特点使其非常适合这些设备,因为它消耗更少的资源,即使在有限的能力下也能实现高效的通信。 - **可靠:**物联网网络常常面临高延迟或连接不稳定的情况。MQTT 支持多种 QoS 等级、会话感知和持久连接,即使在困难的条件下也能保证消息的可靠传递,使其非常适合物联网应用。 三种Qos等级:最多一次(QoS0)、至少一次(QoS1)、仅一次(QoS2) - **便于拓展:**如果有设备需要获取某个传感器的消息,只需要订阅这个主题就好了。 #### 运行框架 **Client:**客户端,即我们使用的设备。 使用MQTT的程序或设备。客户端总是通过网络连接到服务端。 - 发布应用消息给其它相关的客户端。 - 订阅以请求接受相关的应用消息。 - 取消订阅以移除接受应用消息的请求。 - 从服务端断开连接。 **Server:**服务端 作为发送消息的客户端和请求订阅的客户端之间的中介。 - 接受来自客户端的网络连接。 - 接受客户端发布的应用消息。 - 处理客户端的订阅和取消订阅请求。 - 转发应用消息给符合条件的已订阅客户端。 **Topic Name:**主题名 附加在应用消息上的一个标签,服务端已知且与订阅匹配。服务端发送应用消息的一个副本给每一个匹配的客户端订阅。 **Subscription:** 订阅 订阅相应的主题名来获取对应的信息。 **Publish:**发布 在对应主题上发布新的消息。 ### Ali-iotkit使能 在软件包中找到阿里云的软件包,使能后需要修改里面的一些参数,主要是如下列出的四个,需要与阿里云中我们创建的设备和产品参数一致。 ```c RT-Thread online packages ---> ->IoT - internet of things ---> IoT Cloud ---> [*] Ali-iotkit: Aliyun cloud sdk 'iotkit-embedded' for RT-Thread ---> (a1dSQSGZ77X) Config Product Key (NEW) (NfIdVcfBP7rtH24H) Config Product Secret (NEW) (RGB-LED-DEV-1) Config Device Name (NEW) (Ghuiyd9nmGowdZzjPqFtxhm3WUHEbIlI) Config Device Secret (NEW) [*]sample ``` 在阿里云中找到这些参数并修改进去,便可以直接运行。 ``` msh />mqtt_example example_event_handle|108 :: msg->event_type : 9 example_event_handle|108 :: msg->event_type : 9 example_event_handle|108 :: msg->event_type : 3 < { < "message": "hello!" < } ``` ## 五、SPI FLASH文件系统 ### 文件系统定义 **DFS** 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System。 #### 文件系统架构 在 RT-Thread DFS 中,文件系统有统一的根目录,使用 `/` 来表示。 #### 文件系统种类 | 类型 | 特点 | | ----- | :----------------------------------------------------------: | | FatFS | FatFS 是专为小型嵌入式设备开发的一个兼容微软 FAT 格式的文件系统,采用ANSI C编写,具有良好的硬件无关性以及可移植性,是 RT-Thread 中最常用的文件系统类型。我们今天使用到的elm_fat就是这个类型。 | | RomFS | 传统型的 RomFS 文件系统是一种简单的、紧凑的、只读的文件系统,不支持动态擦写保存,按顺序存放数据,因而支持应用程序以 XIP(execute In Place,片内运行) 方式运行,在系统运行时, 节省 RAM 空间。我们一般拿其作为挂载根目录的文件系统 | | DevFS | 即设备文件系统,在 RT-Thread 操作系统中开启该功能后,可以将系统中的设备在 `/dev` 文件夹下虚拟成文件,使得设备可以按照文件的操作方式使用 read、write 等接口进行操作。 | | UFFS | UFFS 是 Ultra-low-cost Flash File System(超低功耗的闪存文件系统)的简称。它是国人开发的、专为嵌入式设备等小内存环境中使用 Nand Flash 的开源文件系统。与嵌入式中常使用的 Yaffs 文件系统相比具有资源占用少、启动速度快、免费等优势。 | | NFS | NFS 网络文件系统(Network File System)是一项在不同机器、不同操作系统之间通过网络共享文件的技术。在操作系统的开发调试阶段,可以利用该技术在主机上建立基于 NFS 的根文件系统,挂载到嵌入式设备上,可以很方便地修改根文件系统的内容。 | #### POSIX接口层 POSIX 表示可移植操作系统接口(Portable Operating System Interface of UNIX,缩写 POSIX),POSIX 标准定义了操作系统应该为应用程序提供的接口标准,是 IEEE 为要在各种 UNIX 操作系统上运行的软件而定义的一系列 API 标准的总称。 > 文件描述符:`file descriptor`(fd),每一个文件描述符会与一个打开文件相对应,同时,不同的文件描述符也可能指向同一个文件。可以简单理解为它可以帮助我们找到我们需要的文件。 | API | 描述 | | ----------------------------------------------- | ------------ | | int `open`(const char *pathname, int flags); | 打开文件 | | int `close`(int fd); | 关闭文件 | | ssize_t `read`(int fd, void *buf, size_t count); | 读取文件 | | ssize_t `write`(int fd, const void *buf, size_t count); | 写入文件 | | off_t `lseek`(int fd, off_t offset, int whence); | 移动文件指针 | | int `unlink`(const char *pathname); | 删除文件 | | int `stat`(const char *file, struct stat *buf); | 获取文件状态 | | int `rename`(const char *old, const char *new); | 文件重命名 | | int `mkdir`(const char *pathname, mode_t mode); | 创建目录 | | DIR * `opendir`(const char *name); | 打开目录 | | struct dirent * `readdir`(DIR *dirp); | 读取目录 | | int `closedir`(DIR *dirp); | 关闭目录 | 还有一些其他常用的API: | API | 描述 | | ----------------------------------------------- | ------------ | | int `rename`(const char *old, const char *new); | 文件重命名 | | int `stat`(const char *file, struct stat *buf); | 获取文件状态 | | int `unlink`(const char *pathname); | 删除文件 | #### 目录管理 除了文件的管理之外我们还需要对目录进行管理,管理使用的API: | API | 描述 | | ----------------------------------------------- | ------------ | | int `mkdir`(const char *pathname, mode_t mode); | 创建目录 | | DIR * `opendir`(const char *name); | 打开目录 | | struct dirent * `readdir`(DIR *dirp); | 读取目录 | | int `closedir`(DIR *dirp); | 关闭目录 | ### 文件系统启动流程 #### DFS组件初始化 在`rt_hw_board_init()`中会调用`dfs_init()`,这个函数会初始化DFS组件,然后会调用`dfs_mount_root()`,这个函数会挂载根目录,然后会调用`dfs_mkfs("elm", "W25Q64")`,这个函数会格式化`W25Q64`,然后会调用`dfs_mount("W25Q64", "/", "elm", 0, 0)`,这个函数会挂载`W25Q64`到根目录下。 #### 各文件系统初始化 在`dfs_init()`中会调用`rt_sfud_init()`,这个函数会初始化`SFUD`组件,然后会调用`rt_sfud_flash_probe()`,这个函数会去探测`SPI_FLASH`设备,然后会调用`rt_sfud_flash_erase()`,这个函数会擦除`SPI_FLASH`设备,然后会调用`rt_sfud_flash_write()`,这个函数会往`SPI_FLASH`设备中写入数据,然后会调用`rt_sfud_flash_read()`,这个函数会从`SPI_FLASH`设备中读取数据。 #### 挂载根目录 ### 文件系统结合FAL配置W25Q64 首先会在`rt_hw_spi_flash()`(在INIT_COMPONENT_EXPORT)中会把一个`spi20`的spi设备挂载在`spi2`总线上,然后通过`rt_sfud_flash_probe`将这个`spi20`设备跟一个`SPI_FLASH`设备(命名为`W25Q64`)进行绑定。然后在FAL中对这个`SPI_FLASH(W25Q64)`设备进行分区,然后对相应的区创建`BLK设备`。 接着我们对这个`BLK设备`进行格式化(即挑选一种文件系统去管理这个BLK设备),然后将这个格式化好的文件系统进行挂载(分配到对应路径上)这样我们就可以使用组件的`API`对`W25Q64`进行读写了。这里使用了POSIX协议接口,我们只需要使用`open()`、`close()`、`read()`、`write()`就可以完成对文件的读写。也可以用`mkdir()`、`opendir()`、`readdir()`、`closedir()`来对目录进行管理。 ### 新建块设备并挂载 在`rt-thread\bsp\stm32\stm32f407-rt-spark\dist\project\board\ports\drv_filesystem.c` line59新加下面这行代码 ``` /* 在 spi flash 中名为 "font" 的分区上创建一个块设备 */ struct rt_device *flash_dev = fal_blk_device_create("font"); ``` 此时再编译并烧录即可观察到系统启动初始化时自动打印出font块设备创建成功的提示信息。 ``` [I/FAL] ==================== FAL partition table ==================== [I/FAL] | name | flash_dev | offset | length | [I/FAL] ------------------------------------------------------------- [I/FAL] | app | onchip_flash_128k | 0x00000000 | 0x00060000 | [I/FAL] | param | onchip_flash_128k | 0x00060000 | 0x000a0000 | [I/FAL] | easyflash | W25Q64 | 0x00000000 | 0x00080000 | [I/FAL] | download | W25Q64 | 0x00080000 | 0x00100000 | [I/FAL] | wifi_image | W25Q64 | 0x00180000 | 0x00080000 | [I/FAL] | font | W25Q64 | 0x00200000 | 0x00300000 | [I/FAL] | filesystem | W25Q64 | 0x00500000 | 0x00300000 | [I/FAL] ============================================================= [I/FAL] RT-Thread Flash Abstraction Layer initialize success. [I/FAL] The FAL block device (filesystem) created successfully [I/app.filesystem] Filesystem initialized! ``` 此时在串口终端输入list device命令即可看到列出的设备中包括刚刚初始化的font块设备。 ``` msh />list device device type ref count -------- -------------------- ---------- w1 Network Interface 1 w0 Network Interface 1 wlan0 Network Interface 1 wlan1 Network Interface 1 wspi SPI Device 0 font Block Device 0 filesyst Block Device 1 W25Q64 Block Device 0 spi20 SPI Device 0 spi2 SPI Bus 0 i2c3 I2C Bus 0 uart1 Character Device 2 pin Pin Device 0 ``` 挂载过程如下: ``` msh /fal>mkdir fontdir [603100] W/time: Cannot find a RTC device! msh /fal>ls Directory /fal: fontdir
msh /fal>mkfs -t elm font [625190] W/time: Cannot find a RTC device! msh /fal>mount font fontdir elm mount device font(elm) onto fontdir ... succeed! ``` ### 总结 1. 通过`rt_sfud_flash_probe`将`spi20`设备跟一个`SPI_FLASH`设备(命名为`W25Q64`)进行绑定。 2. 在FAL中对这个`SPI_FLASH(W25Q64)`设备进行分区,然后对相应的区创建`BLK设备`。 3. 对这个`BLK设备`进行格式化(即挑选一种文件系统去管理这个BLK设备),然后将这个格式化好的文件系统进行挂载(分配到对应路径上)这样我们就可以使用组件的`API`对`W25Q64`进行读写了。这里使用了POSIX协议接口,我们只需要使用`open()`、`close()`、`read()`、`write()`就可以完成对文件的读写。也可以用`mkdir()`、`opendir()`、`readdir()`、`closedir()`来对目录进行管理。 4. 新建块设备并挂载。 5. 通过`open()`、`close()`、`read()`、`write()`就可以完成对文件的读写。也可以用`mkdir()`、`opendir()`、`readdir()`、`closedir()`来对目录进行管理。 6. 通过`stat()`、`rename()`、`unlink()`、`mkdir()`、`opendir()`、`readdir()`、`closedir()`来对文件进行管理。 7.
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
单字一个轩
这家伙很懒,什么也没写!
文章
4
回答
0
被采纳
0
关注TA
发私信
相关文章
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
8
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部