RK Android11 WiFi模组 AIC8800 驱动移植流程

news2025/2/21 11:44:01

RK Android WiFi模组 AIC8800 驱动移植流程

  • 作者:Witheart
  • 更新时间:20250220

概要:本文介绍了基于 AIC8800D40 芯片的 WiFi6 模组 BL-M8800DS2-40 在 RK3568 平台上的驱动移植流程。主要涉及环境搭建、驱动代码分析、设备树修改、驱动编译配置、蓝牙库集成、wpa_supplicant 配置及 WiFi HAL 适配等内容,并提供详细的移植步骤和注意事项。

问题调试在另一篇文章:https://blog.csdn.net/Beihai_Van/article/details/145772085


1. 环境

  • WiFi 模组:BL-M8800DS2-40(基于 AIC8800D40 芯片)
  • CPU:RK3568
  • OS:Android

2. WiFi芯片与WiFi模组的区别

  • WiFi 芯片:核心部件,集成射频前端、基带处理器、数字信号处理等功能。
  • WiFi 模组:基于 WiFi 芯片的完整无线通信组件,包含天线、外围电路、接口等。

AIC8800 属于 WiFi 芯片,而本次移植的 WiFi 模组是 BL-M8800DS2-40(基于 AIC8800D40)。
WiFi6 模组_必联(LB-LINK)官方网站

在这里插入图片描述

3. AIC8800 驱动代码包详解

3.1 驱动代码包结构

厂家送样后,需要获取最新的驱动代码包,并确保版本与模组匹配。驱动代码版本错误可能引发诸多问题。
在这里插入图片描述

3.2 Patch 注意事项

SDIO\patch\for_Rockchip\3566\Android11 目录下,提供了 Rockchip 平台的移植补丁(更像是移植成功的参考案例,不同wifi芯片还要具体配置),移植过程中需对比 modorig 文件夹的区别,可利用 git 进行差异分析。

在移植过程中需要注意一个问题:patch 仅仅指示了需要修改哪些文件以及具体的修改方法,但其中的驱动可能并不适用于你手头的模组。原因在于,官方提供的驱动包适用于多款模组,而 patch 仅是其中某款模组的案例,并且官方更新驱动时,并不会同步更新 patch 中的驱动

因此,在移植时可以参考 patch 进行修改,但对于驱动适配系统的相关配置,一般无需更改。而对于新增的驱动文件,应在 driver_fw 文件夹中查找正确的驱动文件进行添加,而不是直接使用 patch 中的文件。

3.3 Patch 使用方法

在使用 patch 进行移植时,主要是对比 mod 文件夹和 orig 文件夹的区别,然后在你的源码中进行相应的配置修改。直接手动对比可能比较繁琐,因此可以借助 Git 进行对比分析。


3.3.1. 初始化 Git 仓库

首先,在 orig 文件夹中初始化一个 Git 仓库.
接着,找到 mod 相比 orig 新增的文件,通常包含以下三部分:

  1. 模组固件
    • 主要是厂家编译好的二进制 .bin 文件以及 .txt 配置文件。
  2. 模组驱动
    • 用于与内核交互,主要是 .c 源码文件,编译后生成 .ko 驱动文件。
  3. 模组库
    • 例如 libbt 之类的库,编译后生成 .so 共享库文件。

3.3.2. 删除 mod 中的新增文件

由于我们只关心 源码的修改内容,而这些新增的二进制文件、驱动和库文件无需对比修改,仅需直接复制,所以应当先删除 mod 中的新增文件

原因:

  • 这些新增文件会导致 Git 对比时产生大量无关内容,影响分析。
  • 厂商在更新驱动时,不会同步更新 patch 中的驱动,直接使用 patch 提供的驱动可能会导致 bug
    (别问为什么知道的,踩坑经验)

3.3.3. 进行 Git 对比

删除新增文件后,将 mod 文件夹的内容 覆盖 orig,然后使用 Git 进行对比:


⚠ VSCode 的 Git 对比 Bug

坑点提醒:
VSCode 的 Git 对比窗口 在路径长度超过 219 个字符 时,不会显示差异,容易导致遗漏修改。

参考 Issue:
Git diff does not show files with long paths in Source Control View (Windows) #240770

4 设备树(DTS)修改

此处主要是参考RK官方文档去修改

01、Linux\Linux\Wifibt\Rockchip_Developer_Guide_Linux_WIFI_BT_CN.pdf
02、Android\android\wifi\Rockchip_Introduction_WIFI_Configuration_CN&EN.pdf
02、Android\common\MMC\Rockchip_Developer_Guide_SDMMC_SDIO_eMMC_CN.pdf

4.1 蓝牙部分

&wireless_bluetooth {
	compatible = "bluetooth-platdata";
	clocks = <&rk809 1>;
	clock-names = "ext_clock";
	uart_rts_gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_LOW>;
	pinctrl-names = "default", "rts_gpio";
	pinctrl-0 = <&uart8m0_rtsn>;
	pinctrl-1 = <&uart8_gpios>;
	BT,reset_gpio    = <&gpio3 RK_PD5 GPIO_ACTIVE_LOW>;
	status = "okay";
};

wireless-bluetooth {
    uart8_gpios: uart8-gpios {
        rockchip,pins = <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
    };
};
  • 这里比较重要的是BT,reset_gpio,这个模块的34脚,PWR_BT,根据描述来看,高电平时蓝牙部分关闭,低电平时蓝牙部分开启
  • 但是此部分的配置不一定是最终生效的版本,最终还要看驱动里是怎么处理的,有的驱动会对电平作反相处理,所以这部分可以GPIO_ACTIVE_LOW和GPIO_ACTIVE_HIGH都试试看
  • UART 配置: 确保蓝牙与 CPU 通过 UART8 进行通信。

4.2 WiFi 部分

sdio_pwrseq: sdio-pwrseq {
    compatible = "mmc-pwrseq-simple";
    clocks = <&rk809 1>;
    clock-names = "ext_clock";
    pinctrl-names = "default";
    pinctrl-0 = <&wifi_enable_h>;

    /*
        * On the module itself this is one of these (depending
        * on the actual card populated):
        * - SDIO_RESET_L_WL_REG_ON
        * - PDN (power down when low)
        */
    post-power-on-delay-ms = <200>;
    reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_LOW>;
};

重点配置 WiFi reset-gpios,确保正确的电源控制。

wireless_wlan: wireless-wlan {
    compatible = "wlan-platdata";
    rockchip,grf = <&grf>;
    wifi_chip_type = "AIC8800";
    status = "okay";
};

此处的WiFi芯片名称的配置,应该和frameworks\opt\net\wifi\libwifi_hal\rk_wifi_ctrl.cpp
这个文件中的
static wifi_device supported_wifi_devices[]中配置的名称一致(至少前三个字符要为AIC)

&sdmmc2 {
        max-frequency = <150000000>;
        supports-sdio;
        bus-width = <4>;
        disable-wp;
        cap-sd-highspeed;
        cap-sdio-irq;
        keep-power-in-suspend;
        mmc-pwrseq = <&sdio_pwrseq>;
        non-removable;
        pinctrl-names = "default";
        pinctrl-0 = <&sdmmc2m0_bus4 &sdmmc2m0_cmd &sdmmc2m0_clk>;
        sd-uhs-sdr104;
        status = "okay";
};
  • sd-uhs-sdr104表示支持sdio3.0

5. 驱动部分

  • 添加驱动文件,也就是SDIO\driver_fw\driver\aic8800下所有文件添加到
    kernel\drivers\net\wireless\aic8800

  • 然后在同级目录下的mk文件中添加编译选项,通过CONFIG_AIC_WLAN_SUPPORT宏定义控制是否编译aic8800/目录下的内容

kernel\drivers\net\wireless\Makefile
obj-$(CONFIG_AIC_WLAN_SUPPORT) += aic8800/
  • 并且在同级目录下的kconfig中,引用aic8800/目录下的Kconfig文件,用于增加menuconfig中的aic8800驱动编译选项
source "drivers/net/wireless/aic8800/Kconfig"
  • 配置内核编译配置文件kernel\arch\arm64\configs\rockchip_defconfig,请修改你实际上应用的内核编译配置文件
CONFIG_AIC_WLAN_SUPPORT=y
CONFIG_AIC_FW_PATH="/vendor/etc/firmware"
CONFIG_AIC8800_WLAN_SUPPORT=m
    • CONFIG_AIC_WLAN_SUPPORT用于控制编译这个驱动
    • CONFIG_AIC_FW_PATH用于配置模组固件存放的位置,固件最后会被复制到配置的这个位置
    • CONFIG_AIC8800_WLAN_SUPPORT说明驱动将不会被编译进内核,而是以模块的形式动态插入(如果是以模块的形式动态插入,内核将根据sdio读到的vid和pid匹配不同的模块进行加载)
  • vendor\rockchip\common\wifi\wifi.mk文件中,添加编译出来的ko文件的路径,因为是动态加载ko文件的,所以ko文件编译出来后,将被复制到/vendor/lib/modules路径下进行动态加载

AIC_WIFI_KO_FILES := $(shell find $(TOPDIR)kernel/drivers/net/wireless/aic8800 -name "*.ko" -type f)
BOARD_VENDOR_KERNEL_MODULES += \
$(foreach file, $(AIC_WIFI_KO_FILES), $(file))

此处的配置用于找到编译出的ko文件

  • 配置Android 启动时用于加载内核模块(.ko) 的配置文件
    device\rockchip\common\init.insmod.cfg
    加入
insmod /vendor/lib/modules/aic8800_bsp.ko
  • 最终会编译出三个ko文件,分别是
    aic8800_bsp.ko aic8800_btlpm.ko aic8800_fdrv.ko
    • aic8800_bsp用于模组的初始化等基础功能
    • aic8800_fdrv用于WiFi
    • aic8800_btlpm用于蓝牙
  • 移植到RK Android平台时,实际上只加载aic8800_bsp.ko,aic8800_fdrv.ko

6. 蓝牙库 libbt

在这里插入图片描述

libbt用于完成对蓝牙模块硬件初始化与控制。

6.1 添加蓝牙库文件

driver_fw\aic\libbt\8800 目录下所有文件添加到 hardware\aic\aicbt\libbt 目录。

6.2 配置编译 libbt

  • 在libbt同级目录下添加Android.mk,如果BOARD_HAVE_BLUETOOTH_AIC被配置了,那么子目录下所有makefile都生效
ifeq ($(BOARD_HAVE_BLUETOOTH_AIC),true)
LOCAL_PATH := $(call my-dir)
include $(call all-subdir-makefiles)
endif

而BOARD_HAVE_BLUETOOTH_AIC在device\rockchip\common\wifi_bt_common.mk这个mk文件中定义

BOARD_HAVE_BLUETOOTH_AIC := true

  • 同样的,在libbt同级目录下添加aicbt.mk文件
CUR_PATH := hardware/aic/aicbt

BOARD_HAVE_BLUETOOTH := true

PRODUCT_PACKAGES += \
	libbt-vendor-aic

PRODUCT_PACKAGES += libbt-vendor-aic 定义了 libbt-vendor-aic 这个包,用于指定需要编译并包含到最终镜像

注意,此处有一个坑点,需要保证libbt中Android.mk中的LOCAL_MODULE与PRODUCT_PACKAGES一致,原厂的patch由于没有更新,这两者不一致

hardware\aic\aicbt\libbt\Android.mk

LOCAL_MODULE := libbt-vendor-aic
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_OWNER := aic
LOCAL_PROPRIETARY_MODULE := true

LOCAL_MODULE 是用于定义模块名称,也就是最终会编译出libbt-vendor-aic.so这个模块。

7. wpa_supplicant 配置

7.1 wpa_supplicant 概念

wpa_supplicant 是一个用于管理 WiFi 连接的用户空间守护进程,主要负责:

  • 处理 WPA/WPA2 认证
  • 管理 WiFi 连接(扫描、连接、断开)
  • 支持 WiFi Direct(P2P)
  • 通过 socket 接口与 Android WiFi 框架交互

7.2 wpa_supplicant 具体配置

配置aic模块的wpa配置,设置aic模块的启动参数
device\rockchip\common\wpa_config.txt
添加

[aic]
/vendor/bin/hw/wpa_supplicant
-O/data/vendor/wifi/wpa/sockets
-puse_p2p_group_interface=1
-g@android:wpa_wlan0
    • [aic]:表示该配置适用于 AIC WiFi 模块。
    • /vendor/bin/hw/wpa_supplicant:指定 wpa_supplicant 的可执行文件路径。
    • -O/data/vendor/wifi/wpa/sockets:指定 wpa_supplicant 使用的 socket 目录,通常用于与其他组件(如 hostapd 或 Android WiFi 框架)通信。
    • -puse_p2p_group_interface=1:启用 P2P 组接口支持,允许 WiFi Direct 功能。
    • -g@android:wpa_wlan0:定义全局控制接口,@android:wpa_wlan0 允许 Android 通过 wpa_supplicant 进行 WiFi 控制

设置加载wpa_config.txt中的配置
external\wpa_supplicant_8\wpa_supplicant\main.c

#define AIC_MODULE_NAME "[aic]"

else if (0 == strncmp(wifi_type, "AIC", 3)) {
        wpa_printf(MSG_INFO,"Start aic_wpa_supplicant\n");
        ret = read_wpa_param_config(AIC_MODULE_NAME,argv[1]);
}

WiFi芯片类型前缀为AIC时,加载对应的aic的wpa_supplicant参数。

8. WiFi HAL 配置

这部分主要是通过配置vid:pid,选择加载不同的库。

8.1 动态加载原理

sdio握手成功后,就会读到vid:pid,将读到的数值与已经配置vid:pid比较,动态加载不同的库

8.2 具体配置

vid:pid配置

frameworks\opt\net\wifi\libwifi_hal\rk_wifi_ctrl.cpp
supported_wifi_devices 结构体数组中添加WiFi名称以及对应的vid:pid

{"AIC8800",	"5449:0145"},
  • 这里又有一个坑点,patch中提供的这个vid:pid不适用于我这个模组,需要具体配置。
  • 获取真正的vid:pid有两种方式,一种是如果WiFi模组正常上电且sdio握手成功,那么是可以通过读/sys/bus/sdio/devices下的设备目录下的uevent文件得到的
rk3568_HW:/ # cat /sys/bus/sdio/devices/
mmc3:390b:1/   mmc3:390b:2/
rk3568_HW:/ # cat /sys/bus/sdio/devices/mmc3\:390b\:1/uevent
DRIVER=aicwf_sdio
SDIO_CLASS=07
SDIO_ID=C8A1:0082
MODALIAS=sdio:c07vC8A1d0082
rk3568_HW:/ # cat /sys/bus/sdio/devices/mmc3\:390b\:2/uevent
DRIVER=aicbsp_sdio
SDIO_CLASS=07
SDIO_ID=C8A1:0182
MODALIAS=sdio:c07vC8A1d0182

这个WiFi模组扫卡成功后可以读到两个mmc设备,分别是mmc3:390b:1/ mmc3:390b:2/,
读取到的mmc3:390b:1设备的vid:pid为C8A1:0082,那么增加这个vid:pid到rk_wifi_ctrl.cpp中即可。

  • 二是直接向厂家询问,或在驱动包中寻找

接下来是检测流程,调用check_wifi_chip_type_string(wifi_type)函数,尝试获取wifi芯片类型,保存到wifi_type
frameworks\opt\net\wifi\libwifi_hal\rk_wifi_ctrl.cpp

int check_wifi_chip_type_string(char *type)
{
	if (identify_sucess == -1) {
		if (get_wifi_device_id(SDIO_DIR, PREFIX_SDIO) == 0)
			PLOG(DEBUG) << "SDIO WIFI identify sucess";
		else if (get_wifi_device_id(USB_DIR, PREFIX_USB) == 0)
			PLOG(DEBUG) << "USB WIFI identify sucess";
		else if (get_wifi_device_id(PCIE_DIR, PREFIX_PCIE) == 0)
			PLOG(DEBUG) << "PCIE WIFI identify sucess";
		else {
			PLOG(DEBUG) << "maybe there is no usb wifi or sdio or pcie wifi,set default wifi module Brocom APXXX";
			strcpy(recoginze_wifi_chip, "APXXX");
			identify_sucess = 1 ;
		}
	}

	strcpy(type, recoginze_wifi_chip);
	PLOG(ERROR) << "check_wifi_chip_type_string : " << type;
	return 0;
}

还未进行识别时,identify_sucess为-1,此时开始使用get_wifi_device_id()获取设备id,依次尝试sdio、usb、pcie设备

get_wifi_device_id()函数中,通过读uevent获取vid:pid,然后用一个for循环,比较已经在supported_wifi_devices中添加的设备vid:pid与读到的vid:pid,有相符的,就将对应的wifi芯片名称复制到recoginze_wifi_chip中,get_wifi_device_id()执行完成之后,会将recoginze_wifi_chip复制到type中,也就是wifi_type。

接下来配置动态加载不同的库
  • frameworks\opt\net\wifi\libwifi_hal\wifi_hal_common.cpp中,有一个wifi_load_driver()函数,调用了check_wifi_chip_type_string(wifi_type)函数,尝试获取wifi芯片类型wifi_type
  • 需要添加wifi ko驱动的路径,以及驱动与wifi类型的对应
    wifi_hal_common.cpp
#define AIC8800_DRIVER_MODULE_PATH         WIFI_MODULE_PATH"aic8800_fdrv.ko"
#define AIC8800_DRIVER_MODULE_NAME       "aic8800_fdrv"
wifi_ko_file_name module_list[] ={
    {"AIC8800",         AIC8800_DRIVER_MODULE_NAME,   AIC8800_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
}
  • 定义蓝牙使用的库
    hardware\interfaces\bluetooth\1.0\default\vendor_interface.cc
static const char* VENDOR_AIC_LIBRARY_NAME = "libbt-vendor-aic.so";

然后根据wifi芯片类型,得到要加载的库的名称

if ((0 == strncmp(wifi_type, "AIC", 3))) {
    ALOGE("%s try to open %s \n", __func__, VENDOR_AIC_LIBRARY_NAME);
    strcpy(vendor_lib_name, VENDOR_AIC_LIBRARY_NAME);
} 

根据这个名称进行加载

lib_handle_ = dlopen(vendor_lib_name, RTLD_NOW);
  • 根据 Wi-Fi 芯片类型来确定应该使用哪个Wi-Fi 直连(P2P)接口名称
    hardware\interfaces\wifi\1.4\default\wifi_chip.cpp
std::string getP2pIfaceName() {
    std::array<char, PROPERTY_VALUE_MAX> buffer;
	    if (wifi_type[0] == 0) {
	    check_wifi_chip_type_string(wifi_type);
    }
    if (0 == strncmp(wifi_type, "AP", 2) || 0 == strncmp(wifi_type, "AIC", 3)) {
		property_set("vendor.wifi.direct.interface", "p2p-dev-wlan0");
		property_get("wifi.direct.interface", buffer.data(), "p2p-dev-wlan0");
    } else {
		property_set("vendor.wifi.direct.interface", "p2p0");
		property_get("wifi.direct.interface", buffer.data(), "p2p0");
	}
    return buffer.data();
}

注:此处的AP应该是AP系列WiFi芯片的意思

9. 固件添加

  • 主要是厂家编译好的二进制 .bin 文件以及 .txt 配置文件。

  • 将厂家给的驱动包中driver_fw\fw下具体的固件放置在vendor\rockchip\common\wifi\firmware下。

  • BL-M8800DS2-40 使用 driver_fw\fw\aic8800D80 目录下的固件。


至此,驱动配置成功,但是在调试过程中还遇到一些问题,详情见另一篇文章。

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

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

相关文章

Windows PyCharm的python项目移动存储位置后需要做的变更

项目使用的venv虚拟环境&#xff0c;因此项目移动存储位置后需要重新配置python解释器的位置&#xff0c;否则无法识别&#xff0c;若非虚拟环境中运行&#xff0c;则直接移动后打开即可&#xff0c;无需任何配置。 PyCharm版本为2021.3.3 (Professional Edition)&#xff0c;其…

浅棕色人像花卉照片Lr调色,手机滤镜PS+Lightroom预设下载!

调色介绍 提供一系列用于处理浅棕色调人像与花卉照片的后期预设资源&#xff0c;这些预设兼容手机滤镜的 PS 和 Lightroom 软件。其主要作用是令照片达成浅棕色的色调效果&#xff0c;帮助使用者快捷地对人像和花卉照片进行调色处理&#xff0c;无需繁复手动调节参数&#xff0…

POI pptx转图片

前言 ppt页面预览一直是个问题&#xff0c;office本身虽然有预览功能但是收费&#xff0c;一些开源的项目的预览又不太好用&#xff0c;例如开源的&#xff1a;kkfileview pptx转图片 1. 引入pom依赖 我这个项目比较老&#xff0c;使用版本较旧 <dependency><gro…

全志A133 android10 适配SLM770A 4G模块

一&#xff0c;模块基本信息 1.官方介绍 SLM770A是美格智能最新推出的一款LTE Cat.4无线通讯模组&#xff0c;最大支持下行速率150Mbps及上行速率50Mbps。同时向下兼容现有的3G和2G网络&#xff0c;以确保即使在偏远地区也可以进行网络通信。 SLM770A模组支持分集接收和MIMO技…

DP-最长上升子序列

题面&#xff1a; 样例&#xff1a; 思路&#xff1a; 遇到动态规划问题&#xff0c;我们照旧思考两部分&#xff0c;状态表示以及状态计算。这里我们f[N]表示以第i个数结尾的上升子序列的最大值。我们将f[N]划分为若干个部分&#xff0c;因为我们要用到递推思路想办法用前面的…

【C++第二十章】红黑树

【C第二十章】红黑树 红黑树介绍&#x1f9d0; 红黑树是一种自平衡的二叉搜索树&#xff0c;通过颜色标记和特定规则保持树的平衡性&#xff0c;从而在动态插入、删除等操作中维持较高的效率。它的最长路径不会超过最短路径的两倍&#xff0c;它的查找效率比AVL树更慢(对于CPU…

如何修改Windows系统Ollama模型存储位置

默认情况下&#xff0c;Ollama 模型会存储在 C 盘用户目录下的 .ollama/models 文件夹中&#xff0c;这会占用大量 C 盘空间&#xff0c;增加C盘“爆红”的几率。所以&#xff0c;我们就需要修改Ollama的模型存储位置 Ollama提供了一个环境变量参数可以修改Ollama的默认存在位…

OpenAI ChatGPT在心理治疗领域展现超凡同理心,通过图灵测试挑战人类专家

近期&#xff0c;一项关于OpenAI ChatGPT在心理治疗领域的研究更是引起了广泛关注。据报道&#xff0c;ChatGPT已经成功通过了治疗师领域的图灵测试&#xff0c;其表现甚至在某些方面超越了人类治疗师&#xff0c;尤其是在展现同理心方面&#xff0c;这一发现无疑为AI在心理健康…

Netflix Ribbon:云端负载均衡利器

Netflix Ribbon&#xff1a;云端负载均衡利器 ribbon Ribbon is a Inter Process Communication (remote procedure calls) library with built in software load balancers. The primary usage model involves REST calls with various serialization scheme support. 项目地…

【Android】Android 悬浮窗开发 ( 动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

文章目录 一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后返回处理 二、悬浮窗 前台服务和通知1、前台服务 启动 悬浮窗 的必要性① 保持悬浮窗存活② 悬浮窗的要求③ 悬浮窗版本兼容 2、其它类型服务简介① 前台服务…

Python高级语法之jsonpathBeautifulSoup解析器

目录&#xff1a; 1、jsonPath的使用2、使用jsonpath解析淘票票网页3、BeautifulSoup解析器的使用4、BeautifulSoup层级选择器的使用 1、jsonPath的使用 2、使用jsonpath解析淘票票网页 3、BeautifulSoup解析器的使用 4、BeautifulSoup层级选择器的使用

工业安卓主板在智慧粮仓设备中发挥着至关重要的作用

工业安卓主板在智慧粮仓设备中发挥着至关重要的作用。以下是关于其作用的具体分析&#xff1a; 一、提供稳定可靠的运行平台 智慧粮仓设备需要长时间稳定运行&#xff0c;以实现对粮食储存环境的实时监测和精准控制。工业安卓主板采用高性能的处理器和大容量的存储空间&#…

ECMAScript6----var、let、const

ECMAScript6----var、let、const 1.var2.let3.const 1.var &#xff08;1&#xff09;在相同作用域下可重复声明 var a 20 var a 30 console.log(a) // 30&#xff08;2&#xff09;存在变量提升 console.log(a) // undefined var a 20&#xff08;3&#xff09;可修改声…

【ST-LINK未能被keil识别STM32 ST-LINK Utility出现“Can not connect to target】

针对各种品牌32MCU boot0拉高&#xff0c;boot1拉低进入系统存储器&#xff0c;对Flash先擦除在下载 针对STM32f103 通过32复位和stlink Utilit解决 https://blog.csdn.net/Donglutao/article/details/129086960 https://www.bilibili.com/video/BV1F94y1g7be/?spm_id_…

Android Http-server 本地 web 服务

时间&#xff1a;2025年2月16日 地点&#xff1a;深圳.前海湾 需求 我们都知道 webview 可加载 URI&#xff0c;他有自己的协议 scheme&#xff1a; content:// 标识数据由 Content Provider 管理file:// 本地文件 http:// 网络资源 特别的&#xff0c;如果你想直接…

python实践-实现实时语音转文字本地部署版(二)

一、技术栈 python 3.10.6 vosk 需下载对应模型&#xff08;vosk-model-cn-0.22&#xff09;模型下载慢的同学看最后的资源链接。 pyaudio keyboard 二、实现功能 本地化实现麦克风语音录入&#xff0c;实时生成文字&#xff0c;并保存至本地文档。 三、实现代码 fro…

tortoiseSVN 如何克隆项目到本地

导入项目成功&#xff0c;如下图&#xff1a;

解决“QString的split()函数分割中文“报错

在使用Qt平台的QString类里的split()函数&#xff0c;分割.txt文件里中文的字符串时&#xff0c;发现中文会乱码。     问题原因&#xff1a;中文使用UTF-16编码。     解决方法&#xff1a;将.txt文件保存为UTF-16编码&#xff0c;然后使用split()去分割对应的字符串即可。…

云平台结合DeepSeek的AI模型优化实践:技术突破与应用革新

目录 前言 一、技术架构&#xff1a;算力与算法的协同基石 1. 蓝耘平台的核心优势 2. DeepSeek的模型创新 二、应用场景&#xff1a;垂直领域的智能化落地 1. 商业领域&#xff1a;智能推荐与客服 2. 工业领域&#xff1a;质检与流程优化 3. 智慧城市与医…

蓝桥杯(B组)-每日一题(1093字符逆序)

c中函数&#xff1a; reverse(首位置&#xff0c;尾位置&#xff09; reverse(s.begin(),s.end()) 头文件&#xff1a;<algorithm> #include<iostream> #include<algorithm>//运用reverse函数的头文件 using namespace std; int main() {string s;//定义一…