【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第四篇 嵌入式Linux系统移植篇-第七十三章内核添加网卡驱动

news2024/9/22 11:40:22

i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT、4G模块、CAN、RS485等接口一应俱全。H264、VP8视频硬编码,H.264、H.265、VP8、VP9视频硬解码,并提供相关历程,支持8路PDM接口、5路SAI接口、2路Speaker。系统支持Android9.0(支持获取root限)Linux4.14.78+Qt5.10.1、Yocto、Ubuntu20、Debian9系统。适用于智能充电桩,物联网,工业控制,医疗,智能交通等,可用于任何通用工业和物联网应用、

【公众号】迅为电子


第七十三章内核添加网卡驱动

网络驱动是 linux 里面驱动三巨头之一,linux 下的网络功能非常强大,嵌入式 linux 中也常常用到网络功能。本章我们就来学习一下如何在内核配置网卡驱动。

73.1 有线网络设备简介

这里我们不讨论电脑上的有线网卡,主要来看嵌入式上的有线网络设备。在选型的时候我们看某一个CPU支持以太网。但是在外围电路中,有一个叫网卡的芯片。他们是什么关系呢?明明CPU已经支持以太网了,为什么还要在加一个网卡芯片呢。我们带着这个疑问来往下思考。

嵌入式上的有线网络设备我们要分成俩个部分来看,一部分是MAC控制器部分,一部分是PHY芯片部分。而我说某一个CPU支不支持网卡,说的是这个CPU有没有MAC控制器。MAC控制器属于OSI七层网络模型中的数据链路层,主要作用是传输可靠的网络数据。而底板上的网卡芯片属于第二部分,也就是phy芯片。PHY芯片位于OSI七层网络模型中的物理层,主要作用是将MAC控制器发来的数据通过物理介质传输出去,MAC控制器和PHY芯片共同组成了嵌入式上的有线网络设备。

73.2 有线网络硬件方案

正式由于嵌入式上的网络设备分成了俩个部分,所以在嵌入式上常见的网络硬件方案也就被分成了俩种,一种是CPU支持有线网络,也就是CPU带MAC控制器,一种是CPU不支持有线网络,也就是没有MAC控制。我们分部来看一下这俩种方案。

第一种方案:CPU带MAC控制器

CPU带MAC控制器,是不是第一部分MAC控制器部分就满足了,所以我们只需要在外接PHY芯片即可。IMX8mmini内部一共有一个MAC控制器,所以IMX8mmini处理器支持一个网口,我们在设置硬件的时候只需要将这个PHY芯片连接到CPU的MAC控制器管脚即可。

第二种方案:CPU不带MAC控制器

CPU如果不带MAC控制器,是不是这个CPU就不支持网络了。如果我要使用有线网络要怎么办呢,既然CPU里面没有MAC控制器,我们是不是可以找一个外置的MAC芯片呢,不过这种外置的MAC芯片基本都是MAC和PHY一体的。比如我们的4412开发板,三星的4412处理器内部并没有MAC控制器,而是搭载了一个DM9621芯片。DM921芯片内置了MAC控制器和PHY功能,并且提供了一个USB接口,4412处理器通过USB接口来操作DM9621。

优缺点比较:

<1>如果CPU自带MAC控制器,网络速度一般比较快,比如龙芯2K1000处理器是双千兆网,并且成本比较低。

<2>如果CPU没有MAC控制器,使用外置的MAC芯片比较灵活,可以任意扩展多路网口,但是成本比较高,并且速度不是很快,一般只有10M或者100M。

73.3 MAC与PHY连接方式

73.3.1 CPU带MAC控制器

前面我们说了,如果CPU自带MAC控制器,MAC控制器要和PHY芯片连接起来,MAC控制器与PHY芯片的通信方式主要有四种,分别是MII,RMII,GMII和RGMII。

i.MX8M Mini处理器支持RGMII接口,所以在选型的时候我们要选择支持RGMII的网口芯片。如下图所示

底板上的PHY芯片使用的为RGMII,同样也是支持RGMII接口,如下图所示:

 

所以通过RGMII接口将MAC控制器和PHY芯片连接起来,如下图所示: 

73.3.2 CPU不带MAC控制器

如果CPU不带MAC控制器,我们要外接MAC芯片,我们需要将CPU与MAC芯片连接起来,这个通讯放置主要取决于MAC芯片的接口,比如4412开发板上使用的DM9621为USB接口。就要使用CPU的USB接口连接到DM9621,如下图所示:

 

73.3.3 RGMII接口介绍

RGMII全称为Reduced Gigabit Media Independant Interface,主要用来连接PHY和MAC控制器,RGMII一共有12根信号线,具体含义如下:

除了RGMII接口,还有GMII,SMII,MII,RMII等,关于这些接口基本上也都是大同小异,这里就不在过多介绍。

73.3.4 MDIO接口介绍

MDIO全称为Management Data Input/Output,是一种简单的串行接口,一条是时钟线,一条是数据线。主要用来配置和管理PHY芯片。如下图所示:

73.3.5 RJ45接口介绍

RJ45接口一端连接到PHY芯片上,一端连接到网线,如下图所示:

 

但是RJ45座子不能和PHY芯片直接连接,中间需要一个网络变压器,网络变压器的作用主要是用来隔离和滤波。但是有的同学可能就比较疑惑了,为什么我没有在开发板上看到变压器呢。因为现在很多的RJ45的座子上内部都集成了网络变压器,比如iMX8MM开发板上的HR911130C。所以这部分大家在选型的时候一定要注意,如果RJ45座子内部没有集成编译器,需要外接变压器。RJ45 座子上一般有两个灯,一个黄色(橙色),一个绿色,绿色亮的话表示网络连接正常,黄色闪烁的话说明当前正在进行网络通信。这两个灯由 PHY 芯片控制,PHY 芯片会有两个引脚来连接 RJ45 座上的这两个灯。内部 MAC+外部 PHY+RJ45 座(内置网络变压器)就组成了一个完整的嵌入式网络接口硬件

原理图如下:

 

73.3.6 硬件连接框图

为了更形象的给大家展示在嵌入式上得硬件连接方式,作者制作了一个简易的硬件连接框图。

第一种方案:CPU带MAC控制器。第二种方案:CPU不带MAC控制器,使用USB扩展网口

 

73.4修改设备树

本节我们就来简单分析一下 I.MX8MM的网络驱动源码。首先肯定是设备树,NXP的 I.MX系列SOC网络绑定文档为Documentation/devicetree/bindings/net/fsl-fec.txt,此绑定文档描述了 I.MX 系列 SOC 网络设备树节点的要求。

①、必要属性

compatible:这个肯定是必须的,一般是“fsl,<soc>-fec”,比如 I.MX8MM的compatible 属性就是"fsl,imx8mm-fec", "fsl,imx8mq-fec", "fsl,imx6sx-fec"。

reg:SOC 网络外设寄存器地址范围。

interrupts:网络中断。

phy-mode:网络所使用的 PHY 接口模式,是 MII 还是 RMII。

②、可选属性

phy-reset-gpios:PHY 芯片的复位引脚。

phy-reset-duration:PHY 复位引脚复位持续时间,单位为毫秒。只有当设置了phy-resetgpios 属性此属性才会有效,如果不设置此属性的话 PHY 芯片复位引脚的复位持续时间默认为1 毫秒,数值不能大于 1000 毫秒,大于 1000 毫秒的话就会强制设置为 1 毫秒。

phy-supply:PHY 芯片的电源调节。

phy-handle:连接到此网络设备的 PHY 芯片句柄。

fsl,num-tx-queues:此属性指定发送队列的数量,如果不指定的话默认为 1。

fsl,num-rx-queues:此属性指定接收队列的数量,如果不指定的话默认为 2。

fsl,magic-packet:此属性不用设置具体的值,直接将此属性名字写到设备树里面即可,表

示支持硬件魔术帧唤醒。

fsl,wakeup_irq:此属性设置唤醒中断索引。

stop-mode:如果此属性存在的话表明 SOC 需要设置 GPR 位来请求停止模式。

③、可选子节点

mdio:可以设置名为“mdio”的子节点,此子节点用于指定网络外设所使用的 MDIO 总线,

主要做为 PHY 节点的容器,也就是在 mdio 子节点下指定 PHY 相关的属性信息,具体信息可以参考 PHY 的绑定文档 Documentation/devicetree/bindings/net/phy.txt。

PHY 节点相关属性内容如下:

interrupts:中断属性,可以不需要。

interrupt-parent:中断控制器句柄,可以不需要。

reg:PHY 芯片地址,必须的!

compatible:兼容性列表,一般为“ethernet-phy-ieee802.3-c22”或“ethernet-phy-ieee802.3-

c45”,分别对应 IEEE802.3 的 22 簇和 45 簇,默认是 22 簇。也可以设置为其他值,如果 PHY的 ID 不知道的话可以 compatible 属性可以设置为“ethernet-phy-idAAAA.BBBB”,AAAA 和 BBBB 的含义如下:

AAAA:PHY 的 16 位 ID 寄存器 1 值,也就是 OUI 的 bit3~18,16 进制格式。

BBBB:PHY 的 16 位 ID 寄存器 2 值,也就是 OUI 的 bit19~24,16 进制格式。

max-speed:PHY 支持的最高速度,比如 10、100 或 1000。

我们打开/home/topeet/bsp_kernel_imx/bsp_kernel_imx/linux-imx/arch/arm64/boot/dts/freescale/fsl-imx8mm.dtsi文件,fec1节点如下所示:

 

	fec1: ethernet@30be0000 {
		compatible = "fsl,imx8mm-fec", "fsl,imx8mq-fec", "fsl,imx6sx-fec";
		reg = <0x0 0x30be0000 0x0 0x10000>;
		interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
			     <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
			     <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
		clocks = <&clk IMX8MM_CLK_ENET1_ROOT>,
			 <&clk IMX8MM_CLK_ENET1_ROOT>,
			 <&clk IMX8MM_CLK_ENET_TIMER_DIV>,
			 <&clk IMX8MM_CLK_ENET_REF_DIV>,
			 <&clk IMX8MM_CLK_ENET_PHY_REF_DIV>;
		clock-names = "ipg", "ahb", "ptp",
			"enet_clk_ref", "enet_out";
		assigned-clocks = <&clk IMX8MM_CLK_ENET_AXI_SRC>,
				  <&clk IMX8MM_CLK_ENET_TIMER_SRC>,
				  <&clk IMX8MM_CLK_ENET_REF_SRC>,
				  <&clk IMX8MM_CLK_ENET_TIMER_DIV>;
		assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_266M>,
					 <&clk IMX8MM_SYS_PLL2_100M>,
					 <&clk IMX8MM_SYS_PLL2_125M>;
		assigned-clock-rates = <0>, <0>, <125000000>, <100000000>;
		stop-mode = <&gpr 0x10 3>;
		fsl,num-tx-queues=<3>;
		fsl,num-rx-queues=<3>;
		fsl,wakeup_irq = <2>;
		status = "disabled";
	};

但是目前网卡还不能使用,在/home/topeet/bsp_kernel_imx/bsp_kernel_imx/linux-imx/arch/arm64/boot/dts/freescale/itop8mm-evk.dts设备树文件下,已经存在了网卡的设备节点信息,如下所示;

&fec1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_fec1>;
	phy-mode = "rgmii-id";
	phy-handle = <&ethphy0>;
	fsl,magic-packet;
	status = "okay";

	mdio {
		#address-cells = <1>;
		#size-cells = <0>;

		ethphy0: ethernet-phy@0 {
			compatible = "ethernet-phy-ieee802.3-c22";
			reg = <0>;
			at803x,led-act-blind-workaround;
			at803x,eee-okay;
			at803x,vddio-1p8v;
		};
	};
};

但是上述两个网卡信息不完善,需要添加一些内容,红色代码为添加的内容,添加了复位引脚信息,修改后如下所示:

&fec1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_fec1>;
	phy-mode = "rgmii-id";
	phy-handle = <&ethphy0>;
	fsl,magic-packet;
	status = "okay";
	reset-gpio = <&gpio2 10 GPIO_ACTIVE_LOW>;
	mdio {
		#address-cells = <1>;
		#size-cells = <0>;

		ethphy0: ethernet-phy@0 {
			compatible = "ethernet-phy-ieee802.3-c22";
			reg = <0>;
			at803x,led-act-blind-workaround;
			at803x,eee-okay;
			at803x,vddio-1p8v;
		};
	};
};

73.5添加pinctrl信息

打开/home/topeet/bsp_kernel_imx/bsp_kernel_imx/linux-imx/arch/arm64/boot/dts/freescale/itop8mm-evk.dts设备树文件,首先添加GPIO引脚信息,在开发板上有一个网卡芯片,所以会有网卡GPIO引脚信息,在&iomuxc节点下写下如下内容:

pinctrl_fec1: fec1grp {
			fsl,pins = <
				MX8MM_IOMUXC_ENET_MDC_ENET1_MDC		0x3
				MX8MM_IOMUXC_ENET_MDIO_ENET1_MDIO	0x3
				MX8MM_IOMUXC_ENET_TD3_ENET1_RGMII_TD3	0x1f
				MX8MM_IOMUXC_ENET_TD2_ENET1_RGMII_TD2	0x1f
				MX8MM_IOMUXC_ENET_TD1_ENET1_RGMII_TD1	0x1f
				MX8MM_IOMUXC_ENET_TD0_ENET1_RGMII_TD0	0x1f
				MX8MM_IOMUXC_ENET_RD3_ENET1_RGMII_RD3	0x91
				MX8MM_IOMUXC_ENET_RD2_ENET1_RGMII_RD2	0x91
				MX8MM_IOMUXC_ENET_RD1_ENET1_RGMII_RD1	0x91
				MX8MM_IOMUXC_ENET_RD0_ENET1_RGMII_RD0	0x91
				MX8MM_IOMUXC_ENET_TXC_ENET1_RGMII_TXC	0x1f
				MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC	0x91
				MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL	0x91
				MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL	0x1f
				MX8MM_IOMUXC_SAI2_RXC_GPIO4_IO22	0x19
			>;
		};

上述代码中的pinctrl_fec1是网卡信息的pinctrl信息,其实在/home/topeet/bsp_kernel_imx/bsp_kernel_imx/linux-imx/arch/arm64/boot/dts/freescale/itop8mm-evk.dts设备树文件中已经存在了,在iomuxc节点下,然后我们需要添加的是网卡芯片的复位引脚信息。在iomuxc节点下,我们将原来的以下内容删除

MX8MM_IOMUXC_SAI2_RXC_GPIO4_IO22 0x19

添加内容如下:

MX8MM_IOMUXC_SD1_RESET_B_GPIO2_IO10     0x19

 

网卡芯片使用了GPIO2_IO10作为复位引脚。需要我们手动添加。

需要注意的是,引脚功能只能被申请注册一次,所以需要把设备树文件中关于这两个引脚的其他申请信息删除或者注释掉。在设备树文件中搜索这个引脚,发现在pinctrl_usdhc1_gpio节点中使用到了GPIO2_IO10,所以需要把这两条语句删除或者注释掉。如下图所示:

 

73.6修改fec_main.c文件

修改/home/topeet/bsp_kernel_imx/bsp_kernel_imx/linux-imx/drivers/net/ethernet/freescale/fec_main.c文件,添加如下代码:

	struct device *dev = &pdev->dev;
	struct device_node *node = dev->of_node;
	int reset_gpio;

	reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
	if (gpio_is_valid(reset_gpio)) {
		ret = devm_gpio_request_one(dev, reset_gpio, GPIOF_OUT_INIT_HIGH, "FEC reset");
		if (ret) {
			dev_err(dev, "unable to get reset gpio\n");
			//return ret;
		}

		gpio_set_value_cansleep(reset_gpio, 0);
		mdelay(10);
		gpio_set_value_cansleep(reset_gpio, 1);
		mdelay(10);
	}

73.7修改core.c文件

修改/home/topeet/bsp_kernel_imx/bsp_kernel_imx/linux-imx/net/wireless/core.c文件,注释掉如下代码:

static atomic_t wiphy_counter = ATOMIC_INIT(0);

 

添加代码,如下图所示:

static atomic_t wiphy_counter = ATOMIC_INIT(0);

 

添加代码,如下图所示,红色是新增的内容

void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
{
	struct cfg80211_internal_bss *scan, *tmp;
	struct cfg80211_beacon_registration *reg, *treg;
	rfkill_destroy(rdev->rfkill);
	list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
		list_del(&reg->list);
		kfree(reg);
	}
	list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
		cfg80211_put_bss(&rdev->wiphy, &scan->pub);
	//add by apple
	atomic_dec(&wiphy_counter);
	kfree(rdev);
}

73.8 编译测试

重新编译linux源码,然后烧写镜像。当开发板启动完成后,可以使用ifconfig命令查看当前的网卡信息。如下图所示:

可以使用下面的命令打开eth0网卡:

ifconfig eth0 up

然后可以使用网线进行测试,看一下是否能够连接网络。如果网卡设备正常,插入网线会有如下信息打印:

输入以下命令,ping一下路由器的ip地址,如下图所示:

如果我们ping百度的网址,发现ping不通,需要修改dns地址,修改 

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

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

相关文章

有趣的PHP小游戏——猜数字

猜数字 这个游戏会随机生成一个1到100之间的数字&#xff0c;然后你需要猜测这个数字是什么。每次你输入一个数字后&#xff0c;程序会告诉你这个数字是“高了”还是“低了”&#xff0c;直到你猜对为止&#xff01; 使用指南&#xff1a; 代码如下&#xff0c;保存到一个p…

大模型卷入医学图像!PFPs:使用大型视觉和语言模型的提示引导灵活病理分割,用于多样化潜在结果

PS&#xff1a;写在前面&#xff0c;近期感谢很多小伙伴关注到我写的论文解读&#xff0c;我也会持续更新吖~同时希望大家多多支持本人的公主号~ 想了解更多医学图像论文资料请移步公主&#x1f478;号哦~~~后期将持续更新&#xff01;&#xff01; 关注我&#xff0c;让我们一…

【嵌入式】STM3212864点阵屏使用SimpleGUI单色屏接口库——(2)精简字库

一 开源库简介与移植 最近一个项目需要用12864屏幕呈现一组较为复杂的菜单界面&#xff0c;本着不重复造轮子的原则找到了SimpleGUI开源库。 开源地址&#xff1a;SimpleGUI: 一个面向单色显示屏的开源GUI接口库。 SimpleGUI是一款针对单色显示屏设计的接口库。相比于传统的GUI…

kali里面的vulhub靶场搭建

第一步&#xff1a;安装docker镜像容器 sudo apt install docker.io 第二步&#xff1a;开启docker镜像容器 先查看一下docker有没有下载成功 docker -v 再查看一下docker的运行状态 systemctl status docker 第三步&#xff1a;下载docker-compose环境 apt install do…

94 二叉树的中序遍历

解题思路&#xff1a; \qquad 首先理解中序遍历&#xff1a;left node——root——right node。 \qquad 中序遍历的起始点为该树最左边的非空元素。本题可以使用递归、DFS&#xff08;迭代&#xff09;解决。 递归法&#xff1a; \qquad 重复的基础操作&#xff1a;输出roo…

甘肃西北风情贝壳面你吃过吗?

在西北的甘肃&#xff0c;有一种传统面食——麻食&#xff0c;以其独特的制作工艺和浓郁的地方风味&#xff0c;成为了当地人民餐桌上的宠儿。麻食&#xff0c;又被称为“麻什”“麻食子”等&#xff0c;是一种手工搓制而成的面食。它的形状酷似猫耳朵&#xff0c;小巧玲珑&…

超有趣的视觉欺骗

by 游梦 关键词&#xff1a;蜘蛛侠、室内映射、假室内 大家一起先找茬&#xff0c;半分钟找出下图中穿帮镜头 &#xff08;图源&#xff1a;https://zhuanlan.zhihu.com/p/159439811&#xff09; 答案揭晓&#xff1a; 可以看到室内门的位置&#xff0c;在建筑不同视角下的位…

为 Laravel 提供生产模式下的容器化环境:打造现代开发环境的终极指南

为 Laravel 提供生产模式下的容器化环境&#xff1a;打造现代开发环境的终极指南 在现代开发中&#xff0c;容器化已经成为一种趋势。使用 Docker 可以让我们轻松地管理和部署应用程序。本文将带你一步步构建一个高效的 Laravel 容器化环境&#xff0c;确保你的应用程序在开发…

Modbus从站模拟软件

下载地址&#xff1a; Modbus从站模拟软件资源-CSDN文库

linux创建用户并免密切换

useradd ansible passwd ansible 加入到wheel组 sudo usermod -G wheel ansible 编辑文件visudo ansible ALL(ALL) NOPASSWD:ALL chage -M 99999 ansible #设置密码永不过期

2024上半年热门内容透视 | 品牌种草解析

2024年上半年&#xff0c;小红书平台“考公上岸”、“不确定性”、“重养自己一遍”、“人生是旷野”、“原生家庭顶配”等话题热议之下&#xff0c;透露着消费者怎样的需求&#xff1f; 综合热门内容及小红书用户的分享发现&#xff0c;变数和不确定性成为新常态&#xff0c;消…

PTrade常见问题系列18

客户反馈某代码L1快照有延迟&#xff1f; 客户反馈某代码9.30.12的快照在9.30.12策略没有获取到&#xff0c;在9.30.17才获取到&#xff1f; 1、由于交易所的快照不是严格按照3s下发的&#xff0c;例如快照在9.30.12.300更新了&#xff0c;客户策略在9.30.12.100执行到&#…

什么是文档签名证书?如何获取文档签名证书?

在数字化高速发展的当今时代&#xff0c;各行各业都开始向数字化转型&#xff0c;随着国家大力倡导和积极推进数字化&#xff0c;电子文件的应用越来越广泛。然而&#xff0c;电子文件包含了个人隐私、金融交易、电子处方、合同协议等敏感信息&#xff0c;如何确保这些重要文件…

Python开发框架FastAPI系列(1. 初体验)

本文为系列文章Python开发框架FastAPI系列的第一部分。 缘起 其实Python的Web开发框架已经有很多了&#xff0c;包括老将Django和后起之秀Flask都做得很好&#xff0c;各有各的特色。那么为什么FastAPI作为一个后来者&#xff0c;短时间内就人气飙升呢&#xff1f;我也是看到…

【linux】【操作系统】初始化程序之main.c源码阅读

/init/main.c是Linux操作系统启动过程的核心部分&#xff0c;它负责初始化硬件、设备、内存和系统服务&#xff0c;以及启动第一个用户进程&#xff0c;为后续的系统运行奠定基础。 详细解析 1. 内联函数定义 fork, pause, setup, sync: 这些函数被声明为内联&#xff0c;意…

解决secureCRT乱码设置UTF-8显示中文

永久性配置UTF-8 在SecureCRT的安装文件夹中搜索“Default.ini” 找到D:“Filenames Always Use UTF8”00000000&#xff0c;将最后的0变成1&#xff0c;即&#xff1a;D:“Filenames Always Use UTF8”00000001 将S:”Output Transformer Name”Default修改为S:”Output Tran…

如何使用 PHP Simple HTML DOM Parser 轻松获取网页中的特定数据

背景介绍 网页数据的抓取已经成为数据分析、市场调研等领域的重要工具。无论是获取产品价格、用户评论还是其他公开数据&#xff0c;网页抓取技术都能提供极大的帮助。今天&#xff0c;我们将探讨如何使用 PHP Simple HTML DOM Parser 轻松获取网页中的特定数据。PHP Simple H…

SPSSAU | 最好最差权重BWM原理及案例实操分析

BWM&#xff08;best-worse-method&#xff0c;最好最差法&#xff09;是一种多准则决策方法&#xff0c;由Jafar Rezaei于2015年提出&#xff0c;其通常用于确定决策标准的权重。其原理是比如5个指标&#xff0c;如果以前AHP就需要5个指标两两的相对重要性数据。但是现在简化为…

CSS实现文本溢出处理

1.单行文本溢出 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-wid…

如何利用DFMEA优化产品设计?

在快节奏的产品开发周期中&#xff0c;DFMEA如同一双锐利的眼睛&#xff0c;帮助团队在设计初期就识别并预防潜在的问题。它不仅仅是一种分析方法&#xff0c;更是一种系统化的思维工具&#xff0c;通过深入分析每个设计元素可能发生的失效模式、原因、影响及严重程度&#xff…