当前位置: 首页 > news >正文

基于STM32的轻量级Web服务器设计

文章目录

  • 一、前言
    • 1.1 开发背景
    • 1.2 实现的功能
    • 1.3 硬件模块组成
    • 1.4 ENC28J60网卡介绍
    • 1.5 UIP协议栈
      • 【1】目标与特点
      • 【2】核心组件
      • 【3】应用与优势
    • 1.6 添加UIP协议栈实现创建WEB服务器步骤
    • 1.7 ENC28J60添加UIP协议栈实现创建WEB客户端
    • 1.8 ENC28J60移植UIP协议并编写服务器测试示例
    • 1.9 ENC28J60移植UIP协议并编写客户端测试示例
  • 二、硬件设计
    • 2.1 接线说明
      • 【1】ENC28J60接线
      • 【2】LED灯接线
      • 【3】蜂鸣器接线
      • 【4】DS18B20接线
    • 2.2 代码与服务器交互的控制
    • 2.3 修改网页的页面
    • 2.4 设置网卡地址
    • 2.5 程序运行效果
      • 【1】下载程序
      • 【2】串口看效果
      • 【3】ping板子IP地址
      • 【4】打开网页看效果
    • 2.6 ENC28J60驱动代码

一、前言

1.1 开发背景

本项目的目的是构建一个基于STM32F103ZET6微控制器的嵌入式Web服务器,以满足远程监控和控制嵌入式设备的需求。随着物联网技术的快速发展,远程监控和控制嵌入式设备变得越来越重要。本项目通过选择STM32F103ZET6作为主控芯片,结合ENC28J60网卡实现网络通信,并移植UIP协议栈来构建轻量级的Web服务器。项目还集成了DS18B20温度传感器、LED灯模块和高电平触发的有源蜂鸣器,以实现远程监控和控制STM32设备端的功能,如LED灯和蜂鸣器的控制,以及设备端温度和RTC时间的显示。这种设计使得用户能够通过浏览器访问服务器,实时查看和控制嵌入式设备,为物联网应用提供了一种灵活、高效的解决方案。

image-20240530155757078

1.2 实现的功能

(1)网络通信搭建:通过STM32F103ZET6微控制器与ENC28J60以太网控制器的集成,利用SPI接口实现数据传输,成功移植UIP轻量级TCP/IP协议栈,从而在嵌入式平台上搭建起一个功能完备的Web服务器。

(2)网页服务:在STM32内部存储一个简易的网页文件,该网页设计用于用户界面展示及交互。当用户使用任何标准的Web浏览器访问此服务器的IP地址时,即可加载并显示该网页内容。

(3)远程控制功能

  • LED灯控制:网页上设有控制按钮或界面元素,允许用户远程开关连接到STM32的LED灯模块,实现远程照明控制演示。
  • 蜂鸣器控制:同样通过网页界面,用户能激活或关闭STM32连接的高电平触发的有源蜂鸣器,完成远程报警或信号提示功能的测试。

(4)环境监测与显示

  • 温度监控:集成DS18B20数字温度传感器,周期性采集环境温度数据,并通过Web界面实时显示给用户,提供基本的环境监测能力。
  • 实时时钟显示:利用STM32内置的RTC(实时时钟)模块,获取并准确显示当前的时间信息,增强系统的实用性和用户交互体验。

项目不仅实现了从硬件选型、网络配置到软件开发的全过程,还展示了物联网技术在实际应用中的一个小而完整的案例,即通过简单的Web界面远程监控和控制物理设备,体现了STM32平台在物联网领域的灵活性与强大功能。

1.3 硬件模块组成

(1)主控制器模块

  • STM32F103ZET6微控制器:作为系统的核心处理器,负责运行控制程序、管理外设通信、处理网络数据包及执行用户指令。它拥有丰富的外设资源,如SPI、USART、I2C等,支持高速运算和低功耗操作,是实现项目功能的基础。

(2)网络通信模块

  • ENC28J60以太网控制器:通过SPI接口与STM32连接,提供物理层和数据链路层的网络功能,实现与外部网络的连接。它是项目中实现Web服务器功能的关键组件,支持以太网数据包的收发,使嵌入式设备能够接入互联网。

(3)温度监测模块

  • DS18B20数字温度传感器:通过单总线(One-Wire)接口与STM32通信,用于精确测量环境温度。该传感器具有体积小、精度高、直接数字输出等特点,非常适合嵌入式系统中的温度监控应用。

(4)输出控制模块

  • LED灯模块:作为基本的输出设备,通过GPIO(通用输入输出端口)直接由STM32控制,用于响应用户的控制命令,如点亮或熄灭,以直观展示控制效果。
  • 有源蜂鸣器:通过高电平触发的方式连接至STM32的一个GPIO引脚,根据控制信号产生声音,实现报警或状态反馈功能。

(5)电源模块:为确保所有硬件组件稳定工作,需要一个合适的电源供应模块,为STM32微控制器、ENC28J60网卡、传感器及外围电路提供稳定的电压和电流。

1.4 ENC28J60网卡介绍

ENC28J60是一款集成MAC(Media Access Control,媒体访问控制)和10BASE-T PHY(物理层)的以太网控制器,特别适合于嵌入式系统和微控制器应用。

以下是ENC28J60网卡的一些关键特性与介绍:

(1)接口类型:它使用SPI(Serial Peripheral Interface,串行外设接口)作为与外部微控制器通信的主要方式,这使得它能够以较少的引脚数(通常为4或5条线)与诸如STM32、Arduino等微控制器连接,降低了硬件设计的复杂度。

(2)兼容性:ENC28J60兼容IEEE 802.3标准,这意味着它可以无缝地融入标准以太网网络环境中。它支持10Mbps的传输速率,适用于不需要高速网络连接的应用场景。

(3)集成功能:除了MAC和PHY层之外,ENC28J60还集成了其他一些功能,如缓冲区管理、DMA(Direct Memory Access,直接内存访问)支持、以及对多种网络帧类型的支持,包括广播、多播和单播。

(4)网络功能:能够实现完整的以太网数据包的发送和接收,支持IP、TCP、UDP等网络协议栈。开发者通常会结合LwIP(Lightweight IP)这样的轻量级TCP/IP协议栈来实现网络通信。

(5)物理层特性:支持10BASE-T标准,可以通过RJ45接口连接双绞线(UTP),支持自动极性和交叉检测,可工作在全双工或半双工模式下。

(6)功耗与封装:ENC28J60设计考虑到了低功耗应用的需求,适合电池供电设备。它通常采用SSOP(Shrink Small Outline Package)或QFN(Quad Flat No-Leads)等小型封装形式,便于在空间受限的设计中使用。

(7)灵活性与应用:由于其SPI接口和相对较低的成本,ENC28J60被广泛应用于各种嵌入式项目中,如物联网设备、智能家居、工业控制、远程监控系统等。

ENC28J60以其集成度高、接口灵活、成本效益好等特点,成为了许多嵌入式系统设计中实现网络连接的优选解决方案。

1.5 UIP协议栈

UIP(Micro IP)协议栈是一种专门为资源受限的嵌入式系统设计的轻量级TCP/IP协议栈。它最初由Adam Dunkels在SICS(瑞典计算机科学研究所)开发,目的是使即便是8位微控制器也能轻松实现网络通信,而不必负担全尺寸TCP/IP协议栈的开销。下面是UIP协议栈的详细介绍:

【1】目标与特点

  • 轻量化设计:UIP的核心目标是在保持TCP/IP协议核心功能的同时,尽可能减小代码大小和内存占用。其代码量通常仅为几千字节,RAM消耗最低可达几百字节,这使得它非常适合于微控制器等资源有限的环境。

  • 事件驱动编程:UIP采用了事件驱动的编程模型,而不是基于多线程或中断驱动的方法。这种设计减少了对内存的需求,并且简化了程序逻辑,使得协议栈更加易于理解和维护。

  • 协议支持:尽管精简,UIP仍实现了网络层(IP)、网络互联层(ARP)、传输层(TCP)和部分应用层(如ICMP ping)的基本功能。它还支持UDP,尽管可能不如TCP那样全面。对于不常用的TCP/IP特性,如窗口缩放、时间戳等,则被省略以减少资源消耗。

  • 无操作系统依赖:UIP设计为可以在“裸机”环境下运行,即不需要操作系统的支持,这使得它非常灵活,可以部署在各种嵌入式平台上。

【2】核心组件

  • IP层:负责数据包的路由和分片重组,实现基本的网络层功能。
  • ARP层:地址解析协议,用于将IP地址转换为MAC地址,确保数据包能够正确送达物理网络层。
  • ICMP层:因特网控制消息协议,主要用于网络诊断,如ping命令的实现。
  • TCP层:传输控制协议,用于建立可靠的、面向连接的数据传输服务,尽管在UIP中进行了大幅简化以适应嵌入式环境。
  • 内存管理:由于嵌入式系统内存资源有限,UIP实现了高效的内存块管理和缓冲区分配机制。

【3】应用与优势

  • 应用广泛:UIP被广泛应用于物联网设备、智能家居、传感器网络、嵌入式Web服务器等场景。
  • 易于移植:由于其代码结构清晰、依赖少,UIP很容易被移植到不同的微控制器平台上。
  • 资源效率:在保证基本网络功能的同时,极大地节省了系统资源,使得低成本、低功耗的设备也能实现网络连接。

1.6 添加UIP协议栈实现创建WEB服务器步骤

img

img

img

img

img

img

img

1.7 ENC28J60添加UIP协议栈实现创建WEB客户端

img

img

img

img

img

1.8 ENC28J60移植UIP协议并编写服务器测试示例

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

1.9 ENC28J60移植UIP协议并编写客户端测试示例

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

二、硬件设计

2.1 接线说明

【1】ENC28J60接线

image-20240415233409988

【2】LED灯接线

image-20240415233516888

【3】蜂鸣器接线

image-20240415233530012

【4】DS18B20接线

image-20240415233547945

2.2 代码与服务器交互的控制

这是判断网页下发的请求。

image-20240415233906046

image-20240415233845331

2.3 修改网页的页面

这个是写好的网页模版:

image-20240415233956201

代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WEB服务器设计</title>
<style>.LED{margin-left: 10px;}.font{font-size:30px;width:130px;height:60px;}.LED:hover{background: red;}.LED value{background: blue;}
</style>
</head>
<body><div style="border:1px solid black;text-align: center;width:600px;height:500px;margin:auto;"><h1>基于STM32的WEB服务器设计</h1><h1>微信公众号:DS小龙哥嵌入式技术资讯</h1><h1>这是基于ENC28J60+UIP协议栈设计的WEB服务器</h1><div class="paren_LED "><button class="LED font" v="on1" num = "1">LED1</button><button class="LED font" v="on2" num = "2">LED2</button><button class="LED font" v="on3" num = "3">LED3</button><button class="LED font" v="on4" num = "4">LED4</button><button class="LED font" v="on5" num = "5" style="display: block;margin-left:23px;margin-top:5px;">蜂鸣器</button></div><div style="text-align: left;"><span class="font" style="margin-left:22px">温度:</span><input style="font-size: 30px" value="23℃" id="wendu"/></div><div style="text-align: left;"><span class="font" style="margin-left:22px">时间:</span><input style="font-size: 30px" value="1s" id="time"/></div></div><script>var LED = document.getElementsByClassName("paren_LED")[0];var wendu = document.getElementById("wendu");var time = document.getElementById("time");var xhr = new XMLHttpRequest();var xhr2 = new XMLHttpRequest();//控制灯的按钮LED.onclick = function(e){var status = e.target.getAttribute("v");var paren_LED = LED.children;xhr.open("GET","test?data="+status,true);//xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");xhr.send();xhr.onreadystatechange = function () {if(xhr.readyState==4&&xhr.status==200){//获取后台的数据var data = xhr.responseText;var sta = e.target.getAttribute("num");e.target.setAttribute("v",data+sta);for(var i=0;i<paren_LED.length;i++){var str = paren_LED[i].getAttribute("v");var st = str.substring(0,str.length-1);if("off"==st){paren_LED[i].style.background="blue";}else if("on"==st){paren_LED[i].style.background="";}else if("Beep_on"==st){paren_LED[i].style.background="";}else if("Beep_off"==st){paren_LED[i].style.background="blue";}}}}}//定时器var wd =  function(){xhr2.open("GET","test?data=temp",true);xhr2.send();xhr2.onreadystatechange = function () {var data = xhr2.responseText.split("&"); wendu.value= data[0]+"℃";time.value = data[1]+"s";}};setInterval("wd()",1000);</script>
</body>
</html>

将这个文件转为C语言数组放到单片机代码工程里就行了。

如何转换? 用winhex 这个工具。

image-20240415234141048

替换这个数组就行了:

image-20240415234221592

2.4 设置网卡地址

因为板子是静态IP,为了方便通信,ENC28J60通过网线直接与电脑网口连接。 设置固定的IP地址。

image-20240415234301652

2.5 程序运行效果

【1】下载程序

image-20240415234504402

【2】串口看效果

image-20240415234520817

【3】ping板子IP地址

image-20240415234420460

【4】打开网页看效果

image-20240415234546440

2.6 ENC28J60驱动代码

#include "delay.h"
#include <stdio.h>
#include "enc28j60.h"	/*
以下是ENC28J60驱动移植接口:
MISO--->PA6----主机输入
MOSI--->PA7----主机输出
SCLK--->PA5----时钟信号
CS----->PA4----片选
RESET-->PG15---复位
*/
#define ENC28J60_CS		PAout(4) 	//ENC28J60片选信号
#define ENC28J60_RST	PGout(15)	//ENC28J60复位信号
#define ENC28J60_MOSI PAout(7)  //输出
#define ENC28J60_MISO PAin(6)   //输入
#define ENC28J60_SCLK PAout(5)  //时钟线static u8 ENC28J60BANK;
static u32 NextPacketPtr;/*
函数功能:底层SPI接口收发一个字节
说    明:模拟SPI时序,ENC28J60时钟线空闲电平为低电平,在第一个下降沿采集数据
*/
u8 ENC28J60_SPI_ReadWriteOneByte(u8 tx_data)
{u16 cnt=0;				 while((SPI1->SR&1<<1)==0)		 //等待发送区空--等待发送缓冲为空	{cnt++;if(cnt>=65530)return 0; 	  //超时退出  u16=2个字节}	SPI1->DR=tx_data;	 	  		      //发送一个byte cnt=0;while((SPI1->SR&1<<0)==0) 		//等待接收完一个byte   {cnt++;if(cnt>=65530)return 0;	   //超时退出}	  						    return SPI1->DR;          		//返回收到的数据				
}/*
函数功能:复位ENC28J60,包括SPI初始化/IO初始化等
MISO--->PA6----主机输入
MOSI--->PA7----主机输出
SCLK--->PA5----时钟信号
CS----->PA4----片选
RESET-->PG15---复位
*/
void ENC28J60_Reset(void)
{
/*开启时钟*/RCC->APB2ENR|=1<<12;   //开启SPI1时钟RCC->APB2ENR|=1<<2;    //PAGPIOA->CRL&=0X0000FFFF; //清除寄存器GPIOA->CRL|=0XB8B30000;GPIOA->ODR|=0XF<<4; //   	上拉--输出高电平GPIOA->ODR&=~(1<<5);RCC->APB2ENR|=1<<8; //2 3 4 5 6 7 8GPIOG->CRH&=0x0FFFFFFF;GPIOG->CRH|=0x30000000;/*SPI2基本配置*/SPI1->CR1=0X0; 		//清空寄存器SPI1->CR1|=0<<15; //选择“双线双向”模式SPI1->CR1|=0<<11; //使用8位数据帧格式进行发送/接收;SPI1->CR1|=0<<10; //全双工(发送和接收);SPI1->CR1|=1<<9;  //启用软件从设备管理SPI1->CR1|=1<<8;  //NSSSPI1->CR1|=0<<7;  //帧格式,先发送高位SPI1->CR1|=0x1<<3;//当总线频率为36MHZ时,SPI速度为18MHZ,高速。SPI1->CR1|=1<<2;  //配置为主设备SPI1->CR1|=1<<1;  //空闲状态时, SCK保持高电平。SPI1->CR1|=1<<0;  //数据采样从第二个时钟边沿开始。SPI1->CR1|=1<<6;  //开启SPI设备。//针对ENC28J60的特点(SCK空闲为低电平)修改SPI的设置SPI1->CR1&=~(1<<6); 	//SPI设备失能SPI1->CR1&=~(1<<1); 	//空闲模式下SCK为0 CPOL=0SPI1->CR1&=~(1<<0); 	//数据采样从第1个时间边沿开始,CPHA=0  SPI1->CR1|=1<<6; 	  	//SPI设备使能ENC28J60_RST=0;			//复位ENC28J60DelayMs(10);	 ENC28J60_RST=1;			//复位结束				    DelayMs(10);	  
}/*
函数功能:读取ENC28J60寄存器(带操作码) 
参	  数:op:操作码addr:寄存器地址/参数
返 回 值:读到的数据
*/
u8 ENC28J60_Read_Op(u8 op,u8 addr)
{u8 dat=0;	 ENC28J60_CS=0;	 dat=op|(addr&ADDR_MASK);ENC28J60_SPI_ReadWriteOneByte(dat);dat=ENC28J60_SPI_ReadWriteOneByte(0xFF);//如果是读取MAC/MII寄存器,则第二次读到的数据才是正确的,见手册29页if(addr&0x80)dat=ENC28J60_SPI_ReadWriteOneByte(0xFF);ENC28J60_CS=1;return dat;
}/*
函数功能:读取ENC28J60寄存器(带操作码) 
参    数:op:操作码addr:寄存器地址data:参数
*/
void ENC28J60_Write_Op(u8 op,u8 addr,u8 data)
{u8 dat = 0;	    ENC28J60_CS=0;			   dat=op|(addr&ADDR_MASK);ENC28J60_SPI_ReadWriteOneByte(dat);	  ENC28J60_SPI_ReadWriteOneByte(data);ENC28J60_CS=1;
}/*
函数功能:读取ENC28J60接收缓存数据
参    数:len:要读取的数据长度data:输出数据缓存区(末尾自动添加结束符)
*/
void ENC28J60_Read_Buf(u32 len,u8* data)
{ENC28J60_CS=0;			 ENC28J60_SPI_ReadWriteOneByte(ENC28J60_READ_BUF_MEM);while(len){len--;			  *data=(u8)ENC28J60_SPI_ReadWriteOneByte(0);data++;}*data='\0';ENC28J60_CS=1;
}/*
函数功能:向ENC28J60写发送缓存数据
参    数:len:要写入的数据长度data:数据缓存区
*/
void ENC28J60_Write_Buf(u32 len,u8* data)
{ENC28J60_CS=0;			   ENC28J60_SPI_ReadWriteOneByte(ENC28J60_WRITE_BUF_MEM);		 while(len){len--;ENC28J60_SPI_ReadWriteOneByte(*data);data++;}ENC28J60_CS=1;
}/*
函数功能:设置ENC28J60寄存器Bank
参    数:ban:要设置的bank
*/
void ENC28J60_Set_Bank(u8 bank)
{								    if((bank&BANK_MASK)!=ENC28J60BANK)//和当前bank不一致的时候,才设置{				  ENC28J60_Write_Op(ENC28J60_BIT_FIELD_CLR,ECON1,(ECON1_BSEL1|ECON1_BSEL0));ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,ECON1,(bank&BANK_MASK)>>5);ENC28J60BANK=(bank&BANK_MASK);}
}/*
函数功能:读取ENC28J60指定寄存器
参    数:addr:寄存器地址
返 回 值:读到的数据
*/
u8 ENC28J60_Read(u8 addr)
{						  ENC28J60_Set_Bank(addr);//设置BANK		 return ENC28J60_Read_Op(ENC28J60_READ_CTRL_REG,addr);
}/*
函数功能:向ENC28J60指定寄存器写数据
参    数:addr:寄存器地址data:要写入的数据		
*/
void ENC28J60_Write(u8 addr,u8 data)
{					  ENC28J60_Set_Bank(addr);		 ENC28J60_Write_Op(ENC28J60_WRITE_CTRL_REG,addr,data);
}/*
函数功能:向ENC28J60的PHY寄存器写入数据
参    数:addr:寄存器地址data:要写入的数据	
*/
void ENC28J60_PHY_Write(u8 addr,u32 data)
{u16 retry=0;ENC28J60_Write(MIREGADR,addr);	//设置PHY寄存器地址ENC28J60_Write(MIWRL,data);		//写入数据ENC28J60_Write(MIWRH,data>>8);		   while((ENC28J60_Read(MISTAT)&MISTAT_BUSY)&&retry<0XFFF)retry++;//等待写入PHY结束		  
}/*
函数功能:初始化ENC28J60
参    数:macaddr:MAC地址
返 回 值:0,初始化成功;1,初始化失败;
*/
u8 ENC28J60_Init(u8* macaddr)
{		u16 retry=0;		  ENC28J60_Reset(); //复位底层引脚接口ENC28J60_Write_Op(ENC28J60_SOFT_RESET,0,ENC28J60_SOFT_RESET);//软件复位while(!(ENC28J60_Read(ESTAT)&ESTAT_CLKRDY)&&retry<500)//等待时钟稳定{retry++;DelayMs(1);};if(retry>=500)return 1;//ENC28J60初始化失败// do bank 0 stuff// initialize receive buffer// 16-bit transfers,must write low byte first// set receive buffer start address	   设置接收缓冲区地址  8K字节容量NextPacketPtr=RXSTART_INIT;// Rx start//接收缓冲器由一个硬件管理的循环FIFO 缓冲器构成。//寄存器对ERXSTH:ERXSTL 和ERXNDH:ERXNDL 作//为指针,定义缓冲器的容量和其在存储器中的位置。//ERXST和ERXND指向的字节均包含在FIFO缓冲器内。//当从以太网接口接收数据字节时,这些字节被顺序写入//接收缓冲器。 但是当写入由ERXND 指向的存储单元//后,硬件会自动将接收的下一字节写入由ERXST 指向//的存储单元。 因此接收硬件将不会写入FIFO 以外的单//元。//设置接收起始字节ENC28J60_Write(ERXSTL,RXSTART_INIT&0xFF);	ENC28J60_Write(ERXSTH,RXSTART_INIT>>8);	  //ERXWRPTH:ERXWRPTL 寄存器定义硬件向FIFO 中//的哪个位置写入其接收到的字节。 指针是只读的,在成//功接收到一个数据包后,硬件会自动更新指针。 指针可//用于判断FIFO 内剩余空间的大小  8K-1500。 //设置接收读指针字节ENC28J60_Write(ERXRDPTL,RXSTART_INIT&0xFF);ENC28J60_Write(ERXRDPTH,RXSTART_INIT>>8);//设置接收结束字节ENC28J60_Write(ERXNDL,RXSTOP_INIT&0xFF);ENC28J60_Write(ERXNDH,RXSTOP_INIT>>8);//设置发送起始字节ENC28J60_Write(ETXSTL,TXSTART_INIT&0xFF);ENC28J60_Write(ETXSTH,TXSTART_INIT>>8);//设置发送结束字节ENC28J60_Write(ETXNDL,TXSTOP_INIT&0xFF);ENC28J60_Write(ETXNDH,TXSTOP_INIT>>8);// do bank 1 stuff,packet filter:// For broadcast packets we allow only ARP packtets// All other packets should be unicast only for our mac (MAADR)//// The pattern to match on is therefore// Type     ETH.DST// ARP      BROADCAST// 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9// in binary these poitions are:11 0000 0011 1111// This is hex 303F->EPMM0=0x3f,EPMM1=0x30//接收过滤器//UCEN:单播过滤器使能位//当ANDOR = 1 时://1 = 目标地址与本地MAC 地址不匹配的数据包将被丢弃//0 = 禁止过滤器//当ANDOR = 0 时://1 = 目标地址与本地MAC 地址匹配的数据包会被接受//0 = 禁止过滤器//CRCEN:后过滤器CRC 校验使能位//1 = 所有CRC 无效的数据包都将被丢弃//0 = 不考虑CRC 是否有效//PMEN:格式匹配过滤器使能位//当ANDOR = 1 时://1 = 数据包必须符合格式匹配条件,否则将被丢弃//0 = 禁止过滤器//当ANDOR = 0 时://1 = 符合格式匹配条件的数据包将被接受//0 = 禁止过滤器ENC28J60_Write(ERXFCON,ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN);ENC28J60_Write(EPMM0,0x3f);ENC28J60_Write(EPMM1,0x30);ENC28J60_Write(EPMCSL,0xf9);ENC28J60_Write(EPMCSH,0xf7);// do bank 2 stuff// enable MAC receive//bit 0 MARXEN:MAC 接收使能位//1 = 允许MAC 接收数据包//0 = 禁止数据包接收//bit 3 TXPAUS:暂停控制帧发送使能位//1 = 允许MAC 发送暂停控制帧(用于全双工模式下的流量控制)//0 = 禁止暂停帧发送//bit 2 RXPAUS:暂停控制帧接收使能位//1 = 当接收到暂停控制帧时,禁止发送(正常操作)//0 = 忽略接收到的暂停控制帧ENC28J60_Write(MACON1,MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);// bring MAC out of reset//将MACON2 中的MARST 位清零,使MAC 退出复位状态。ENC28J60_Write(MACON2,0x00);// enable automatic padding to 60bytes and CRC operations//bit 7-5 PADCFG2:PACDFG0:自动填充和CRC 配置位//111 = 用0 填充所有短帧至64 字节长,并追加一个有效的CRC//110 = 不自动填充短帧//101 = MAC 自动检测具有8100h 类型字段的VLAN 协议帧,并自动填充到64 字节长。如果不//是VLAN 帧,则填充至60 字节长。填充后还要追加一个有效的CRC//100 = 不自动填充短帧//011 = 用0 填充所有短帧至64 字节长,并追加一个有效的CRC//010 = 不自动填充短帧//001 = 用0 填充所有短帧至60 字节长,并追加一个有效的CRC//000 = 不自动填充短帧//bit 4 TXCRCEN:发送CRC 使能位//1 = 不管PADCFG如何,MAC都会在发送帧的末尾追加一个有效的CRC。 如果PADCFG规定要//追加有效的CRC,则必须将TXCRCEN 置1。//0 = MAC不会追加CRC。 检查最后4 个字节,如果不是有效的CRC 则报告给发送状态向量。//bit 0 FULDPX:MAC 全双工使能位//1 = MAC工作在全双工模式下。 PHCON1.PDPXMD 位必须置1。//0 = MAC工作在半双工模式下。 PHCON1.PDPXMD 位必须清零。ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,MACON3,MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN|MACON3_FULDPX);// set inter-frame gap (non-back-to-back)//配置非背对背包间间隔寄存器的低字节//MAIPGL。 大多数应用使用12h 编程该寄存器。//如果使用半双工模式,应编程非背对背包间间隔//寄存器的高字节MAIPGH。 大多数应用使用0Ch//编程该寄存器。ENC28J60_Write(MAIPGL,0x12);ENC28J60_Write(MAIPGH,0x0C);// set inter-frame gap (back-to-back)//配置背对背包间间隔寄存器MABBIPG。当使用//全双工模式时,大多数应用使用15h 编程该寄存//器,而使用半双工模式时则使用12h 进行编程。ENC28J60_Write(MABBIPG,0x15);// Set the maximum packet size which the controller will accept// Do not send packets longer than MAX_FRAMELEN:// 最大帧长度  1500ENC28J60_Write(MAMXFLL,MAX_FRAMELEN&0xFF);	ENC28J60_Write(MAMXFLH,MAX_FRAMELEN>>8);// do bank 3 stuff// write MAC address// NOTE: MAC address in ENC28J60 is byte-backward//设置MAC地址ENC28J60_Write(MAADR5,macaddr[0]);	ENC28J60_Write(MAADR4,macaddr[1]);ENC28J60_Write(MAADR3,macaddr[2]);ENC28J60_Write(MAADR2,macaddr[3]);ENC28J60_Write(MAADR1,macaddr[4]);ENC28J60_Write(MAADR0,macaddr[5]);//配置PHY为全双工  LEDB为拉电流ENC28J60_PHY_Write(PHCON1,PHCON1_PDPXMD);	 // no loopback of transmitted frames	 禁止环回//HDLDIS:PHY 半双工环回禁止位//当PHCON1.PDPXMD = 1 或PHCON1.PLOOPBK = 1 时://此位可被忽略。//当PHCON1.PDPXMD = 0 且PHCON1.PLOOPBK = 0 时://1 = 要发送的数据仅通过双绞线接口发出//0 = 要发送的数据会环回到MAC 并通过双绞线接口发出ENC28J60_PHY_Write(PHCON2,PHCON2_HDLDIS);// switch to bank 0//ECON1 寄存器//寄存器3-1 所示为ECON1 寄存器,它用于控制//ENC28J60 的主要功能。 ECON1 中包含接收使能、发//送请求、DMA 控制和存储区选择位。	   ENC28J60_Set_Bank(ECON1);// enable interrutps//EIE: 以太网中断允许寄存器//bit 7 INTIE: 全局INT 中断允许位//1 = 允许中断事件驱动INT 引脚//0 = 禁止所有INT 引脚的活动(引脚始终被驱动为高电平)//bit 6 PKTIE: 接收数据包待处理中断允许位//1 = 允许接收数据包待处理中断//0 = 禁止接收数据包待处理中断ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,EIE,EIE_INTIE|EIE_PKTIE);// enable packet reception//bit 2 RXEN:接收使能位//1 = 通过当前过滤器的数据包将被写入接收缓冲器//0 = 忽略所有接收的数据包ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,ECON1,ECON1_RXEN);if(ENC28J60_Read(MAADR5)== macaddr[0])return 0;//初始化成功else return 1; 	  }/*
函数功能:读取EREVID
参    数:
*/
u8 ENC28J60_Get_EREVID(void)
{//在EREVID 内也存储了版本信息。 EREVID 是一个只读控//制寄存器,包含一个5 位标识符,用来标识器件特定硅片//的版本号return ENC28J60_Read(EREVID);
}/*
函数功能:通过ENC28J60发送数据包到网络
参    数:len   :数据包大小packet:数据包
*/
void ENC28J60_Packet_Send(u32 len,u8* packet)
{//设置发送缓冲区地址写指针入口ENC28J60_Write(EWRPTL,TXSTART_INIT&0xFF);ENC28J60_Write(EWRPTH,TXSTART_INIT>>8);//设置TXND指针,以对应给定的数据包大小	   ENC28J60_Write(ETXNDL,(TXSTART_INIT+len)&0xFF);ENC28J60_Write(ETXNDH,(TXSTART_INIT+len)>>8);//写每包控制字节(0x00表示使用macon3的设置) ENC28J60_Write_Op(ENC28J60_WRITE_BUF_MEM,0,0x00);//复制数据包到发送缓冲区//printf("len:%d\r\n",len);	//监视发送数据长度ENC28J60_Write_Buf(len,packet);//发送数据到网络ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,ECON1,ECON1_TXRTS);//复位发送逻辑的问题。参见Rev. B4 Silicon Errata point 12.if((ENC28J60_Read(EIR)&EIR_TXERIF))ENC28J60_Write_Op(ENC28J60_BIT_FIELD_CLR,ECON1,ECON1_TXRTS);
}/*
函数功能:从网络获取一个数据包内容
函数参数:maxlen:数据包最大允许接收长度packet:数据包缓存区
返 回 值:收到的数据包长度(字节)	
*/
u32 ENC28J60_Packet_Receive(u32 maxlen,u8* packet)
{u32 rxstat;u32 len;    													 if(ENC28J60_Read(EPKTCNT)==0)return 0;  //是否收到数据包?	   //设置接收缓冲器读指针ENC28J60_Write(ERDPTL,(NextPacketPtr));ENC28J60_Write(ERDPTH,(NextPacketPtr)>>8);	   // 读下一个包的指针NextPacketPtr=ENC28J60_Read_Op(ENC28J60_READ_BUF_MEM,0);NextPacketPtr|=ENC28J60_Read_Op(ENC28J60_READ_BUF_MEM,0)<<8;//读包的长度len=ENC28J60_Read_Op(ENC28J60_READ_BUF_MEM,0);len|=ENC28J60_Read_Op(ENC28J60_READ_BUF_MEM,0)<<8;len-=4; //去掉CRC计数//读取接收状态rxstat=ENC28J60_Read_Op(ENC28J60_READ_BUF_MEM,0);rxstat|=ENC28J60_Read_Op(ENC28J60_READ_BUF_MEM,0)<<8;//限制接收长度	if (len>maxlen-1)len=maxlen-1;	//检查CRC和符号错误// ERXFCON.CRCEN为默认设置,一般我们不需要检查.if((rxstat&0x80)==0)len=0;//无效else ENC28J60_Read_Buf(len,packet);//从接收缓冲器中复制数据包	    //RX读指针移动到下一个接收到的数据包的开始位置 //并释放我们刚才读出过的内存ENC28J60_Write(ERXRDPTL,(NextPacketPtr));ENC28J60_Write(ERXRDPTH,(NextPacketPtr)>>8);//递减数据包计数器标志我们已经得到了这个包 ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,ECON2,ECON2_PKTDEC);return(len);
}

相关文章:

基于STM32的轻量级Web服务器设计

文章目录 一、前言1.1 开发背景1.2 实现的功能1.3 硬件模块组成1.4 ENC28J60网卡介绍1.5 UIP协议栈【1】目标与特点【2】核心组件【3】应用与优势 1.6 添加UIP协议栈实现创建WEB服务器步骤1.7 ENC28J60添加UIP协议栈实现创建WEB客户端1.8 ENC28J60移植UIP协议并编写服务器测试示…...

用r语言处理 Excel数据当中的缺失值方法

以下是使用 R 编程语言处理 Excel 缺失数据的一些常见方法示例代码&#xff1a;&#xff08;无需循环&#xff09; 读取包含缺失数据的 Excel 文件 data <- read.csv(“your_file.csv”) 查看数据中是否有缺失值 sum(is.na(data)) 用平均值填充缺失值 data c o l u m …...

AWS 高防和阿里云高防深度对比

随着网络攻击的不断增加&#xff0c;企业对于网络安全的需求也越来越高。在这种情况下&#xff0c;高防护服务成为了企业网络安全的重要组成部分。AWS和阿里云作为全球领先的云计算服务提供商&#xff0c;都提供了高防护服务&#xff0c;但它们之间存在着一些差异。我们九河云一…...

ctfshow web 月饼杯II

web签到 <?php //Author:H3h3QAQ include "flag.php"; highlight_file(__FILE__); error_reporting(0); if (isset($_GET["YBB"])) {if (hash("md5", $_GET["YBB"]) $_GET["YBB"]) {echo "小伙子不错嘛&#xff…...

「前端+鸿蒙」核心技术HTML5+CSS3(二)

1、开发者文档 开发者文档通常由浏览器厂商或技术社区提供,包含有关Web技术(如HTML、CSS、JavaScript)的详细信息,API文档,以及最佳实践。例如,MDN Web Docs是一个广泛认可的开发者资源。 2、块级元素与行列元素 块级元素:在页面上占据整行的元素,如<div>、<…...

unity接入live2d

在bilibili上找到一个教程&#xff0c;首先注意一点&#xff0c;你直接导入那个sdk&#xff0c;并且打开示例&#xff0c;显示的模型是有问题的&#xff0c;你需要调整模型上脚本的一个枚举值&#xff0c;调整它的渲染顺序是front z to我看教程时候&#xff0c;很多老师都没有提…...

练习题-17

以下题目来自2024年5月清华大学“丘成桐数学科学领军计划数学水平考试”。第11题本人参考了网友Fiddie (数学兔的极大理想&#xff09;的解答&#xff0c;原网址是 https://mp.weixin.qq.com/s/q9slRWL4iO_TcSdkmbfbbw. 第10题&#xff1a;在10维列向量构成的内积空间 V V V中…...

乐高小人分类项目

数据来源 LEGO Minifigures | Kaggle 建立文件目录 BASE_DIR lego/star-wars-images/ names [YODA, LUKE SKYWALKER, R2-D2, MACE WINDU, GENERAL GRIEVOUS ] tf.random.set_seed(1)# Read information about dataset if not os.path.isdir(BASE_DIR train/):for name in …...

个人关于ChatGPT的用法及建议

概述 这里只是个人常用的几个软件&#xff0c;做一下汇总&#xff0c;希望对各位有用。 如果有更高认知的朋友&#xff0c;请留下你的工具名称&#xff0c;提醒我一下&#xff0c;谢谢&#xff5e; 常用的chatgpt模型工具&#xff1a; 以下是一些知名的例子&#xff1a; 文…...

神经网络的工程基础(二)——随机梯度下降法|文末送书

相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型&#xff1a;从线性回归到通用人工智能》&#xff0c;欢迎有兴趣的读者多多支持。 本文涉及到的代码链接如下&#xff1a;regression2chatgpt/ch06_optimizer/stochastic_gradient_descent.ipynb 本文将讨论利用…...

常见的几种编码方式

常见的编码方式及其特点&#xff1a; 编码方式的设计是为了适应不同的字符集和应用需求&#xff0c;因此它们在表示字符时使用的位数和字节数各不相同 常见编码方式及其位数和字节数 ASCII&#xff08;American Standard Code for Information Interchange&#xff09;&#x…...

ubuntu移动硬盘重命名

因为在ubuntu上移动硬盘的名字是中文的&#xff0c;所以想要改成英文的。 我的方法&#xff1a; 将移动硬盘插到windows上&#xff0c;直接右键重命名。再插到ubuntu上名字就改变了。 别人的方法&#xff1a; ubuntu下如何修改U盘名字-腾讯云开发者社区-腾讯云 在自带的软件…...

VUE框架前置知识总结

一、前言 在学习vue框架中&#xff0c;总是有些知识不是很熟悉&#xff0c;又不想系统的学习JS&#xff0c;因为学习成本太大了&#xff0c;所以用到什么知识就学习什么知识。此文档就用于记录零散的知识点。主要是还是针对与ES6规范的JS知识点。 以下实验环境都是在windows环…...

张宇1000题80%不会?别急,这个方法肯定有用!

这太正常了&#xff0c;1000题的难度本来就高&#xff0c;不要慌 我考研的时候跟的也是张宇老师&#xff0c;但是1000题我根本就没做几道题就给换成880题660题了&#xff0c;而且只是强化阶段用880题&#xff0c;基础阶段我用的都是汤家凤的1800题。 不要担心做的不是张宇老师…...

【python】爬虫记录每小时金价

数据来源&#xff1a; https://www.cngold.org/img_date/ 因为这个网站是数据随时变动的&#xff0c;用requests、BeautifulSoup的方式解析html的话&#xff0c;数据的位置显示的是“--”&#xff0c;并不能取到数据。 所以采用webdriver访问网站&#xff0c;然后从界面上获取…...

一行命令将已克隆的本地Git仓库推送到内网服务器

一、需求背景 我们公司用gitea搭建了一个git服务器&#xff0c;其中支持win7的最高版本是v1.20.6。 我们公司的电脑在任何时候都不能连接外网&#xff0c;但是希望将一些开源的仓库移植到内网的服务器来。一是有相关代码使用的需求&#xff0c;二是可以建设一个内网能够查阅的…...

Linux文本处理三剑客(详解)

一、文本三剑客是什么&#xff1f; 1. 对于接触过Linux操作系统的人来说&#xff0c;应该都听过说Linux中的文本三剑客吧&#xff0c;即awk、grep、sed&#xff0c;也是必须要掌握的Linux命令之一&#xff0c;三者都是用来处理文本的&#xff0c;但侧重点各不相同&#xff0c;a…...

AI在线UI代码生成,不需要敲一行代码,聊聊天,上传图片,就能生成前端页面的开发神器

ioDraw的在线UI代码生成器是一款开发神器&#xff0c;它可以让您在无需编写一行代码的情况下创建前端页面。 主要优势&#xff1a; 1、极简操作&#xff1a;只需聊天或上传图片&#xff0c;即可生成响应式的Tailwind CSS代码。 2、节省时间&#xff1a;自动生成代码可以节省大…...

go-zero整合单机版ClickHouse并实现增删改查

go-zero整合单机版ClickHouse并实现增删改查 本教程基于go-zero微服务入门教程&#xff0c;项目工程结构同上一个教程。 本教程主要实现go-zero框架整合单机版ClickHouse&#xff0c;并暴露接口实现对ClickHouse数据的增删改查。 go-zero微服务入门教程&#xff1a;https://b…...

行政工作如何提高效率?桌面备忘录便签软件哪个好

在行政管理工作中&#xff0c;效率的提高无疑是每个行政人员都追求的目标。而随着科技的发展&#xff0c;各种便捷的工具也应运而生&#xff0c;其中桌面备忘录便签软件便是其中的佼佼者。那么&#xff0c;这类软件又如何帮助我们提高工作效率呢&#xff1f; 首先&#xff0c;…...

利用向日葵和微信/腾讯会议实现LabVIEW远程开发

利用向日葵远程控制软件结合微信或腾讯会议的视频通话功能&#xff0c;可以实现LabVIEW的远程开发和调试。通过向日葵进行远程桌面访问&#xff0c;配合视频通话工具进行实时沟通与问题解决&#xff0c;不仅提高了开发效率&#xff0c;还减少了地域限制带来的不便。介绍这种远程…...

SpringBoot 单元测试 指定 环境

如上图所示&#xff0c;在配置窗口中添加--spring.profiles.activedev&#xff0c;就可以了。...

Flutter 中的 SliverOpacity 小部件:全面指南

Flutter 中的 SliverOpacity 小部件&#xff1a;全面指南 Flutter 是一个功能强大的 UI 框架&#xff0c;由 Google 开发&#xff0c;允许开发者使用 Dart 语言来构建高性能、美观的跨平台应用。在 Flutter 的滚动组件体系中&#xff0c;SliverOpacity 是一个用来为其子 Slive…...

源码分析の前言

源码分析路线图&#xff1a; 初级部分&#xff1a;ArrayList->LinkedList->Vector->HashMap(红黑树数据结构&#xff0c;如何翻转&#xff0c;变色&#xff0c;手写红黑树)->ConcurrentHashMap 中级部分&#xff1a;Spring->Spring MVC->Spring Boot->M…...

接口性能测试复盘:解决JMeter超时问题的实践

在优化接口并重新投入市场后&#xff0c;我们面临着一项关键任务&#xff1a;确保其在高压环境下稳定运行。于是&#xff0c;我们启动了一轮针对该接口的性能压力测试&#xff0c;利用JMeter工具模拟高负载场景。然而&#xff0c;在测试进行约一分钟之后&#xff0c;频繁出现了…...

[数据集][目标检测]猕猴桃检测数据集VOC+YOLO格式1838张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1838 标注数量(xml文件个数)&#xff1a;1838 标注数量(txt文件个数)&#xff1a;1838 标注…...

摸鱼大数据——Hive函数7-9

7、日期时间函数 Hive函数链接&#xff1a;LanguageManual UDF - Apache Hive - Apache Software Foundation SimpleDateFormat (Java Platform SE 8 ) current_timestamp: 获取时间原点到现在的秒/毫秒,底层自动转换方便查看的日期格式 常用 to_date: 字符串格式时间…...

python连接数据库

python连接MYSQL、postgres、oracle等的基本操作 python连接mysql MySQLdb MySQLdb又叫MySQL-python &#xff0c;是 Python 连接 MySQL 的一个驱动&#xff0c;很多框架都也是基于此库进行开发&#xff0c;只支持 Python2.x&#xff0c;而且安装的时候有很多前置条件&#…...

能不能接受这些坑?买电车前一定要看

图片来源&#xff1a;汽车之家 文 | Auto芯球 作者 | 雷慢 刚有个朋友告诉我&#xff0c;买了电车后感觉被骗了&#xff0c; 很多“坑”都是他买车后才知道的。 不提前研究&#xff0c;不做功课&#xff0c;放着我这个老司机不请教&#xff0c; 这个大冤种他不当谁当&…...

k8s中pod如何排错?

排除Kubernetes Pod故障通常涉及一系列步骤&#xff0c;以诊断问题并找到解决方案。以下是一些常见的故障排除方法&#xff1a; 检查Pod状态: 使用kubectl get pods查看Pod的状态。如果Pod没有处于Running状态&#xff0c;查看更详细的信息&#xff0c;使用kubectl describe …...

【手撕面试题】Vue(高频知识点二)

每天10道题&#xff0c;100天后&#xff0c;搞定所有前端面试的高频知识点&#xff0c;加油&#xff01;&#xff01;&#xff01;&#xff0c;在看文章的同时&#xff0c;希望不要直接看答案&#xff0c;先思考一下自己会不会&#xff0c;如果会&#xff0c;自己的答案是什么&…...

四、.Net8对接Ollama实现文字翻译(.Net8+SemanticKernel+Ollama)本地运行自己的大模型

.Net8SemanticKernelOllama 一、Semantic Kernel官方定义SK能做什么&#xff1f; 二、基本使用1、普通对话2、使用插件实现文本翻译功能 三、IChatCompletionService、ITextGenerationService、ITextEmbeddingGenerationService 很多情况都有这样的需求&#xff0c;使用自有系统…...

初始C++

感谢大佬的光临各位&#xff0c;希望和大家一起进步&#xff0c;望得到你的三连&#xff0c;互三支持&#xff0c;一起进步 个人主页&#xff1a;LaNzikinh-CSDN博客 文章目录 前言一.引用二.内联函数三.类和对象总结 前言 之前讲c的命令空间和第一个程序的运行&#xff0c;继…...

Chapter 5 Current Mirrors and Biasing Techniques

Chapter 5 Current Mirrors and Biasing Techniques 这一章介绍电流镜 5.1 Basic Current Mirrors MOS工作在饱和区, 表现为一个电流源. 考虑电源变化, PVT波动, 我们会首先产生一路精准电流源, 再复制这路电流. 如何复制呢? 电流转电压再转电流就行了, 如下图所示 考虑到…...

Avalonia Image控件上通过鼠标拖动画出矩形框

注册鼠标事件&#xff1a;首先&#xff0c;你需要注册 Image 控件上的鼠标事件&#xff0c;包括 PointerPressed、PointerMoved 和 PointerReleased。你可以在 XAML 文件或代码中注册这些事件。 <Image PointerPressed"Image_PointerPressed" PointerMoved"…...

Wireshark Lua插件入门

摘要 开发中经常通过抓包分析协议&#xff0c;对于常见的协议如 DNS wireshark 支持自动解析&#xff0c;便于人类的理解&#xff0c;对于一些私有协议&#xff0c;wireshark 提供了插件的方式自定义解析逻辑。 1 动手 废话少说&#xff0c;直接上手。 第一步当然是装上wiresh…...

XXE漏洞简介

目录 漏洞原理 漏洞危害 前置知识 XML简介 DTD简介 DTD的两种声明方式 实体 实体分类 内置实体(Built-inentities) 字符实体&#xff08;Characterentities&#xff09; 通用实体&#xff08;Generalentities&#xff09; 参数实体(Parameterentities) XXE漏洞…...

小白跟做江科大32单片机之蜂鸣器

1.复制之前编写的工程库项目&#xff0c;详细工程库创建过程如下链接&#xff1a; 小白跟做江科大32单片机之LED闪烁-CSDN博客https://blog.csdn.net/weixin_58051657/article/details/139295351?spm1001.2014.3001.55022.按照江科大老师给的图片进行连接蜂鸣器 接线时要用公…...

IsoBench:多模态基础模型性能的基准测试与优化

随着多模态基础模型的快速发展&#xff0c;如何准确评估这些模型在不同输入模态下的性能成为了一个重要课题。本文提出了IsoBench&#xff0c;一个基准数据集&#xff0c;旨在通过提供多种同构&#xff08;isomorphic&#xff09;表示形式的问题&#xff0c;来测试和评估多模态…...

MyEclipse使用教程

MyEclipse使用教程如下&#xff0c;按照以下步骤&#xff0c;您可以逐步熟悉并掌握MyEclipse的基本使用&#xff1a; 一、MyEclipse安装与准备 软件准备&#xff1a; 在使用MyEclipse之前&#xff0c;您需要确保已经安装了JDK&#xff08;Java Development Kit&#xff09;。J…...

TiDB学习9:Ti Cloud简介

目录 1. 为什么选择TiDB 2. 多租户 3. TiDB架构 4. 什么是TiDB Cloud 5. TiDB Cloud Provider Region 6. TiDB Cloud 入门 6.1 在浏览器中打开TiDB Cloud 6.2 创建您的账户 6.3 Developer Tier 与Dedicated Tier 6.3.1 Developer Tier 6.3.2 Dedicated Tier 6.3.2.…...

JavaScript 创建新节点的方法

在 JavaScript 中&#xff0c;可以使用 document.createElement() 方法来创建新的节点。该方法接受一个字符串参数&#xff0c;表示要创建的节点类型&#xff0c;如 "div"、"p" 等。 创建一个新节点的基本步骤如下&#xff1a; 使用 document.createElem…...

在phpstorm2024版里如何使用Jetbrains ai assistant 插件 ?

ai assistant激活成功后&#xff0c;如图 ai assistant渠道&#xff1a;https://web.52shizhan.cn/activity/ai-assistant 在去年五月份的 Google I/O 2023 上&#xff0c;Google 为 Android Studio 推出了 Studio Bot 功能&#xff0c;使用了谷歌编码基础模型 Codey,Codey 是…...

进程间通信(27000字超详解)

&#x1f30e;进程间通信 文章目录&#xff1a; 进程间通信 进程间通信简介       进程间通信目的       初识进程间通信       进程间通信的分类 匿名管道通信       认识管道       匿名管道       匿名管道测试       管道的四种…...

一、大模型推理

https://github.com/hiyouga/LLaMA-Factory/blob/main/README_zh.md https://github.com/hiyouga/LLaMA-Factory/blob/main/examples/README_zh.md 安装 v7.1 https://github.com/hiyouga/LLaMA-Factory/releases/tag/v0.7.1 git clone --depth 1 https://github.com/hiyoug…...

.NET IoC 容器(三)Autofac

目录 .NET IoC 容器&#xff08;三&#xff09;AutofacAutofacNuget 安装实现DI定义接口定义实现类依赖注入 注入方式构造函数注入 | 属性注入 | 方法注入注入实现 接口注册重复注册指定参数注册 生命周期默认生命周期单例生命周期每个周期范围一个生命周期 依赖配置Nuget配置文…...

Day44 动态规划part04

背包问题 01背包问题&#xff1a;每件物品只能用一次完全背包问题&#xff1a;每件物品可以使用无数次 01背包问题 暴力解法&#xff1a;每一件物品其实只有两个状态&#xff0c;取或者不取&#xff0c;所以可以使用回溯法搜索出所有的情况&#xff0c;那么时间复杂度就是 o…...

html期末复习速览

一.基础标签 1.段落标签<p></p> 特点&#xff1a;分段分割 2.标题标签<h1></h1>……<h6></h6> 特点&#xff1a;文字加粗&#xff0c;单独占一行 3.换行标签<br /> 特点&#xff1a;单标签&#xff0c;强制换行 二.文本格式化…...

CTFHUB-信息泄露-目录遍历和PHPINFO

目录 目录遍历 PHPINFO 目录遍历 很简单&#xff0c;挨着把每个目录都点开看一下 发现2目录下有个 flag.txt 文件&#xff0c;点开发现了本关的flag PHPINFO 这关也很简单&#xff0c;进来之后是一个phpinfo页面&#xff0c;按 CTRL F键打开查询&#xff0c;输入flag&#…...

面向Java程序员的Go工程开发入门流程

对于一个像我这样没有go背景的java程序员来说&#xff0c;使用go开发一个可用的程序的速度是肉眼可见的缓慢。 其难点不在于go语言本身&#xff0c;而是搭建整个工程链路的过程&#xff0c;即所谓的“配环境”。 本文主要讲述如何配出一个适合go开发的环境&#xff0c;以免有同…...