W25QXX系列Flash存储器模块驱动代码

news2024/12/28 2:56:44

目录

W25QXX简介

硬件电路

W25Q128框图 

Flash操作注意事项

驱动代码

W25QXX.h

W25QXX.c


W25QXX简介

W25Qxx系列是一种低成本、小型化、使用简单的非易失性存储器,常应用于数据存储、字库存储、固件程序存储等场景

存储介质:Nor Flash(闪存)

时钟频率:80MHz / 160MHz (Dual SPI) / 320MHz (Quad SPI)

SPI模式:支持SPI模式0和模式3

存储容量(24位地址):     

W25Q40:      4Mbit / 512KByte     

W25Q80:      8Mbit / 1MByte     

W25Q16:      16Mbit / 2MByte     

W25Q32:      32Mbit / 4MByte     

W25Q64:      64Mbit / 8MByte     

W25Q128:  128Mbit / 16MByte     

W25Q256:  256Mbit / 32MByte

注意:W25Q256分为三字节地址模式和四字节地址模式,三字节寻址只能前16M,1大于16M的内存读写需要使用四字节寻址

硬件电路

引脚功能
VCC、GND电源(2.7~3.6V)
CS(SS)SPI片选
CLK(SCK)SPI时钟
DI(MOSI)SPI主机输出从机输入
DO(MISO)SPI主机输入从机输出
WP写保护
HOLD数据保持

W25Q128框图 

 W25Q128(W25Q64)将16M(8M)的容量分为256(128)个块(Block),每个块大小为64K(64*1024=65536)字节,每个块又分为16个扇区(Sector),每个扇区4K(4096)个字节。W25Qxx的最小擦除单位为一个扇区,也就是每次必须擦除4K个字节。这样我们需要给W25Qxx开辟一个至少4K的缓存区,这样对SRAM要求比较高,要求芯片必须有4K以上SRAM才能很好的操作。

Flash操作注意事项

写入操作时

  • 写入操作前,必须先进行写使能
  • 每个数据位只能由1改写为0,不能由0改写为1
  • 写入数据前必须先擦除(擦除必须按最小擦除单元进行),擦除后,所有数据位变为1
  • 连续写入多字节时,最多写入一页的数据,超过页尾位置的数据,会回到页首覆盖写入
  • 写入操作结束后,芯片进入忙状态,不响应新的读写操作

读取操作时

直接调用读取时序,无需使能,无需额外操作,没有页的限制,读取操作结束后不会进入忙状态,但不能在忙状态时读取

驱动代码

void W25QXX_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);

该函数可以在 W25Q128 的任意地址开始写入任意长度(必须不超过 W25Q128 的容量)的数据。我们这里简单介绍一下思路:先获得首地址(WriteAddr)所在的扇区,并计算在扇区内的偏移,然后判断要写入的数据长度是否超过本扇区所剩下的长度,如果不超过,再先看看是否要擦除,如果不要,则直接写入数据即可,如果要则读出整个扇区,在偏移处开始写入指定长度的数据,然后擦除这个扇区,再一次性写入。当所需要写入的数据长度超过一个扇区的长度的时候,我们先按照前面的步骤把扇区剩余部分写完,再在新扇区内执行同样的操作,如此循环,直到写入结束

W25QXX.h

#ifndef __W25QXX_H
#define __W25QXX_H			    

	  
//W25X系列/Q系列芯片列表	   
//W25Q80  ID  0XEF13
//W25Q16  ID  0XEF14
//W25Q32  ID  0XEF15
//W25Q64  ID  0XEF16	
//W25Q128 ID  0XEF17	
#define W25Q80 	0XEF13 	
#define W25Q16 	0XEF14
#define W25Q32 	0XEF15
#define W25Q64 	0XEF16
#define W25Q128	0XEF17

#define NM25Q80 	0X5213 	
#define NM25Q16 	0X5214
#define NM25Q32 	0X5215
#define NM25Q64 	0X5216
#define NM25Q128	0X5217
#define NM25Q256 	0X5218
				 
/
 
//指令表
#define W25X_WriteEnable		0x06 
#define W25X_WriteDisable		0x04 
#define W25X_ReadStatusReg		0x05 
#define W25X_WriteStatusReg		0x01 
#define W25X_ReadData			0x03 
#define W25X_FastReadData		0x0B 
#define W25X_FastReadDual		0x3B 
#define W25X_PageProgram		0x02 
#define W25X_BlockErase			0xD8 
#define W25X_SectorErase		0x20 
#define W25X_ChipErase			0xC7 
#define W25X_PowerDown			0xB9 
#define W25X_ReleasePowerDown	0xAB 
#define W25X_DeviceID			0xAB 
#define W25X_ManufactDeviceID	0x90 
#define W25X_JedecDeviceID		0x9F 

 		


extern uint16_t W25QXX_TYPE;					//定义W25QXX芯片型号	


//外部调用
void W25QXX_Init(void);//初始化
uint16_t W25QXX_ReadID(void); //读取芯片ID  		    
void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead);//在指定地址开始读取指定长度的数据
void W25QXX_Write_Page(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);//SPI在一页(0~65535)内写入少于256个字节的数据
void W25QXX_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);//在指定地址开始写入指定长度的数据
void W25QXX_Erase_Sector(uint32_t Dst_Addr);//擦除一个扇区
void W25QXX_Erase_Chip(void);//擦除整个芯片	
void W25QXX_PowerDown(void);//进入掉电模式
void W25QXX_WAKEUP(void); //唤醒


//外部很少调用,基本内部使用
void W25QXX_CS(uint8_t BitVal);
void W25QXX_Wait_Busy(void);
uint8_t W25QXX_ReadSR(void);
void W25QXX_Write_SR(uint8_t sr);
void W25QXX_Write_Enable(void);
void W25QXX_Write_Disable(void);
void W25QXX_Write_NoCheck(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
#endif


W25QXX.c

#include "stm32f10x.h"
#include "w25qxx.h" 
#include "spi.h"
#include "delay.h"
#include "usart.h"


uint16_t W25QXX_TYPE = W25Q128;	//默认是W25Q128的ID号

//W25Q128容量为16M字节
//4Kbytes为一个扇区(Sector)
//16个扇区为1个Block
//共有256个Block,4096个Sector

void W25QXX_CS(uint8_t BitVal)
{
	GPIO_WriteBit(GPIOB, GPIO_Pin_12, (BitAction)BitVal);//W25QXX的片选信号
}

void W25QXX_Init(void)
{	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//PORTB时钟使能 

	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;  // PB12 
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
 
	W25QXX_CS(1);				//SPI总线中W25QXX的CS不选中

	SPI2_Init();		   	//初始化SPI
	SPI2_SetSpeed(SPI_BaudRatePrescaler_2);//设置为18M时钟,高速模式
	W25QXX_TYPE = W25QXX_ReadID();//读取FLASH ID.  

}  

//读取W25QXX的状态寄存器,默认:0x00
//BIT7  6   5   4   3   2   1   0
//SPR   RV  TB BP2 BP1 BP0 WEL BUSY
//SPR:默认0,状态寄存器保护位,配合WP使用
//TB,BP2,BP1,BP0:FLASH区域写保护设置
//WEL:写使能锁定
//BUSY:忙标记位(1,忙;0,空闲)
uint8_t W25QXX_ReadSR(void)   
{  
	uint8_t byte = 0;   
	W25QXX_CS(0);                            //使能器件   
	SPI2_ReadWriteByte(W25X_ReadStatusReg); //发送读取状态寄存器命令    
	byte = SPI2_ReadWriteByte(0Xff);          //读取一个字节  
	W25QXX_CS(1);                             //取消片选     
	return byte;   
}

//写W25QXX状态寄存器
//只有SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)可以写!!!
void W25QXX_Write_SR(uint8_t sr)   
{   
	W25QXX_CS(0);                             //使能器件   
	SPI2_ReadWriteByte(W25X_WriteStatusReg);//发送写取状态寄存器命令    
	SPI2_ReadWriteByte(sr);               	//写入一个字节  
	W25QXX_CS(1);                             //取消片选     	      
}

//W25QXX写使能	
//将WEL置位   
void W25QXX_Write_Enable(void)   
{
	W25QXX_CS(0);                          	//使能器件   
    SPI2_ReadWriteByte(W25X_WriteEnable); 		//发送写使能  
	W25QXX_CS(1);                            	//取消片选     	      
}


//W25QXX禁止写	
//将WEL清零  
void W25QXX_Write_Disable(void)   
{  
	W25QXX_CS(0);                            //使能器件   
    SPI2_ReadWriteByte(W25X_WriteDisable);  //发送写禁止指令    
	W25QXX_CS(1);                             //取消片选     	      
} 


//读取芯片ID
//返回值如下:				   
//0XEF13,表示芯片型号为W25Q80  
//0XEF14,表示芯片型号为W25Q16    
//0XEF15,表示芯片型号为W25Q32  
//0XEF16,表示芯片型号为W25Q64 
//0XEF17,表示芯片型号为W25Q128 	  
uint16_t W25QXX_ReadID(void)
{
	uint16_t Temp = 0;	  
	W25QXX_CS(0); 				    
	SPI2_ReadWriteByte(0x90);//发送读取ID命令	    
	SPI2_ReadWriteByte(0x00); 	    
	SPI2_ReadWriteByte(0x00); 	    
	SPI2_ReadWriteByte(0x00); 	 			   
	Temp|=SPI2_ReadWriteByte(0xFF)<<8;  
	Temp|=SPI2_ReadWriteByte(0xFF);	 
	W25QXX_CS(1); 				    
	return Temp;
}   		    
 


//在指定地址开始读取指定长度的数据
//pBuffer:数据存储区
//ReadAddr:开始读取的地址(24bit)
//NumByteToRead:要读取的字节数(最大65535)
void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)   
{ 
 	uint16_t i;   										    
	W25QXX_CS(0);                             	//使能器件   
    SPI2_ReadWriteByte(W25X_ReadData);         	//发送读取命令   
    SPI2_ReadWriteByte((uint8_t)((ReadAddr)>>16));  	//发送24bit地址    
    SPI2_ReadWriteByte((uint8_t)((ReadAddr)>>8));   
    SPI2_ReadWriteByte((uint8_t)ReadAddr);   
    for(i = 0; i < NumByteToRead; i++)
	{ 
        pBuffer[i] = SPI2_ReadWriteByte(0XFF);   	//循环读数  
    }
	W25QXX_CS(1);  				    	      
} 



//SPI在一页(0~65535)内写入少于256个字节的数据
//在指定地址开始写入最大256字节的数据
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!	 
void W25QXX_Write_Page(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
 	uint16_t i;  
    W25QXX_Write_Enable();                  	//SET WEL 
	W25QXX_CS(0);                            	//使能器件   
    SPI2_ReadWriteByte(W25X_PageProgram);      	//发送写页命令   
    SPI2_ReadWriteByte((uint8_t)((WriteAddr)>>16)); 	//发送24bit地址    
    SPI2_ReadWriteByte((uint8_t)((WriteAddr)>>8));   
    SPI2_ReadWriteByte((uint8_t)WriteAddr);   
    for(i = 0; i < NumByteToWrite; i++)
		SPI2_ReadWriteByte(pBuffer[i]);//循环写数  
	W25QXX_CS(1);                             	//取消片选 
	W25QXX_Wait_Busy();					   		//等待写入结束
} 



//无检验写SPI FLASH 
//必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
//具有自动换页功能 
//在指定地址开始写入指定长度的数据,但是要确保地址不越界!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大65535)
void W25QXX_Write_NoCheck(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)   
{ 			 		 
	uint16_t pageremain;	   
	pageremain = 256-WriteAddr % 256; //写地址所在页剩余的字节数		 	    
	if(NumByteToWrite <= pageremain)
		pageremain = NumByteToWrite;//要写入的字节不超过这一页
	while(1)
	{	   
		W25QXX_Write_Page(pBuffer,WriteAddr, pageremain);
		if(NumByteToWrite == pageremain) break;//写入结束了
	 	else //NumByteToWrite>pageremain
		{
			pBuffer+=pageremain;//pBuffer移到该写的缓存区位置
			WriteAddr+=pageremain;	//WriteAddr移到该写的地址

			NumByteToWrite-=pageremain;			  //减去已经写入了的字节数
			if(NumByteToWrite > 256)pageremain = 256; //一次可以写入256个字节
			else pageremain = NumByteToWrite; 	  //不够256个字节了
		}
	};	    
} 


//写SPI FLASH  
//在指定地址开始写入指定长度的数据
//该函数带擦除操作!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)						
//NumByteToWrite:要写入的字节数(最大65535)   
uint8_t W25QXX_BUFFER[4096];		 
void W25QXX_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)   
{ 
	uint32_t secpos;
	uint16_t secoff;
	uint16_t secremain;	   
 	uint16_t i;    
	uint8_t * W25QXX_BUF;	  
   	W25QXX_BUF = W25QXX_BUFFER;	     
 	secpos = WriteAddr/ 4096;//扇区地址,一个扇区(Sector)有4KB  
	secoff = WriteAddr % 4096;//在扇区内的偏移
	secremain = 4096-secoff;//扇区剩余空间大小   
 	//printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//测试用
 	if(NumByteToWrite <= secremain)secremain = NumByteToWrite;//要写入的字节不超过这一扇区
	while(1) 
	{	
		W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读出整个扇区的内容
		for(i = 0; i< secremain; i++)//校验数据
		{
			if(W25QXX_BUF[secoff + i] != 0XFF) break;//需要擦除  	  
		}
		if(i < secremain)//需要擦除
		{
			W25QXX_Erase_Sector(secpos);		//擦除这个扇区
			for(i = 0;i < secremain; i++)	   		//复制
			{
				W25QXX_BUF[i + secoff] = pBuffer[i];	  
			}
			W25QXX_Write_NoCheck(W25QXX_BUF, secpos * 4096, 4096);//写入整个扇区  

		}else W25QXX_Write_NoCheck(pBuffer, WriteAddr, secremain);//写已经擦除了的,直接写入扇区剩余区间. 				   
		if(NumByteToWrite == secremain) break;//写入结束了
		else//写入未结束
		{
			secpos++;//扇区地址增1
			secoff = 0;//偏移位置为0 	 

		   	pBuffer+=secremain;  				//指针偏移
			WriteAddr+=secremain;				//写地址偏移	   
		   	NumByteToWrite-=secremain;			//字节数递减
			if(NumByteToWrite > 4096) secremain = 4096;//下一个扇区还是写不完
			else secremain = NumByteToWrite;		//下一个扇区可以写完了
		}	 
	};	 
}


//擦除整个芯片		  
//等待时间超长...
void W25QXX_Erase_Chip(void)   
{                                   
    W25QXX_Write_Enable();                 	 	//SET WEL 
    W25QXX_Wait_Busy();   
  	W25QXX_CS(0);                             	//使能器件   
    SPI2_ReadWriteByte(W25X_ChipErase);        	//发送片擦除命令  
	W25QXX_CS(1);                             	//取消片选     	      
	W25QXX_Wait_Busy();   				   		//等待芯片擦除结束
}


//擦除一个扇区
//Dst_Addr:扇区地址 根据实际容量设置
//擦除一个山区的最少时间:150ms
void W25QXX_Erase_Sector(uint32_t Dst_Addr)   
{  
	//监视falsh擦除情况,测试用   
 	printf("fe:%x\r\n", Dst_Addr);	  
 	Dst_Addr*=4096;//扇区首地址
    W25QXX_Write_Enable();                  	//SET WEL 	 
    W25QXX_Wait_Busy();   
  	W25QXX_CS(0);                             	//使能器件   
    SPI2_ReadWriteByte(W25X_SectorErase);      	//发送扇区擦除指令 
    SPI2_ReadWriteByte((uint8_t)((Dst_Addr)>>16));  	//发送24bit地址    
    SPI2_ReadWriteByte((uint8_t)((Dst_Addr)>>8));   
    SPI2_ReadWriteByte((uint8_t)Dst_Addr);  
	W25QXX_CS(1);                             	//取消片选     	      
    W25QXX_Wait_Busy();   				   		//等待擦除完成
} 


//等待空闲
void W25QXX_Wait_Busy(void)   
{   
	while((W25QXX_ReadSR() & 0x01) == 0x01);  		// 等待BUSY位清空
} 


//进入掉电模式
void W25QXX_PowerDown(void)   
{ 
  	W25QXX_CS(0);                            	 	//使能器件   
    SPI2_ReadWriteByte(W25X_PowerDown);        //发送掉电命令  
	W25QXX_CS(1);                             	//取消片选     	      
    delay_us(3);                               //等待TPD  
}


//唤醒
void W25QXX_WAKEUP(void)   
{  
  	W25QXX_CS(0);                             	//使能器件   
    SPI2_ReadWriteByte(W25X_ReleasePowerDown);	//  send W25X_PowerDown command 0xAB    
	W25QXX_CS(1);                             	//取消片选     	      
    delay_us(3);                            	//等待TRES1
}   

更多内容见参考手册

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

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

相关文章

Apache SeaTunnel Zeta引擎源码解析(三) Server端接收任务的执行流程

作者&#xff1a;刘乃杰 编辑整理&#xff1a;曾辉 引入 本系列文章是基于 Apache SeaTunnel 2.3.6版本&#xff0c;围绕Zeta引擎给大家介绍其任务是如何从提交到运行的全流程&#xff0c;希望通过这篇文档&#xff0c;对刚刚上手SeaTunnel的朋友提供一些帮助。 我们整体的文…

ios xib 子控件约束置灰不能添加约束

添加约束时发现置灰不可点的问题 layout切换为inferred&#xff0c;就可以添加约束了

[SIGGRAPH-24] CharacterGen

[pdf | code | proj] LRM能否用于3D数字人重建&#xff1f;问题在于&#xff1a;1&#xff09;缺少3D数字人数据&#xff1b;2&#xff09;重建任意姿态的3D数字人不利于后续绑定和驱动。构建3D数字人数据集&#xff1a;在VRoidHub上采集数据&#xff0c;得到13746个风格化角色…

青柠视频云——记一次大华摄像头公网语音对讲失败的问题分析

今天有客户反馈&#xff0c;使用大华摄像头接入青柠视频云&#xff0c;在公网环境下无法进行语音对讲&#xff0c;用户的设备是支持语音对讲的。 这是用户提供的注册截图&#xff0c;看起来也没什么问题&#xff0c;而且用户摄像头带有拾音功能和外放喇叭。 于是我们联系客户开…

Maple常用命令

1. 重启内核&#xff1a; restart 2. 化简式子 simplify(式子) 3. 引用前面出现的公式&#xff1a; CtrlL&#xff0c;在弹出的以下对话框中输入要引用的公式编号 4.

GHOST重装后DEF盘丢失:深度解析与高效数据恢复方案

在数字信息爆炸的时代&#xff0c;数据安全与恢复成为了每个计算机用户必须面对的重要课题。GHOST作为系统备份与恢复领域的佼佼者&#xff0c;以其快速、便捷的特点赢得了广泛的用户基础。然而&#xff0c;在使用GHOST进行系统重装的过程中&#xff0c;不少用户遭遇了DEF盘&am…

Qt_多元素控件

目录 1、认识多元素控件 2、QListWidget 2.1 使用QListWidget 3、QTableWidget 3.1 使用QListWidget 4、QTreeWidget 4.1 使用QTreeWidget 5、QGroupBox 5.1 使用QGroupBox 6、QTabWidget 6.1 使用QTabWidget 结语 前言&#xff1a; 在Qt中&#xff0c;控件之间…

【Linux】常见指令(3)

1.head指令 head指令用于显示文件的前几行内容&#xff0c;默认head指令打印其相应文件的开头10行。 使用方法&#xff1a;head [选项] [文件名] 常见的选项有&#xff1a; -n&#xff1a;指定显示文件的前几行&#xff0c;例如显示前五行可以输入命令“head -n 5 output.txt”…

ChromaDB教程_2024最新版(上)

前言 在上一篇&#xff08;快捷入口&#xff09;文章中&#xff0c;博主提到了一个向量存储&#xff0c;其中用到了Chroma数据库。代码示例如下&#xff1a; vectordb Chroma.from_documents(documentsdocs,embeddingembedding,persist_directoryvector_dir )这是基于langc…

智能车镜头组入门(一)车模的选择

这篇文章&#xff0c;我会简单的介绍下车模的、轮胎和负压的选择 今年的镜头组是自制车模&#xff0c;这比较考验学校之前参赛的经验。我们选择了某飞的mini车模。提供智能车方案的无非就两家&#xff0c;某飞和某邱&#xff0c;我们学校之前都用的是某飞的&#xff0c;在某飞…

功能测试干了2年,快要废了...

8年前刚进入到IT行业&#xff0c;到现在学习软件测试的人越来越多&#xff0c;所以在这我想结合自己的一些看法给大家提一些建议。 最近聊到软件测试的行业内卷&#xff0c;越来越多的转行和大学生进入测试行业&#xff0c;导致软件测试已经饱和了&#xff0c;想要获得更好的待…

14 款全新「史诗级」可穿戴装备即将面世,附上获取教程!

14 个新的可穿戴装备原理图火热出炉&#xff0c;随时可供锻造 &#x1f525; 2024 年 7 月&#xff0c;AavegotchiDAO 举办了一次社区设计竞赛&#xff0c;才华横溢的艺术家们施展了他们的设计技能&#xff0c;创造出了 14 个新的可穿戴装备原理图。 现在&#xff0c;这些独一…

spring-boot-maven-plugin插件打包和java -jar命令执行原理

文章目录 1. Maven生命周期2. jar包结构2.1 不可执jar包结构2.2 可执行jar包结构 3. spring-boot-maven-plugin插件打包4. 执行jar原理 1. Maven生命周期 Maven的生命周期有三种&#xff1a; clean&#xff1a;清除项目构建数据&#xff0c;较为简单&#xff0c;不深入探讨&a…

【隐私计算篇】不经意传输协议(OT/OTE)的进一步补充

1. 背景介绍 关于不经意传输(OT)和不经意传输扩展(OT Extension), 我们在之前的文章《OT&OT扩展(不经意传输扩展)深入浅出》做了详细的说明。但对于OT/OTE的一些技术或者概念&#xff0c;还有一定的内容欠缺&#xff0c;因此本文根据冯登国院士关于安全多方计算协议…

实用测评!7种方式将PDF导出为图片,pdf转jpg一键转换!

pdf怎么转换成jpg&#xff1f;pdf是一种通用的便携文件格式之一&#xff0c;而jpg是一种广泛使用的图像格式&#xff0c;平时处理这两种格式文件时&#xff0c;难免会遇到需要将pdf转成jpg格式的情况&#xff0c;例如在学术研究、创意设计、报告提交等领域。 pdf转jpg是一个很常…

GEO数据库提取疾病样本和正常样本|GEO数据库区分疾病和正常样本|直接用|生物信息|生信

GEO数据库提取疾病样本和正常样本|GEO数据库区分疾病和正常样本|直接用|生物信息|生信 代码都可以直接用&#xff0c;修改GSE就可以&#xff01; 通过代码查看数据的分类&#xff0c;是疾病还是正常样本 ##############################查看对饮GSE样本疾病or正常信息# 指定…

[mysql]mysql排序和分页

#排序和分页本身是两块内容,因为都比较简单,我们就把它分到通一个内容里. #1排序: SELECT * FROM employees #我们会发现,我们没有做排序操作,但是最后出来的107条结果还是会按顺序发出,而且是每次都一样.这我们就有一个疑惑了,现在我们的数据库是根据什么来排序的,在我们没有进…

Linux权限理解【Shell的理解】【linux权限的概念、管理、切换】【粘滞位理解】

目录 Linux权限理解1.Xshell命令以及运行原理2.linux权限的学习2.1linux权限的切换2.2linux权限的概念2.3linux权限管理2.3.1linux中文件访问者的分类2.3.2文件类型和访问权限(文件属性)2.3.2.1文件类型2.3.2.2文件权限拓展—文件的起始权限 2.3.3文件权限管理2.3.4文件权限的应…

Linux环境基础开发工具---vim

1.快速的介绍一下vim vim是一款多模式的编辑器&#xff0c;里面有很多子命令&#xff0c;来实现代码编写操作。 2.vim的模式 vim一共有三种模式&#xff1a;底行模式&#xff0c;命令模式&#xff0c;插入模式。 2.1vim模式之间的切换 2.2 谈论常见的模式---命令模式&#xf…

GEC6818初次连接使用

目录 1.开发板资源接口​编辑​编辑 2.安装 SecureCRT工具 2.1SecureCRT相关问题 3.连接开发板 4.开发板文件传输 4.1串口传输 rx 从电脑下载文件到开发板 sz 从开发板把文件发送到电脑 4.2U盘/SD卡传输 4.3网络传输[重点] 5.运行传到开发板的可执行文件 6.开发板网络…