STM32——“SPI Flash”
引入
在给单片机写程序的时候,有时会用到显示屏,就拿市面上的0.96寸单色显示器来说,一张全屏的图片就占用8x128=1024个字节,即1kb的空间,这对于单片机来说确实有点奢侈,于是我买了一个8Mb的SPI Flash,型号为华邦的W25Q64。
在手册里很容易看到他的介绍:
它支持四线的SPI,在很大程度上增加了读写速度,同时在H7系列中还可以用作扩展的Flash,自带的QSPI功能强大,但是在F1系列中没有QSPI的功能,因此这里只介绍用STM32的普通硬件SPI来驱动这块Flash。
想要驱动这块Flash,首先要配置STM32的硬件SPI:
一、配置SPI
SPI_HandleTypeDef g_W25Qxx_Handle;void SPI_Init()
{g_W25Qxx_Handle.Instance = SPIx;g_W25Qxx_Handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;g_W25Qxx_Handle.Init.CLKPhase = SPI_PHASE_1EDGE;g_W25Qxx_Handle.Init.CLKPolarity = SPI_POLARITY_LOW;g_W25Qxx_Handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;g_W25Qxx_Handle.Init.CRCPolynomial = 1;g_W25Qxx_Handle.Init.DataSize = SPI_DATASIZE_8BIT;g_W25Qxx_Handle.Init.Direction = SPI_DIRECTION_2LINES;g_W25Qxx_Handle.Init.FirstBit = SPI_FIRSTBIT_MSB;g_W25Qxx_Handle.Init.Mode = SPI_MODE_MASTER;g_W25Qxx_Handle.Init.NSS = SPI_NSS_SOFT;g_W25Qxx_Handle.Init.TIMode = SPI_TIMODE_DISABLE;HAL_SPI_Init(&g_W25Qxx_Handle);}void SPI_GPIO_Init()
{SPI_FLASH_SCLK_RCC();SPI_FLASH_CS_RCC();SPI_FLASH_MISO_RCC();SPI_FLASH_MOSI_RCC();SPI_FLASH_SPI_RCC();GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pin = FLASH_SCLK_PIN;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(SPI_FLASH_SCLK_PORT,&GPIO_InitStruct);GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pin = FLASH_MISO_PIN;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(SPI_FLASH_MISO_PORT, &GPIO_InitStruct);GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pin = FLASH_MOSI_PIN;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(SPI_FLASH_MOSI_PORT,&GPIO_InitStruct);GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 普通输出GPIO_InitStruct.Pin = FLASH_CCS_PIN;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(SPI_FLASH_CCS_PORT, &GPIO_InitStruct);
}void SelectChip()
{HAL_GPIO_WritePin(SPI_FLASH_CCS_PORT,FLASH_CCS_PIN,GPIO_PIN_RESET);
}void UnselectChip()
{HAL_GPIO_WritePin(SPI_FLASH_CCS_PORT,FLASH_CCS_PIN,GPIO_PIN_SET);
}
引脚宏为:
#define SPIx SPI1#define FLASH_CCS_PIN GPIO_PIN_4
#define FLASH_SCLK_PIN GPIO_PIN_5
#define FLASH_MISO_PIN GPIO_PIN_6
#define FLASH_MOSI_PIN GPIO_PIN_7#define SPI_FLASH_SCLK_PORT GPIOA
#define SPI_FLASH_CCS_PORT GPIOA
#define SPI_FLASH_MISO_PORT GPIOA
#define SPI_FLASH_MOSI_PORT GPIOA#define SPI_FLASH_SCLK_RCC() __HAL_RCC_GPIOA_CLK_ENABLE()
#define SPI_FLASH_CS_RCC() __HAL_RCC_GPIOA_CLK_ENABLE()
#define SPI_FLASH_MISO_RCC() __HAL_RCC_GPIOA_CLK_ENABLE()
#define SPI_FLASH_MOSI_RCC() __HAL_RCC_GPIOA_CLK_ENABLE()#define SPI_FLASH_SPI_RCC() __HAL_RCC_SPI1_CLK_ENABLE()
在SPI的配置上使用模式0或者模式3的高位先发,在这里我使用模式0,即:极性为低,相位是在第一个上升沿。
体现在上边的代码为:
g_W25Qxx_Handle.Init.CLKPhase = SPI_PHASE_1EDGE;g_W25Qxx_Handle.Init.CLKPolarity = SPI_POLARITY_LOW;
由于在我写硬件SPI代码的过程中,遇到了不能准确识别芯片的问题,研究了很久,才发现是片选代码的问题,即:在写了OLED驱动之后由于思维惯性,我的想法是只要持续拉低片选就一直可以通信,但现实是的确可以通信,只是Flash貌似识别不了我发的命令。最后的解决方法是在每次通信之前拉低片选,通信完之后拉高片选。这里的通信是有命令发出的时候。
解决完这个问题之后,首先要做的就是和Flash建立通信,即获取Flash的ID。
二、查询ID
在手册里,Flash的ID为:EF4017
对应的查询命令为:0x9F
第一个是厂商ID,后边的是芯片ID。
/*
**** 函数名 W25Q64GetID
**** 功能 W25Q64 读取设备ID号
**** 参数 无
****
*/uint32_t W25Qxx_GetID()
{uint32_t ID = 0;uint8_t id[3];uint8_t cmd = JEDEC_ID;SelectChip();HAL_SPI_Transmit(&g_W25Qxx_Handle,&cmd,1,1000);HAL_SPI_Receive(&g_W25Qxx_Handle,id,3,1000);ID = (((((ID | id[0]) << 8) | id[1]) << 8) | id[2]);UnselectChip();return ID;
}
这里发送命令,然后接收三个字节的ID,最后拼接ID并返回。
int main()
{HAL_Init();SystemClock_Config();OLED_Init();LED_Init();W25Qxx_Init();UsartInit(115200);printf("现在进行硬件SPI实验!\n\n");uint32_t id = W25Qxx_GetID();printf("芯片ID为:%X\n\n",id);while(1){}
}
执行后的效果如下:
可见完全没问题。
三、读状态寄存器
接下来是写数据,但是在写数据之前需要写使能和擦除扇区,另外在进行这两个操作之前需要检查Flash是否繁忙,于是接下来是检查Flash的状态,即,检查状态寄存器1
我们主要检查第一个寄存器的第一个比特位。然而检查第一个寄存器状态的命令是0x05
返回之后对第一位进行检查:
/*
**** 函数名 W25Q64CheckBusy
**** 功能 W25Q64 读状态寄存器
**** 参数 无
****
*/
void W25Qxx_CheckBusy()
{uint8_t ret = 0;uint8_t cmd = ReadStatusRegister;SelectChip();HAL_SPI_Transmit(&g_W25Qxx_Handle,&cmd,1,1000);do{HAL_SPI_Receive(&g_W25Qxx_Handle,&ret,1,1000);}while((ret & 0x01) == 0x01);UnselectChip();
}
倘若Flash繁忙,则第一位为1,反之为0,为1就一直检查,直到芯片空闲。
接下来是写使能。
四、写使能
Flash手册里提到:在进行写入,擦除,写状态寄存器等操作之前必须进行写使能。
它对应的命令是0x06
/*
**** 函数名 W25Q64WriteEnable
**** 功能 W25Q64 写使能
**** 参数 无
****
*/
void W25Qxx_WriteEnable()
{uint8_t cmd = WriteEnable;SelectChip();HAL_SPI_Transmit(&g_W25Qxx_Handle,&cmd,1,1000);UnselectChip();
}
准备工作进行完之后就是擦除了。
五、擦除
W25Q64的擦除命令有四个:扇区擦除(4kb)-0x20,块擦除(32kb)-0x52,块擦除(64kb)-0xD8,全片擦除-0x60。
由于前三个的代码大同小异,因此只介绍一下第一个和最后一个。
1.扇区擦除(4kb)
这里是需要输入地址的,因此在发送命令以后需要发送地址,大小为24位:
/*
**** 函数名 W25Q64SectorErase
**** 功能 W25Q64 扇区擦除(4kb)
**** 参数 address:24位的地址
****
*/
void W25Qxx_SectorErase(uint32_t address)
{uint8_t cmd[4];cmd[0] = SectorErase;cmd[1] = (address >> 16) & 0xFF;cmd[2] = (address >> 8) & 0xFF;cmd[3] = address & 0xFF;W25Qxx_CheckBusy();W25Qxx_WriteEnable();W25Qxx_CheckBusy();SelectChip();HAL_SPI_Transmit(&g_W25Qxx_Handle,cmd,4,1000);UnselectChip();
}
擦除之前记得写使能和检查芯片状态。
2.全片擦除
全片擦除不需要输入地址,但是全片擦除等待的时间很长。
/*
**** 函数名 W25Q64ChipErase
**** 功能 W25Q64 全片擦除
**** 参数 无
****
*/
void W25Qxx_ChipErase()
{uint8_t cmd[1];cmd[0] = ChipErase;W25Qxx_CheckBusy();W25Qxx_WriteEnable();W25Qxx_CheckBusy();SelectChip();HAL_SPI_Transmit(&g_W25Qxx_Handle,cmd,1,1000);UnselectChip();W25Qxx_CheckBusy();
}
这里可以测试一下全片擦除的时间:
int main()
{HAL_Init();SystemClock_Config();OLED_Init();LED_Init();W25Qxx_Init();UsartInit(115200);printf("现在进行硬件SPI实验!\n\n");uint32_t id = W25Qxx_GetID();printf("芯片ID为:%X\n\n",id);uint32_t head = 0,tail = 0;if(id == 0xEF4017){head = HAL_GetTick();W25Qxx_ChipErase();tail = HAL_GetTick();printf("全片擦除所用的时间为%d ms\n\n",tail - head); }while(1){}
}
时间还是比较长的。另外值得注意的是,根据我的实验结果,擦除时候并不是按照你给的地址开始擦除,而是擦除你地址所在的扇区或者块。
六、页编程
页编程的命令是0x02
在此之前付下如图:
这个图介绍了编程的最小范围是一页,编程超过一页的需要手动变换地址,因为一页写满之后,地址并不会自动跳到下一页继续写,而是回到该页首地址继续写,这样会造成前后数据的覆盖。另外一页是256字节。
/*
**** 函数名 W25Q64PageProgram
**** 功能 W25Q64 页编程(一页256字节)
**** 参数 address:24位的地址
**** 参数 data: 写入的数据
**** 参数 Size:数据的大小,单位:字节
*/
void W25Qxx_PageProgram(uint32_t address,uint8_t* data,uint16_t Size)
{uint8_t cmd[4];cmd[0] = PageProgram;cmd[1] = (address >> 16) & 0xFF;cmd[2] = (address >> 8) & 0xFF;cmd[3] = address & 0xFF;W25Qxx_CheckBusy();W25Qxx_WriteEnable();W25Qxx_CheckBusy();SelectChip();HAL_SPI_Transmit(&g_W25Qxx_Handle,cmd,4,1000);HAL_SPI_Transmit(&g_W25Qxx_Handle,data,Size,10000);UnselectChip();
}
这个页编程介绍的东西不多,最重要的是下边的随意地址编程,最重要的就是解决写满一页以后需要手动解决地址偏移的问题。
七、写任意大小数据
由于页BUFF的限制,一次性只能写入256个字节,因此这个操作就是持续重复写入256及以下字节。
/*
**** 函数名 W25Q64WriteData
**** 功能 W25Q64 写入数据
**** 参数 address:24位的地址
**** 参数 databuffer:写入的数据
**** 参数 Size:读取数据的大小,单位:字节3
*/
void W25Qxx_WriteData(uint32_t address, uint8_t* data, uint32_t Size)
{if (address > 0x7FFFFF || data == NULL) // 检查输入参数合法性{return;}uint8_t offset = address % 256; // 当前地址的页内偏移uint16_t remainingInPage = 256 - offset; // 当前页剩余空间大小// 判断数据是否跨页if (Size <= remainingInPage) // 数据小于或等于当前页剩余空间{W25Qxx_PageProgram(address, data, Size); // 写入当前页return;}// 数据跨页// 先填满当前页W25Qxx_PageProgram(address, data, remainingInPage);// 更新地址和数据指针address += remainingInPage;data += remainingInPage;Size -= remainingInPage;// 写入完整页的数据while (Size >= 256){W25Qxx_PageProgram(address, data, 256);address += 256;data += 256;Size -= 256;}// 写入最后不足一页的数据if (Size > 0){W25Qxx_PageProgram(address, data, Size);}
}
在代码中,offset是计算的相对于该写入地址所在的页的首地址的偏移量,remainingInPage 用于计算该页剩余可写入空间大小。举个例子,一个地址是0x100即256,该地址所在的页是[256,511] 一共256个字节,因为前一个页是[0,255]。那么我要在256地址处写数据,那么它的offset = 256%256 = 0,剩余可写入空间为remainingInPage = 256 - 0 = 256。所以我们可以按照这样的算法,来先把当前页填充满,当前页填充满之后就可以成整数倍的填充256个字节,当剩余的数据小于256字节的时候,在单独填充,这样做的好处就是可以在任意地址写入任意大小的数据,且不用担心数据覆盖。
八、读任意大小数据
读数据的命令是0x03。
/*
**** 函数名 W25Q64ReadData
**** 功能 W25Q64 读取数据
**** 参数 address:24位的地址
**** 参数 databuffer:数据接收缓冲区
**** 参数 Size:读取数据的大小,单位:字节
*/
void W25Qxx_ReadData(uint32_t address,uint8_t* databuffer,uint32_t Size)
{uint8_t cmd[4];cmd[0] = ReadData;cmd[1] = (address >> 16) & 0xFF;cmd[2] = (address >> 8) & 0xFF;cmd[3] = address & 0xFF;W25Qxx_CheckBusy();SelectChip();HAL_SPI_Transmit(&g_W25Qxx_Handle,cmd,4,1000);HAL_SPI_Receive(&g_W25Qxx_Handle,databuffer,Size,100000);UnselectChip();}
这个可讲解的地方不多,单纯发送读命令后再接收数据。
九、测试
最后测试一下代码效果:
void W25QxxTest()
{uint16_t head,tail;for(uint16_t i = 0;i < 8192;i++){data[i] = '1';}data[8191] = '\0';printf("现在进行硬件SPI实验!\n\n");uint32_t id = W25Qxx_GetID();printf("芯片ID为:%X\n\n",id);if(id == W25Q64_ID){printf("正在擦除...\n");W25Qxx_BlockErase(0x000000);printf("擦除成功!\n\n");printf("正在写入...写入数据量为8kb\n");head = HAL_GetTick();W25Qxx_WriteData(0x00000A,data,8192);tail = HAL_GetTick();printf("写入成功!,写入花费的时间为:%d ms\n\n",tail - head);printf("正在读取数据,读取数据量为8kb\n");head = HAL_GetTick();W25Qxx_ReadData(0x00000A,test,8192);tail = HAL_GetTick();if(memcmp(test,data,8192) == 0){printf("读取成功,读取花费的时间为:%d ms\n\n",tail - head);}else{printf("读取失败\n");}printf("读取到的数据是: %s\n",test);}}
END............
相关文章:
STM32——“SPI Flash”
引入 在给单片机写程序的时候,有时会用到显示屏,就拿市面上的0.96寸单色显示器来说,一张全屏的图片就占用8x1281024个字节,即1kb的空间,这对于单片机来说确实有点奢侈,于是我买了一个8Mb的SPI Flash&#x…...
Zookeeper基本命令解析
ZooKeeper -server host:port -client-configuration properties-file cmd args addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE addauth scheme auth 一、整体命令格式 ZooKeeper -serve…...
React-更新state的数据,dom没有重新渲染
{entourageList.map((person) > (<Row key{person.id}> {/* 使用唯一的 person.id */}<Col span{16}><Row gutter{16}><Col lg{9} md{18} sm{24}><FormItem label{姓名}>{getFieldDecorator(name-${person.id}, {initialValue: person.name,…...
消息队列技术的发展历史
消息队列技术的演进历程宛如一幅波澜壮阔的科技画卷,历经多个标志性阶段,各阶段紧密贴合不同的技术需求与市场风向,下面为您详细道来。 第一阶段:消息中间件的起源(1970 年代末期 - 1980 年代中期) 在计算…...
20.抽卡只有金,带保底(WPF) C#
这是一个界面应用化后的抽卡,目前只能抽金,只有基础概率加保底概率 适合界面化应用初学者。 这是展示图: 使用的是WPF不是winform,我也是第一次做WPF内容,就可以试一试,代码都在这里了,简单来…...
DALFox-一款XSS自动化扫描工具
声明!本文章所有的工具分享仅仅只是供大家学习交流为主,切勿用于非法用途,如有任何触犯法律的行为,均与本人及团队无关!!! 目录标题 一、介绍及使用启动及使用1. 单个扫描2. 多个扫描3. 文件扫描…...
软件测试之压力测试【详解】
压力测试 压力测试是一种软件测试,用于验证软件应用程序的稳定性和可靠性。压力测试的目标是在极其沉重的负载条件下测量软件的健壮性和错误处理能力,并确保软件在危急情况下不会崩溃。它甚至可以测试超出正常工作点的测试,并评估软件在极端…...
电视大全 1.3.8|汇聚多频道资源,秒切换流畅播放
电视大全TV版是一款功能丰富的TV端直播软件,由悠兔电视的同一开发者打造。最新版本更新了更多频道,包括央视、卫视和地方频道等,提供了多线路流畅播放体验,并支持节目回看、线路选择、开机自启等功能。该应用免登录且无购物频道&a…...
MaxKB基于大语言模型和 RAG的开源知识库问答系统的快速部署教程
1 部署要求 1.1 服务器配置 部署服务器要求: 操作系统:Ubuntu 22.04 / CentOS 7.6 64 位系统CPU/内存:4C/8GB 以上磁盘空间:100GB 1.2 端口要求 在线部署MaxKB需要开通的访问端口说明如下: 端口作用说明22SSH安装…...
大恒相机开发(3)—大恒相机工业检测的实际案例
大恒相机工业检测的实际案例 工业检测的实际案例图像采集性能优化技巧工业环境下的稳定性 工业检测的实际案例 以下是一些使用大恒相机进行工业检测的实际案例: 多特征光学成像系统: 在这个案例中,使用大恒相机构建了一个全方位、多特征的图…...
《Java 与 OpenAI 协同:开启智能编程新范式》
在当今科技飞速发展的时代,人工智能已成为推动各领域创新变革的核心力量。OpenAI 作为人工智能领域的领军者,其开发的一系列强大模型,如 GPT 系列,为自然语言处理等诸多任务带来了前所未有的突破。而 Java,作为一种广泛…...
HarmonyOS NEXT 技术实践-基于基础视觉服务的多目标识别
在智能手机、平板和其他智能设备日益智能化的今天,视觉识别技术成为提升用户体验和智能交互的重要手段。HarmonyOS NEXT通过基础视觉服务(HMS Core Vision)提供了一套强大的视觉识别功能,其中多目标识别作为其关键技术之一&#x…...
MySQL体系架构
MySQL Server架构自顶向下大致可以分网络连接层、服务层、存储引擎层和系统文件层。 网络连接层 客户端连接器(Connectors):提供与MySQL服务器建立的支持。目前几乎支持所有主 流的服务端编程技术,例如常见的 Java、C、Python、.…...
如何学习Trustzone
阅读官方文档 ARM 官方文档是学习 Trustzone 最权威的资料来源。例如,ARM Architecture Reference Manual 中详细介绍了 Trustzone 的架构原理、寄存器定义和操作模式等内容。这些文档虽然比较复杂,但能够提供最准确的技术细节,适合在学习过…...
【视觉SLAM:Panoptic FPN全景分割网络】
Panoptic FPN是一种全景分割(Panoptic Segmentation)的经典网络,最早由 Kirillov 等人在 2019 年提出。全景分割是一种统一的视觉任务,结合了实例分割(Instance Segmentation)和语义分割(Semant…...
【Linux】数据呈现
一、数据的输入与输出 1、标准文件描述符 Linux系统会将每个对象都当做文件来处理,包括输入和输出。它用文件描述符来标识每个文件对象。 文件描述符是一个非负整数,唯一会标识的是会话中打开的文件。每个进程一次最多可以打开9个文件描述符。bash sh…...
编译原理期末复习--伪代码部分
1.词法分析 token token nexttoken()c getchar();switch(c):case <:c getchar();switch(c):case : return RE;case >: return NE;default: rollback(); return LT;case :return EQ;case >:c getchar();switch(c):case : return GE;default: rollback(); return GT…...
云原生相关的 Go 语言工程师技术路线(含博客网址导航)
要成为一名云原生相关的 Go 语言工程师,需要在 Go 语言、云原生技术栈以及相关的开发和运维工具上建立扎实的基础。下面是一个前字节员工总结的技术路线规划: 1. 掌握 Go 语言基础 深入理解 Go 语言:你需要熟练掌握 Go 的语法、数据结构、并…...
基于Springboot + vue实现的汽车资讯网站
🥂(❁◡❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞 💖📕🎉🔥 支持我:点赞👍收藏⭐️留言📝欢迎留言讨论 🔥🔥&…...
【YashanDB知识库】ycm-YashanDB列表有数据库显示故障排除步骤
本文内容来自YashanDB官网,原文内容请见 https://www.yashandb.com/newsinfo/7802959.html?templateId1718516 数据库状态 正常 异常 1、查看告警列表 例如:告警显示实例无法连接,一般是数据库实例服务掉了,需要尽快联系系统…...
如何使用 FastAPI 框架创建 RESTful API ?
FastAPI是一个现代、快速(高性能)的Web框架,用于构建API,它基于Python 3.6的类型提示功能,可以自动生成交互式API文档(使用Swagger UI或ReDoc),并且支持异步编程。 二、创建第一个F…...
Java 继承
继承是所有 OOP 语言和 Java 语言不可缺少的组成部分。 继承是 Java 面向对象编程技术的一块基石,是面向对象的三大特征之一,也是实现软件复用的重要手段,继承可以理解为一个对象从另一个对象获取属性的过程。 如果类 A 是类 B 的父类&…...
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
此项目是基于人脸识别的考勤系统开发,包括如下模块: 1、人脸识别考勤系统GUI界面设计,包括: (1)Qt环境(window环境/linux环境) ; (2)Qt工程创建分析; &am…...
门户系统需要压测吗?以及门户系统如何压力测试?
一、门户系统为什么要进行压力测试? 首先一点要明确一下,统一门户上线以后,将是所有应用系统的入口,对应门户稳定性要求较高,门户实现了统一入口和统一认证,系统宕机将影响其他系统使用。一般部署架构要求…...
Linux扩展——shell编程
前置:Linux基础及命令复习 目录 shell概述Shell脚本入门案例 sh bash ./ . source 变量系统预定义变量 $HOME $PWD $SHELL等自定义变量 unset readonly补充:开启子Shell进程的常见方法 (...) $(...) ... <(...) >(...) 特殊变量 $n $# $* $ $&…...
golang, go sum文件保证下载的依赖模块是一致的
在 Go 编程语言中,go.sum 文件是 Go 模块管理的一部分,主要用于记录模块的校验信息(模块版本的校验和)。它的设计目标是确保模块的完整性和安全性,解决以下关键问题: 1. 确保模块版本的一致性 go.sum 文件…...
TANGO与LabVIEW控制系统集成
TANGO 是一个开源的设备控制和数据采集框架,主要用于管理实验室设备、自动化系统和工业设备。它为不同类型的硬件提供统一的控制接口,并支持设备之间的通信,广泛应用于粒子加速器、同步辐射光源、实验室自动化和工业控制等领域。 1. TANGO的核…...
【day14】异常处理与Object类深入解析
【day13】回顾 在深入探讨异常处理与Object类之前,让我们回顾一下【day13】中的关键内容: 权限修饰符: public:最广的访问范围,任何地方都可以访问。protected:在同包和子类中可以访问。默认(无…...
云技术基础知识(二):虚拟化与容器技术
内容预览 ≧∀≦ゞ 虚拟化与容器技术虚拟化技术一、虚拟化的核心概念二、虚拟化的主要类型1. 服务器虚拟化2. 操作系统虚拟化(容器化)3. 网络虚拟化4. 存储虚拟化 三、虚拟化的实现方法和工具1. 服务器虚拟化实现2. 操作系统虚拟化(容器化&am…...
【Java基础面试题033】Java泛型的作用是什么?
Java的基础语法可以看尚硅谷的这个PDF:尚硅谷JavaSE基础/《Java从入门到精通(JDK17版)》_尚硅谷电子书.pdf Autism_Btkrsr/Blog_md_to_pdf - 码云 - 开源中国 (gitee.com) 回答重点 Java泛型的作用是通过在编译时检查类型安全,允许程序员编写更通用和…...
Linux 基本使用和程序部署
1. Linux 环境搭建 1.1 环境搭建方式 主要有 4 种: 直接安装在物理机上。但是Linux桌面使用起来非常不友好,所以不建议。[不推荐]。使用虚拟机软件,将Linux搭建在虚拟机上。但是由于当前的虚拟机软件(如VMWare之类的)存在一些bugÿ…...
react中使用ResizeObserver来观察元素的size变化
在 React 中使用 ResizeObserver 来观察元素的大小变化,可以通过创建一个自定义 Hook 来封装 ResizeObserver 的逻辑,并在组件中使用这个 Hook。以下是一个完整的示例,展示了如何在 React 中使用 ResizeObserver 来观察元素的大小变化。 自定…...
常见数据结构
1.数组 vector 2.链表 list 双向链表,不能通过下标找元素 3.栈 stack 4.队列 queue 优先队列priority_queue. 默认队头为最大值,可以用来任务调度,图算法,霍夫曼树 5.双端队列 deque 6.集合 set multiset s.begin() //返回…...
【服务器】linux服务器管理员查看用户使用内存情况
【服务器】linux服务器管理员查看用户使用硬盘内存情况 1、查看所有硬盘内存使用情况 df -h2、查看硬盘挂载目录下所有用户内存使用情况 du -sh /public/*3、查看某个用户所有文件夹占用硬盘内存情况 du -sh /public/zhangsan/*...
Java-冒泡排序、选择排序、二分查找算法
1. 冒泡排序 (1) 冒泡排序:每次从数组中找出最大值放在数值的后面去 public static void main(String[] args) {//冒泡排序int[] arr {5, 6 ,4, 9, 3, 1};for (int i 0; i < arr.length - 1; i) {for (int j 0; j < arr.length - i - 1; j) {if (arr[j] &…...
leetcode之hot100---240搜索二维矩阵II(C++)
思路一:通过遍历主对角线上元素判断查找方向 主对角线遍历: 遍历主对角线上的每个元素(matrix[i][i]),其中 i 的范围是 [0, min(m, n) - 1]。如果目标值小于当前主对角线元素,说明目标值可能在当前元素的左…...
牛客--求小球落地5次后所经历的路程和第5次反弹的高度,称砝码
求小球落地5次后所经历的路程和第5次反弹的高度 描述 假设有一个小球从 hh 米高度自由落下,我们不考虑真实的物理模型,而是简洁的假定,该小球每次落地后会反弹回原高度的一半;再落下,再反弹;……。 求小球…...
EasyPoi 使用$fe:模板语法生成Word动态行
1 Maven 依赖 <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-spring-boot-starter</artifactId><version>4.0.0</version> </dependency> 2 application.yml spring:main:allow-bean-definition-over…...
在 PowerShell 中优雅地显示 Python 虚拟环境
在使用 Python 进行开发时,虚拟环境管理是一个非常重要的部分。无论是使用 venv 还是 conda,我们都希望能够清晰地看到当前所处的虚拟环境。本文将介绍如何在 PowerShell 中配置提示符,使其能够优雅地显示不同类型的 Python 虚拟环境。 问题…...
GUI07-学工具栏,懂MVC
MVC模式,是天底下编写GUI程序最为经典、实效的一种软件架构模式。当一个人学完菜单栏、开始学习工具栏时,就是他的一生中,最适合开始认识 MVC 模式的好时机之一。这节将安排您学习: Model-View-Controller 模式如何创建工具栏以及…...
免费线上签字小程序,开启便捷电子签名
虽如今数字化飞速发展的时代,但线上签名小程序的开发制作却并非易事。需要攻克诸多技术难题,例如确保签名的真实性与唯一性,防止签名被伪造或篡改。 要精准地捕捉用户手写签名的笔迹特征,无论是笔画的粗细、轻重,还是…...
计算机的错误计算(一百八十九)
摘要 用大模型计算 tan(12.345) . 自变量取弧度。结果保留10位有效数字。不同于前面两节的大模型,本节调用了新的两个大模型。然而,很遗憾,它们给出的答案似乎仍然是“匹配”出来的,不是计算出来的。当然,均是错误的。…...
HDR视频技术之十一:HEVCH.265 的 HDR 编码方案
前文我们对 HEVC 的 HDR 编码优化技术做了介绍,侧重编码性能的提升。 本章主要阐述 HEVC 中 HDR/WCG 相关的整体编码方案, 包括不同应用场景下的 HEVC 扩展编码技术。 1 背景 HDR 信号一般意味着使用更多比特,一般的 HDR 信号倾向于使用 10…...
使用 AI 辅助开发一个开源 IP 信息查询工具:一
本文将分享如何借助当下流行的 AI 工具,一步步完成一个开源项目的开发。 写在前面 在写代码时,总是会遇到一些有趣的机缘巧合。前几天,我在翻看自己之前的开源项目时,又看到了 DDNS 相关的讨论。虽然在 2021 年我写过两篇相对详细的教程&am…...
『 Linux 』高级IO (一)
文章目录 内容回顾及铺垫五种IO模型不同类型IO的区别非阻塞IOfcntl( ) 多路转接 - select( )select( ) 的基本使用 - SelectServer服务器 内容回顾及铺垫 在博客『 Linux 』基础IO/文件IO (万字)中介绍了对IO的认识; IO实际上为Input/Output,输入输出; 以网络协议栈的视角来看,…...
Cisco WebEx 数据平台:统一 Trino、Pinot、Iceberg 及 Kyuubi,探索 Apache Doris 在 Cisco 的改造实践
导读:Cisco WebEx 早期数据平台采用了多系统架构(包括 Trino、Pinot、Iceberg 、 Kyuubi 等),面临架构复杂、数据冗余存储、运维困难、资源利用率低、数据时效性差等问题。因此,引入 Apache Doris 替换了 Trino、Pinot…...
Java - 日志体系_Apache Commons Logging(JCL)日志接口库
文章目录 官网1. 什么是JCL?2. JCL的主要特点3. JCL的核心组件4. JCL的实现机制5. SimpleLog 简介6. CodeExample 1 : 默认日志实现 (JCL 1.3.2版本)Example 2 : JCL (1.2版本) Log4J 【安全风险高,请勿使用】 7. 使用…...
Linux驱动开发 IIC I2C驱动 编写APP访问EEPROM AT24C02
在嵌入式开发中,I2C(Inter-Integrated Circuit)是一种常用的串行通信协议,广泛应用于与外设(如 EEPROM、传感器、显示屏等)进行数据交换。AT24C02 是一种常见的 I2C EEPROM 存储器,它提供 2Kbit…...
盒子模型(外边距的设置)
用于页面中元素的合理布局所有的元素都可以有宽高所有元素都是一个矩形所有元素都可以看成一个盒子盒子包括 外边距边框内边距元素内容 外边距设置 外边距的要素:top、bottom、left、right外边距的尺寸:合法的尺寸单位外边距语法:marign-方…...
买卖股票的最佳时机 IV - 困难
************* C topic:188. 买卖股票的最佳时机 IV - 力扣(LeetCode) ************* Stock angin: Still stocks. Intuitively, it feels hard. For once: class Solution { public:int maxProfit(vector<int>& prices) {in…...