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

#stm32驱动外设模块总结w5500模块

1简介

2硬件连接

3软件编程

3.1 初始化

3.1.1 SPI初始化

这里注意配置 设置为全双工模式、主机SPI、8为数据模式、工作模式0 片选由外部引脚管理,设置预分频值为2 、高位先行、CRC多项式为7 使能SPI

void W5500_SPI1_Configuration(void)
{GPIO_InitTypeDef 	GPIO_InitStructure;SPI_InitTypeDef   	SPI_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO, ENABLE);/* 初始化SCK、MISO、MOSI引脚 */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOA, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);/* 初始化CS引脚 */GPIO_InitStructure.GPIO_Pin = W5500_SCS;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(W5500_SCS_PORT, &GPIO_InitStructure);GPIO_SetBits(W5500_SCS_PORT, W5500_SCS);/* 初始化配置STM32 SPI1 */SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;	//SPI设置为双线双向全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master;							//设置为主SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;						//SPI发送接收8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;							//时钟悬空低SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;							//数据捕获于第1个时钟沿SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;								//NSS由外部管脚管理SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;	//波特率预分频值为2SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;					//数据传输从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7;								//CRC多项式为7SPI_Init(SPI1, &SPI_InitStructure);									//根据SPI_InitStruct中指定的参数初始化外设SPI1寄存器SPI_Cmd(SPI1, ENABLE);	//STM32使能SPI1
}

3.1.2 SPI初始化GPIO设置初始化

这里指的是RST INT引脚的初始化
RST配置为推完输出
INT设置为上拉输入
开启外部中断0,模式为中断模式下降沿触发 中断线使能,
配置中断优先级为0,0最高了

void W5500_GPIO_Configuration(void)
{GPIO_InitTypeDef  GPIO_InitStructure;EXTI_InitTypeDef  EXTI_InitStructure;NVIC_InitTypeDef  NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA , ENABLE);/* W5500_RST引脚初始化配置(PA0) */GPIO_InitStructure.GPIO_Pin  = W5500_RST;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(W5500_RST_PORT, &GPIO_InitStructure);GPIO_ResetBits(W5500_RST_PORT, W5500_RST);/* W5500_INT引脚初始化配置(PB1) */GPIO_InitStructure.GPIO_Pin = W5500_INT;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(W5500_INT_PORT, &GPIO_InitStructure);/* Connect EXTI Line1 to PB0 */GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);/* PB1 as W5500 interrupt input */EXTI_InitStructure.EXTI_Line = EXTI_Line0;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);		}

3.2 装载网络参数

将本地(本地MCU对应的)IP、目标(服务器的)IP、子网掩码(我不知道子网掩码的具体作用,IPV4这里可以设置为255.255.255.0(0xFFFFFF00))、网关(192.168.1.1)、DNS(192.168.1.1)、物理地址(MAC地址是由stm32的序列号得来的)、本机端口、目标端口

u8 Gateway_IP[4];//网关IP地址
u8 Sub_Mask[4];	//子网掩码
u8 Phy_Addr[6];	//物理地址(MAC)
u8 IP_Addr[4];	//本机IP地址
u8 DNS[4];	//DNSu8 S0_Port[2];	//端口0的端口号(5000)
u8 S0_DIP[4];	//端口0目的IP地址
u8 S0_DPort[2];	//端口0目的端口号(6000)
void Load_Net_Parameters(void)//加载网关参数
{IP_Addr[0] = (PNetData->Local_IP & 0xFF000000) >> 24; //加载本机IP地址IP_Addr[1] = (PNetData->Local_IP & 0x00FF0000) >> 16;IP_Addr[2] = (PNetData->Local_IP & 0x0000FF00) >> 8;IP_Addr[3] = (PNetData->Local_IP & 0x000000FF);S0_DIP[0] = (PNetData->Dest_IP & 0xFF000000) >> 24; //加载端口0的目的IP地址S0_DIP[1] = (PNetData->Dest_IP & 0x00FF0000) >> 16;S0_DIP[2] = (PNetData->Dest_IP & 0x0000FF00) >> 8;S0_DIP[3] = (PNetData->Dest_IP & 0x000000FF);Sub_Mask[0] = (PNetData->SubMask & 0xFF000000) >> 24; //加载子网掩码Sub_Mask[1] = (PNetData->SubMask & 0x00FF0000) >> 16;Sub_Mask[2] = (PNetData->SubMask & 0x0000FF00) >> 8;Sub_Mask[3] = (PNetData->SubMask & 0x000000FF);Gateway_IP[0] = (PNetData->GateWay & 0xFF000000) >> 24;Gateway_IP[1] = (PNetData->GateWay & 0x00FF0000) >> 16;Gateway_IP[2] = (PNetData->GateWay & 0x0000FF00) >> 8;Gateway_IP[3] = (PNetData->GateWay & 0x000000FF);DNS[0] = (PNetData->DNS & 0xFF000000) >> 24;DNS[1] = (PNetData->DNS & 0x00FF0000) >> 16;DNS[2] = (PNetData->DNS & 0x0000FF00) >> 8;DNS[3] = (PNetData->DNS & 0x000000FF);Phy_Addr[0] = (PNetData->MAC_Addr1 & 0xFF00) >> 8; //加载物理地址Phy_Addr[1] = (PNetData->MAC_Addr1 & 0x00FF);Phy_Addr[2] = (PNetData->MAC_Addr2 & 0xFF00) >> 8;Phy_Addr[3] = (PNetData->MAC_Addr2 & 0x00FF);Phy_Addr[4] = (PNetData->MAC_Addr3 & 0xFF00) >> 8;Phy_Addr[5] = (PNetData->MAC_Addr3 & 0x00FF);S0_Port[0] = (PNetData->S_PORT & 0xFF00) >> 8 ;//加载端口0的端口号5000S0_Port[1] = (PNetData->S_PORT & 0x00FF);S0_DPort[0] = (PNetData->D_PORT & 0xFF00) >> 8 ;//加载端口0的目的端口号8080S0_DPort[1] = PNetData->D_PORT & 0x00FF;S0_Mode = TCP_CLIENT; //加载端口0的工作模式,TCP客户端模式}

3.3硬件复位w5500

低电平复位
在这里插入图片描述

void W5500_Hardware_Reset(void)
{u8 i = 0;GPIO_ResetBits(W5500_RST_PORT, W5500_RST);//复位引脚拉低delay_ms(50);//OSTimeDly(50);GPIO_SetBits(W5500_RST_PORT, W5500_RST);//复位引脚拉高delay_ms(200);//OSTimeDly(200);for(i = 0; i < 3; i++){if((Read_W5500_1Byte(PHYCFGR) & LINK) == 1){break;}}//	while((Read_W5500_1Byte(PHYCFGR) & LINK)==0);//等待以太网连接完成		读取W5500 PHY 配置寄存器 判断该字节最低位的连接状态
}	

片选拉低发送16位寄存器地址 PHYCFGR 0x002e
在这里插入图片描述
发送一帧数据的格式
在这里插入图片描述
这个用作寄存器地址
在这里插入图片描述
2.2.2是控制段这里不好截图就不接 7:3 选择哪个寄存器00000表示通用寄存器
2表示读写模式 0读 1写
1:0 OM表示SPI工作模式:这个和stm32上说的0123工作模式不是一个意思,这里指的是SPI 模式支持 2 种模式:可变数据长度模式和固定长度模式
可变数据长度模式(VDM):数据长度通过 SCSn 控制;
外设主机使 SCSn 信号拉低(高电平到低电平),并通知 W5500 SPI数据帧地址段的起始地址。然后外设主机传输控制段。此时,OM[1:0]=’00’。在 N 字节数据段传输完毕后,SCSn 信号拉高(低电平到高电平)且通知 W5500SPI 数据帧数据段的结束地址。在可变数据长度模式下,SCSn 必须通过外设主机通过 SPI 数据帧单元控制。(参见图 4)

  • 固定数据长度模式(FDM)
    : 在固定数据长度模式下,数据的长度通过 OM[1:0]位来设定,但是不能为‘00’。所以,SCSn 信号应该保持低电平状态,然后根据 OM[1:0]的值确定一种长度类型(介于 1 字节,2 字节,4 字节)
    在这里插入图片描述
    这里有点冲突我使用图4接法程序中用的却是1个固定字节
    2.2.3 数据段
    在 SPI 工作模式位 OM[1:0]设定了控制端之后,数据段被设定为 2 种长度类型:1 种为可变的 N 字节长度(可变数据长度模式),另以一种为确定的 1/2/4 字节长度(固定数据长度模式)。此时,1 字节数据从最大标志位到最小标志位,通过 MOSI 或者 MISO 信号传输。
    这里我理解是高位先行然后因为是全双工模式MISO先读一个数据,MOSI还得发一个假数据 然后再读了一下是怕数据出错吗?
    这里读的是寄存器PHYCFGR 0x002e 如果bit0=1表示链接成功
unsigned char Read_W5500_1Byte(unsigned short reg)
{unsigned char i;GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址SPI1_Send_Byte(FDM1 | RWB_READ | COMMON_R); //通过SPI1写控制字节,1个字节数据长度,读数据,选择通用寄存器i = SPI_I2S_ReceiveData(SPI1);SPI1_Send_Byte(0x00);//发送一个哑数据i = SPI_I2S_ReceiveData(SPI1); //读取1个字节数据GPIO_SetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为高电平return i;//返回读取到的寄存器数据
}

3.4设置寄存器初始化5500

Write_W5500_1Byte(MR, RST) 内部寄存器初始化
在这里插入图片描述
Write_W5500_nByte(GAR, Gateway_IP, 4); 写网关IP寄存器
在这里插入图片描述

Write_W5500_nByte(SUBR, Sub_Mask, 4); 写子网掩码寄存器
在这里插入图片描述

Write_W5500_nByte(SHAR, Phy_Addr, 6);写mac地址寄存器在这里插入图片描述
Write_W5500_nByte(SIPR, IP_Addr, 4);写本机IP(源IP)在这里插入图片描述
for(i = 0; i < 8; i++)
{
Write_W5500_SOCK_1Byte(i, Sn_RXBUF_SIZE, 0x02); //Socket Rx memory size=2k
Write_W5500_SOCK_1Byte(i, Sn_TXBUF_SIZE, 0x10); //Socket Tx mempry size=16k
}
配置每个socket的收发缓冲区分别为2K和16K
在这里插入图片描述
Write_W5500_2Byte(RTR, 0x07d0);设置重传超时时间
在这里插入图片描述

Write_W5500_1Byte(IMR, IM_IR7 | IM_IR6);//配置中断屏蔽寄存器
在这里插入图片描述
Write_W5500_1Byte(RCR, 8);//设置超时重发次数寄存器
在这里插入图片描述
Write_W5500_1Byte(SIMR, S0_IMR);设置socket中断屏蔽寄存器
在这里插入图片描述

Write_W5500_SOCK_1Byte(0, Sn_IMR, IMR_SENDOK | IMR_TIMEOUT | IMR_RECV | IMR_DISCON | IMR_CON);//向socket0 的Sn_IMR寄存器写值

在这里插入图片描述

void W5500_Init_Reg(void)
{u8 i = 0;Write_W5500_1Byte(MR, RST);//软件复位W5500,置1有效 复位,复位后自动清0 模式寄存器用于S/W软件复位delay_ms(10);//延时10ms,自己定义该函数//OSTimeDly(10);//设置网关(Gateway)的IP地址,Gateway_IP为4字节unsigned char数组,自己定义//使用网关可以使通信突破子网的局限,通过网关可以访问到其它子网或进入InternetWrite_W5500_nByte(GAR, Gateway_IP, 4);//设置子网掩码(MASK)值,SUB_MASK为4字节unsigned char数组,自己定义//子网掩码用于子网运算Write_W5500_nByte(SUBR, Sub_Mask, 4);//设置物理地址,PHY_ADDR为6字节unsigned char数组,自己定义,用于唯一标识网络设备的物理地址值//该地址值需要到IEEE申请,按照OUI的规定,前3个字节为厂商代码,后三个字节为产品序号//如果自己定义物理地址,注意第一个字节必须为偶数Write_W5500_nByte(SHAR, Phy_Addr, 6);//设置本机的IP地址,IP_ADDR为4字节unsigned char数组,自己定义//注意,网关IP必须与本机IP属于同一个子网,否则本机将无法找到网关Write_W5500_nByte(SIPR, IP_Addr, 4);//设置发送缓冲区和接收缓冲区的大小,参考W5500数据手册for(i = 0; i < 8; i++){Write_W5500_SOCK_1Byte(i, Sn_RXBUF_SIZE, 0x02); //Socket Rx memory size=2kWrite_W5500_SOCK_1Byte(i, Sn_TXBUF_SIZE, 0x10); //Socket Tx mempry size=16k}//设置重试时间,默认为2000(200ms)//每一单位数值为100微秒,初始化时值设为2000(0x07D0),等于200毫秒Write_W5500_2Byte(RTR, 0x07d0);//设置重试次数,默认为8次//如果重发的次数超过设定值,则产生超时中断(相关的端口中断寄存器中的Sn_IR 超时位(TIMEOUT)置“1”)Write_W5500_1Byte(RCR, 8);//启动中断,参考W5500数据手册确定自己需要的中断类型//IMR_CONFLICT是IP地址冲突异常中断,IMR_UNREACH是UDP通信时,地址无法到达的异常中断//其它是Socket事件中断,根据需要添加Write_W5500_1Byte(IMR, IM_IR7 | IM_IR6);Write_W5500_1Byte(SIMR, S0_IMR);Write_W5500_SOCK_1Byte(0, Sn_IMR, IMR_SENDOK | IMR_TIMEOUT | IMR_RECV | IMR_DISCON | IMR_CON);
}

3.5使用

W5500_Socket_Set();//W5500端口初始化配置 每次循环都要重新配置 主要是设置模式为TCP_CLIENT模式打开socket0 连接socket0
W5500端口初始化配置

   W5500_Socket_Set();//W5500端口初始化配置

S0_State 是个全局变量
初始化时加载网络参数 已经将S0_Mode 设置为TCP_CLIENT

void W5500_Socket_Set(void)
{if(S0_State == 0) //端口0初始化配置{if(S0_Mode == TCP_CLIENT) //TCP客户端模式{if(Socket_Connect(0) == TRUE){S0_State = S_INIT;}elseS0_State = 0;}}
}

Write_W5500_SOCK_1Byte(s, Sn_MR, MR_TCP); //设置socket为TCP模式
Sn_MR寄存器 socket 模式寄存器设置为TCP模式
Write_W5500_SOCK_1Byte(s, Sn_CR, OPEN); //打开Socket
Sn_CR (Socket n 配置寄存器) 设置为socket打开

Read_W5500_SOCK_1Byte(s, Sn_SR) != SOCK_INI
TCP模式下对应的Sn_SR值
Write_W5500_SOCK_1Byte(s, Sn_CR, CONNECT);
配为链接状态 在这里插入图片描述

unsigned char Socket_Connect(SOCKET s)
{Write_W5500_SOCK_1Byte(s, Sn_MR, MR_TCP); //设置socket为TCP模式Write_W5500_SOCK_1Byte(s, Sn_CR, OPEN); //打开Socketdelay_ms(10);//延时5ms//	OSTimeDly(5);if(Read_W5500_SOCK_1Byte(s, Sn_SR) != SOCK_INIT) //如果socket打开失败{Write_W5500_SOCK_1Byte(s, Sn_CR, CLOSE); //打开不成功,关闭Socketreturn FALSE;//返回FALSE(0x00)}Write_W5500_SOCK_1Byte(s, Sn_CR, CONNECT); //设置Socket为Connect模式return TRUE;//返回TRUE,设置成功
}

获取信号量获取不到被挂起

  OSSemPend(W5500INTFLAG, 0, &err);

这个信号量会在终端中被释放 所以每当有中断 就会触发信号量释放 这个任务就会被就绪

void EXTI0_IRQHandler(void)
{OS_CPU_SR cpu_sr;OS_ENTER_CRITICAL();              // Tell uC/OS-II that we are starting an ISR    //OSIntNesting++;OS_EXIT_CRITICAL();if(EXTI_GetITStatus(EXTI_Line0) != RESET){EXTI_ClearITPendingBit(EXTI_Line0);OSSemPost(W5500INTFLAG);}OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR       */
}

然后是中断处理
先看是什么中断
i = Read_W5500_1Byte(IR);//读取中断标志寄存器
再把中断清除由于只有高4位有用这里与上0xf0
Write_W5500_1Byte(IR, (i & 0xf0)); //回写清除中断标志
在这里插入图片描述
在这里插入图片描述
查看是不是socket中断
i = Read_W5500_1Byte(SIR); //读取端口中断标志寄存器
Write_W5500_SOCK_1Byte(0, SIR, i);//我觉的这写反了应该是 Write_W5500_1Byte( SIR, 0); 把SIR清零 而且这应该是写通用寄存器
在这里插入图片描述

后面才是查看socket寄存器

这里注意想把Sn_IR的某位清零就对这位写1 所以中断是谁就把谁写去

这里分了几种情况
1、连接成功中断
做一下处理 连接标识符写为1
断开时间归零
连接状态全局变量|上连接成功
网络状态指示灯关
2、断开连接中断
做一下处理 socket0断开连接标识符写为1
关闭socket0
初始化socket0
连接状态全局变量设置为连接失败
网络状态指示灯开
3、数据发送成功中断
复位接收与发送数据超时计数归零
socket0断开连接标识符写为0
断开连接时间归零
发送数据状态为发送数据完成
网络状态指示灯关
4、接收数据成功中断
复位接收与发送数据超时计数归零
socket0断开连接标识符写为0
断开连接时间归零
发送数据状态为接收数据完成
网络状态指示灯关
5、Socket连接或数据传输超时处理
超时标志位设置为
关闭socket0
网络连接状态为连接失败0
网络状态指示灯亮
在这里插入图片描述
在这里插入图片描述

void W5500_Interrupt_Process(void)
{unsigned char i, j;i = Read_W5500_1Byte(IR);//读取中断标志寄存器Write_W5500_1Byte(IR, (i & 0xf0)); //回写清除中断标志if((i & CONFLICT) == CONFLICT)//IP地址冲突异常处理{IP_Conflict = 1;//30秒后自动复位}if((i & UNREACH) == UNREACH)//UDP模式下地址无法到达异常处理{//自己添加代码//			SaveEventLog(3, 0, "UDP UNREACH");}i = Read_W5500_1Byte(SIR); //读取端口中断标志寄存器Write_W5500_SOCK_1Byte(0, SIR, i);if((i & S0_INT) == S0_INT)//Socket0事件处理{j = Read_W5500_SOCK_1Byte(0, Sn_IR); //读取Socket0中断标志寄存器Write_W5500_SOCK_1Byte(0, Sn_IR, j);if((j & IR_CON) == IR_CON) //在TCP模式下,Socket0成功连接{Socket0_Connect_Flag = 1;//连接标识S0_Con_FailTime = 0;//断开时间归零S0_State |= S_CONN; //网络连接状态0x02,端口完成连接,可以正常传输数据DBG_LED3_OFF();//网络连接状态指示灯 连接//						DBG_LED4_OFF();//网络连接超时 灭//						DEBUG_OUT("Socket0 Success Connect\r\n");//断开超时归零}if((j & IR_DISCON) == IR_DISCON) //在TCP模式下Socket断开连接处理{Socket0_Disconnect_Flag = 1;//断开连接标识Write_W5500_SOCK_1Byte(0, Sn_CR, CLOSE); //关闭端口,等待重新打开连接Socket_Init(0);		//指定Socket(0~7)初始化,初始化端口0S0_State = 0; //网络连接状态0x00,端口连接失败DBG_LED3_ON();//网络连接状态指示灯 断开//						DEBUG_OUT("Socket0 Disconnect\r\n");}if((j & IR_SEND_OK) == IR_SEND_OK) //Socket0数据发送完成,可以再次启动S_tx_process()函数发送数据{Net_Contect = 0;//复位接收与发送数据超时计数Socket0_Disconnect_Flag = 0;S0_Con_FailTime = 0;//断开时间归零S0_Data |= S_TRANSMITOK; //端口发送一个数据包完成DBG_LED3_OFF();//W5500发送数据完成指示灯 //						DBG_LED4_OFF();//网络连接超时 灭}if((j & IR_RECV) == IR_RECV) //Socket接收到数据,可以启动S_rx_process()函数{Net_Contect = 0;//复位接收与发送数据超时计数Socket0_Disconnect_Flag = 0;S0_Con_FailTime = 0;//断开时间归零S0_Data |= S_RECEIVE; //端口接收到一个数据包DBG_LED3_OFF();//W5500接收数据完成指示灯//						DBG_LED4_OFF();//网络连接超时 灭}if((j & IR_TIMEOUT) == IR_TIMEOUT) //Socket连接或数据传输超时处理{Socket0_Timeout_Flag = 1;Write_W5500_SOCK_1Byte(0, Sn_CR, CLOSE); // 关闭端口,等待重新打开连接S0_State = 0; //网络连接状态0x00,端口连接失败DBG_LED3_ON();//网络连接超时 亮//						DEBUG_OUT("Socket0 Connect Timeout\r\n");}}
}

然后判断读取状态读到了就使用吧
if((S0_Data & S_RECEIVE) == S_RECEIVE)//如果Socket0接收到数据
S0_Data &= ~S_RECEIVE;//将状态位清零
Read_SOCK_Data_Buffer(0, Rx_Buffer);

先写到这吧后面可能会补充一些网络的知识
参考文件《W5500 数据手册Version 1.0》官网上可以找到

相关文章:

  • FlinkCDC快速搭建实现数据监控
  • 每日OJ题_牛客HJ87 密码强度等级(IO型OJ)
  • C#关键字学习
  • Vscode连接外部虚拟环境
  • 两天学会微服务网关Gateway-Gateway工作原理
  • 【c++】 STL的组件简介与容器的使用时机
  • 使用腾讯云快速搭建WordPress网站流程详解
  • 什么是margin重叠问题?如何解决?
  • 09 Qt扩展LineEdit组件:Input输入框
  • icon格式软解码
  • 使用Homebrew搭建java环境
  • 基于PyTorch深度学习实战入门系列-(2)Numpy基础上
  • 定时执行专家V7.1 多国语言版本日文版发布 - タスク自動実行ツールV7.1 日本語版リリース
  • 通过iframe下载文件,怎么判断文件是否下载成功?
  • Linux minfo命令教程:详解MS-DOS文件系统参数查看命令(附实例详解和注意事项)
  • SegmentFault for Android 3.0 发布
  • java小心机(3)| 浅析finalize()
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • vue自定义指令实现v-tap插件
  • 从setTimeout-setInterval看JS线程
  • 计算机在识别图像时“看到”了什么?
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 区块链将重新定义世界
  • 如何设计一个微型分布式架构?
  • 线性表及其算法(java实现)
  • 异步
  • postgresql行列转换函数
  • PostgreSQL之连接数修改
  • 容器镜像
  • #1014 : Trie树
  • (八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (第一天)包装对象、作用域、创建对象
  • (多级缓存)缓存同步
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (转)项目管理杂谈-我所期望的新人
  • ****** 二 ******、软设笔记【数据结构】-KMP算法、树、二叉树
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • .NET 设计模式—适配器模式(Adapter Pattern)
  • .NET 设计一套高性能的弱事件机制
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .netcore 获取appsettings
  • .net项目IIS、VS 附加进程调试
  • /bin/bash^M: bad interpreter: No such file or directory
  • @JoinTable会自动删除关联表的数据
  • @SentinelResource详解
  • @Service注解让spring找到你的Service bean
  • @Transaction注解失效的几种场景(附有示例代码)
  • [ vulhub漏洞复现篇 ] ECShop 2.x / 3.x SQL注入/远程执行代码漏洞 xianzhi-2017-02-82239600
  • [C#]使用DlibDotNet人脸检测人脸68特征点识别人脸5特征点识别人脸对齐人脸比对FaceMesh
  • [C/C++]数据结构 循环队列
  • [CentOs7]iptables防火墙安装与设置
  • [CISCN 2023 初赛]go_session
  • [CSS]CSS 字体属性
  • [CSS]浮动