外设驱动库开发笔记49:BY25Qxx存储器驱动

news2024/11/29 0:49:35

  在有一些应用中,我们可能需要大一些容量的存储单元,而实现的形式多种多样,在这一篇中我们将来讨论怎么使用BY25QXXX系列NOR FLASH存储器的问题。

1、功能概述

  在开始实现BY25QXXX系列NOR FLASH存储器的驱动之前,我们需要先了解一下它的基本情况。

1.1、QSPI接口

  QSPI接口,是QueuedSPI的缩写。和之前谈到的SPI一样都是出自Motorola。QSPI在SPI基础上做了一些增强,且向下兼容SPI。QSPI相对SPI最显著的差异就是增加了发送接收数据队列,Queued的称呼就是这么来的。这样做的好处就是,无需每次数据传输都需要CPU参与,可以降低CPU的资源占用。
  QSPI采用6先模式,同样也可以按Standard SPI、Dual SPI方式工作。我们引用STM32H7上一张QSPI接口与Flash的连接图来展示其连线方式。

  QSPI接口可以在以下三种模式下工作:间接模式,使用 QSPI 寄存器执行全部操作;状态轮询模式,周期性读取外部 Flash 状态寄存器,而且标志位置 1 时会产生中断(如擦除或烧写完成,会产生中断);内存映射模式,外部 Flash 映射到微控制器地址空间,从而系统将其视作内部存储器。我们在这里考虑BY25QXXX系列NOR FLASH存储器的驱动问题其实就是以间接模式访问的情况。
#1.2、BY25Q基本特点
  BY25QXXX系列NOR FLASH存储器支持标准SPI模式、双线SPI模式、四线SPI模式。其封装级引脚定义如下:

  这些引脚中,片选信号CS和始终信号SCLK在各种模式下是没有区别的。而SO(IO1)引脚在标准SPI模式下用作串行输出,在双线模式和四线模式下则是IO1。SI(IO0)引脚在标准SPI模式下用作串行输入,在双线模式和四线模式下则是IO0。WP(IO2)引脚在标准和双线模式下为写保护,在四线模式下为IO2。HOLD(IO3)引脚在标准和双线模式下为HOLD,在四线模式下为IO3。
#1.3、操作指令
  BY25QXXX系列NOR FLASH存储器在间接访问模式下,主要有四类指令:配置与状态指令、读指令、ID和安全指令、编程和擦除指令。。
配置与状态指令,用于配置操作方式及获取工作状态,主要包括使能及状态操作,具体指令如下所示:

  读指令,用于读取数据。读取数据支持在标准模式下、双线模式下、四线模式下进行操作,具体的指令如下所示:

  ID和安全指令,用于读取或配置一些特定操作,如获取制造商编号以及设备编号等,具体的指令如下所示:

  编程和擦除指令,用以实现对扇区、块以及整片的擦除以及指定的区域的编程等功能,具体的指令如下所示:

  对于BY25QXXX系列NOR FLASH存储器,不管是读写操作还是其它操作在指令阶段都是标准的SPI操作方式。

2、驱动设计与实现

  我们已经大致了解了BY25QXXX系列NOR FLASH存储器操作方式及指令,接下来我们就来考虑实现以间接模式访问它的驱动问题。

2.1、对象定义

  我们依旧是基于对象的模式来考虑这一问题,所以我们首先需要定义BY25QXXX系列NOR FLASH存储器的对象类型。我们先来分析一下,作为对象BY25QXXX系列NOR FLASH存储器都有哪些必要的属性和操作。
  先说一说属性问题,对于BY25QXXX系列NOR FLASH存储器对象来说可以标识器身份和状态的无非是ID和状态寄存器,而ID有包括制造商ID、设备ID、JEDEC ID和uniqueID等,我们可以将其作为对象的属性以标识不同的对象,当这些属性并不是必须的。
  再来看一看操作问题,对于BY25QXXX系列NOR FLASH存储器,它的操作指令有很多,但我们通过分析他们的时序不难发现所有的指令都可归纳为:命令发送、数据发送、数据接收等内容。不同的指令包括不同的组合,所以我们只需要将命令发送、数据发送、数据接收作为对象的操作,通过组合就可以实现全部的操作指令。还有一点需要考虑的是,在写  数据或者擦除是需要等待是否完成,所以我们额外添加一个就绪检测操作。通过上述分析我们可以定义BY25QXXX系列NOR FLASH存储器对象类型如下:

/*定义BY25QXX对象类型 */
typedef struct BY25QObject{
    uint8_t status[3];
    uint8_t mfrID[2];
    uint8_t jedecID[3];
    uint8_t uniqueID[8];
    
    void (*Write)(BY25QCommandConfigType config,uint8_t *wDatas);   //写数据操作指针
    void (*Read)(BY25QCommandConfigType config,uint8_t *rDatas);    //读数据操作指针
    void (*Command)(BY25QCommandConfigType config);                 //下发无数据操作命令
    void (*Ready)(void);                                            //检查Flash是否处于BUSY
    
}BY25QObjectType;

  定义了对象类型后,我们便可以基于它得到对象变量,但对象变量必须实例化才可使用,我们我们来考虑BY25QXXX系列NOR FLASH存储器对象的初始化问题。

/*实现BY25Q初始化配置*/
void BY25QInitialization(BY25QObjectType *by250q,   /*BY250Q存储器对象*/
                         BY25QWriteType write,      /*写函数指针*/
                         BY25QReadType read,        /*读函数指针*/
                         BY25QCommandType command,  /*命令下发函数指针*/
                         BY25QReadyType ready       /*就绪检测函数指针*/
                         )
{
    if((by250q==NULL)||(write==NULL)||(read==NULL)||(command==NULL)||(ready==NULL))
    {
        return;
    }
    
    by250q->Write=write;
    by250q->Read=read;
    by250q->Command=command;
    by250q->Ready=ready;
    
    GetBy25qxxID(by250q);
    ReadStatusRegister(by250q);
}

  在这一初始化函数中,我们主要是配置了用于读写操作的函数指针,并读取了设备的各类ID以及状态寄存器的值。如果有其他需要在初始化是完成的工作也可以在此函数中实现。

2.2、对象操作

  我们得到了对象类型,而且也可以为对象变量实现初始化配置。接下来我们看一看对象需要实现哪些操作。由于BY25QXXX系列NOR FLASH存储器的操作指令有很多,我们这里只是先几个必要的操作函数。

2.2.1、写使能

  写使能操作需要在写入数据之前完成,不仅是写存储区域是需要操作,在写寄存器之前也需要先进行此操作。该操作只有一个0x06指令写入,存储器就会自己完成相应操作,并反应到状态寄存器上。其操作时序图如下:

  此操作只占用标准SPI接口,事实上全部的命令都是如此。根据前述的描述及时序图,我们可以编写“写使能”的操作函数如下:

/* 写使能 */
static void WriteEnable(BY25QObjectType *by250q)
{
    BY25QCommandConfigType config;
    
    config.Instruction=WRITE_ENABLE;    // 写使能指令0x06
    config.DummyCycles=0;       // 空指令周期数
    config.AddressMode=0;
    config.Address=0;
    config.DataMode=0;
    config.NbData=0;

    by250q->Command(config);
}

2.2.2、读取数据

  从BY25QXXX系列NOR FLASH存储器读取数据是必不可少的操作,而且有多个操作指令,这里我们实现Quad快速读指令。读取数据时,发送指令和地址都使用单线操作,获取数据则使用四线操作。其时序图如下:

  根据前述的描述及时序图,我们可以编写“读取数据”的操作函数如下:

/*读取数据*/
static void QuadFastRead(BY25QObjectType *by250q,uint32_t readAddress,uint8_t *readBuffer,uint32_t readSize)
{
    BY25QCommandConfigType config;
    
    config.Instruction=0xEB;    // 读ID指令0xEB
    config.DummyCycles=6;       // 空指令周期数
    config.AddressMode=3;
    config.Address=readAddress;
    config.DataMode=3;
    config.NbData=readSize;
    
    by250q->Read(config,readBuffer);
}

2.2.3、擦除数据

  擦除和编程就其本质是一样的。对于BY25QXXX系列NOR FLASH存储器,其擦除指令有扇区擦除、块擦除和整片擦除四种,我们这里实现常用的扇区擦除。只需要发送擦除指令和扇区首地址即可。其操作时序图如下:

  根据前述的描述及时序图,我们可以编写“擦除数据”的操作函数如下:

/*擦除指定的扇区,扇区大小4KB*/
static void SectorErase(BY25QObjectType *by250q,uint32_t eraseAddress)
{
	BY25QCommandConfigType config;

    config.Instruction=0x20;    // 读ID指令0x90
    config.DummyCycles=0;       // 空指令周期数
    config.AddressMode=1;
    config.Address=eraseAddress;
    config.DataMode=0;
    config.NbData=0;

    by250q->Command(config);
}

2.2.4、编程数据

  向存储器中写数据又称之为编程数据,而BY25QXXX系列NOR FLASH存储器有三种编程指令:页编程、Quad页编程以及快速页编程。这里我们实现Quad页编程。在编程时,发送指令和地址采用单线模式,发送数据则采用四线模式。其指令操作时序图如下:

  根据前述的描述及时序图,我们可以编写“编程数据”的操作函数如下:

/*写数据*/
static void QuadPageProgram(BY25QObjectType *by250q,uint32_t writeAddress,uint8_t *writeBuffer,uint32_t writeSize)
{
    BY25QCommandConfigType config;

    config.Instruction=0x32;    // 读ID指令0x32
    config.DummyCycles=0;       // 空指令周期数
    config.AddressMode=1;
    config.Address=writeAddress;
    config.DataMode=3;
    config.NbData=writeSize;
    
    by250q->Write(config,writeBuffer);
}

3、驱动的使用

  前述我们已经完成了BY25QXXX系列NOR FLASH存储器驱动的设计与实现。接下来我们需要具体使用这一驱动程序来操作BY25QXXX系列NOR FLASH存储器,以便验证驱动程序的正确性。

3.1、声明并初始化对象

  我们先声明一个BY25QXXX系列NOR FLASH存储器对象变量,然后的操作都是基于这一对象变量来进行的。

BY25QObjectType by250q;

  如我们前面所述,对象变量必须要初始化才能使用。所以我们先来使用前面定义的初始化函数BY25QInitialization对这个对象变量进行初始化。这个初始化函数拥有多个输入变量如下:

BY25QObjectType *by250q,   /*BY250Q存储器对象*/
BY25QWriteType write,      /*写函数指针*/
BY25QReadType read,        /*读函数指针*/
BY25QCommandType command,  /*命令下发函数指针*/
BY25QReadyType ready       /*就绪检测函数指针*/

  在这些参数中,第一个参数就是我们要初始化的队形变量。后面的4个参数则是需要定义的操作函数指针。与具体的应用有关,需要我们在特定的应用场景中定义并作为参数传递给对象变量初始化函数。在这里,我们使用的是STM32H750的硬件平台和ST的HAL库函数,具体的实现如下:

/*读操作*/
static void ReadActionForBY25Q(BY25QCommandConfigType config,uint8_t *readBuffer)
{
    QSPI_CommandTypeDef sCommand;
    uint32_t addressMode[4]={QSPI_ADDRESS_NONE,QSPI_ADDRESS_1_LINE,QSPI_ADDRESS_2_LINES,QSPI_ADDRESS_4_LINES};
    uint32_t dataMode[4]={QSPI_DATA_NONE,QSPI_DATA_1_LINE,QSPI_DATA_2_LINES,QSPI_DATA_4_LINES};
    
    sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
    sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
    sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
    sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
    sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
    sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
    
    sCommand.Instruction = config.Instruction;
    sCommand.DummyCycles= config.DummyCycles;
    sCommand.AddressMode = addressMode[config.AddressMode];
    sCommand.Address     = config.Address;
    sCommand.DataMode    = dataMode[config.DataMode];
    sCommand.NbData = config.NbData;
    
    if (HAL_QSPI_Command(&hqspi, &sCommand,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
    {
        Error_Handler();
    }
    
    if (HAL_QSPI_Receive(&hqspi, readBuffer,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
    {
        Error_Handler();
    }
}

/*写操作*/
static void WriteActionForBY25Q(BY25QCommandConfigType config,uint8_t *writeBuffer)
{
     QSPI_CommandTypeDef sCommand;
    uint32_t addressMode[4]={QSPI_ADDRESS_NONE,QSPI_ADDRESS_1_LINE,QSPI_ADDRESS_2_LINES,QSPI_ADDRESS_4_LINES};
    uint32_t dataMode[4]={QSPI_DATA_NONE,QSPI_DATA_1_LINE,QSPI_DATA_2_LINES,QSPI_DATA_4_LINES};
    
    sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
    sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
    sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
    sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
    sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
    sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
    
    sCommand.Instruction = config.Instruction;
    sCommand.DummyCycles= config.DummyCycles;
    sCommand.AddressMode = addressMode[config.AddressMode];
    sCommand.Address     = config.Address;
    sCommand.DataMode    = dataMode[config.DataMode];
    sCommand.NbData = config.NbData;
    
    if (HAL_QSPI_Command(&hqspi, &sCommand,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
    {
        Error_Handler();
    }
    
    if (HAL_QSPI_Transmit(&hqspi, writeBuffer,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
    {
        Error_Handler();
    }
}

/*配置命令*/
static void ConfigCommandForBY25Q(BY25QCommandConfigType config)
{
    QSPI_CommandTypeDef sCommand;
    uint32_t addressMode[4]={QSPI_ADDRESS_NONE,QSPI_ADDRESS_1_LINE,QSPI_ADDRESS_2_LINES,QSPI_ADDRESS_4_LINES};
    uint32_t dataMode[4]={QSPI_DATA_NONE,QSPI_DATA_1_LINE,QSPI_DATA_2_LINES,QSPI_DATA_4_LINES};
    
    sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
    sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
    sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
    sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
    sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
    sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
    
    sCommand.Instruction = config.Instruction;
    sCommand.DummyCycles= config.DummyCycles;
    sCommand.AddressMode = addressMode[config.AddressMode];
    sCommand.Address     = config.Address;
    sCommand.DataMode    = dataMode[config.DataMode];
    sCommand.NbData = config.NbData;
    
    if (HAL_QSPI_Command(&hqspi, &sCommand,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
    {
        Error_Handler();
    }
}

/* 检测存储器是否就绪 */
static void QSPI_AutoPollingMemReady(void)
{
    QSPI_CommandTypeDef     sCommand;
    QSPI_AutoPollingTypeDef sConfig;
    
    /* Configure automatic polling mode to wait for memory ready ------ */  
    sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
    sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
    sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
    sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
    sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
    sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
    
    sCommand.Instruction       = 0x05;
    sCommand.AddressMode       = QSPI_ADDRESS_NONE;
    sCommand.DataMode          = QSPI_DATA_1_LINE;
    sCommand.DummyCycles       = 0;
    
    sConfig.Match           = 0x00;
    sConfig.Mask            = 0x01;
    sConfig.MatchMode       = QSPI_MATCH_MODE_AND;
    sConfig.StatusBytesSize = 1;
    sConfig.Interval        = 0x10;
    sConfig.AutomaticStop   = QSPI_AUTOMATIC_STOP_ENABLE;
    
    if (HAL_QSPI_AutoPolling(&hqspi, &sCommand, &sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
    {
        Error_Handler();
    }
}

  有了这些参数后,我们就可以使用这些参数来初始化BY25QXXX系列NOR FLASH存储器的对象变量了。

/*实现BY25Q初始化配置*/
BY25QInitialization(&by250q,   /*BY250Q存储器对象*/
                 WriteActionForBY25Q,      /*写函数指针*/
                 ReadActionForBY25Q,        /*读函数指针*/
                 ConfigCommandForBY25Q,  /*命令下发函数指针*/
                 QSPI_AutoPollingMemReady   /*就绪检测函数指针*/
                 );

3.2、基于对象进行操作

  我们设计这样一个操作场景,我们更具一个变量的值来读写BY25QXXX系列NOR FLASH存储器。当我们为指定的变量赋值为1时,我们从指定的地址读取一定数量的数据出来,并复位变量。当我们为指定的变量赋值为2时,我们擦除指定的地址所在的扇区,然后在指定地址写入一定数量的数据,并复位变量。

/*程序存储器测试*/
void FlashOperation(void)
{
    switch(swBY25Q)
    {
    case 1:
        {
            ReadDataFromBy25q(&by250q,QSPI_MEM_ADDRESS,readBuffer,READ_LENGTH);
            
            swBY25Q=0;
            break;
        }
    case 2:
        {
            pTimes++;
            for(int i=0;i<WRITE_LENGTH;i++)
            {
                writeBuffer[i]=i+pTimes;
            }
            
            EraseSectorForBy25q(&by250q,QSPI_MEM_ADDRESS);
                    
            WriteDataToBy25q(&by250q,QSPI_MEM_ADDRESS,writeBuffer,256);
            WriteDataToBy25q(&by250q,QSPI_MEM_ADDRESS+256,&writeBuffer[256],WRITE_LENGTH-256);
            
            swBY25Q=0;
            break;
        }
    default:
        {
            swBY25Q=0;
            break;
        }
        
    }
}

  我们同过在先修改变量swBY25Q的值,先修改为2以写入100个字节的数据;然后将变量赋值为1以读取先前写入的100个数据用以验证是否正确。测试结果发现,写入的数据和读出的数据是完全一致的,说明的们设计的驱动程序是正确的。

4、应用总结

  在这一篇中,我们设计并实现了BY25QXXX系列NOR FLASH存储器在间接操作模式下的驱动程序。后续我们也同过简单的读写操作实例验证了驱动成需的正确性。至此,BY25QXXX系列NOR FLASH存储器驱动程序的设计工作就完成了。
  在使用BY25QXXX系列NOR FLASH存储器驱动程序时需要注意,状态寄存的QE位非常重要。在使用Quad SPI时,该位必须置“1”,否则以Quad SPI模式写数据是不会成功的。而在SPI和Dual SPI方式时,该位最好置“0”,这样WP和HOLD操作才能有效。
  在使用BY25QXXX系列NOR FLASH存储器驱动程序时需要注意,在使用QSPI接口时,需要尽可能将对应的GPIO速度配置的快一点,否则可能会不能操作。

欢迎关注:

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

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

相关文章

Mysql-解决创建存储函数This function has none of DETERMINISTIC

问题 当二进制日志启用后&#xff0c;这个变量就会启用。它控制是否可以信任存储函数创建者&#xff0c;不会创建写入二进制日志引起不安全事件的存储函数。 如果设置为0&#xff08;默认值&#xff09;&#xff0c;用户不得创建或修改存储函数&#xff0c;除非它们具有除CRE…

COLMAP生成MVSNet数据集

一. colmap2mvsnet.py COLMAP可以给图像数据集标定一套相机外参及视图选择。如果想用COLMAP导出的结果输入MVSNet测试&#xff0c;需要把数据集&#xff08;图片、相机参数等&#xff09;转化为MVSNet的输入格式。MVSNet的作者yaoyao在Github上提供了colmap2mvsnet.py代码&…

Java内存区域

目录复制 Java内存区域区域划分内存溢出异常区域划分 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。根据《Java虚拟机规格》的规定&#xff0c;Java虚拟机所管理的内存包括以下几个运行时数据区域。 线程独占的有&#xff1a;程序计数器…

《web课程设计》 基于HTML+CSS+JavaScript实现中国水墨风的小学学校网站模板(6个网页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

[附源码]SSM计算机毕业设计网上零食商城JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Spring | 一文带你掌握IOC技术

&#x1f451; 博主简介&#xff1a;    &#x1f947; Java领域新星创作者    &#x1f947; 阿里云开发者社区专家博主、星级博主、技术博主 &#x1f91d; 交流社区&#xff1a;BoBooY&#xff08;优质编程学习笔记社区&#xff09; 文章目录IOC 控制反转1、概念2、分析…

无线传感器网络:传输层

文章目录Challenges for Transport LayerEnd-to-End MeasuresApplication-Dependent OperationEnergy ConsumptionConstrained Routing/AddressingBiased ImplementationReliable Multi-Segment Transport (RMST) ProtocolPump Slowly, Fetch Quickly (PSFQ) ProtocolPump Oper…

超详细的PHP入门知识点讲解

目录 一、简介 二、php基本语法 二、变量和作用域 三、常量 四、数据类型 五、运算符 六、流程控制 七、超全局变量 一、简介 基础知识&#xff1a; 需要一定的html和css的语法知识 基本概念&#xff1a; PHP&#xff08;超文本预处理器&#xff09;是一种通用开源脚本…

汽车销量数据库(分车型、分品牌月度销量数据 2005-2021)

1、数据来源&#xff1a;汽车工业协会 2、时间跨度&#xff1a;2005年1月-2021年5月 3、区域范围&#xff1a;全国 4、指标说明&#xff1a; 该份数据包含全国各种汽车销量数十个相关指标&#xff01; 该份数据包含如下指标&#xff1a; 轿车&#xff1a;一汽大众、上海大…

TMS Sphinx Alexandria Full Source

TMS Sphinx Alexandria Full Source 用于身份访问管理的TMS Sphinx Delphi框架&#xff0c;包括授权和身份验证。 TMS Sphinx允许您为多个应用程序实现单点登录(SSO)&#xff1a;web、本机、移动或机器到机器API通信。它可用于通过登录表单、类似的用户界面和基于服务的身份验证…

「低代码」跑通现代BI“最后一公里”的背后

文|智能相对论 作者|沈浪 “未来不懂低代码就和二十年前不会用word一样。未来80%的应用会由业务人员通过低代码开发。”在2022云栖大会上&#xff0c;阿里云智能总裁张建锋对低代码的发展前景依旧保持着非常积极的态度。 无独有偶&#xff0c;微软中国CTO韦青在他的专栏《万…

100天精通Python(数据分析篇)——第66天:Pandas透视表基础+实战案例(pivot_table函数)

文章目录每篇前言一、透视表基础参数说明实战案例0. 导入Excel数据1. data2. index3. values4. columns5. aggfunc6. fill_value7. dropna8. margins9. margins_name10. observed11. sort每篇前言 &#x1f3c6;&#x1f3c6;作者介绍&#xff1a;Python领域优质创作者、华为云…

linux dolphin为tags协议服务的进程意外退出,kioslave5已经意外关闭

刚开始用archlinux的使用的是dolphin感觉还是挺好用的。不过最近不知道为什么dolphin每次打开都会弹出个错误&#xff0c;很影响效率和心情。我简单的搜索报错代码&#xff0c;也没有成功解决报错。于是打算重新安装一个文件管理器做替换。 现象 运行dolphin或者运行浏览器中…

在PyCharm快速加载第三方模块的设置方法

在《小白学Python》慕课中说明了多种加载第三方模块的方法&#xff0c;这里补充一个在PyCharm中更为方便设置国内镜像源加载的方法。 因为默认情况下&#xff0c;PyCharm是加载国外网站的模块资源&#xff0c;因此常常会因为网络不稳定导致加载失败。因此&#xff0c;可以设置…

基于JAVA的学校图书管理系统(Swing+GUI)

目 录 第1章 绪论 1 1.1系统开发背景和意义 1 1.2系统可行性研究 1 1.3系统开发目标 2 1.4开发平台、运行环境 2 第2章 相关技术概述 3 2.1Java语言简介 3 2.2 Sqllite技术简介 4 2.3 Swing技术简介 5 第3章 需求分析 6 3.1 设计目标 6 3.2 功能分析 6 3.2.1 用户管理 6 3.2.2 …

深度学习day01

Marchine leariing 机器学习就是自动找函式 告诉机器要找的函式用 Supervised Learning 函式的Loss ——评价函式的好坏 Reinforcement就是让机器自己下象棋&#xff0c;输赢自己尝试&#xff0c;没像监督学习那样有人为规定 给函式寻找范围&#xff1a; 函式寻找方法——…

基于STM32实现USB组合设备CDC+MSC正确打开方式

摘要&#xff1a; 前一段时间对无刷电机的驱动有了兴趣&#xff0c;移植了odrive和simpleFOC代码&#xff0c;里面有关于stm32实现USB复合的实例&#xff0c;最近也有打算在electronbot里实现U盘通讯来实现bootloader和语音文件的拷贝和管理。看了网上也有相关实现文章&#x…

【mysql是怎样运行的】-客户端与服务器连接

文章目录1. 几种连接方式1.1 TCP/IP1.2 命名管道和共享内存1.3 UNIX 域套接字2. 服务器处理客户端请求2.1 连接管理2.2 解析与优化2.3 存储引擎1. 几种连接方式 1.1 TCP/IP 数据库服务器进程和客户端进程可能运行在不同的主机中&#xff0c;它们之间必须通过网络进行通信。My…

韩国研究人员开发交通信号控制新算法

由Keemin Sohn教授领导的韩国中央大学的研究小组提出了一种用于交通信号控制的元RL模型。具体来说&#xff0c;该团队开发了一个扩展的深度Q网络&#xff08;EDQN&#xff09;结合的基于上下文的元RL模型&#xff0c;用于交通信号控制。传统的交通信号控制器通常无法处理交通拥…

Echarts画散点图

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Echarts画散点图前言一、散点图悬浮框鼠标移入可滚动操作二、散点图偏下方的点悬浮数据显示不全三、数据量大、数据类别多、数据重复点多造成散点图散点展示不全或展示散点出…