STM32 W25QXX芯片

news2025/4/21 22:47:47

 W25QXX芯片介绍
W25QXX芯片是华邦公司推出的大容量SPI FLASH产品,该系列有W25Q16/32/62/128等。本例程使用W25Q64,W25Q64容量为64Mbits(8M字节):8MB的容量分为128个块(Block)(块大小为64KB),每个块又分为16个扇区(Sector)(扇区大小为4KB);W25Q64的最小擦除单位为一个扇区即4KB,因此在选择芯片的时候必须要有4K以上的SRAM(可以开辟4K的缓冲区)。W25Q64的擦写周期多达10万次,具有20年的数据保存期限。
 

引脚介绍

下面只介绍W25Q64标准SPI接口,因为目前开发板上的封装使用的就是标准SPI接口。

 

下表是W25QXX的常用命令表

2. 硬件设计

D1指示灯用来提示系统运行状态,K_UP按键用来控制W25Q64数据写入,K_DOWN按键用来控制W25Q64数据读取,串口1用来打印写入和读取的数据信息

  • D1指示灯
  • K_UP和K_DOWN按键
  • USART1
  • SPI
  • W25Q64

在这里插入图片描述

 软件设计
STM32CubeMX设置

  • RCC设置外接HSE,时钟设置为72M
  • PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平
  • USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位
  • PA0设置为GPIO输入模式、下拉模式;PE3设置为GPIO输入模式、上拉模式
  • PG13设置为GPIO推挽输出模式、上拉、高速(片选引脚)名称为W25Q_CS
  • 激活SPI2,不开启NSS,数据长度8位,MSB先输出,分频因子256,CPOL为HIGH,CPHA为第二个边沿,不开启CRC检验,NSS为软件控制

在这里插入图片描述

 MDK-ARM编程

  • 在spi.c文件下可以看到SPI2的初始化函数,片选管脚的初始化在gpio.c中
void MX_SPI2_Init(void){
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;	//设置为主模式
  hspi2.Init.Direction = SPI_DIRECTION_2LINES;	//双线模式
  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;	//	8位数据长度
  hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;	//串行同步时钟空闲状态为高电平
  hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;	//第二个跳变沿采样
  hspi2.Init.NSS = SPI_NSS_SOFT;	//NSS软件控制
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;	//分配因子256
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;	//MSB先行
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;	//关闭TI模式
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;	//关闭硬件CRC校验
  hspi2.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi2) != HAL_OK){
    Error_Handler();
  }
}

void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle){
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(spiHandle->Instance==SPI2){
  __HAL_RCC_SPI2_CLK_ENABLE();  
  __HAL_RCC_GPIOB_CLK_ENABLE();
  /**SPI2 GPIO Configuration    
  PB13     ------> SPI2_SCK
  PB14     ------> SPI2_MISO
  PB15     ------> SPI2_MOSI */
  GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  GPIO_InitStruct.Pin = GPIO_PIN_14;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  }
}
  • 创建按键驱动文件key.c 和相关头文件key.h。
  • 创建包含W25Q64芯片的相关操作函数及驱动函数的文件w25qxx.c和w25qxx.h
#include "w25q64.h"
#include "redirect.h"

/*内部函数声明区*/
static HAL_StatusTypeDef w25q64_Transmit(uint8_t * T_pData, uint16_t T_Size);
static HAL_StatusTypeDef w25q64_Receive(uint8_t * R_pData, uint16_t R_Size);


/*内部函数定义区*/

/*
函数参数:
		1、T_pData:发送数据缓冲区中取出数据发送出去
		2、T_Size :需要发送的数据的长度
*/
static HAL_StatusTypeDef w25q64_Transmit(uint8_t * T_pData, uint16_t T_Size)
{
	return HAL_SPI_Transmit(&W25Q_SPI, T_pData, T_Size, 0xff);
}

/*
函数参数:
		1、R_pData:接收数据并放置到接收数据缓冲区中
		2、R_Size :需要接收的数据的长度
*/
static HAL_StatusTypeDef w25q64_Receive(uint8_t * R_pData, uint16_t R_Size)
{
	return HAL_SPI_Receive(&W25Q_SPI, R_pData, R_Size, 0xff);
}

/*
写使能或失能
	参数:
		Type:
			1、为1时使能
			2、为0时失能
*/
HAL_StatusTypeDef Write_En_De(uint8_t Type)
{
	uint8_t cmd;
	HAL_StatusTypeDef STD = HAL_ERROR;
	
	W25Q_CS_Level(0);

	switch(Type)
	{
		case 1:
			cmd = W25Q_W_ENA;
			break;
		case 0:
			cmd = W25Q_W_DIS;
			break;
		default:
			cmd = W25Q_W_DIS;
			break;
	}

	if(w25q64_Transmit(&cmd, 1) == HAL_OK)
	{
		STD = HAL_OK;
	}
	
	W25Q_CS_Level(1);
	return STD;
}

/*
读状态寄存器
	参数:Select
		1、为0时是寄存器1
		2、为1时是寄存器2
	参数:State(指针)
		1、返回的状态标志

	流程:先写入命令,然后读取状态
*/
HAL_StatusTypeDef Read_State_Reg(uint8_t Select, uint8_t* State)
{
	uint8_t cmd[4] = {0,0,0,0};
	HAL_StatusTypeDef STD = HAL_ERROR;
	
	W25Q_CS_Level(0);
	
	switch(Select)
	{
		case 0:
			cmd[0] = W25Q_R_STA_REG1;
			break;
		case 1:
			cmd[0] = W25Q_R_STA_REG2;
			break;
		default:
			cmd[0] = W25Q_R_STA_REG1;
			break;
	}
		
	if(w25q64_Transmit(cmd, 4) == HAL_OK)
	{
		if(w25q64_Receive(State,1) == HAL_OK)
		{
			STD = HAL_OK;
		}
	}

	W25Q_CS_Level(1);
	
	return STD;
}

/*
判忙
		用处:判断当前flash是否在忙碌状态
*/
void Judge_Busy(void)
{
	uint8_t State;	
	do{
		Read_State_Reg(0, &State);	//不要用指针类型局部变量传进去,必被卡死
		State &= 0x01;
	}while(State == 0x01);
}


/*
写状态寄存器
	参数:State(数组指针)
	参数解释:长度为两个字节的数组指针,
						第一个字节写入状态寄存器1;
						第二个字节写入状态寄存器2。

	流程:先写命令,再写状态
*/
HAL_StatusTypeDef Write_State_Reg(uint8_t * State)
{
	uint8_t cmd = W25Q_W_STA_REG_;
	HAL_StatusTypeDef STD = HAL_ERROR;
	
	Judge_Busy();
	Write_En_De(1);	
	W25Q_CS_Level(0);
//	Judge_Busy();
	
	if(w25q64_Transmit(&cmd, 1) == HAL_OK)
	{
		if(w25q64_Transmit(State, 2) == HAL_OK)
		{
			STD = HAL_OK;
		}
	}
	
	W25Q_CS_Level(1);
	Write_En_De(0);	
	return STD;
}

/*
读数据
			参数:R_Addr
						1、读取数据的地址
			参数:R_Data(数组指针)
						1、获取读取的数据
			参数:R_Size
						1、读取的数据的大小
*/
HAL_StatusTypeDef Read_Data(uint32_t R_Addr, uint8_t * R_Data, uint16_t R_Size)
{
	uint8_t cmd = W25Q_R_Dat;
	HAL_StatusTypeDef STD = HAL_ERROR;
	
	R_Addr <<= 8;	//只要24位,3个字节
	
	Judge_Busy();	//判忙
	W25Q_CS_Level(0);
//	Judge_Busy();
	
	if(w25q64_Transmit(&cmd, 1) == HAL_OK)
	{
		if(w25q64_Transmit((uint8_t *)&R_Addr, 3) == HAL_OK)
		{
			if(w25q64_Receive(R_Data,R_Size) == HAL_OK)
			{
				STD = HAL_OK;
			}
		}
	}
	
	W25Q_CS_Level(1);
	
	return STD;
}


/*
页编程
	页的描述:1字节到 256 字节(一页)
	页写的前提条件:编程之前必须保证额你存空间是0xff,
									所以得先进行擦除(擦除后模式全为1)
	页写的注意事项:进行页编程时,如果数据字节数超过了 256 字节,
									地址将自动回到页的起始地址,覆盖掉之前的数据。

	参数:WriteAddr
				1、地址,三个字节地址
	参数:PW_Data(数组指针)
				1、要写入的数据,长度根据PW_size来定
				2、高位先传
	参数:PW_Size
				2、要写入的数据长度

	流程:先开写使能、判忙,再写命令,
				再写3个字节的地址,后写入数据,最后写失能
*/

HAL_StatusTypeDef Page_Write(uint32_t WriteAddr, uint8_t * PW_Data, uint16_t PW_Size)
{
	uint8_t cmd = W25Q_Page_Program;
	HAL_StatusTypeDef STD = HAL_ERROR;
	
	WriteAddr <<= 8;	//只要24位,3个字节
	
	Judge_Busy();	//判忙
	Write_En_De(1);	
	Judge_Busy();

	W25Q_CS_Level(0);

	if(w25q64_Transmit(&cmd, 1) == HAL_OK)
	{
		if(w25q64_Transmit((uint8_t *)&WriteAddr, 3) == HAL_OK)
		{
			if(w25q64_Transmit(PW_Data, PW_Size) == HAL_OK)
			{
				STD = HAL_OK;
			}
		}
	}

	W25Q_CS_Level(1);
	Judge_Busy();
	
	return STD;
}



/*
扇区擦除
	扇区的描述:W25Q64总共8MB,分为128块(每块64KB),
							每块16个扇区,每个扇区4K个字节。
	扇区的备注:W25Q64的最小擦除单位就是一个扇区
							所以至少给芯片开辟一个4KB的缓存区,
							以防止一次性删除太多,而丢失数据。(显然单片机不会给他开辟这么大的空间)
	
	参数:Sector_Addr
				1、扇区地址,以4KB为单位寻址
				2、高位先发
*/
HAL_StatusTypeDef Sector_Erase(uint32_t Sector_Addr)
{
	uint8_t cmd = W25Q_Sector_Erase;
	HAL_StatusTypeDef STD = HAL_ERROR;
	
	//一个扇区有4KB的大小,
	//为了使找到对应的扇区地址,所以要乘以4KB
	Sector_Addr *= (1<<12);
	Sector_Addr <<= 8;	//只需要24位表示地址,并且高位先传
	
	Judge_Busy();
	Write_En_De(1);	
	W25Q_CS_Level(0);

	if(w25q64_Transmit(&cmd, 1) == HAL_OK)
	{
		if(w25q64_Transmit((uint8_t *)&Sector_Addr, 3) == HAL_OK)
		{
			STD = HAL_OK;
		}
	}

	W25Q_CS_Level(1);
	
	Judge_Busy();
	
	return STD;
}



/*
块擦除
	块的描述:W25Q64有8MB的容量,而8MB有128个块,所以1块有64kB的大小,
						所以这个函数一次能擦除64KB的大小。
	
	参数:Block_Addr
				1、块地址,共128个块,对应128个地址,以64K为单位寻址
				2、高位先传

	流程:先开写使能、判忙,再写命令,
				再写3个字节的地址,最后写失能
*/
HAL_StatusTypeDef	Block_Erase(uint32_t Block_Addr)
{
	uint8_t cmd = W25Q_Block_Erase;
	HAL_StatusTypeDef STD = HAL_ERROR;
	
	//总共有128个块,而一个块有64KB的大小,
	//为了使找到对应的块地址,所以要乘以64KB
	Block_Addr *= (1<<16);
	Block_Addr <<= 8;	//只需要24位表示地址,并且高位先传
	
	Judge_Busy();
	Write_En_De(1);	
	Judge_Busy();
	W25Q_CS_Level(0);

	if(w25q64_Transmit(&cmd, 1) == HAL_OK)
	{
		if(w25q64_Transmit((uint8_t *)&Block_Addr, 3) == HAL_OK)
		{
			STD = HAL_OK;
		}
	}
	
	W25Q_CS_Level(1);
	Judge_Busy();
	return STD;
}


/*
全片擦除
	描述:直接把芯片全部擦除
*/
HAL_StatusTypeDef Full_Erase(void)
{
	uint8_t cmd = W25Q_Full_Erase;
	HAL_StatusTypeDef STD = HAL_ERROR;
	
	Judge_Busy();
	Write_En_De(1);	
	W25Q_CS_Level(0);

	if(w25q64_Transmit(&cmd, 1) == HAL_OK)
	{
		STD = HAL_OK;
	}

	W25Q_CS_Level(1);
	Judge_Busy();
	
	return STD;
}


/*
读ID
	描述:读3个字节分别是生产厂家、存储器类型、容量
*/
HAL_StatusTypeDef Read_Jedec_ID(uint8_t * R_Jedec_ID)
{
	uint8_t cmd = W25Q_JEDEC_ID;
	HAL_StatusTypeDef STD = HAL_ERROR;
	
	Judge_Busy();
	W25Q_CS_Level(0);
//	Judge_Busy();
	
	if(w25q64_Transmit(&cmd, 1) == HAL_OK)
	{
		if(w25q64_Receive(R_Jedec_ID, 3) == HAL_OK)
		{
			STD = HAL_OK;
		}
	}
	
	W25Q_CS_Level(1);

	return STD;
}

#ifndef W25Q64__H__
#define W25Q64__H__

#include "spi.h"

/*句柄重命名*/
#define W25Q_SPI					hspi2

/*片选引脚定义与函数调用*/
#define W25Q_CS_Pin 			GPIO_PIN_0
#define W25Q_CS_Port			GPIOC

#define W25Q_CS_Level(_CS_STATE__)		HAL_GPIO_WritePin(W25Q_CS_Port, W25Q_CS_Pin, (GPIO_PinState)_CS_STATE__)

//#define W25Q_CS_Level(_CS_STATE__) (*((volatile unsigned int *)(0x42000000+((uint32_t)&GPIOC->ODR-0x40000000)*32+0*4))) = _CS_STATE__

#define W25Q_W_ENA				0x06		//写使能
#define W25Q_W_DIS				0x04		//写禁止

#define W25Q_R_Dat				0x03		//读数据

#define W25Q_R_STA_REG1		0x05		//读状态寄存器1,紧跟着的字节就是当前状态
#define	W25Q_R_STA_REG2		0x35		//读状态寄存器2,紧跟着的字节就是当前状态

#define W25Q_W_STA_REG_		0x01		//写状态寄存器,写入两个字节,分别到寄存器1,和寄存器2

#define W25Q_Page_Program 0x02		//页编程,先跟3个地址字节,再跟一个数据字节

#define W25Q_Block_Erase	0xD8		//块擦除64k,三个地址字节

#define W25Q_Sector_Erase	0x20		//扇区擦除,跟三个地址

#define W25Q_Full_Erase		0xC7		//全片擦除
												//0x60
												
#define W25Q_Susp_Erase		0x75		//暂停擦除

#define W25Q_Rest_Erase		0x7A		//恢复擦除

#define W25Q_PowDow_Mode	0xB9		//掉电模式

#define W25Q_HPer_Mode		0xA3		//高性能模式

#define W25Q_JEDEC_ID			0x9F		//读3个字节分别是生产厂家、存储器类型、容量

/*写使能或失能*/
HAL_StatusTypeDef Write_En_De(uint8_t Type);

/*读状态寄存器*/
HAL_StatusTypeDef Read_State_Reg(uint8_t Select, uint8_t* State);

/*判忙*/
void Judge_Busy(void);

/*写状态寄存器*/
HAL_StatusTypeDef Write_State_Reg(uint8_t * State);

/*读数据*/
HAL_StatusTypeDef Read_Data(uint32_t R_Addr, uint8_t * R_Data, uint16_t R_Size);

/*页写*/
HAL_StatusTypeDef Page_Write(uint32_t WriteAddr, uint8_t * PW_Data, uint16_t PW_Size);

/*扇区擦除*/
HAL_StatusTypeDef Sector_Erase(uint32_t Sector_Addr);

/*块擦除*/
HAL_StatusTypeDef	Block_Erase(uint32_t Block_Addr);

/*全片擦除*/
HAL_StatusTypeDef Full_Erase(void);

/*读ID*/
HAL_StatusTypeDef Read_Jedec_ID(uint8_t * R_Jedec_ID);


#endif /*W25Q64__H__*/

main.c

头文件

#include "w25q64.h"

变量

uint8_t device_id[3];
uint8_t read_buf[10] = {0};
uint8_t write_buf[10] = {0};
int i;

代码主体

	
  Read_Jedec_ID((uint8_t *)device_id);
  printf("W25Q64 ID 0x%x, 0x%x, 0x%x\r\n", device_id[0], device_id[1], device_id[2]);

  /* 为了验证,首先读取要写入地址处的数据 */
  printf("-------- read data before write -----------\r\n");
  Read_Data(0, read_buf, 10);

  for(i = 0; i < 10; i++) 
  {
    printf("[0x%08x]:0x%02x\r\n", i, *(read_buf+i));
  }

  /* 擦除该扇区 */
  printf("\r\n-------- erase sector 0 -----------\r\n");
  Sector_Erase(0);

  /* 再次读数据 */
  printf("-------- read data after erase -----------\r\n");
  Read_Data(0, read_buf, 10);
  for(i = 0; i < 10; i++)
  {
    printf("[0x%08x]:0x%02x\r\n", i, *(read_buf+i));
  }

  /* 写数据1,擦除扇区后的写入 */
  printf("\r\n-------- write data 11111 -----------\r\n");
  for(i = 0; i < 10; i++)
  {
    write_buf[i] = i;
  }
  Page_Write(0, write_buf, 10);

  /* 再次读数据 */
  printf("-------- read data after write -----------\r\n");
  Read_Data(0, read_buf, 10);
  for(i = 0; i < 10; i++)
  {
    printf("[0x%08x]:0x%02x\r\n", i, *(read_buf+i));
  }
	
//	Sector_Erase(0);
  /* 写数据2,未擦除连续写入,观察未擦除能否写入 */
  printf("\r\n-------- write data 22222 -----------\r\n");
  for(i = 0; i < 10; i++)
  {
    write_buf[i] = i*16;
  }
  Page_Write(0, write_buf, 10);

  /* 再次读数据 */
  printf("-------- read data after write -----------\r\n");
  Read_Data(0, read_buf, 10);
  for(i = 0; i < 10; i++)
  {
    printf("[0x%08x]:0x%02x\r\n", i, *(read_buf+i));
  }

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

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

相关文章

Python每日一练(20230413)

目录 1. 最后一个单词的长度 ※ 2. 全排列 &#x1f31f;&#x1f31f; 3. 计数质数 ※ &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 最后一个单词的长度 给你一个字符串 s&…

clickhouse布隆过滤器跳数索引最佳实践

背景 本文来聊一下clickhouse的这个列式存储数据库的布隆过滤器的跳数索引类型,来了解它的数据结构&#xff0c;它可以为那些查询类型提供查询优化。 跳数索引-布隆过滤器 首先布隆过滤器家族的跳数索引分成三种类型&#xff1a; ngrambf_v1,tokenbf_v1,bloom_filter其原理是…

Visual Studio 2022如何安装和使用MSDN

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;在后台收到提问&#xff0c;问我Visual Studio 2022如何安装和使用MSDN&#xff0c;这个我之前也没有在这个版本上装过MSDN&#xff0c;我之前是在Visual Studio 2017版上装过MSDN&#xff0c;那既然有人问了…

蓝桥杯【第14届省赛】Python B组

测试链接&#xff1a;https://www.dotcpp.com/oj/train/1093/ 测试结果还是蛮惨烈&#xff0c;主要原因有几个&#xff1a; C 语言网的时间限制是 3 s&#xff1a;但实际比赛的时间限制都是 10 s 起步&#xff0c;甚至有 30 s 的莫名其妙的运行报错&#xff1a;我不知道 D 题…

浅谈ChatGPT的关键技术与落地发展

分享嘉宾 | 刘焕勇 文稿整理 | William 1、从大规模语言模型看ChatGPT的起源与本质 ChatGPT可以拆开分为Chat和GPT去理解&#xff0c;前一个表示一种应用形式&#xff0c;后一个是生成式的模型。在百度百科里面定义为ChatGPT是人工智能技术驱动的自然语言处理工具&#xff0c…

数组与字符串C语言代码总结

《array》 arr.c #include <stdio.h>int main(int argc, char *argv[]) {int a[2][3]; int i, j;for (i 0; i < 2; i) {for (j 0; j < 3; j) printf("%p ", &a[i][j]); //验证二维数组连续性}printf("%p %…

d2l Markov序列模型

本节的任务是使用Markov模型对后续序列进行预测&#xff0c;使用sin函数&#xff0b;噪声绘制1000个样本点&#xff0c;取tau为4&#xff0c;即利用后四个的信息预测第五个。 目录 1.构造样本点 2.抽取iter 3.构造网络 4.训练 5.预测 5.1单步 5.1多步 1.构造样本点 T …

【程序人生】5个月从职场打杂到月薪14000的女测试工程师逆袭之路

大家好&#xff0c;我是来自湖南的一位辣妹子&#xff0c;毕业于一所工业大学&#xff0c;大学的专业是软件与工程&#xff0c;其实也算是本专业&#xff0c;大学期间掌握的知识也算比较广&#xff0c;各个方面都会一丢丢&#xff0c;就是不是特别深入。 之所以这么说&#xf…

nginx配置文件介绍

nginx配置文件介绍 nginx默认的配置文件是在安装目录下的 conf目录下&#xff0c;后续对 nginx 的使用基本上都是对此配置文件进行相应的修改。 配置文件中用#符号表示注释内容。 配置文件主要包括三部分&#xff0c;main、events和http main 用于进行nginx全局信息的配置…

Netty应用篇

Netty应用 粘包和半包 服务器代码 public class StudyServer {static final Logger log LoggerFactory.getLogger(StudyServer.class);void start() {NioEventLoopGroup boss new NioEventLoopGroup(1);NioEventLoopGroup worker new NioEventLoopGroup();try {ServerBoo…

【WebRTC技术专题】未来可期,WebRTC的诞生发展的概述介绍(1)

近几年实时音视频通信应用呈现出了大爆发的趋势。在这些实时通信技术的背后&#xff0c;有一项不得不提的技术 ——WebRTC。 前言背景 2021年1月26日&#xff0c;W3C&#xff08;万维网联盟&#xff09; 和 IETF &#xff08;互联网工程任务组&#xff09; 同时宣布 WebRTC&…

企业办公WLAN覆盖方案的设计与实现_kaic

企业办公WLAN覆盖方案的设计与实现 摘要&#xff1a; 无线LAN技术的快速发展已经使它在当今的数字通讯行业中变得越来越重要。它的优点包括易于部署、灵活操作、价格实惠&#xff0c;使它能够在不同的场景中提供支持。无线LAN技术已经被许多不同类型的人所接受&#xff0c;并且…

linux下使用lftp的小结

lftp的功能比较强大&#xff0c;相比原来用ftp&#xff0c;方便了很多。 1、登陆&#xff1a; lftp ftp://yournamesite pwd:***** 或 open ftp://yournamesite 2、基本操作&#xff08;转&#xff09; lftp使用介绍 lftp 是一个功能强大的下载工具&#xff0c;它支持访问…

React-Native 创建App项目

# React-Native 创建App项目 环境搭建 概述 RN的官方网站百度谷歌 安装环境介绍 操作系统&#xff1a;win10系统手机&#xff1a;安卓手机真机一部或夜神模拟器必须安装的依赖有&#xff1a;Node,JDK,Yarn,Android SDK,Python2 Node的安装 先到官网去下载node版本&#…

Cypress触摸芯片自己做的demo 代码

1.前言 &#xff08;1&#xff09;cyprees芯片主要是可以做一些触摸的检测并实现一些IO输出&#xff0c;使用的工具psoc creater &#xff08;2&#xff09;psoc creater 可以i直接通过GUI的方式配置一些GPIO的状态以及集成的功能模块&#xff0c;编译后&#xff0c;我们可直接…

基于深度学习的花卉识别

1、数据集 春天来了&#xff0c;我在公园的小道漫步&#xff0c;看着公园遍野的花朵&#xff0c;看起来真让人心旷神怡&#xff0c;一周工作带来的疲惫感顿时一扫而光。难得一个糙汉子有闲情逸致俯身欣赏这些花朵儿&#xff0c;然而令人尴尬的是&#xff0c;我一朵都也不认识。…

2022蓝桥杯省赛——砍竹子

问题描述 这天, 小明在砍竹子&#xff0c; 他面前有 n 棵竹子排成一排&#xff0c;一开始第 i 棵竹子的 高度为 hi​。 他觉得一棵一棵砍太慢了&#xff0c; 决定使用魔法来砍竹子。魔法可以对连续的一 段相同高度的竹子使用&#xff0c; 假设这一段竹子的高度为 H&#xff0…

UNIX环境高级编程——系统数据文件和信息

6.1 引言 UNIX系统的正常运行需要使用大量与系统有关的数据文件&#xff0c;这些文件都是ASCII文本文件&#xff0c;并且使用标准I/O库读这些文件。 6.2 口令文件 UNIX口令文件是/etc/passwd&#xff0c;每一行包含下图中的各字段&#xff0c;字段之间用冒号分隔&#xff0c…

除了Jira、禅道还有哪些更好的敏捷开发过程管理平台?

无论是从国内的敏捷调研开发调研报告还是从国外的敏捷状态调查&#xff0c;工具支持一直是决定敏捷成功的关键因素之一&#xff0c;它们可以帮助团队提高软件开发的效率、质量、协作和满意度。选择合适的敏捷开发管理工具&#xff0c;并正确地使用它们&#xff0c;是每个敏捷团…

JAVA SMART系统-系统框架设计与开发

SMART系统是一个新型智能在线考试信息管理系统&#xff0c;该系统主要实现了学生在线考试与评估以及教师对学生在线考试信息的管理和维护。本文按照SMART系统的非功能性需求&#xff0c;基于Struts、Spring、Hibernate三种开源技术&#xff0c;构建了一个具有良好的可扩展性、可…