【ESP32 IDF SPI硬件驱动W25Q64】

目录

  • SPI
    • SPI介绍
    • idf配置
      • 初始化配置
      • 通信
  • 驱动代码

SPI

SPI介绍

详细SPI介绍内容参考我之前写的内容【ESP32 IDF 软件模拟SPI驱动 W25Q64存储与读取数组】

idf配置

初始化配置

spi_bus_initialize()
在这里插入图片描述
参数1 :spi几,例如spi2,spi3
在这里插入图片描述

参数2:指向spi_bus_config_t的结构体,该结构体有较多值,取自己用的就行
参数3:是否使用DMA

对于参数2,有如下成员变量:

typedef struct {int miso_io_num;   // MISO引脚号int mosi_io_num;   // MOSI引脚号int sclk_io_num;   // 时钟引脚号int quadwp_io_num; // 用于Quad模式的WP引脚号,未使用时设置为-1int quadhd_io_num; // 用于Quad模式的HD引脚号,未使用时设置为-1int max_transfer_sz; // 最大传输大小
} spi_bus_config_t;

设备配置
spi_bus_add_device()
在这里插入图片描述

在这里插入图片描述
参数1:和上面的一样,选择spi几
参数2:指向设备的结构体
参数3:返回该设备的句柄

其中参数2,成员变量如下:
在这里插入图片描述
在这里插入图片描述

参数二的结构体的成员变量也很多,我们一样是挑着用上的配置。

    spi_device_handle_t dev_handle;spi_device_interface_config_t device_initer={.command_bits=0,//指令的位数.address_bits=0,//地址的位数.mode=0,//模式0,spi四种模式.spics_io_num=15,//ss/cs片选引脚号.clock_speed_hz=1000*1000//时钟通信频率};if(spi_bus_add_device(SPI2_HOST,&dev_handle,&dev_handle)!=ESP_OK)  printf("add device success\r\n");

通信

spi_device_transmit()
在这里插入图片描述
在这里插入图片描述
参数二的结构体成员变量也不少,但是我们配置好要发送的数据和长度,以及接收数据的地方和长度即可。
举例

uint32_t bsp_spi_flash_ReadID(spi_device_handle_t handle)
{//00 定义错误标志esp_err_t e;//01 接收数据的时候发送的空指令uint8_t data[3];data[0] = 0xff;data[1] = 0xff;data[2] = 0xff;//02 定义用于返回的数据uint32_t Temp;//03 定义数据发送接收结构体spi_transaction_ext_t ext;                  //因为读取设备ID的指令结构与前面定义的默认的不一样,所以需要更改位长memset(&ext, 0, sizeof(ext));               //初始化结构体ext.command_bits =  8;                      //指令位长度为8ext.address_bits =  0;                      //地址位长度为0ext.base.cmd =      W25X_JedecDeviceID;     //设备IDext.base.length =   3 * 8;                  //要发送数据的长度ext.base.tx_buffer = data;                  //要发送数据的内容ext.base.rx_buffer = NULL;                  //接收数据buffer使用结构体内部带的ext.base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_USE_RXDATA;  //04 数据收发e=spi_device_polling_transmit(handle, &ext.base);if (e != ESP_OK){printf("get ID error!\n");return 0;}//05 返回获取的数据IDuint8_t temp0 = ext.base.rx_data[0];uint8_t temp1 = ext.base.rx_data[1];uint8_t temp2 = ext.base.rx_data[2];Temp = (temp0 << 16) | (temp1 << 8) | temp2;

驱动代码

w25q64.c

#include "W25Q64.h"/*********************************************************** 函 数 名 称:w25q64_init_config* 函 数 功 能:w25q64初始化* 传 入 参 数:无* 函 数 返 回:无* 备       注:无
**********************************************************/
esp_err_t w25q64_init_config(spi_device_handle_t* handle)
{   //00 定义错误标志esp_err_t e;//01 配置总线初始化结构体static spi_bus_config_t bus_cfg;    //总线配置结构体bus_cfg.miso_io_num     = Flash_SPI_MISO;                //misobus_cfg.mosi_io_num     = Flash_SPI_MOSI;                //mosibus_cfg.sclk_io_num     = Flash_SPI_SCLK;                //sclkbus_cfg.quadhd_io_num   = Flash_SPI_HD;                 // HDbus_cfg.quadwp_io_num   = Flash_SPI_WP;                 // WPbus_cfg.max_transfer_sz = 4092;                         //非DMA最大64bytes,DMA最大4092bytes//bus_cfg.intr_flags = 0;                               //这个用于设置中断优先级的,0是默认bus_cfg.flags = SPICOMMON_BUSFLAG_MASTER;//这个用于设置初始化的时候要检测哪些选项。比如这里设置的是spi初始化为主机模式是否成功。检测结果通过spi_bus_initialize函数的//返回值进行返回。如果初始化为主机模式成功,就会返回esp_ok//02 初始化总线配置结构体e = spi_bus_initialize(Flash_SPI, &bus_cfg, SPI_DMA_CH_AUTO);if (e != ESP_OK){printf("bus initialize failed!\n");return e;}//03 配置设备结构体static spi_device_interface_config_t interface_cfg; //设备配置结构体interface_cfg.address_bits = Flash_Address_Bits;   //配置地址位长度//(1)如果设置为0,在通讯的时候就不会发送地址位。//(2)如果设置了非零值,就会在spi通讯的地址发送阶段发送指定长度的address数据。//如果设置了非零值并且在后面数据发送结构体中没有定义addr的值,会默认发送指定长度0值//(3)我们后面发送数据会使用到spi_transaction_t结构体,这个结构体会使用spi_device_interface_config_t中定义好address、command和dummy的长度//如果想使用非固定长度,就要使用spi_transaction_ext_t结构体了。这个结构体包括了四个部分,包含了一个spi_transaction_t和address、command、dummy的长度。//我们要做的就是在spi_transaction_ext_t.base.flags中设置SPI_TRANS_VARIABLE_ADDR/CMD/DUMMY//然后定义好这三部分数据的长度,然后用spi_transaction_ext_t.base的指针代替spi_transaction_t的指针即可interface_cfg.command_bits = Flash_Command_Bits;  //配置命令位长度//与address_bits是一样的interface_cfg.dummy_bits = Flash_Dummy_Bits;  //配置dummy长度//这里的配置方法与address_bits是一样的。但是要着重说一下这个配置的意义,后面会再说一遍//(1)dummy_bits是用来用来补偿输入延迟。//(2)在read phase开始阶段之前被插入进去。在dummy_bits的时钟下,并不进行数据读取的工作//相当于这段时间发送的clock都是虚拟的时钟,并没有功能。在输入延迟最大允许时间不够的时候,可以通过这种方法进行配置,从而//能够使得系统工作在更高的时钟频率下。//(3)如果主机设备只进行write操作,可以在flags中设置SPI_DEVICE_NO_DUMMY,关闭dummy bits的发送。只有写操作的话,即使使用了gpio交换矩阵,时钟周期也可以工作在80MHZ//interface_cfg.input_delay_ns = 0;  //配置输入延时的允许范围//时钟发出信号到miso进行输入直接会有延迟,这个参数就是配置这个允许的最大延迟时间。//如果主机接收到从机时钟,但是超过这个时间没有收到miso发来的输入信号,就会返回通讯失败。//这个时间即使设置为0,也能正常工作,但是最好通过手册或逻辑分析仪进行估算。能够实现更好的通讯。//超过8M的通讯都应该认真设置这个数字interface_cfg.clock_speed_hz = Flash_CLK_SPEED;  //配置时钟频率//配置通讯的时钟频率。//这个频率受到io_mux和input_delay_ns限制。//如果是io直连的,时钟上限是80MHZ,如果是gpio交换矩阵连接进来的,时钟上限是40MHZ。//如果是全双工,时钟上限是26MHZ。并且还要考虑输入延时。在相同输入延时的条件下,使用gpio交换矩阵会比使用io mux最大允许的时钟频率小。可以通过//spi_get_freq_limit()来计算能够允许的最大时钟频率是多少//有关SPI通讯时钟极限和配置的问题,后面会详细说一下。interface_cfg.mode = 0; //设置SPI通讯的相位特性和采样边沿。包括了mode0-3四种。要看从设备能够使用哪种模式interface_cfg.spics_io_num = Flash_SPI_CS; //配置片选线interface_cfg.duty_cycle_pos = 0;  //配置占空比//设置时钟的占空比,比例是 pos*1/256,默认为0,也就是50%占空比//interface_cfg.cs_ena_pretrans; //在传输之前,片选线应该保持激活状态多少个时钟,只有全双工的时候才需要配置//interface_cfg.cs_ena_posttrans; //在传输之后,片选线应该保持激活状态多少个时钟,只有全双工的时候才需要配置interface_cfg.queue_size = 6; //传输队列的长度,表示可以在通讯的时候挂起多少个spi通讯。在中断通讯模式的时候会把当前spi通讯进程挂起到队列中//interface_cfg.flags; //配置与从机有关的一些参数,比如MSB还是LSB,使不使用三线SPI//interface_cfg.pre_cb; //配置通讯前中断。比如不在这里配置cs片选线,把片选线作为自行控制的线,把片选线拉低放在通讯前中断中//interface_cfg.post_cb;//配置通讯后中断。比如不在这里配置cs片选线,把片选线作为自行控制的线,把片选线拉高放在通讯前中断中//04 设备初始化e = spi_bus_add_device(Flash_SPI, &interface_cfg, handle);if (e != ESP_OK){printf("device config error\n");return e;}return ESP_OK;
}uint32_t bsp_spi_flash_ReadID(spi_device_handle_t handle)
{//00 定义错误标志esp_err_t e;//01 接收数据的时候发送的空指令uint8_t data[3];data[0] = Dummy_Byte;data[1] = Dummy_Byte;data[2] = Dummy_Byte;//02 定义用于返回的数据uint32_t Temp;//03 定义数据发送接收结构体spi_transaction_ext_t ext;                  //因为读取设备ID的指令结构与前面定义的默认的不一样,所以需要更改位长memset(&ext, 0, sizeof(ext));               //初始化结构体ext.command_bits =  8;                      //指令位长度为8ext.address_bits =  0;                      //地址位长度为0ext.base.cmd =      W25X_JedecDeviceID;     //设备IDext.base.length =   3 * 8;                  //要发送数据的长度ext.base.tx_buffer = data;                  //要发送数据的内容ext.base.rx_buffer = NULL;                  //接收数据buffer使用结构体内部带的ext.base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_USE_RXDATA;  //04 数据收发e=spi_device_polling_transmit(handle, &ext.base);if (e != ESP_OK){printf("get ID error!\n");return 0;}//05 返回获取的数据IDuint8_t temp0 = ext.base.rx_data[0];uint8_t temp1 = ext.base.rx_data[1];uint8_t temp2 = ext.base.rx_data[2];Temp = (temp0 << 16) | (temp1 << 8) | temp2;return Temp;
}/**
* @breif flash写使能。在执行页写入和擦除命令之前,都必须执行一次页写入
* @param[in]  handle: 提供SPI的操作句柄
* @retval 无
**/void bsp_spi_flash_WriteEnable(spi_device_handle_t handle)
{esp_err_t e; //错误标志位// 定义数据发送接收结构体spi_transaction_ext_t ext;                  //写使能的长度与默认的不同,需要修改memset(&ext, 0, sizeof(ext));               //初始化结构体ext.command_bits = 8;                       //指令位长度为8ext.address_bits = 0;                       //地址位长度为0ext.base.cmd = W25X_WriteEnable;            //写使能ext.base.length = 0;                        //要发送数据的长度,这里不需要发送数据ext.base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR;//发送指令e = spi_device_polling_transmit(handle, &ext.base);if (e != ESP_OK){printf("write enable failed!\n");}}/**
* @breif 等待flash完成当前操作
* @param[in]  handle: 提供SPI的操作句柄
* @retval 无
**/void bsp_spi_flash_WaitForWriteEnd(spi_device_handle_t handle)
{// 定义数据发送接收结构体spi_transaction_ext_t ext;                  //写使能的长度与默认的不同,需要修改memset(&ext, 0, sizeof(ext));               //初始化结构体ext.command_bits = 8;                       //指令位长度为8ext.address_bits = 0;                      //地址位长度为 0ext.base.cmd = W25X_ReadStatusReg;          //读取状态寄存器ext.base.length = 1 * 8;                    //要发送数据的长度,这里不需要发送数据ext.base.rx_buffer = NULL;                  //不使用外部数据ext.base.tx_buffer = NULL;                  //不使用外部数据ext.base.tx_data[0] = Dummy_Byte;           //发送数据ext.base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA;do{//发送指令spi_device_polling_transmit(handle, &ext.base);}while ( (ext.base.rx_data[0] & WIP_Flag )== WIP_SET);
}/**
* @breif 扇区擦除
* @param[in]  handle: 提供SPI的操作句柄
* @param[in] SectorAddr: 要擦除的起始扇区地址
* @retval 无
**/void bsp_spi_flash_SectorErase(spi_device_handle_t handle,uint32_t SectorAddr)
{bsp_spi_flash_WriteEnable(handle);bsp_spi_flash_WaitForWriteEnd(handle);// 定义数据发送接收结构体spi_transaction_t t;                        //配置位与默认一致,不需要修改memset(&t, 0, sizeof(t));                   //初始化结构体t.cmd = W25X_SectorErase;                   //擦除指令t.addr = SectorAddr;                        //擦除地址t.length = 0;                               //不需要额外数据了//发送指令spi_device_polling_transmit(handle, &t);//等待擦除完毕bsp_spi_flash_WaitForWriteEnd(handle);
}/**
* @breif 页写入
* @param[in]  handle: 提供SPI的操作句柄
* @param[in]  pBuffer:要写入的数据地址
* @param[in]  WriteAddr:要写入的地址
* @param[in]  NumByteToWrite: 要写入的长度
* @retval 无
**/void bsp_spi_flash_PageWrite(spi_device_handle_t handle, uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{bsp_spi_flash_WriteEnable(handle);// 定义数据发送接收结构体spi_transaction_t t;                        //配置位与默认一致,不需要修改memset(&t, 0, sizeof(t));                   //初始化结构体t.cmd = W25X_PageProgram;                   //页写入t.addr = WriteAddr;                         //擦除地址t.length = 8*NumByteToWrite;                //写入长度t.tx_buffer = pBuffer;                      //写入的数据t.rx_buffer = NULL;                         //不需要读取数据if (NumByteToWrite > SPI_Flash_PageSize){printf("length is too long!\n");return ;}//发送指令spi_device_polling_transmit(handle, &t);//等待擦除完毕bsp_spi_flash_WaitForWriteEnd(handle);}/**
* @breif 不定量数据写入
* @param[in]  handle: 提供SPI的操作句柄
* @param[in]  pBuffer:要写入的数据地址
* @param[in]  WriteAddr:要写入的地址
* @param[in]  NumByteToWrite: 要写入的长度
* @retval 无
**/void bsp_spi_flash_BufferWrite(spi_device_handle_t handle, uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;//进行取余运算,查看是否进行了页对齐Addr = WriteAddr % SPI_Flash_PageSize;//差count个数据值可以进行页对齐count = SPI_Flash_PageSize - Addr;//计算要写多少个完整的页NumOfPage = NumByteToWrite / SPI_Flash_PageSize;//计算剩余多少字节不满1页NumOfSingle = NumByteToWrite % SPI_Flash_PageSize;//如果Addr=0,也就是进行了页对齐if (Addr == 0){//如果写不满1页if (NumOfPage == 0){bsp_spi_flash_PageWrite(handle, pBuffer, WriteAddr, NumByteToWrite);}else{//如果超过1页,先把满的写了while (NumOfPage--){bsp_spi_flash_PageWrite(handle, pBuffer, WriteAddr, SPI_Flash_PageSize);WriteAddr += SPI_Flash_PageSize;pBuffer += SPI_Flash_PageSize;}//不满的1页再写bsp_spi_flash_PageWrite(handle, pBuffer, WriteAddr, NumOfSingle);}}//如果没有进行页对齐else{if (NumOfPage == 0){//如果当前页剩下的count个位置比NumOfSingle小,1页写不完if (NumOfSingle > count){//先把这页剩下的写了temp = NumOfSingle - count;bsp_spi_flash_PageWrite(handle, pBuffer, WriteAddr, count);WriteAddr += count;pBuffer += count;//再把多了的写了bsp_spi_flash_PageWrite(handle, pBuffer, WriteAddr, temp);}else{//如果剩下的空间足够大,就直接写bsp_spi_flash_PageWrite(handle, pBuffer, WriteAddr, NumByteToWrite);}}//如果不止1页else{//先把对不齐的字节写了NumByteToWrite -= count;NumOfPage = NumByteToWrite / SPI_Flash_PageSize;NumOfSingle = NumByteToWrite % SPI_Flash_PageSize;bsp_spi_flash_PageWrite(handle, pBuffer, WriteAddr,count);//重复地址对齐的情况WriteAddr += count;pBuffer += count;while (NumOfPage--){bsp_spi_flash_PageWrite(handle, pBuffer, WriteAddr, SPI_Flash_PageSize);pBuffer += SPI_Flash_PageSize;WriteAddr += SPI_Flash_PageSize;}if (NumOfSingle != 0){bsp_spi_flash_PageWrite(handle, pBuffer, WriteAddr, NumOfSingle);}}}}/**
* @breif 数据读取
* @param[in]  handle: 提供SPI的操作句柄
* @param[out]  pBuffer:要读取的数据buffer地址
* @param[in]  WriteAddr:要写入的地址
* @param[in]  NumByteToWrite: 要写入的长度
* @retval 无
**/void bsp_spi_flash_BufferRead(spi_device_handle_t handle, uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{bsp_spi_flash_WriteEnable(handle);// 定义数据发送接收结构体spi_transaction_t t;                        //配置位与默认一致,不需要修改memset(&t, 0, sizeof(t));                   //初始化结构体t.cmd = W25X_ReadData;                      //读取数据t.addr = WriteAddr;                         //擦除地址t.length = 8 * NumByteToWrite;              //读取长度t.tx_buffer = NULL;                         //不需要写入数据t.rx_buffer = pBuffer;                      //读取数据//发送指令spi_device_polling_transmit(handle, &t);//等待擦除完毕bsp_spi_flash_WaitForWriteEnd(handle);}

w25q64.h

/** @Author: i want to 舞动乾坤* @Date: 2024-07-27 09:26:08* @LastEditors: i want to 舞动乾坤* @LastEditTime: 2024-07-27 17:21:08* @FilePath: \spi_hardware_driver_w25q64\main\W25Q64.h* @Description: * * Copyright (c) 2024 by i want to 舞动乾坤, All Rights Reserved. */
#ifndef __W25Q64_H__
#define __W25Q64_H__#include "driver/spi_master.h"
#include "driver/spi_common.h"
#include "hal/gpio_types.h"
#include <string.h>   //定义Flash实验所需要的引脚
#define Flash_SPI                               SPI3_HOST
#define Flash_SPI_MISO                          GPIO_NUM_19     
#define Flash_SPI_MOSI                          GPIO_NUM_23
#define Flash_SPI_SCLK                          GPIO_NUM_18
#define Flash_SPI_CS                            GPIO_NUM_5     
#define Flash_SPI_WP                            -1
#define Flash_SPI_HD                            -1
#define Flash_SPI_DMA                           SPI_DMA_CH1//定义设备参数
#define Flash_CLK_SPEED                         6 * 1000 * 1000  //6M的时钟
#define Flash_Address_Bits                      3*8             //地址位长度
#define Flash_Command_Bits                      1*8             //命令位长度
#define Flash_Dummy_Bits                        0*8             //dummy位长度
#define SPI_Flash_PageSize                      256             //页写入最大值//定义命令指令
#define W25X_JedecDeviceID                      0x9F        //获取flashID的指令
#define W25X_WriteEnable                        0x06        //写入使能
#define W25X_WriteDisable                       0x04        //禁止写入
#define W25X_ReadStatusReg                      0x05        //读取状态寄存器
#define W25X_SectorErase                        0x20        //扇区擦除
#define W25X_BlockErase                         0xD8        //块擦除
#define W25X_ChipErase                          0xC7        //芯片擦除
#define W25X_PageProgram                        0x02        //页写入
#define W25X_ReadData                           0x03        //数据读取#define Dummy_Byte                              0xFF        //空指令,用于填充发送缓冲区
#define WIP_Flag                                0x01        //flash忙碌标志位
#define WIP_SET                                 1 esp_err_t w25q64_init_config(spi_device_handle_t* handle);
uint32_t bsp_spi_flash_ReadID(spi_device_handle_t handle);void bsp_spi_flash_SectorErase(spi_device_handle_t handle,uint32_t SectorAddr);
void bsp_spi_flash_PageWrite(spi_device_handle_t handle, uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
void bsp_spi_flash_BufferWrite(spi_device_handle_t handle, uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void bsp_spi_flash_BufferRead(spi_device_handle_t handle, uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);#endif

main.c

/** @Author: i want to 舞动乾坤* @Date: 2024-07-27 09:14:50* @LastEditors: i want to 舞动乾坤* @LastEditTime: 2024-07-27 17:16:23* @FilePath: \spi_hardware_driver_w25q64\main\main.c* @Description: * * Copyright (c) 2024 by i want to 舞动乾坤, All Rights Reserved. */#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "W25Q64.h"
#include <esp_log.h>spi_device_handle_t spi2_handle;
static const char * TAG = "Task";void app_main(void)
{uint8_t pBuffer[11] = { 0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0x00 };uint8_t rBuffer[11] = {0};int id=0;//配置W25Q64w25q64_init_config(&spi2_handle);//读取器件IDid=bsp_spi_flash_ReadID(spi2_handle);ESP_LOGI(TAG,"id = %X\r\n",id);//向W25Q64的地址0写入10个数据bsp_spi_flash_SectorErase(spi2_handle, 0);ESP_LOGI(TAG,"Sector erase successfully\r\n");bsp_spi_flash_BufferWrite(spi2_handle, pBuffer, 0, 10);ESP_LOGI(TAG,"Write successfully\r\n");//向W25Q64的地址0读取10个数据bsp_spi_flash_BufferRead(spi2_handle, rBuffer, 0, 10);for (int i = 0; i < 10; i++){ESP_LOGI(TAG,"0x%x ", rBuffer[i]);}ESP_LOGI(TAG,".");while(1){ESP_LOGI(TAG,".");vTaskDelay(1000/portTICK_PERIOD_MS);}
}

项目结构:
在这里插入图片描述

调试
在这里插入图片描述

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

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

相关文章

GitHub Actions是什么

目录 GitHub Actions是什么 GitHub Actions的使用方法 示例 注意事项 GitHub Actions配置文件中-工作流的 :Workflow 一、自动化任务执行 二、规范团队协作 三、灵活配置和定制 四、提高开发效率 五、集成GitHub生态 六、可复用性和共享性 仓库中的“Actions”部分…

mac 使用ssh 密钥登录linux 服务器

本地操作 1. 生成SSH密钥对 # your_emailexample.co 自行定义即可 ssh-keygen -t rsa -b 4096 -C "your_emailexample.com"这会提示你输入文件保存位置和密码(密码可以留空)&#xff1a; Generating public/private rsa key pair. Enter file in which to save the…

Postman入门(三):创建post请求及请求参数

创建post请求Raw data&#xff1a; 请求方式&#xff1a;Post 请求体&#xff1a;raw,选择json格式 参数{}内数据&#xff0c;点击send即可发送请求 创建post请求Form-data: 请求方式&#xff1a;Post 请求体&#xff1a;form-data, 参数&#xff1a;在form-data内&#…

Lombok的认识

Lombok的作用 Lombok是一个Java库&#xff0c;它可以通过简单的注解形式来帮助开发人员简化Java代码的编写&#xff0c;特别是减少模板代码的书写。具体来说&#xff0c;Lombok的主要作用包括&#xff1a; 减少模板代码&#xff1a;Lombok可以通过注解自动生成getter、setter、…

Javascript 沙漏图案(Hour-glass Pattern)

给定正整数 n&#xff0c;以沙漏形式打印数字模式。示例&#xff1a; 输入&#xff1a;rows_no 7 输出&#xff1a; 1 2 3 4 5 6 7 2 3 4 5 6 7 3 4 5 6 7 4 5 6 7 5 6 7 6 7 7 6 7 5 6 7 4 5 6 7 3 4 5 6 7 2 3 4 5 6 7 1 2 3 4 5 6…

Windows系统安全加固方案:快速上手系统加固指南(上)

无论是个人用户、小型企业还是大型机构&#xff0c;都需要采取措施保护其计算机系统免受各种威胁、系统加固常见的应用场景有个人用户、 AWD 比赛、公共机构以及企业环境等等 文档目录 一、Windows常用命令二、Windows常见端口三、账户安全3.1 默认账户安全3.2 按照用户分配账户…

大数据-44 Redis 慢查询日志 监视器 慢查询测试学习

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

代码随想录算法训练营day25 | 491.递增子序列 、46.全排列 、47.全排列 II、51.N皇后、37.解数独

碎碎念&#xff1a;加油加油&#xff0c;继续坚持 参考&#xff1a;代码随想录 491.递增子序列 题目链接 491.递增子序列 思想 注意结果中不能有重复的子集。 不能排序后处理&#xff0c;因为进行排序以后改变元素顺序&#xff0c;求的递增子序列会改变。 树形图&#xf…

大模型金九银十秋招:AI时代的就业新趋势,收藏我这篇就够了非常详细

随着人工智能技术的飞速发展&#xff0c;大模型&#xff08;Large Models&#xff09;在各个领域的应用日益广泛&#xff0c;从自然语言处理到图像识别&#xff0c;从自动驾驶到智能推荐系统&#xff0c;大模型正逐渐成为AI领域的新宠。在这个背景下&#xff0c;大模型的秋招&a…

sizeof和strlen区别

如图&#xff0c;sizeof来计算的时候&#xff0c;得出的是计算机用多少个字节来表示一个地址 而strlen来计算的时候&#xff0c;只是计算出他的有效字符长度 打印出的不同地址就是其不同的区别

Visual Studio 智能代码插件:Fitten Code

Fitten Code 是由非十大模型驱动的AI编程助手&#xff0c;它可以自动生成代码&#xff0c;提升开发效率&#xff0c;协助调试 Bug&#xff0c;节省时间。还可以对话聊天&#xff0c;解决编程碰到的问题。 Fitten Code 免费且多种编程语言&#xff0c;包括 Python、C、Javascri…

Python 爬虫入门(一):从零开始学爬虫 「详细介绍」

Python 爬虫入门&#xff08;一&#xff09;&#xff1a;从零开始学爬虫 「详细介绍」 前言1.爬虫概念1.1 什么是爬虫&#xff1f;1.2 爬虫的工作原理 2. HTTP 简述2.1 什么是 HTTP&#xff1f;2.2 HTTP 请求2.3 HTTP 响应2.4 常见的 HTTP 方法 3. 网页的组成3.1 HTML3.2 CSS3.…

数据分析:微生物数据的荟萃分析框架

介绍 Meta-analysis of fecal metagenomes reveals global microbial signatures that are specific for colorectal cancer提供了一种荟萃分析的框架&#xff0c;它主要基于常用的Wilcoxon rank-sum test和Blocked Wilcoxon rank-sum test 方法计算显著性&#xff0c;再使用分…

SpringBoot启动命令过长

Error running DromaraApplication: Command line is too long. Shorten command line for DromaraApplication or also for Spring Boot default configuration?

线上环境服务器CPU飙升排查

前因 收到线上服务器CPU使用率100%的告警信息。 环境 jdk1.8CentOS Linux &#xff1b;CentOS Linux 排查 查看服务器CPU使用率 果然cpu已经达到了100%了 命令 top 使用arthas工具 使用方式 arthas 执行命令java -jar arthas-boot.jar 然后执行命令 thread 看到有两个…

【linux】Shell脚本三剑客之awk命令的详细用法攻略

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

【基础教程】Tutorial on Pytorch 结合官方基础文档和个人经验

参考与前言 此教程首次书写于2021年12月份 至 2022年4月份间不断补充&#xff1b;阅读本文时可以对着代码运行查看 官方网址&#xff1a;https://pytorch.org/tutorials/ 【基本从这里翻译而来 更简洁版碎碎念】https://pytorch.org/tutorials/beginner/blitz/cifar10_tutori…

vue3+element-plus 实现动态菜单和动态路由的渲染

在 Vue.js 中&#xff0c;使用 Vue Router 管理路由数据&#xff0c;并将其用于渲染 el-menu&#xff08;Element UI 的菜单组件&#xff09;通常涉及以下几个步骤&#xff1a; 定义路由元数据&#xff1a; 在你的路由配置中&#xff0c;为每个路由项添加 meta 字段&#xff0c…

无人机10公里WiFi图传摄像模组,飞睿智能超清远距离无线监控,智能安防新潮流

在这个科技日新月异的时代&#xff0c;我们对影像的捕捉和传播有了更高的要求。从传统的有线传输到无线WiFi图传&#xff0c;每一次技术的飞跃都为我们带来了全新的视觉体验。今天&#xff0c;我们要探讨的&#xff0c;正是一款具有划时代意义的科技产品——飞睿智能10公里WiFi…

自学网络安全,从小白到大神的破茧之路!

在当今数字化高速发展的时代&#xff0c;网络安全已经成为了至关重要的领域。无论是个人的隐私保护&#xff0c;还是企业、国家的关键信息资产维护&#xff0c;都离不开网络安全的有力保障。出于对这一领域的浓厚兴趣以及对未来职业发展的清晰规划&#xff0c;我毅然决然地踏上…