当前位置: 首页 > 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文件系统参数查看命令(附实例详解和注意事项)
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • DataBase in Android
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • ECMAScript6(0):ES6简明参考手册
  • Fastjson的基本使用方法大全
  • Java基本数据类型之Number
  • JSDuck 与 AngularJS 融合技巧
  • Linux CTF 逆向入门
  • Sass 快速入门教程
  • scala基础语法(二)
  • Spring框架之我见(三)——IOC、AOP
  • Vim Clutch | 面向脚踏板编程……
  • vue 配置sass、scss全局变量
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 机器学习 vs. 深度学习
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 面试遇到的一些题
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 小程序开发之路(一)
  • 一个JAVA程序员成长之路分享
  • 一个完整Java Web项目背后的密码
  • mysql面试题分组并合并列
  • 从如何停掉 Promise 链说起
  • 带你开发类似Pokemon Go的AR游戏
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​sqlite3 --- SQLite 数据库 DB-API 2.0 接口模块​
  • ​渐进式Web应用PWA的未来
  • #162 (Div. 2)
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (AngularJS)Angular 控制器之间通信初探
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (八十八)VFL语言初步 - 实现布局
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (五)网络优化与超参数选择--九五小庞