rt-thread应用篇(03)---基于STM32F429实现web服务器功能

2023-05-16

目录

参考示例

前言

一、需使用的组件与软件包及其ENV配置

1、文件系统相关组件与软件包

1.1、DFS 框架

1.2、fal 软件包

1.3、SFUD 组件

2、网络通信相关组件和软件包

2.1、SAL组件

2.2、netdev组件

2.3、协议栈组件

2.4、netutils工具集软件包

2.5、webnet软件包

二、添加驱动和初始化代码

1、SPI FLASH驱动

2、网卡驱动

3、FAL配置

4、格式化块设备

三、web服务器开发基础

1、HTTP简介

1.1、工作原理

1.2、消息结构

2、HTML简介

2.1、HTML 网页结构

2.2、HTML 标签

2.3、HTML 属性

3、CSS简介

4、CGI技术简介

5、SSI简介

四、web服务器应用程序设计

1、网页制作

1.1、效果图

1.2、CGI类型与SSI标签

2、功能实现

2.1、自定义注册CGI执行函数

2.2、自定义注册SSI执行函数

3、页面文件上传

4、启动webnet

5、解决的问题


参考示例

网络协议栈驱动移植笔记

在 STM32F407 上应用网络功能

在 STM32F429 上应用文件系统

SPI Flash 文件系统例程

前言

1、此次实现的web服务器是使用了rtthread的webnet软件包来实现的。WebNet 软件包是 RT-Thread 自主研发的,基于 HTTP 协议的 Web 服务器实现,它不仅提供设备(HTTP Seerver)与 HTTP Client 通讯的基本功能,而且支持多种模块功能扩展,满足开发者对嵌入式设备服务器的功能需求。要将WebNet软件包用起来,基础的网络通信功能肯定是需要的,同时还需要能对 静态页面 进行存储、上传 等功能,所以WebNet的使用还需要文件系统相关的组件网络通信相关的组件的支持,通过这些组件和软件包可以快速搭建好一个在STM32开发web服务器的环境。在搭建好环境后,先使用HBuilder(HTML5的Web开发IDE)制作好你的网页,然后将这些网页使用tftp工具上传到/webnet目录下,最后使用webnet软件包提供的SSI、CGI等功能模块实现web服务器与浏览器之间的交互

2、使用的硬件为  正点原子的阿波罗STM32F429开发板

3、在ENV中选中的组件或软件包,如果开启了包管理器自动更新或者手动使用 pkgs --update 命令,就能自动将选择的软件包更新到BSP中;然后再使用 scons --target=xxx 命令编译BSP时,选择的软件包相关源代码就会被自动添加进工程中并进行编译

一、需使用的组件与软件包及其ENV配置

1、文件系统相关组件与软件包

1.1、DFS 框架

DFS 框架 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System,即设备虚拟文件系统。DFS 框架为应用程序提供统一的 POSIX 文件和目录操作接口,如 read、write、poll/select 等。DFS 框架支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。

1.2、fal 软件包

fal 全称为 Flash Abstraction Layer,即 Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API。并提供了将分区创建成 MTD 设备的 API

1.3、SFUD 组件

SFUD 是一款开源的串行 SPI Flash 通用驱动库。现有市面的大部分串行 Flash,用户只需要提供 SPI 或 QSPI 的读写接口,SFUD 就可以识别并驱动。同时 RT-Thread 提供了 FAL 针对 SFUD 的驱动移植,可以使两个组件无缝连接

2、网络通信相关组件和软件包

2.1、SAL组件

SAL 套接字抽象层,通过它 RT-Thread 系统能够适配下层不同的网络协议栈,并提供给上层统一的网络编程接口,方便不同协议栈的接入。套接字抽象层为上层应用层提供接口有:accept、connect、send、recv 等。具有如下特点:

  • 抽象、统一多种网络协议栈接口;
  • 提供 Socket 层面的 TLS 加密传输特性;
  • 支持标准 BSD Socket API;
  • 统一的 FD 管理,便于使用 read/write poll/select 来操作网络功能;

2.2、netdev组件

netdev 网卡层,主要作用是解决多网卡情况设备网络连接和网络管理相关问题,通过 netdev 网卡层用户可以统一管理各个网卡信息和网络连接状态,并且可以使用统一的网卡调试命令接口

2.3、协议栈组件

协议栈层包括几种常用的 TCP/IP 协议栈,例如嵌入式开发中常用的轻型 TCP/IP 协议栈 lwIP 以及 RT-Thread 自主研发的 AT Socket 网络功能实现等。这些协议栈或网络功能实现直接和硬件接触,完成数据从网络层到传输层的转化。这里使用的是lwip

2.4、netutils工具集软件包

netutils软件包中汇集了 RT-Thread 可用的全部网络小工具集合,这里主要使用TFTP小工具,TFTP (Trivial File Transfer Protocol, 简单文件传输协议)是 TCP/IP 协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务,端口号为 69 ,比传统的 FTP 协议要轻量级很多,适用于小型的嵌入式产品上。在板卡上开启TFTP Server后,就可以在PC上使用TFTP Client软件将HTML网页文件上传到板卡的SPI FLASH中。

2.5、webnet软件包

官网有很详细的介绍,WebNet 软件包功能特点:

  • 支持 HTTP 1.0/1.1
  • 支持 CGI 功能
  • 支持 ASP 变量替换功能
  • 支持 AUTH 基本认证功能
  • 支持 INDEX 目录文件显示功能
  • 支持 ALIAS 别名访问功能
  • 支持 SSI 文件嵌入功能
  • 支持文件上传功能
  • 支持预压缩功能
  • 支持缓存功能
  • 支持断点续传功能

浏览器访问设备 IP 地址不显示页面信息

  • 原因:设置的根目录地址错误。
  • 解决方法:确定设置的根目录地址(/webnet)和设备文件系统上创建的目录地址一致,确定根目录下有页面文件。也就是说必须先在块设备上初始化文件系统,且在文件系统中有 /webnet 这个文件夹,同时页面文件也已经上传到了跟目录下。

二、添加驱动和初始化代码

1、SPI FLASH驱动

1.1、在spi_flash_init.c中添加如下内容,注册softspi1总线,注册softspi10设备并挂载到softspi1总线上;使能SFUD驱动W25Q64块设备

#include <rtthread.h>
#include "spi_flash.h"
#include "spi_flash_sfud.h"
#include "drv_soft_spi.h"

#if defined(BSP_USING_SPI_FLASH)
static int rt_hw_spi_flash_init(void)
{
    __HAL_RCC_GPIOG_CLK_ENABLE();
    rt_soft_spi_device_attach("softspi1", "softspi10", GPIOG, GPIO_PIN_10);

    if (RT_NULL == rt_sfud_flash_probe("W25Q64", "softspi10"))
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
#endif

1.2、在ENV中开启模拟SPI,开启BSP_USING_SOFT_SPIBSP_USING_SOFT_SPI1宏定义,这样在scons构建工程时,drv_soft_spi.c 就能自动添加进工程中

2、网卡驱动

2.1、网卡驱动部分rtthread已经在drv_eth.c/h中写好了,唯一要改的就是在phy_reset.c中添加PHY网卡的复位,添加如下内容

#define ETH_RESET_IO    GET_PIN(H, 3)                //PHY RESET PIN
/* phy reset */
void phy_reset(void)
{
    rt_pin_write(ETH_RESET_IO, PIN_HIGH);
    rt_thread_mdelay(100);
    rt_pin_write(ETH_RESET_IO, PIN_LOW);
    rt_thread_mdelay(100);
}

int phy_init(void)
{
    rt_pin_mode(ETH_RESET_IO, PIN_MODE_OUTPUT);
    rt_pin_write(ETH_RESET_IO, PIN_LOW);
    return RT_EOK;
}
INIT_BOARD_EXPORT(phy_init);

2.2、在ENV中选中网卡驱动,开启 BSP_USING_ETH PHY_USING_LAN8720A宏定义,这样在scons构建工程时,drv_eth.c phy_reset.c 就能自动添加进工程中

3、FAL配置

3.1、在 fal_cfg.h中定义 flash 设备、flash 设备表、flash 分区表。flash设备表中,nor_flash0是使用了SFUD接口实现片外SPI FLASH操作的fal_flash设备,具体实现在FAL针对 SFUD 的移植文件fal_flash_sfud_port.c中。stm32_onchip_flash_xx 是直接操作单片机片内FLASH的fal_flash设备,具体实现在 drv_flash_f4.c

/* flash device table */
#define FAL_FLASH_DEV_TABLE                              \
{                                                        \
	&stm32_onchip_flash_16k,                                         \
    &stm32_onchip_flash_64k,                                         \
    &stm32_onchip_flash_128k,                                        \
    &nor_flash0,                                         \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG

/* partition table */
#define FAL_PART_TABLE                                                                                                     \
{                                                                                                                          \
    {FAL_PART_MAGIC_WROD, "bl", 		"onchip_flash_16k",  0 , FLASH_SIZE_GRANULARITY_16K , 0}, \
    {FAL_PART_MAGIC_WROD, "easyflash",  "onchip_flash_64k",  0 , FLASH_SIZE_GRANULARITY_64K , 0}, \
    {FAL_PART_MAGIC_WROD, "app",        "onchip_flash_128k", 0 , FLASH_SIZE_GRANULARITY_128K, 0}, \
	{FAL_PART_MAGIC_WROD, "fs",        	FAL_USING_NOR_FLASH_DEV_NAME, 0 , 4 * 1024 * 1024, 0}, \
	{FAL_PART_MAGIC_WROD, "tgfx",       FAL_USING_NOR_FLASH_DEV_NAME, 4 * 1024 * 1024 , 4 * 1024 * 1024, 0}, \
}

3.2、在 spi_flash_init.c 中调用fal_init()初始化该组件

#if defined(PKG_USING_FAL)
int fs_init(void)
{
    /* partition initialized */
    fal_init();
	return 0;
}
INIT_COMPONENT_EXPORT(fs_init);
#endif

4、格式化块设备

4.1、将FAL的"fs"分区挂载到根目录下,用于存储静态网页,第一次挂载的时候可能会失败,因为该分区还没有文件系统,需要先在 "fs"分区创建elmFAT文件系统。此时可以在系统起来后,直接在shell中输入 mkfs -t elm fs 命令对“fs”分区进行格式化

#if defined(RT_USING_DFS_ELMFAT)
#define FS_PARTITION_NAME "fs"
int elm_fatfs_init(void)
{
    /* partition initialized */
//    elm_init();
	//dfs_mkfs("elm", "fs"); /* 在fs块设备上创建elm文件系统*/
  
	/* Create a block device on the "fs" partition of spi flash */
    struct rt_device *flash_dev = fal_blk_device_create(FS_PARTITION_NAME);
    if (flash_dev == NULL){
        rt_kprintf("Can't create a block device on '%s' partition.\n", FS_PARTITION_NAME);
    } else {
        rt_kprintf("Create a block device on the %s partition of flash successful.\n", FS_PARTITION_NAME);
    }
	
	/* mount the file system from "fs" partition of spi flash. */
    if (dfs_mount(FS_PARTITION_NAME, "/", "elm", 0, 0) == 0)
    {
        LOG_I("Filesystem initialized!");
    }
    else
    {
        LOG_E("Failed to initialize filesystem!");
        LOG_D("You should create a filesystem on the block device first!");
    }
	return 0;
}
INIT_COMPONENT_EXPORT(elm_fatfs_init);

三、web服务器开发基础

1、HTTP简介

HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从服务器传输超文本到本地浏览器的传送协议。

1.1、工作原理

HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)HTTP协议工作于客户端-服务端架构上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。默认端口为80。HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。

HTTP三点注意事项:

  • HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
  • HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。
  • HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

1.2、消息结构

客户端请求消息格式:由四个部分组成,分别是:请求行(request line)、请求头部(header)、空行、请求数据

示例:

GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi

xxxxxxxxxxxxxx

服务器响应消息格式:也由四个部分组成分别是:状态行、消息报头、空行、响应正文

2、HTML简介

超文本标记语言(HyperText Markup Language),是一种用于创建网页的标准标记语言。HTML 运行在浏览器上,由浏览器来解析。

2.1、HTML 网页结构

2.2、HTML 标签

HTML 标记标签通常被称为 HTML 标签 (HTML tag)。

  • HTML 标签是由尖括号包围的关键词,比如 <html>
  • HTML 标签通常是成对出现的,比如 <b> 和 </b>
  • 标签对中的第一个标签是开始标签,第二个标签是结束标签
  • 开始和结束标签也被称为开放标签和闭合标签

2.3、HTML 属性

  • HTML 标签可以设置属性
  • 属性可以在元素中添加附加信息
  • 属性一般描述于开始标签
  • 属性总是以名称/值对的形式出现,比如:name="value"
  • 一个标签中可以同时设置多个属性,属性之间需要用空格隔开
<a href="http://www.runoob.com">这是一个链接</a> <h1>这是<font color="red" size="10">一个</font>网页</h1>

3、CSS简介

CSS 指层叠样式表 (Cascading Style Sheets),样式表定义如何显示 HTML 元素,就像 HTML 中的字体标签和颜色属性所起的作用那样。样式通常保存在外部的 .css 文件中。我们只需要编辑一个简单的 CSS 文档就可以改变所有页面的布局和外观。根据CSS样式在HTML中被引用的方式可分为以下三种类型:

内部样式表:包含含HTML文件的head标签中,在body中的所以标签的可以使用

<style type="text/css"> p{color:red;font-size:40px;}</style>

外部样式表:外部独立的.css文件中,通过在HTML文件中引用这个.css文件使用其样式

<link rel="stylesheet" type="text/css" href="css文件路径" />

内联样式:直接写在标签的开始标签中,只对该标签有效

<p style="color:red;font-size:40px;"> </p>

4、CGI技术简介

公共网关接口(Common Gateway Interface),是外部应用程序与web服务器之间的接口标准。CGI规范允许web服务器执行外部程序,并将它们的输出发送给web浏览器,CGI在物理上是一段程序,运行在服务器上,提供同客服端HTML页面的接口。绝大多数的CGI程序被用来解释处理来自表单的输入信息,并在服务器产生相应的处理,或经相应的信息反馈给浏览器,CGI程序使网页具有交互功能,比如通过web来处理浏览器提交的表单数据。如下图,一个表单在浏览被提交,发送给web被处理的过程:

1、登录网页

2、提交表单(Checkbox, Radio button, selection list etc)

3、CGI程序处理

4、返回处理结果

5、SSI简介

服务器侧包含(server side include),是一种类似于ASP的基于服务器的网页制作技术。是指将HTML内容发送到浏览器之前,先使用SSI指令将文本、图形、或变量数据信息包含到网页中,再发给浏览器解析。对于在多个文件中重复出现的文本或图形,使用SSI包含技术是一种简便的方法,只需将内容存入一个包含文件中即可,而不必将内容写入到所有的文件,通过一个非常简单的语句即可调用包含文件,此语句指示web服务器将内容插入到网页的位置。

实现SSI功能的原理也很简单,就是在发送网页文件的时候遍历整个文件,查找文件中的SSI指令,如果出现有<!--#include file="xxx" --> 指令,则将xxx文件的内容嵌入到网页中;如果出现有<!--#include virtual="xxx" --> 指令,则匹配注册好的xxx名称,如果有注册则执行其回调函数。想想如果发送每个网页的时候都这么去查找,效率肯定很低,而且很多网页并没有文件或变量需要嵌入,所以使用SSI指令的网页有特殊的扩展名,默认有 .stm、.shtm、.shtml,查找前会先匹配文件的扩展名,如果不是SSI默认的扩展名文件则不回配置SSI指令。如下图,浏览器请求一个.shtml扩展名的文件:

1、用户请求SSI页面(后缀名是 .shtm .shtml .ssi .xml 的特殊的html网页)

2、服务器根据页面SSI标签(<!--#include file="xxx" -->或<!--#include virtual="xxx" -->)动态插入数据。

3、服务器返回动态生成的页面

四、web服务器应用程序设计

1、网页制作

一个网页主要由三部分构成:结构、表现、行为。结构:用于描述页面的结构;表现:用于控制页面中元素的样式;行为:用于响应用户的操作。

此次设计的有如下几个网页,网页使用HBuilder编写

1.1、效果图

1.2、CGI类型与SSI标签

1、在需要提交表单的页面中,将表单的action属性填写成web服务器可识别的URL,表明向何处提交你的表单,这样wen服务器在收到表单数据后,就会去执行跟action匹配的自定义注册好的CGI执行函数。在rtthread的webnet中默认的CGI类型是/cgi-bin开头的,需要注意!!

<form action="cgi-bin/ethip" method="post" target="nm_iframe">
...
</form>

2、在需要动态嵌入变量或文件的.shtml页面中,需要通过注释的方式定义好SSI标签,这样web服务器在发送这个页面的时候就会去匹配页面中的SSI标签,然后去执行跟SSI标签名称匹配的自定义注册好的SSI回调函数。如下,实时获取传感器数据的HTML

<table>
	<tr>
        <th height="50" colspan="2"><div align="center"><span class="font1">传感器实时数据</span></div><hr /></th>
	<tr>
	
	<tr>
        <td class="td_left">温度:</td>
        <td class="td_right"><span class="font2"><!--#include virtual="sensor_temp" --> ℃</span></td>
	</tr>
	
	<tr>
        <td class="td_left">湿度:</td>
        <td class="td_right"><span class="font2"><!--#include virtual="sensor_humit" --> %RH</span></td>
	</tr>
	
	<tr>
        <td class="td_left">太阳能电压:</td>
        <td class="td_right"><span class="font2"><!--#include virtual="sensor_adc" --> mV</span></td>
	</tr>
	
</table>

2、功能实现

2.1、自定义注册CGI执行函数

需要在启动web服务器之前注册好你的CGI执行函数,我这里注册的函数如下

以通过网页远程控制板卡为例,浏览器给web服务器发送的数据如下:

程序解析过程如下:

static void cgi_remotectl_handler(struct webnet_session* session)
{
/* defined the LED0 pin: PH2 */
#define LED0_PIN    GET_PIN(H, 2)
/* defined the BEEP pin: PE3 */
#define BEEP_PIN    GET_PIN(E, 3)
  
	struct webnet_request* request;
    const char* mimetype;  
    const char *led1,*beep,*relay;
	char led1_value=0,beep_value=0,relay_value=0;
		
    RT_ASSERT(session != RT_NULL);

    /* get mimetype */
    mimetype = mime_get_type(".html");

	request = session->request;
	
    /* set http header */
    session->request->result_code = 200;
    webnet_session_set_header(session, mimetype, 200, "Ok", -1);

    /* 解析 */
	led1 = webnet_request_get_query(request, "led1");
	beep = webnet_request_get_query(request, "beep");
	relay = webnet_request_get_query(request, "relay");	
	led1_value = atoi(led1);
	beep_value = atoi(beep);
	relay_value = atoi(relay);
	if (led1_value) rt_pin_write(LED0_PIN, PIN_LOW);
	else rt_pin_write(LED0_PIN, PIN_HIGH);

	if (beep_value) rt_pin_write(BEEP_PIN, PIN_HIGH);
	else  rt_pin_write(BEEP_PIN, PIN_LOW);
}

2.2、自定义注册SSI执行函数

rtthread实现的webnet中只实现了在网页中嵌入文件的功能,即只识别 <!--#include file="xxx" --> 标签,需要修改下 wn_module_ssi.c 实现 <!--#include virtual="xxx" --> 标签的识别与处理。同理需要在启动web服务器之前注册好你的SSI执行函数,如上图所示。我这里以获取以太网IP地址为例,在浏览器请求 ethip.shtml 的时候,web服务器会执行注册好的回调函数

在回调函数中直接将网卡的IP地址发送给浏览器

static void ssi_eth_ipaddr_value_handler(struct webnet_session* session)
{
    struct netdev *netdev = netdev_get_by_name("e0");
    webnet_session_printf(session, "%s", inet_ntoa(netdev->ip_addr));
}

3、页面文件上传

开启RT-Thread 的设备虚拟文件系统后,需要将静态页面上传到文件系统中服务器的根目录下(这里根目录为 /webnet),需要依次执行下面操作:

1、使用 mkdir webnet 命令创建 WebNet 软件包根目录 /webnet,并使用 cd webnet 命令进入该目录;

2、使用 mkdir admin mkdir upload mkdir download命令创建 /webnet/admin/webnet/upload/webnet/download,用于 AUTH 功能、 upload 功能和download功能的测试

3、将设计的所有网页依次上传到设备 /webnet 目录中。(可以使用 TFTP 工具上传文件,具体操作方式参考 TFTP 使用说明)

4、启动webnet

设备启动,网络连接成功,创建目录和上传文件成功之后,就可以启动例程,测试 WebNet 软件功能来了,过程如下:在 Shell 命令行输入 webnet_test 命令即可启动 WebNet 服务器

msh /webnet>webnet_test
[D/wn.log] server initialize success.
[I/wn] RT-Thread webnet package (V2.0.0) initialize success.

5、解决的问题

1、在浏览器获取不到网页的问题

获取的网页需要写成绝对地址,比如获取/webnet/frame_table.html页面时,需要写成 /frame_table.html,不能只写成 frame_table.html

2、在提交完表单后会切换当前的页面,有时候其实是不需要切换的,还停留在当前页面。这时候可以巧妙运用 iframe,在页面中放置一个面积为0的iframe,使其跳转在iframe中完成,即实际跳转了,只是不可见

<iframe id="id_iframe" name="nm_iframe" style="display:none;"></iframe>
<form action="cgi-bin/ethip" method="post" target="nm_iframe">

3、动态实时刷新页面

<meta charset="utf-8" http-equiv="refresh" content="1">

4、登录的时候,先判断用户名和密码,不对的话打印提示信息

<script type="text/javascript">
function check(form)
{
    var a = form.username.value;
    var b = form.password.value;

    if (a != "admin")
    {
        alert("User name error,Please input correct user name!");
    }
    else
    {
        if (b != "admin")
        {
            alert("Pass word error,Please input correct pass word!");
        }
        else
        {
            form.submit();
        }
    }
 }
</script>

<input type="button" name="login" id="" style="position:absolute; left:48%;" value="登录" onclick="check(form)"/>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

rt-thread应用篇(03)---基于STM32F429实现web服务器功能 的相关文章

  • STM32学习教程

    STM32学习教程 硬石电子 资料下载库的区分启动模式选择NVICDMAstm32 hal库 pb3做普通ioUSART 串口通讯DMA 直接存储寄存器读取DMA USART1接发RS 485通信 洋桃电子 STM32入门100步第33步U
  • 写字机器人使用教程

    一次制作写字机器人的过程 xff08 含制作教程 xff09 arduino 写字机器人制作教程 写字机器人制作教程2 0 购买链接 资料下载地址 xff1a 智宇科技 写字机器人 光盘资料 xff08 A盘资料 xff09 解压密码 xf
  • Inter RealSenseT265测试总结

    1 光线对定位有影响 xff0c 在一定范围内 xff0c 光线越充足 xff0c 定位精度越高 xff0c 但是当光线达到一定条件之后 xff0c 光照强度就不再跟定位精度成正比了 xff1b 2 周围环境对定位有影响 xff0c 周围的
  • 论文小技巧

    文件 选项 LM3405AXMKE NOPB與LM3405AXMK NOPB LM3405AXMKX NOPB對比 激光二极管 期刊查询 在word里面插入图片时怎样才成是100 比例的 文献 封装与功率 高手支招 xff1a 教你利用裸露
  • 激光啄木鸟使用教程

    软件下载地址 1 红色方框内的按钮长按开机 2 红色方框内的按钮轻触自动对焦 3 打开手机APP选择要雕刻的素材 4 设置要雕刻区域的大小 xff0c 开始预览可以查看雕刻的位置 5 打开蓝牙 xff0c 点击连接设备 6 选择被雕刻物件的
  • STM32 HAL库

    STM32 HAL库 第三章 MDK5 软件入门bug解决关键文件介绍程序仿真User Keywords语法提示代码编辑 查看技巧 第四章 STM32F1 基础知识入门MDK 下 C 语言基础复习STM32F103 时钟系统STM32F10
  • LWIP网络-基于STM32平台

    LWIP P1无操作系统移植RAW UDP实验RAW TCP实验Webserver实验 P1无操作系统移植 MAC 43 PHY 通过符合 IEEE802 3的MII和RMII接口与外接快速以太网PHY进行通信 MII和RMII实现数据交换
  • 树莓派学习

    树莓派学习教程 系统安装数据源的更新与配置命令设定固定IP网络地址 xff1a 法一法二 给树莓派安装中文环境和中文输入法远程控制树莓派SSH方式 xff1a 通过putty软件实现 xff08 不需要屏幕 xff09 VNC方式 xff0
  • C++学习教程

    C 43 43 学习教程 C 43 43 内存分区模型数据类型循环语句for循环语句 跳转语句指针指针 数组 函数 结构体指针 内存分区模型 工具vs codeDEV C 43 43 C 43 43 内存分区模型 程序运行前 全局区和代码区
  • core dumped ?完了?

    微信公众号 xff1a linux码头 core dumped xff1a 当程序在运行过程中发生异常 xff0c 这时linux系统可以把程序出错的内存 内容存储在一个core文件中 xff0c 又叫核心转存 应用程序在运行过程汇总经常会
  • Ubuntu18.04安装网络调试助手 NetAssist

    下载地址 链接 xff1a https pan baidu com s 1DUqZBtxFh pGTsRR2kXaPA 提取码 xff1a fp32 安装步骤 1 xff09 建立依赖关系 sudo apt get install f 2
  • C语言中左移(<<)和右移(>>)的理解

    lt lt 左移 xff1a 相当于乘法 a lt lt b 61 a 2 b 举例 xff1a 1 lt lt 5 xff0c 相当于1 2 5 61 32 1 lt lt 0 xff0c 相当于1 2 0 61 1 gt gt 右移 x
  • 《Linux运维总结:firewalld防火墙使用教程》

    文章目录 一 firewalld基础知识1 1 firewalld基本介绍1 2 firewalld与iptables关系与区别1 3 firewalld默认策略1 4 firewalld配置模式1 5 firewalld配置方法1 6 f
  • ROS常用的功能包

    坐标系 坐标变换 xff08 tf xff09 tf功能包提供了一个基于ROS的分布式框架 xff0c 可以随着时间的推移计算多个坐标系的位置 3D可视化工具 xff08 rviz xff09 机器人模型的可视化 图像数据的可视化 地图数据
  • 树莓派4B+Ubuntu 18.04 LTS + 桌面desktop + ros安装@树莓派4B、Ubuntu、desktop、ros

    树莓派4B 43 Ubuntu 18 04 LTS 43 桌面desktop 43 ros安装 64 树莓派4B Ubuntu desktop ros 久违的一篇博客 xff0c 说实话CSDN的编辑器还是用不太习惯 xff0c 记录一下树
  • 云台控制协议总结(VISCA/PELCOD/PELCOP)

  • error: #20: identifier "TIM_TimeBaseInitTypeDef" is undefined

    如果出现多句错误 xff1a identifier 34 34 is undefined 解决问题方法一 xff1a C C 43 43 include paths 把文件路径添加进去 解决问题方法二 xff1a 在stm32f10x co
  • 使用pyqt5实现键盘(含组合键)鼠标事件响应

    使用pyqt5实现键盘 xff08 含组合键 xff09 鼠标事件响应 使用python3 6 xff0c pyqt5 xff0c 在macOS上测试有效 span class hljs keyword import span sys sp
  • 递归思想刷题总结

    核心思想 我们在调用递归函数的时候 xff0c 把递归函数当做普通函数 xff08 黑箱 xff09 来调用 xff0c 即明白该函数的输入输出是什么 xff0c 而不用管此函数内部在做什么 xff08 千万不要跳进去了 xff0c 你脑袋
  • anonymous unions are only supported in --gnu mode, or when enabled with #pragma anon_unions

    在keil工程下移植代码 xff0c 编译出现了这个问题 xff0c 字面上解决办法有 xff1a 1 打开GNU模式 option gt GNU extensions 2 在代码前加上 pragma anon union 就是代表支持匿名

随机推荐

  • 串口的深入理解

    1 串口是如何发送数据的 xff1f 一般说来 xff0c 串口发送数据是往数据寄存器sbuf填写数据 xff0c 一个字节一个字节的写入 xff0c 如果有串口中断 xff0c 那么发送完一个字节的数据 xff0c 就会进入串口中断一次
  • CMakeLists.txt的简单使用

    Makefile和CMakeLists的关系 环境准备 xff1a 需要安装gcc xff0c g 43 43 xff0c make sudo apt get install gcc g 43 43 sudo apt get isntall
  • .so文件的基本理解,使用。

    一 基本概念 Linux下的 so是基于Linux下的动态链接 其功能和作用类似与windows下 dll文件 代码编译 xff0c 链接 xff0c 最后生成可执行文件 xff1b 这个可执行文件就可看作是一个静态链接 xff0c 因为代
  • jz2440:QT控制LED灯点亮熄灭(11)

    1 LED灯的驱动 xff1a 首先要准备好在驱动文件 xff0c 通过insmod led ko来加载模块 xff0c 然后在QT的代码里面配合调用open xff0c write read函数来点亮 xff0c 关闭LED灯 这一步 x
  • win10下安装ubuntu双系统

    本文章记录自己在Win10系统下安装ubuntu双系统的过程 xff0c 以及注意事项 另一个不错的安装教程 1 下载系统镜像 在官网或清华镜像 xff0c 根据需要的ubuntu版本下载需要的ubuntu镜像文件 这里要注意 xff0c
  • C++ shared_ptr的reset 用法

    include lt iostream gt include lt memory gt class Tmp public Tmp int a Tmp void print a std cout lt lt 34 value 61 34 lt
  • C++ 模板类的继承

    模板类 xff1a template lt typename T gt 说白了就是向之后的内容传递参数类型 xff0c 把T当作一个数据类型传递 xff0c 而在声明一个变量的时候 xff0c 通过base lt xxxx gt pp xx
  • linuxptp源码研究

    目录 1 检查网卡是否支持相应的时间戳 2 linuxptp的目录架构 3 ptp4l的大致流程分析 4 gptp协议对应的sync follow up delay request delay response消息在代码的位置 5 slav
  • xv6---Lab3: page tables

    目录 参考资料 RISC V页表的简化图如下所示 编辑 多级页表 xv6内核页表 3 6 Process Address Space 3 7 Code Sbrk 3 8 Code Exec Print a page table A kern
  • 内存管理---分页机制

    目录 物理内存管理带来的问题 直接映射 一级页表 二级页表 参考 xff1a xff08 C语言内存七 xff09 分页机制究竟是如何实现的 xff1f Smah 博客园 物理内存管理带来的问题 比如4GB的flash 如果应用程序可直接访
  • xv6---Lab4 traps

    参考 xff1a Lab Traps 关于寄存器s0和堆栈 https pdos csail mit edu 6 828 2020 lec l riscv slides pdf RISC V assembly Q 哪些寄存器包含函数的参数
  • stm32F4 hal库之CAN通信的实现

    本文的目的是为了能够实现功能 xff0c 故写的时候比较简略 参考资料 xff1a https blog csdn net u012308586 article details 81001102 正点原子开发手册 目标 xff1a 通过ca
  • 调试sim800L模块

  • 51单片机 串口中断

    1 什么是中断 广义上的中断是指一个过程 xff0c 举个简单的例子 xff0c 打开了电脑 xff0c 你正在放音乐 xff0c 点击了暂停按钮 xff0c 于是歌停了 这就是一个很明显的中断的例子 CPU正在做自己的事情 xff08 放
  • STM32CubeMX应用 -- 定时器输入脉冲计数

    目录 参考链接 一 实现过程 二 STM32CubeMX配置示例 三 C语言示例程序 参考链接 https blog csdn net m0 37845735 article details 105395643 一 实现过程 当选择外部的同
  • 机器人导航dwa(局部避障)分析

    前面部分引用http blog csdn net lqygame article details 72861439 xff08 1 xff09 初始化 xff1a 在move base节点中 xff0c 通过类加载模块载入了BaseLoca
  • 2019年最新VSLAM比较汇总

    2019年最新VSLAM比较汇总 闭源SOFTSOFT2ESOsGAN VOLG SLAMRotRocc 43 GDVOElbrusROCCMonoROCCcv4xv1 sc 开源 xff1a VINS FusionORB SLAM2Ste
  • CMSIS到底是个什么东西

    目录 一 前言 二 CMSIS标准 三 CMSIS文件 1 Include文件 2 Source文件 四 总结 一 前言 使用过ARM单片机的朋友肯定听说过CMSIS xff0c 可以说CMSIS是开启ARM单片机的金钥匙 xff0c 是不
  • TouchGFX介绍

    目录 一 关于TouchGFX 1 TouchGFX是一个图形框架 2 TouchGFX可以减轻CPU负载 3 TouchGFX充分利用了STM32的硬件图形外设 4 TouchGFX创建最佳性能的用户界面 5 TouchGFX可工作于ST
  • rt-thread应用篇(03)---基于STM32F429实现web服务器功能

    目录 参考示例 前言 一 需使用的组件与软件包及其ENV配置 1 文件系统相关组件与软件包 1 1 DFS 框架 1 2 fal 软件包 1 3 SFUD 组件 2 网络通信相关组件和软件包 2 1 SAL组件 2 2 netdev组件 2