STM32F4的USB Host驱动移植详细步骤及问题解决

news2025/5/24 18:18:28

文章目录

  • 1、库文件准备
  • 2、工程准备
  • 3、移植
    • 3.1、新建USB相关文件夹
    • 3.2、加USB相关代码
    • 3.3、添加头文件路径
  • 4、修改相关代码
    • 1、修改usbh_usr.c
      • ①,usb_conf.h,include部分,
      • ②,定义全局宏
      • ③,修改usbh_usr.c
    • 2、修改diskio.c
    • 3、修改ffconf.h
    • 4、修改usb_bsp.c
    • 5、修改main.c
  • 5、功能测试

1、库文件准备

在这里插入图片描述
这三个从上到下分别为USB从机驱动库,USB主机驱动库,USB_OTG内核驱动代码,本次使用HOST和OTG进行移植

2、工程准备

FATFS实验工程,并将LCD改为printf,因为没有用到LCD,调试信息就只有通过printf进行查看

3、移植

3.1、新建USB相关文件夹

打开工程,新建USB文件夹并拷贝USB驱动库,在拷贝的目录下并新建一个USB_APP文件夹
在这里插入图片描述
MSC相关代码到USB_APP文件夹内相关代码,即:en.stm32_f105-07_f2_f4_usb-host-device_lib\Project\USB_Host_Examples\MSC\src下的部分代码:usb_bsp.c 、usbd_usr.c 2个.c 文件,
同时拷贝 en.stm32_f105-07_f2_f4_usb-host-device_lib\Project\USB_Host_Examples\MSC\inc下面的:usb_conf.h、usbd_conf.h 和 usbd_usr.h 等三个文件,添加完成后如下图所示:
在这里插入图片描述

3.2、加USB相关代码

工程添加USB相关代码,如下图所示:
根据ST官方的MSC例程,新建USB_OTG组,存放USB_OTG内核驱动代码,新建USB_DEVICE组,存放USB从机与MSC相关代码,新建USB_APP存放用户配置相关驱动代码
在这里插入图片描述
USB_OTG组代码路径为USB\STM32_USB_OTG_Driver\src
USB_DEVICE组代码路径为USB\STM32_USB_Device_Library\Core\src以及USB\STM32_USB_Device_Library\Class\msc\src
USB_APP组代码路径为USB\USB_APP内

3.3、添加头文件路径

在这里插入图片描述

4、修改相关代码

1、修改usbh_usr.c

编译代码,根据报错提示,修改相关内容。先从第一个错误开始修改

①,usb_conf.h,include部分,

使用如下代码替代:
#include "stm32f4xx.h"

在这里插入图片描述

②,定义全局宏

在C/C++选项卡,定义全局宏:USE_USB_OTG_FS,选择使用USB OTG FS,如图所示:
在这里插入图片描述

③,修改usbh_usr.c

3.1,删除lcd_log.h等头文件,并添加usart.h等头文件
如下所示:

#include "usbh_usr.h" 
#include "led.h"
#include "ff.h" 
#include "usart.h" 

在这里插入图片描述
3.2,修改为AppState变量
用AppState变量,替换原来的USBH_USR_ApplicationState,用于记录执行状态。然后,删除一些用不到的变量(头文件至USBH_Usr_cb_TypeDef USR_cb以及USBH_Usr_cb_TypeDef USR_cb至USBH_USR_Init之间的申明和变量),并添加USB中断处理函数(官方例程在stm32fxxx_it.c里面处理)到本.c文件,如下所示:

static u8 AppState;
extern USB_OTG_CORE_HANDLE  USB_OTG_Core;//在main函数定义!!

//USB OTG 中断服务函数
//处理所有USB中断
void OTG_FS_IRQHandler(void)
{
  	USBH_OTG_ISR_Handler(&USB_OTG_Core);
} 

在这里插入图片描述
3.3,修改USBH_USR_Init函数为:

void USBH_USR_Init(void)
{
	printf("USB OTG HS MSC Host\r\n");
	printf("> USB Host library started.\r\n");
	printf("  USB Host Library v2.1.0\r\n\r\n");
}

3.4,修改USBH_USR_DeviceAttached函数为:

void USBH_USR_DeviceAttached(void)//U盘插入
{
	LED1=1;
	printf("检测到USB设备插入!\r\n");
}

3.5,修改USBH_USR_UnrecoveredError函数为:

void USBH_USR_UnrecoveredError (void)
{
	printf("无法恢复的错误!!!\r\n\r\n");	
}

3.6,修改USBH_USR_DeviceDisconnected函数为:

void USBH_USR_DeviceDisconnected (void)//U盘移除
{
	LED1=0;
	printf("USB设备拔出!\r\n");
} 

3.7,修改USBH_USR_ResetDevice函数为:

void USBH_USR_ResetDevice(void)
{
	printf("复位设备...\r\n");
}

3.8,修改USBH_USR_DeviceSpeedDetected函数为:

void USBH_USR_DeviceSpeedDetected(uint8_t DeviceSpeed)
{
	if(DeviceSpeed==HPRT0_PRTSPD_HIGH_SPEED)
	{
		printf("高速(HS)USB设备!\r\n");
 	}  
	else if(DeviceSpeed==HPRT0_PRTSPD_FULL_SPEED)
	{
		printf("全速(FS)USB设备!\r\n"); 
	}
	else if(DeviceSpeed==HPRT0_PRTSPD_LOW_SPEED)
	{
		printf("低速(LS)USB设备!\r\n");  
	}
	else
	{
		printf("设备错误!\r\n");  
	}
}

3.9,修改USBH_USR_Device_DescAvailable函数为:

void USBH_USR_Device_DescAvailable(void *DeviceDesc)
{ 
	USBH_DevDesc_TypeDef *hs;
	hs=DeviceDesc;   
	printf("VID: %04Xh\r\n" , (uint32_t)(*hs).idVendor); 
	printf("PID: %04Xh\r\n" , (uint32_t)(*hs).idProduct); 
}

3.10,修改USBH_USR_DeviceAddressAssigned函数为:

void USBH_USR_DeviceAddressAssigned(void)
{
	printf("从机地址分配成功!\r\n");   
}

3.11,修改USBH_USR_Configuration_DescAvailable函数为:

void USBH_USR_Configuration_DescAvailable(USBH_CfgDesc_TypeDef * cfgDesc,
                                          USBH_InterfaceDesc_TypeDef *itfDesc,
                                          USBH_EpDesc_TypeDef *epDesc)
{
	USBH_InterfaceDesc_TypeDef *id; 
	id = itfDesc;   
	if((*id).bInterfaceClass==0x08)
	{
		printf("可移动存储器设备!\r\n"); 
	}else if((*id).bInterfaceClass==0x03)
	{
		printf("HID 设备!\r\n"); 
	}    
}

3.12,修改USBH_USR_Manufacturer_String函数为:

void USBH_USR_Manufacturer_String(void *ManufacturerString)
{
	printf("Manufacturer: %s\r\n",(char *)ManufacturerString);
}

3.13,修改USBH_USR_Product_String函数为:

void USBH_USR_Product_String(void *ProductString)
{
	printf("Product: %s\r\n",(char *)ProductString);  
}

3.14,修改USBH_USR_SerialNum_String函数为:

void USBH_USR_SerialNum_String(void *SerialNumString)
{
	printf("Serial Number: %s\r\n",(char *)SerialNumString);    
} 

3.15,修改USBH_USR_EnumerationDone函数为:

void USBH_USR_EnumerationDone(void)
{ 
	printf("设备枚举完成!\r\n\r\n");    
}

3.16,修改USBH_USR_DeviceNotSupported函数为:

void USBH_USR_DeviceNotSupported(void)
{
	printf("无法识别的USB设备!\r\n\r\n");    
} 

3.17,修改USBH_USR_UserInput函数为:

USBH_USR_Status USBH_USR_UserInput(void)
{ 
	printf("跳过用户确认步骤!\r\n");
	return USBH_USR_RESP_OK;
} 

3.18,修改USBH_USR_OverCurrentDetected函数为:

void USBH_USR_OverCurrentDetected (void)
{
	printf("端口电流过大!!!\r\n");
} 

3.19,修改USBH_USR_MSC_Application函数为:

extern u8 USH_User_App(void);		//用户测试主程序,在main函数定义!!
int USBH_USR_MSC_Application(void)
{
	u8 res=0;
	switch(AppState)
	{
		case USH_USR_FS_INIT://初始化文件系统 
			printf("开始执行用户程序!!!\r\n");
			AppState=USH_USR_FS_TEST;
			break;
		case USH_USR_FS_TEST://执行USB OTG 测试主程序
			res=USH_User_App(); //用户主程序
			res=0;
			if(res)AppState=USH_USR_FS_INIT;
			break;
		default:break;
	} 
	return res;
}

3.20,修改usbh_usr.h,新增包含:usb_hcd_int.h头文件,并将宏定义:USH_USR_FS_READLIST,改为:USH_USR_FS_TEST,并删掉后续的2个宏定义。
在这里插入图片描述
3.21,删除后续除USBH_USR_DeInit函数以外的其他所有函数,并修改:USBH_USR_DeInit函数为:

void USBH_USR_DeInit(void)
{
  	AppState=USH_USR_FS_INIT;
}

3.22,为了让fatfs 可以访问U盘,我们在usbh_usr.c的最后,新增3个函数,提供给fatfs的diskio.c调用。首先要声明一个USB_Host结构体(在main函数定义),如下:

extern USBH_HOST              USB_Host;//USB HOST结构体,存储主机相关状态。
然后,增加USBH_UDISK_Status函数,用于读取U盘状态,如下:
//获取U盘状态,返回值:0,U盘未就绪,1,就绪
u8 USBH_UDISK_Status(void)
{
	return HCD_IsDeviceConnected(&USB_OTG_Core);//返回U盘状态
}

3.23,新增USBH_UDISK_Read函数,用于读U盘,如下:

//读U盘
//buf:读数据缓存区
//sector:扇区地址
//cnt:扇区个数	
//返回值:错误状态;0,正常;其他,错误代码;		 
u8 USBH_UDISK_Read(u8* buf,u32 sector,u32 cnt)
{
	u8 res=1;
	if(HCD_IsDeviceConnected(&USB_OTG_Core)&&AppState==USH_USR_FS_TEST)//连接在&APP测试
	{  		    
		do
		{
			res=USBH_MSC_Read10(&USB_OTG_Core,buf,sector,512*cnt);
			USBH_MSC_HandleBOTXfer(&USB_OTG_Core ,&USB_Host);		      
			if(!HCD_IsDeviceConnected(&USB_OTG_Core))
			{
				res=1;//读写错误
				break;
			};   
		}while(res==USBH_MSC_BUSY);
	}else res=1;		  
	if(res==USBH_MSC_OK)res=0;	
	return res;
}

3.24,新增USBH_UDISK_Write函数,用于写U盘,如下:

//写U盘
//buf:写数据缓存区
//sector:扇区地址
//cnt:扇区个数	
//返回值:错误状态;0,正常;其他,错误代码;		 
u8 USBH_UDISK_Write(u8* buf,u32 sector,u32 cnt)
{
	u8 res=1;
	if(HCD_IsDeviceConnected(&USB_OTG_Core)&&AppState==USH_USR_FS_TEST)//连接在&APP测试
	{  		    
		do
		{
			res=USBH_MSC_Write10(&USB_OTG_Core,buf,sector,512*cnt); 
			USBH_MSC_HandleBOTXfer(&USB_OTG_Core ,&USB_Host);		      
			if(!HCD_IsDeviceConnected(&USB_OTG_Core))
			{
				res=1;//读写错误
				break;
			};   
		}while(res==USBH_MSC_BUSY);
	}else res=1;		  
	if(res==USBH_MSC_OK)res=0;	
	return res;
}

3.25,最后,新增的这三个函数,由于要在diskio.c里面调用,我们把这三个函数的声明,放到usbh_usr.h里面,如下所示:

u8 USBH_UDISK_Status(void);
u8 USBH_UDISK_Read(u8* buf,u32 sector,u32 cnt);
u8 USBH_UDISK_Write(u8* buf,u32 sector,u32 cnt);

编译一下,会提示一下错误,首先解决头文件问题,把 #include "lcd_log.h"屏蔽掉,其他的问题暂时不管

2、修改diskio.c

修改diskio.c。添加对U盘访问的支持。
1,新增usbh_usr.h头文件,并新增USB_DISK宏定义,如下所示:

#include "usbh_usr.h"

#define SD_CARD	 0  //SD卡,卷标为0
#define EX_FLASH 1	//外部flash,卷标为1
#define USB_DISK 2	//U盘,卷标为2

2,修改disk_initialize函数,添加U盘初始化部分,如下所示:

	case USB_DISK://U盘
	  		if(USBH_UDISK_Status())return 0;	//U盘连接成功,则返回1.否则返回0		  
			else return 1;

在这里插入图片描述
3,修改disk_read函数,添加U盘读函数,如下所示:

case USB_DISK://U盘 
			res=USBH_UDISK_Read(buff,sector,count);	  
			break;

4,修改disk_write函数,添加U盘写函数,如下所示:

case USB_DISK://U盘
			res=USBH_UDISK_Write((u8*)buff,sector,count); 
			break;

5,修改disk_ioctl函数,添加U盘支持部分,如下所示:

else if(pdrv==USB_DISK)	//U盘
	{
	    switch(cmd)
	    {
		    case CTRL_SYNC:
				res = RES_OK; 
		        break;	 
		    case GET_SECTOR_SIZE:
		        *(WORD*)buff=512;
		        res = RES_OK;
		        break;	 
		    case GET_BLOCK_SIZE:
		        *(WORD*)buff=512;
		        res = RES_OK;
		        break;	 
		    case GET_SECTOR_COUNT:
		        *(DWORD*)buff=USBH_MSC_Param.MSCapacity;
		        res = RES_OK;
		        break;
		    default:
		        res = RES_PARERR;
		        break;
	    }		
	}

3、修改ffconf.h

将_VOLUMES的值,修改为3,以支持3个磁盘(SD卡、SPI FLASH、U盘)。

4、修改usb_bsp.c

1,新增sys.h和delay.h等几个头文件,,如下所示:

#include "usb_bsp.h"
#include "sys.h"  
#include "delay.h" 

2,删掉用不到的宏定义和全局变量(头文件至USB_OTG_BSP_Init),并添加USB_HOST_PWRCTRL宏,用于控制USB HOST接口的对外供电,如下所示:

//USB主机电源控制口
#define USB_HOST_PWRCTRL 	PAout(15)	//PA15 

3,修改USB_OTG_BSP_Init函数为:

void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev)
{
	GPIO_InitTypeDef  GPIO_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
	RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE);//使能USB OTG时钟	钟
	//GPIOA11,A12设置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;//PA11/12复用功能输出	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PA15推挽输出		
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//输出功能
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
	USB_HOST_PWRCTRL=1;	//开启USB HOST电源供电
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_OTG_FS);//PA11,AF10(USB)
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_OTG_FS);//PA12,AF10(USB)
}

4,修改USB_OTG_BSP_EnableInterrupt函数为:

void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev)
{
	NVIC_InitTypeDef   NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_IRQn; 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能通道
	NVIC_Init(&NVIC_InitStructure);//配置  
}

5,修改USB_OTG_BSP_DriveVBUS函数为:

void USB_OTG_BSP_DriveVBUS(USB_OTG_CORE_HANDLE *pdev, uint8_t state)
{ 
}

6,修改USB_OTG_BSP_ConfigVBUS函数为:

void  USB_OTG_BSP_ConfigVBUS(USB_OTG_CORE_HANDLE *pdev)
{ 
} 

7,删除USB_OTG_BSP_TimeInit、USB_OTG_BSP_TimerIRQ、BSP_Delay、BSP_SetTime等函数。
8,修改USB_OTG_BSP_uDelay函数为:

void USB_OTG_BSP_uDelay (const uint32_t usec)
{ 
   	delay_us(usec);
}

9,修改USB_OTG_BSP_mDelay函数为:

void USB_OTG_BSP_mDelay (const uint32_t msec)
{  
	delay_ms(msec);
} 

再编译一下,错误如下所示
在这里插入图片描述
有三个USB相关的未定义,这个会在主函数定义,而第一个错误是官方的例程用LCD,到时候修改或替换下即可,暂时可不用管它,进行下一步

5、修改main.c

#include "sys.h"
#include "delay.h"  
#include "usart.h"   
#include "led.h"
#include "lcd.h"
#include "key.h"  
#include "usmart.h"  
#include "sram.h"   
#include "malloc.h" 
#include "w25qxx.h"    
#include "sdio_sdcard.h"
#include "ff.h"  
#include "exfuns.h"    	 
#include "usbh_usr.h" 

//ALIENTEK 探索者STM32F407开发板 实验53
//USB U盘 实验-库函数版本 
//技术支持:www.openedv.com
//淘宝店铺:http://eboard.taobao.com
//广州市星翼电子科技有限公司    
//作者:正点原子 @ALIENTEK 

USBH_HOST  USB_Host;
USB_OTG_CORE_HANDLE  USB_OTG_Core;


//用户测试主程序
//返回值:0,正常
//       1,有问题
u8 USH_User_App(void)
{ 
	u32 total,free;
	u8 res=0;
	printf("设备连接成功!.");	 
	res=exf_getfree("2:",&total,&free);
	if(res==0)
	{
		printf("FATFS OK!");	
		printf("U Disk Total Size:%d MB",total);	 
		printf("U Disk  Free Size:%d MB",free); 	    
	} 
 
	while(HCD_IsDeviceConnected(&USB_OTG_Core))//设备连接成功
	{	
		LED1=!LED1;
		delay_ms(200);
	}   
	printf("设备连接中...");
	return res;
} 


int main(void)
{        
	u8 t;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	uart_init(115200);		//初始化串口波特率为115200
	LED_Init();				//初始化与LED连接的硬件接口
	KEY_Init();				//按键
  	
	W25QXX_Init();			//SPI FLASH初始化
	my_mem_init(SRAMIN);	//初始化内部内存池	
 	exfuns_init();			//为fatfs相关变量申请内存 

  	f_mount(fs[0],"0:",1); 	//挂载SD卡  
  	f_mount(fs[1],"1:",1); 	//挂载SD卡  
  	f_mount(fs[2],"2:",1); 	//挂载U盘     
 
	printf("设备连接中...");	
	
	//初始化USB主机
  	USBH_Init(&USB_OTG_Core,USB_OTG_FS_CORE_ID,&USB_Host,&USBH_MSC_cb,&USR_cb);  
	while(1)
	{
		USBH_Process(&USB_OTG_Core, &USB_Host);
		delay_ms(1);
		t++;
		if(t==200)
		{
			LED0=!LED0;
			t=0;
		}
	}	
}

将main函数整个替换掉即可,然后编译,就剩下上面说的LCD这个错误,那么将这个错误解决掉即可
…\OBJ\FATFS.axf: Error: L6218E: Undefined symbol LCD_ErrLog (referred from usbh_msc_core.o).
解决办法:将LCD_ErrLog替换为printf,并添加#include "usart.h"头文件即可

5、功能测试

运行程序,插入U盘出现如下信息则表示功能测试OK
在这里插入图片描述

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

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

相关文章

iis建立站点外网无法访问(防火墙的入站规则和出站)

iis建立站点 外网无法访问 原因: 被防火墙拦截了 处理方式: 打开window防火墙--高级设置--入站 出站就是你访问外网,入站就是外网访问你,用户可以创建入站和出站规则,从而阻挡或者允许特定程序或者端口进行连接; 可以使…

每日一博 - 图解进程(Process)和线程(Thread)区别联系

文章目录 概述图解小结 概述 进程(Process)和线程(Thread)是操作系统中管理和执行任务的两个基本概念,它们之间有以下主要区别: 独立性: 进程是独立的执行单位。每个进程有自己的独立地址空间、…

Nginx神奇的499竟然不在HTTP响应码标准内?快来了解一下!

1 前言 高性能的HTTP和反向代理服务器,Nginx用来: 搭建Web Server作负载均衡供配置的日志字段丰富,从各类HTTP头部到内部性能数据都有 Nginx的访问日志中,存在499状态码的日志。但常见4xx状态码只有400、401、403、404等&#…

【数据结构】二叉树的链式结构

【数据结构】二叉树的链式存储结构 二叉树的存储结构 typedef int BTDataType; // 二叉树的结构 typedef struct BinaryTreeNode {BTDataType data; // 树的值struct BinaryTreeNode *left; // 左孩子struct BinaryTreeNode *right;// 右孩子 } BinaryTreeNode;二…

【数据结构】TOP-K问题/使用堆解决

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …

第70步 时间序列建模实战:ARIMA建模(JMP)

基于WIN10的64位系统演示 一、写在前面 这一期,我们使用JMP进行SARIMA模型的构建。 同样,这里使用这个数据: 《PLoS One》2015年一篇题目为《Comparison of Two Hybrid Models for Forecasting the Incidence of Hemorrhagic Fever with …

flutter简单的本地草稿箱功能

需求1:发帖退出时提示是否保存草稿 需求2:每条草稿中可以保存多张图片(最多9张)或一条视频及三十来个其它参数 需求3:每条草稿都是可以被覆盖的、可以点击删除 需求4:草稿页面可以一键清空 需求5:草稿随app删除一起没掉…

简单2D几何求交点

2D图形SVG工具添加了通过选项属性显示交点的功能。 PaladinDu:2D图形SVG化工具0 赞同 0 评论文章 在这个工具中,已经定义的数据结构有点,线段,有向线段,射线,直线,多边形,和圆。 …

【技巧】如何保护PDF文件不被随意修改?

做好的PDF文件,不想被他人随意修改,只要给PDF设置“限制保护”就可以了,设置保护后需要输入密码才能进行编辑。 设置“限制保护”我们需要用到PDF编辑器,以小编使用的编辑器为例,首先通过编辑器打开PDF文件后&#xf…

医学访问学者申请四点规划建议

医学领域一直以来都是人类社会的重要组成部分,而作为一名有志于成为一名医学领域的访问学者,您需要明确自己的目标并做好充分准备。知识人网小编将为您提供四点规划建议,以帮助您成功申请医学访问学者的机会。 第一点:明确研究方向…

input 的 placeholder 样式

::placeholder 伪元素 这个伪元素可以改变 input、textarea 占位文本的样式。 input::placeholder {color: green; }完整的兼容性写法: input {&::-webkit-input-placeholder, /* WebKit browsers*/ &:-moz-input-placeholder, /* Mozilla Firefox 4 to …

2个小时的腾讯面试经历(C++),来看看它终究考察了些什么?

今天分享一位同学实习面试鹅厂 c 岗的面试,全程都是问 C 和计算机基础(系统、网络、算法)的内容了。难度中规中矩吧,基本都是追问式的问法,一层一层往下问。 C相关 对面向对象的理解 C面向对象编程就是把一切事物都…

Kubernetes 部署应用(nginx)的两种方式,你更喜欢哪一种?

k8s发布应用的两种方式: kubernetes-dashboardkubectl命令行 一、Dashboard方式 配置部署:包含应用名称、容器镒、pod数量、Service非常的方便,不想设置配置yaml的可以很方便的部署。 点击部署就成功了k8s应用的部署了。部署后可以看到相应…

python爬虫经典案例(一)

爬虫(Web Scraping)是一种自动获取互联网信息的技术,广泛用于数据采集、分析和应用开发。无论你是数据科学家、市场营销专家还是应用程序开发者,都可以通过编写爬虫来获取所需的信息。在本文中,我们将介绍五个实用的爬…

从0开始实现简易版vue2

文章目录 前言原理思路分析实现Observer实现Watcher实现Compile 前言 Vue.js的双向绑定原理是其最重要的特性之一,它使得数据模型和DOM之间的同步变得非常简单和高效。 先上个成果图来吸引各位: new SimpleVue({el: #app,data: {title: SimpleVue,name…

re学习(37)DASCTF 2023_7 controlflow

IDA载入一下 发现flag的长度为40,然后将input[i]的值赋值给str[i],str[i]又执行一个异或操作,但是上面又有一些函数,导致这个程序的控制流有点奇怪..... 输入40只,检验是否是flag。 F5直接罢工了,暂时先忽…

Java入坑之代理

一、代理模式和静态代理 1.1代理模式 代理模式 - Proxy Pattern, 23个经典模式的一种,又称委托模式 -为目标对象提供(包装)了一个代理,这个代理可以控制对目标对象的访问 外界不用直接访问目标对象,而是访问代理对象,由代理对象再…

软件外包开发bug管理工具

国内有一些常用的Bug管理工具,这些工具旨在帮助团队有效地发现、跟踪和解决软件开发中的缺陷和问题。以下是一些国内的Bug管理工具,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 1.禅道&…

在openSUSE上开启护眼模式

色温 色温是用来衡量光源色彩时所用到的一个概念,单位为开尔文。热黑体辐射体与光源温度相同时的温度,就是该光源的色温。 显而易见,色温越低时,光源看起来越黄;色温越高时,光源看起来越蓝。下面是一些常见…

【LangChain系列 9】Prompt模版——MessagePromptTemplate

原文地址:【LangChain系列 9】Prompt模版——MessagePromptTemplate 本文速读: MessagePromptTemplate MessagesPlaceholder 在对话模型(chat model) 中, prompt主要是封装在Message中,LangChain提供了一些MessagePromptTemplat…