【随手笔记】FLASH-W25Q16(三)

#include "bsp_w25q16.h"/*内部函数声明区*/
static HAL_StatusTypeDef bsp_w25q_Transmit(uint8_t * T_pData, uint16_t T_Size);
static HAL_StatusTypeDef bsp_w25q_Receive(uint8_t * R_pData, uint16_t R_Size);/*内部函数定义区*//*
函数参数:1、T_pData:发送数据缓冲区中取出数据发送出去2、T_Size :需要发送的数据的长度
*/
static HAL_StatusTypeDef bsp_w25q_Transmit(uint8_t * T_pData, uint16_t T_Size)
{return HAL_SPI_Transmit(&W25Q_SPI, T_pData, T_Size, 0xffff);
}/*
函数参数:1、R_pData:接收数据并放置到接收数据缓冲区中2、R_Size :需要接收的数据的长度
*/
static HAL_StatusTypeDef bsp_w25q_Receive(uint8_t * R_pData, uint16_t R_Size)
{return HAL_SPI_Receive(&W25Q_SPI, R_pData, R_Size, 0xffff);
}/*
写使能或失能参数:Type:1、为1时使能2、为0时失能
*/
HAL_StatusTypeDef Bsp_Write_En_De(uint8_t Type)
{uint8_t cmd;HAL_StatusTypeDef STD = HAL_ERROR;W25Q_CS_Level(0);SPI_Delay(1);switch(Type){case 1:cmd = W25Q_W_EN;break;case 0:cmd = W25Q_W_DIS;break;default:cmd = W25Q_W_DIS;break;}if(bsp_w25q_Transmit(&cmd, 1) == HAL_OK){STD = HAL_OK;}W25Q_CS_Level(1);return STD;
}/*
读状态寄存器参数:Select1、为0时是寄存器12、为1时是寄存器2参数:State(指针)1、返回的状态标志流程:先写入命令,然后读取状态
*/
HAL_StatusTypeDef Bsp_Read_State_Reg(uint8_t Select, uint8_t* State)
{uint8_t cmd;HAL_StatusTypeDef STD = HAL_ERROR;W25Q_CS_Level(0);SPI_Delay(1);switch(Select){case 0:cmd = W25Q_R_STA_REG1;break;case 1:cmd = W25Q_R_STA_REG2;break;default:cmd = W25Q_R_STA_REG1;break;}if(bsp_w25q_Transmit(&cmd, 1) == HAL_OK){if(bsp_w25q_Receive(State,1) == HAL_OK){STD = HAL_OK;}}W25Q_CS_Level(1);return STD;
}/*
判忙用处:判断当前flash是否在忙碌状态BUSY只读寄存器忙时高电平空闲低电平
*/
void Bsp_Judge_Busy(void)
{uint8_t State;do{Bsp_Read_State_Reg(0, &State);  //不要用指针类型局部变量传进去,必被卡死State &= 0x01;}while(State == 0x01);//寄存器为1时为忙
}/*
读数据参数:R_Addr1、读取数据的地址参数:R_Data(数组指针)1、获取读取的数据参数:R_Size1、读取的数据的大小
*/
HAL_StatusTypeDef Bsp_W25Q_Read_Data(uint32_t R_Addr, uint8_t * R_Data, uint16_t R_Size)
{HAL_StatusTypeDef STD = HAL_ERROR;uint8_t addr[4] = {0};addr[0] = W25Q_R_Data;addr[1] = (R_Addr >> 16) & 0xFF;addr[2] = (R_Addr >> 8) & 0xFF;addr[3] = (R_Addr) & 0xFF;Bsp_Judge_Busy();   //判忙W25Q_CS_Level(0);SPI_Delay(1);if(bsp_w25q_Transmit(addr, 4) == HAL_OK){if(bsp_w25q_Receive(R_Data,R_Size) == HAL_OK){STD = HAL_OK;}}W25Q_CS_Level(1);return STD;
}/*
写数据-页页的描述:1字节到 256 字节(一页)页写的前提条件:编程之前必须保证额你存空间是0xff,所以得先进行擦除(擦除后模式全为1)页写的注意事项:进行页编程时,如果数据字节数超过了 256 字节,地址将自动回到页的起始地址,覆盖掉之前的数据。参数:WriteAddr1、地址,三个字节地址参数:PW_Data(数组指针)1、要写入的数据,长度根据PW_size来定2、高位先传参数:PW_Size2、要写入的数据长度先通过状态寄存器判断是否在忙,然后写使能,接着判忙,拉底片选选中,发命令字节0x02,发三个地址,高位优先,然后发你要写的数据,最后拉高片选
*/HAL_StatusTypeDef Bsp_W25Q_Page_Write(uint32_t WriteAddr, uint8_t * PW_Data, uint16_t PW_Size)
{HAL_StatusTypeDef STD = HAL_ERROR;uint8_t addr[4] = {0};addr[0] = W25Q_Page_Program;addr[1] = (WriteAddr >> 16) & 0xFF;addr[2] = (WriteAddr >> 8) & 0xFF;addr[3] = (WriteAddr) & 0xFF;Bsp_Judge_Busy();   //判忙Bsp_Write_En_De(1);Bsp_Judge_Busy();W25Q_CS_Level(0);SPI_Delay(1);if(bsp_w25q_Transmit(addr, 4) == HAL_OK){if(bsp_w25q_Transmit(PW_Data, PW_Size) == HAL_OK){STD = HAL_OK;}}W25Q_CS_Level(1);Bsp_Judge_Busy();return STD;
}/*
扇区擦除扇区的描述:W25Q16总共2MB,分为32块(每块64KB),每块16个扇区,每个扇区4K个字节。扇区的备注:W25Q16的最小擦除单位就是一个扇区所以至少给芯片开辟一个4KB的缓存区,以防止一次性删除太多,而丢失数据。(显然单片机不会给他开辟这么大的空间)参数:num : 扇区的序号*/
HAL_StatusTypeDef Bsp_W25Q_Sector_Erase(uint32_t num)
{HAL_StatusTypeDef STD = HAL_ERROR;//一个扇区有4KB的大小,//为了使找到对应的扇区地址,所以要乘以4KB//(1<<12) = 4096num *= (1<<12);uint8_t addr[4] = {0};addr[0] = W25Q_Sector_Erase;addr[1] = (num >> 16) & 0xFF;addr[2] = (num >> 8) & 0xFF;addr[3] = (num) & 0xFF;Bsp_Judge_Busy();Bsp_Write_En_De(1);Bsp_Judge_Busy();W25Q_CS_Level(0);SPI_Delay(1);if(bsp_w25q_Transmit(addr, 4) == HAL_OK){STD = HAL_OK;}W25Q_CS_Level(1);Bsp_Judge_Busy();return STD;
}/*
块擦除块的描述:W25Q16有2MB的容量,而2MB有32个块,所以1块有64kB的大小,所以这个函数一次能擦除64KB的大小。参数:Block_Addr1、块地址,共32个块,对应32个地址,以64K为单位寻址2、高位先传流程:先开写使能、判忙,再写命令,再写3个字节的地址,最后写失能参数:num : 块的序号
*/
HAL_StatusTypeDef   Bsp_W25Q_Block_Erase(uint32_t num)
{uint8_t cmd = W25Q_Block_Erase;HAL_StatusTypeDef STD = HAL_ERROR;//总共有32个块,而一个块有64KB的大小,//为了使找到对应的块地址,所以要乘以64KBnum *= (1<<16);uint8_t addr[4] = {0};addr[0] = W25Q_Block_Erase;addr[1] = (num >> 16) & 0xFF;addr[2] = (num) & 0xFF;addr[3] = (num) & 0xFF;Bsp_Judge_Busy();Bsp_Write_En_De(1);Bsp_Judge_Busy();W25Q_CS_Level(0);SPI_Delay(1);if(bsp_w25q_Transmit(addr, 4) == HAL_OK){STD = HAL_OK;}W25Q_CS_Level(1);Bsp_Judge_Busy();return STD;
}/*
全片擦除描述:直接把芯片全部擦除
*/
HAL_StatusTypeDef Bsp_W25Q_Full_Erase(void)
{uint8_t cmd = W25Q_Full_Erase;HAL_StatusTypeDef STD = HAL_ERROR;Bsp_Judge_Busy();Bsp_Write_En_De(1);Bsp_Judge_Busy();W25Q_CS_Level(0);SPI_Delay(1);if(bsp_w25q_Transmit(&cmd, 1) == HAL_OK){STD = HAL_OK;}W25Q_CS_Level(1);Bsp_Judge_Busy();return STD;
}/*
读ID描述:读3个字节分别是生产厂家、存储器类型、容量
*/
HAL_StatusTypeDef Bsp_Read_Jedec_ID(uint8_t * R_Jedec_ID)
{uint8_t read_id[3] = {0};uint8_t cmd = W25Q_JEDEC_ID;HAL_StatusTypeDef STD = HAL_ERROR;Bsp_Judge_Busy();W25Q_CS_Level(0);SPI_Delay(1);if(bsp_w25q_Transmit(&cmd, 1) == HAL_OK){if(bsp_w25q_Receive(read_id, 3) == HAL_OK){STD = HAL_OK;}}W25Q_CS_Level(1);if(STD == HAL_OK){LOG_OUT("read_id= %x %x %x\r\n", read_id[0], read_id[1], read_id[2]);}else{LOG_OUT("read_id= err\r\n");}return STD;
}/** 电源开启*/
void W26Q16_Power_On(void)
{MX_SPI1_Init();//W25Q_WP_HIGH;rt_thread_mdelay(100);Bsp_Read_Jedec_ID(NULL);}/** 电源关闭*/
void W26Q16_Power_Off(void)
{//WP拉低开启读保护//W25Q_WP_LOW;W25Q_CS_Level(GPIO_PIN_RESET);rt_thread_mdelay(10);//失能SPI配置为IOw25q16_init_sleep();rt_thread_mdelay(1000);
}
#ifndef __DRV_W25Q16_H
#define __DRV_W25Q16_H#include "app_user.h"
#include "spi.h"/*句柄重命名*/
#define W25Q_SPI                hspi1#define SPI_Delay(ms)           rt_thread_mdelay(ms+1)/*片选引脚定义与函数调用*/
#define W25Q_CS_Pin             GPIO_PIN_4
#define W25Q_CS_Port            GPIOA#define W25Q_CS_Level(_CS_STATE__)      HAL_GPIO_WritePin(W25Q_CS_Port, W25Q_CS_Pin, (GPIO_PinState)_CS_STATE__)//#define W25Q_WP_HIGH   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET)
//#define W25Q_WP_LOW    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET)#define W25Q_W_EN               0x06        //写使能
#define W25Q_W_DIS              0x04        //写禁止#define W25Q_R_Data             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 Bsp_Write_En_De(uint8_t Type);/*读状态寄存器*/
HAL_StatusTypeDef Bsp_Read_State_Reg(uint8_t Select, uint8_t* State);/*判忙*/
void Bsp_Judge_Busy(void);/*读数据*/
HAL_StatusTypeDef Bsp_W25Q_Read_Data(uint32_t R_Addr, uint8_t * R_Data, uint16_t R_Size);/*页写*/
HAL_StatusTypeDef Bsp_W25Q_Page_Write(uint32_t WriteAddr, uint8_t * PW_Data, uint16_t PW_Size);/*扇区擦除*/
HAL_StatusTypeDef Bsp_W25Q_Sector_Erase(uint32_t num);/*块擦除*/
HAL_StatusTypeDef   Bsp_W25Q_Block_Erase(uint32_t num);/*全片擦除*/
HAL_StatusTypeDef Bsp_W25Q_Full_Erase(void);/*读ID*/
HAL_StatusTypeDef Bsp_Read_Jedec_ID(uint8_t * R_Jedec_ID);void W26Q16_Power_On(void);
void W26Q16_Power_Off(void);
#endif /*W25Q16__H__*/
/* USER CODE BEGIN Header */
/********************************************************************************* @file    spi.c* @brief   This file provides code for the configuration*          of the SPI instances.******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "spi.h"/* USER CODE BEGIN 0 *//* USER CODE END 0 */SPI_HandleTypeDef hspi1;/* SPI1 init function */
void MX_SPI1_Init(void)
{/* USER CODE BEGIN SPI1_Init 0 *//* USER CODE END SPI1_Init 0 *//* USER CODE BEGIN SPI1_Init 1 *//* USER CODE END SPI1_Init 1 */hspi1.Instance = SPI1;hspi1.Init.Mode = SPI_MODE_MASTER;hspi1.Init.Direction = SPI_DIRECTION_2LINES;hspi1.Init.DataSize = SPI_DATASIZE_8BIT;hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;hspi1.Init.NSS = SPI_NSS_SOFT;hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi1.Init.TIMode = SPI_TIMODE_DISABLE;hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi1.Init.CRCPolynomial = 7;if (HAL_SPI_Init(&hspi1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN SPI1_Init 2 *//* USER CODE END SPI1_Init 2 */}void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(spiHandle->Instance==SPI1){/* USER CODE BEGIN SPI1_MspInit 0 *//* USER CODE END SPI1_MspInit 0 *//* SPI1 clock enable */__HAL_RCC_SPI1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**SPI1 GPIO ConfigurationPA5     ------> SPI1_SCKPA6     ------> SPI1_MISOPA7     ------> SPI1_MOSI*/GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF0_SPI1;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USER CODE BEGIN SPI1_MspInit 1 *//* USER CODE END SPI1_MspInit 1 */}
}void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{if(spiHandle->Instance==SPI1){/* USER CODE BEGIN SPI1_MspDeInit 0 *//* USER CODE END SPI1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_SPI1_CLK_DISABLE();/**SPI1 GPIO ConfigurationPA5     ------> SPI1_SCKPA6     ------> SPI1_MISOPA7     ------> SPI1_MOSI*/HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);/* USER CODE BEGIN SPI1_MspDeInit 1 *//* USER CODE END SPI1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 *//* USER CODE END 1 */

void w25q16_init_sleep(void)
{extern SPI_HandleTypeDef hspi1;HAL_SPI_DeInit(&hspi1);__HAL_RCC_GPIOA_CLK_ENABLE();GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_PULLDOWN;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);
}

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

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

相关文章

《Vue3 报错》Uncaught TypeError: s.finally is not a function

解决方案&#xff1a; 新建文件 my-polyfill.js // 当浏览器环境不支持Promise.prototype.finally if (!Promise.prototype[finally]) {Promise.prototype[finally] function(callback) {let P this.constructor;return this.then(value > P.resolve(callback()).then(…

RabbitMQ 七种工作模式介绍

目录 1.简单模式队列 2.WorkQueue(⼯作队列) 3 Publish/Subscribe(发布/订阅) 4 Routing(路由模式) 5.Topics(通配符模式) 6 RPC(RPC通信) 7 Publisher Confirms(发布确认) RabbitMQ 共提供了7种⼯作模式供我们进⾏消息传递,接下来一一介绍它的实现与目的 1.简单模式队列…

数组类算法【leetcode】

704. 二分查找 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 二分查找 用于有序数组中&#xff0c;没有重复的数组。…

Pandas 数据分析工具详细教程

Pandas 数据分析工具详细教程 Pandas 是一个强大的 Python 数据分析库&#xff0c;广泛应用于数据科学、数据分析和机器学习等领域。它提供了高效的数据操作和分析功能&#xff0c;使得数据处理变得简单而高效。本文将详细介绍 Pandas 的基本概念、数据结构、常用操作及其在数…

基于 EventBridge + DashVector 打造 RAG 全链路动态语义检索能力

作者&#xff1a;肯梦 本文将演示如何使用事件总线&#xff08;EventBridge&#xff09;&#xff0c;向量检索服务&#xff08;DashVector&#xff09;&#xff0c;函数计算&#xff08;FunctionCompute&#xff09;结合灵积模型服务 [ 1] 上的 Embedding API [ 2] &#xff0…

GooglePlay: 应用和游戏的内容分级

对于后台私信的开发者们,希望能够携带详细过审记录和拒审邮件一同发来,方便我们尽快解决问题 应用与游戏 为您的应用或游戏选择类别和标签选择要添加的标签选择类别并添加标签类别示例与应用、游戏以及两者中所投放广告的内容分级相关的要求应用如何获得内容分级内容分级的用…

将Notepad++添加到右键菜单【一招实现】

一键添加注册表 复制以下代码保存为 Notepad.reg&#xff0c;将红框内路径修改为自己电脑的“Notepad.exe路径”后&#xff0c;再双击运行即可。 Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\*\shell\NotePad] "Notepad" "Icon""D:\\N…

[复健计划][紫书]Chapter 7 暴力求解法

7.1 简单枚举 例7-1 Division uva725 输入正整数n&#xff0c;按从小到大的顺序输出所有形如abcde/fghij n的表达式&#xff0c;其中a&#xff5e;j恰好为数字0&#xff5e;9的一个排列&#xff08;可以有前导0&#xff09;&#xff0c;2≤n≤79。枚举fghij&#xff0c;验证a…

【测试工具篇一】全网最强保姆级教程抓包工具Fiddler(2)

本文接上篇Fiddler介绍&#xff0c;开始讲fiddler如何使用之前&#xff0c;给大家讲讲http以及web方面的小知识&#xff0c;方便大家后面更好得理解fiddler使用。 目录 一、软件体系结构---B/S与C/S架构 B/S架构 C/S架构 二、HTTP基础知识 什么是http请求和响应? http协…

如何基于pdf2image实现pdf批量转换为图片

最近为了将pdf报告解析成为文本和图片&#xff0c;需要将大量多页的pdf文件拆分下单独的一页一页的图像&#xff0c;以便后续进行OCR和图像处理&#xff0c;因此就需要实现将pdf2image&#xff0c;本文主要结合开源的pdf2image和poppler&#xff0c;实现了pdf转换为png格式图片…

【Linux】Linux下查看cpu信息指令(top/mpstat/iostat/pidstat)说明

top命令 top(1) - Linux manual page (man7.org) top查看总的CPU利用率 us: 用户空间消耗的CPU资源占比&#xff0c;进程在用户态执行函数调用&#xff0c;编解码消耗的都是us sy: 内核空间消耗的CPU资源占比&#xff0c;进程调用系统调用达到内核后会增加sy的消耗 ni&…

Java学习者的福音:SpringBoot教学辅助平台

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理教学辅助平台的相关信息成为必然。开发合适…

csrf令牌

csrf get请求 路由 // index.php Route::get(/, function () {// return view(welcome);return view(login); });Route::get(d3,function(Request $request){echo "输入的内容是" . "<font color>".$request -> input(mytext)."</fon…

高校实验室安全巡检系统设计与实现(源码+定制+开发)高校实验室巡检系统、实验室安全管理平台、实验室安全监控系统、智能实验室巡查系统、高校实验室风险管理

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

容器内pip安装Apache Airflow的经历:如何重置初始密码

背景 Apache Airflow™https://github.com/apache/airflow 是一个开源平台&#xff0c;用于开发、调度和监控面向批处理的工作流程。Airflow 可扩展的 Python 框架使您能够构建几乎可以连接任何技术的工作流程。Web 界面有助于管理工作流程的状态。Airflow 可以通过多种方式部…

微服务透传日志traceId

问题 在微服务架构中&#xff0c;一次业务执行完可能需要跨多个服务&#xff0c;这个时候&#xff0c;我们想看到业务完整的日志信息&#xff0c;就要从各个服务中获取&#xff0c;即便是使用了ELK把日志收集到一起&#xff0c;但如果不做处理&#xff0c;也是无法完整把一次业…

精心整理教育研究专题数据资源大全-最新出炉_附下载链接

教育研究专题数据资源大全V1.0 下载链接-点它&#x1f449;&#x1f449;&#x1f449;&#xff1a;教育研究专题数据资源大全-最新出炉.zip 资源介绍 一、中国教育统计年鉴面板数据 简介&#xff1a;《中国教育统计年鉴》是由教育部发展规划司根据全国各省、自治区、直辖市…

汽修行业员工培训SOP的智能化搭建

汽修行业正经历着技术革新和服务模式的双重变革&#xff0c;员工的专业培训变得尤为重要。智能化的员工培训标准操作程序&#xff08;SOP&#xff09;在线知识库不仅能够提升培训效率&#xff0c;还能确保服务质量和作业安全。本文将探讨汽修行业如何智能化地搭建员工培训的SOP…

还在担心Mac卸载不干净?XApp帮你干净完成卸载

Mac的卸载机制非常独特&#xff0c;虽然将app拖拽到废纸篓也能够完成卸载&#xff0c;但是会有很多的文件残留&#xff0c;那么如何卸载干净非常重要 XApp&#xff0c;免费的Mac卸载工具&#xff0c;有着强大的垃圾检测机制&#xff0c;检测出更深层的垃圾&#xff0c;卸载更干…

游戏测试之浅谈测试思维

一、游戏测试与软件测试的区别 1、测试目标 软件测试&#xff1a;主要目标是确保软件在功能、性能、安全性等方面达到预期质量标准。关注点主要是软件的正确性、稳定性、安全性和效率。 游戏测试&#xff1a;不仅关注游戏的功能性和稳定性&#xff0c;还要关注游戏的体验性、平…