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

目录

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个Sectorvoid 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();		   	//初始化SPISPI2_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++;//扇区地址增1secoff = 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.mzph.cn/diannao/54217.shtml

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

相关文章

算法入门-贪心1

第八部分&#xff1a;贪心 409.最长回文串&#xff08;简单&#xff09; 给定一个包含大写字母和小写字母的字符串 s &#xff0c;返回通过这些字母构造成的最长的回文串 的长度。 在构造过程中&#xff0c;请注意 区分大小写 。比如 "Aa" 不能当做一个回文字符串…

如何通过 PhantomJS 模拟用户行为抓取动态网页内容

引言 随着网页技术的不断进步&#xff0c;JavaScript 动态加载内容已成为网站设计的新常态&#xff0c;这对传统的静态网页抓取方法提出了挑战。为了应对这一挑战&#xff0c;PhantomJS 作为一个无头浏览器&#xff0c;能够模拟用户行为并执行 JavaScript&#xff0c;成为了获…

Android RecycleView 深度解析与面试题梳理

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 引言 在 Android 开发中&#xff0c;列表和网格布局是非常常见的界面元素&#xff0c;它们用于展示大量数据集合。RecyclerView 是 Android 提…

小众语言ruby在苹果中的初步应用

前言 感觉Ruby在苹果系统中充当一种脚本语言来使用。 1、直接输入ruby没有反应 2、可显示结果的命令 ruby -e "puts Goodbye, cruel world!" 效果如下图&#xff1a; 说明苹果系统中ruby已经安装完毕&#xff0c;或者就是自带的。 3、编辑运行第一个ruby程序 输入…

nodejs+express+vue教辅课程辅助教学系统 43x2u前后端分离项目

目录 技术栈具体实现截图系统设计思路技术可行性nodejs类核心代码部分展示可行性论证研究方法解决的思路Express框架介绍源码获取/联系我 技术栈 该系统将采用B/S结构模式&#xff0c;开发软件有很多种可以用&#xff0c;本次开发用到的软件是vscode&#xff0c;用到的数据库是…

Linux常见查看文件命令

目录 一、cat 1.1. 查看文件内容 1.2. 创建文件 1.3. 追加内容到文件 1.4. 连接文件 1.5. 显示多个文件的内容 1.6. 使用管道 1.7. 查看文件的最后几行 1.8. 使用 -n 选项显示行号 1.9. 使用 -b 选项仅显示非空行的行号 二、tac 三、less 四、more 五、head 六、…

解决Gson将长数字( json字符串)转换为科学记数法格式

Gson&#xff08;又称Google Gson&#xff09;是Google公司发布的一个开放源代码的Java库&#xff0c;主要用途为序列化Java对象为JSON字符串&#xff0c;或反序列化JSON字符串成Java对象。 依赖 Gradle: dependencies {implementation com.google.code.gson:gson:2.11.0 }…

nginx基础篇(一)

文章目录 学习链接概图一、Nginx简介1.1 背景介绍名词解释 1.2 常见服务器对比IISTomcatApacheLighttpd其他的服务器 1.3 Nginx的优点(1)速度更快、并发更高(2)配置简单&#xff0c;扩展性强(3)高可靠性(4)热部署(5)成本低、BSD许可证 1.4 Nginx的功能特性及常用功能基本HTTP服…

内存压力测试工具的开发与实现

内存压力测试工具的开发与实现 一、工具设计概述二、工具实现1. 伪代码设计2. C代码实现三、工具使用与扩展四、结论在软件开发过程中,内存稳定性与可靠性是确保系统长期稳定运行的关键因素。为了验证系统在高负载下的内存表现,内存压力测试工具显得尤为重要。本文将基于C语言…

上市公司-客户ESG数据集(dta+xlsx+参考文献)(2009-2023年)

参考《经济问题》中李普玲&#xff08;2024&#xff09;的做法&#xff0c;将供应商与主要客户数据对应起来&#xff0c;并对上市公司及关联上市公司的ESG数据进行匹配&#xff0c;形成“供应商——客户ESG”的数据集&#xff0c;保留客户的销售占比 一、数据介绍 数据名称&am…

pdf文件怎么转换成ppt?介绍几种pdf转ppt的方法

pdf文件怎么转换成ppt&#xff1f;将pdf文件转换成ppt格式是一种常见且实用的需求&#xff0c;特别是在制作演示文稿和准备报告时。pdf格式因其文件内容的固定排版和高兼容性而广泛应用于文档的保存和分享。然而&#xff0c;在某些情况下&#xff0c;将pdf文件转换为ppt格式可以…

开源 AI 智能名片 S2B2C 商城小程序中的全渠道供应策略

摘要&#xff1a;本文深入探讨在开源 AI 智能名片 S2B2C 商城小程序的情境下&#xff0c;全渠道供应的运行机制。阐述各环节企业相互配合的重要性&#xff0c;重点分析零售企业在其中的关键作用&#xff0c;包括协调工作、信息传递、需求把握等方面&#xff0c;旨在实现高效的全…

鸿蒙开发之ArkUI 界面篇 十二 背景属性

backgroundColor背景色(纯颜色&#xff0c;没法实现立体感之类高级效果)、 backgroundImage背景图(一般是设计师设计好的图)、 backgroundImageSize背景图尺寸(用于调整背景图的尺寸)、 backgroundImagePosition背景图位置(用于调整背景图的位置)。 背景图的添加是属性backgrou…

测试工程师学历路径:从功能测试到测试开发

现在软件从业者越来越多&#xff0c;测试工程师的职位也几近饱和&#xff0c;想要获得竞争力还是要保持持续学习。基本学习路径可以从功能测试-自动化测试-测试开发工程师的路子来走。 功能测试工程师&#xff1a; 1、软件测试基本概念&#xff1a; 学习软件测试的定义、目的…

使用ShardingSphere实现MySql的分库分表

目录 一 什么是ShardingSphere分库分表 二 代码实现 1.导入相关依赖 2.配置相关参数 3.创建学生类以及mapper接口 4.实现 StandardShardingAlgorithm接口自定义分片算法 唐洋洋我知道你在看!!!嘿嘿 一 什么是ShardingSphere分库分表 我们平时在设计数据库的时候&#xf…

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

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

Android Tools | 如何使用Draw.io助力Android开发:从UI设计到流程优化

Android Tools | 如何使用Draw.io助力Android开发&#xff1a;从UI设计到流程优化 1. 引言 在Android开发中&#xff0c;视觉化设计与流程管理至关重要。虽然开发工具如Android Studio强大&#xff0c;但它并不适用于所有设计场景。Draw.io是一款免费的在线绘图工具&#xff…

先楫HPM6750 Windows下VSCode开发环境配置

用的是EVKmini&#xff0c;ft2232作为调试器jtag接口调试 启动start_gui.exe 以hello_world为例&#xff0c;更改一下build path&#xff0c;可以generate并使用gcc compile 最后会得到这些 点击start_gui里面的命令行&#xff0c;用命令行启动vscode 新建.vscode文件夹&…

硬件工程师笔试面试——集成电路

目录 17、集成电路 17.1 基础 集成电路实物图 17.1.1 概念 17.1.2 集成电路的发展历程 17.1.3 集成电路的分类 17.1.4 集成电路的制造工艺 17.1.5 集成电路的应用 17.2 相关问题 17.2.1 集成电路的制造工艺中,光刻技术是如何实现的? 17.2.2 在集成电路设计中,如何…

海外云手机——跨国业务的高效工具

海外云手机是一种基于云计算的虚拟手机服务&#xff0c;依托海外服务器实现跨国网络访问。这项服务不仅具备传统智能手机的所有功能&#xff0c;还突破了地域限制&#xff0c;为跨国业务提供更加便捷、高效、安全的解决方案。 随着全球化的加速和互联网的快速普及&#xff0c;跨…