STM32F4 | 新建工程模板——寄存器版本 | HAL库入门 | 新建工程模板——库函数版本

news2024/11/17 5:47:29

文章目录

    • 一、新建工程模板——寄存器版本
    • 二、HAL入门
      • 1.固件库和寄存器的区别
      • 2.STM32CubeF4
      • 3.HAL库包介绍
    • 三、新建HAL库工程模板

一、新建工程模板——寄存器版本


  • 开发环境:MDK5
  • 软件包:STM32CubeF4包

  新建工程模板的一般步骤为:

  • 新建工程目录,复制需要的文件到工程目录
      首先,打开 MDK软件。然后点击 Project->New uVision Project
    在这里插入图片描述
    弹出如图所示界面:
    在这里插入图片描述
    之后,弹出选择器件的对话框,如图所示。因为 ALIENTEK 阿波罗 STM32F429 开发板所使用的 STM32 型号为 STM32F429IGT6,所以在这里我们选择:STMicroelectronics->STM32F4 Series->STM32F429->STM32F429IG->STM32F429IGTx
    在这里插入图片描述
    点击 OK,MDK 会弹出 Manage Run-Time Environment 对话框,如图所示:
    在这里插入图片描述
    这是 MDK5 新增的一个功能,在这个界面,我们可以添加自己需要的组件,从而方便构建开发环境,不过这里我们不做介绍。所以在图中所示界面,我们直接点击 Cancel,即可,得到如下界面。

      到这里,我们还只是建了一个框架,还需要添加启动代码,以及.c 文件等。需要引入下面文件
    在这里插入图片描述
    启动文件放入USER文件夹,头文件放入CORE文件夹。
    在这里插入图片描述
    在这里插入图片描述

  • 把工程需要的文件添加到工程
    在这里插入图片描述
    启动代码是一段和硬件相关的汇编代码。是必不可少的!这代码主要作用如下:1、堆栈(SP)的初始化;2、初始化程序计数器(PC);3、设置向量表异常事件的入口地址;4、调用 main 函数。
      这个启动文件,修改了Reset_Handler 函数,该函数修改后代码如下:

    ; Reset handler
    Reset_Handler    PROC
                     EXPORT  Reset_Handler             [WEAK]
            ;IMPORT  SystemInit					//寄存器代码,不需要在这里调用 SystemInit 函数,
    											//故屏蔽掉,库函数版本代码,可以留下.
    											//不过需要在外部实现 SystemInit 函数,否则会报错.
            IMPORT  __main
                     LDR     R0, =0xE000ED88    // 使能浮点运算 CP10,CP11
                     LDR     R1,[R0]
                     ORR     R1,R1,#(0xF << 20)
                     STR     R1,[R0]
    				 
                     ;LDR     R0, =SystemInit	//寄存器代码,未用到,屏蔽
                     ;BLX     R0				//寄存器代码,未用到,屏蔽
                     LDR     R0, =__main
                     BX      R0
                     ENDP
    

      这段代码,我们主要加入了开启 STM32F429 硬件 FPU 的代码,以使能 STM32F429 的浮点运算单元。其中,0xE000ED88 就是协处理器控制寄存器(CPACR)的地址,该寄存器的第 20~23位用来控制是否支持浮点运算,这里我们全设置为 1,以支持浮点运算。
      特别注意:我们在汇编代码里面使能了 FPU,所以在 MDK 里面,我们也要设置使用 FPU,否则可能代码会无法运行,设置方法如下:选择 Options for Target ‘Target1’,打开 Target 选项卡,在 Code Generation 里面,选择 Use Single Precision,如图所示:
    在这里插入图片描述

  • MDK中设置把头文件存放路径
    在这里插入图片描述

  • 配置MDK:全局宏定义等
    重要的预编译全局宏定义标识符:STM32F429xx
    在这里插入图片描述

  • 编写用户函数
    新建test.c文件,并添加到工程组中
    在这里插入图片描述
    在这里插入图片描述
    此时,编译代码有错误!
    在这里插入图片描述
    这是因为寄存器代码,不需要在这里调用 SystemInit 函数,故屏蔽掉。库函数版本代码,可以留下;不过需要在外部实现 SystemInit 函数,否则会报错。
    在这里插入图片描述
    此时,再次编译工程,没有警告,没有错误!
    在这里插入图片描述

  • 添加ALIENTEK系统文件夹SYSTEM
    在这里插入图片描述
    SYSTEM中的文件添加到工程组中
    在这里插入图片描述
    设置头文件存放路径
    在这里插入图片描述
    此时,可以删除CORE文件夹,因为SYSTEM文件夹中已经包含。

二、HAL入门

1.固件库和寄存器的区别

  STM32 固件库到底是什么,和寄存器开发有什么关系?其实一句话就可以概括:固件库就是函数的集合,把寄存器操作封装起来。固件库函数的作用是向下负责与寄存器直接打交道,向上提供用户函数调用的接口(API)。
  在 51 的开发中我们常常的作法是直接操作寄存器,比如要控制某些 IO 口的状态,我们直接操作寄存器:

P0=0x11;

而在 STM32 的开发中,我们同样可以操作寄存器:

GPIOF->BSRR=0x00000001; //这里是针对 STM32F4 系列

这种方法当然可以,但是这种方法的劣势是你需要去掌握每个寄存器的用法,你才能正确使用STM32,而对于 STM32 这种级别的 MCU,数百个寄存器记起来又是谈何容易。于是 ST推出了官方固件库,固件库将这些寄存器底层操作都封装起来,提供一整套接口(API)供开发者调用,大多数场合下,你不需要去知道操作的是哪个寄存器,你只需要知道调用哪些函数即可。比如上面的控制 BSRRL 寄存器实现电平控制,官方 HAL 库封装了一个函数:

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{
	 if(PinState != GPIO_PIN_RESET)
	 {
	 	GPIOx->BSRR = GPIO_Pin;
	 }
	 else
	 {
	 	GPIOx->BSRR = (uint32_t)GPIO_Pin << 16;
	 }
}

这个时候你不需要再直接去操作BSRRL寄存器了,你只需要知道怎么使用HAL_GPIO_WritePin这个函数就可以了。

2.STM32CubeF4

  STM32CubeF4 包目录结构,如下图所示:
在这里插入图片描述
  接下来介绍一下 STM32CubeF4 中几个关键的文件夹,

  • Drivers 文件夹。Drivers 文件夹包含 BSPCMSISSTM32F4xx_HAL_Driver 三个子文件夹。

    • BSP 文件夹
      此支持包提供的是直接与硬件打交道的 API,例如触摸屏,LCD,SRAM 以及 EEPROM等板载硬件资源等驱动。BSP 文件夹下面有多种 ST官方 Discovery开发板, Nucleo开发板以及 EVAL 板的硬件驱动 API 文件,每一种开发板对应一个文件夹。
    • CMSIS 文件夹
      顾名思义就是符合 CMSIS 标准的软件抽象层组件相关文件。文件夹内部文件比较多。主要包括 DSP库(DSP_LIB 文件夹),Cortex-M 内核及其设备文件(Include 文件夹),微控制器专用头文件/启动代码/
      专用系统文件等(Device 文件夹)。
    • STM32F4xx_HAL_Driver文件夹
      这个文件夹非常重要,它包含了所有的 STM32F4xx系列 HAL 库头文件和源文件,也就是所有底层硬件
      抽象层 API 声明和定义。它的作用是屏蔽了复杂的硬件寄存器操作,统一了外设的接口函数。该文件
      夹包含 Src 和 Inc 两个子文件夹,其中 Src 子文件夹存放的是.c 源文件,Inc 子文件夹存放的是与之对应
      的.h 头文件。每个.c 源文件对应一个.h 头文件。源文件名称基本遵循 stm32f4xx_hal_ppp.c 定义格式,
      头文件名称基本遵循 stm32f4xx_hal_ppp.h 定义格式。比如 gpio 相关的 API 的声明和定义在文件
      stm32f4xx_hal_gpio.h 和 stm32f4xx_hal_gpio.c 中。
  • Middlewares 文件夹。
    该文件夹下面有 STThird_Party 2 个子文件夹。ST 文件夹下面存放的是 STM32 相关的一些文件,包括 STemWinUSB 库等。Third_Party 文件夹是第三方中间件,这些中间价都是非常成熟的开源解决方案。

    • ST文件夹
      在这里插入图片描述
    • Third_Party文件夹
      在这里插入图片描述
  • Projects 文件夹。
    该文件夹存放的是一些可以直接编译的实例工程。

  • Utilities 文件夹。
    该文件夹下面是一些其他组件,在项目中使用得不多。

3.HAL库包介绍

  新建一个工程常需要以下HAL库文件:
在这里插入图片描述
接下来我们看看 HAL 库工程模板中各个文件之间的包含关系,
在这里插入图片描述
从上面工程文件包含关系图可以看出,顶层头文件 stm32f4xx.h 直接或间接包含了其他所有工程必要头文件,所以在我们的用户代码中,我们只需要包含顶层头文件 stm32f4xx.h 即可。这里我们还需要说明一下,在我们 ALIENTEK 提供的 SYSTEM 文件夹内部的 sys.h 头文件中,我们默认包含了 stm32f4xx.h 头文件,所以在我们用户代码中,只需要包含 sys.h 头文件即可,当然也可以直接包含顶层头文件 stm32f4xx.h

三、新建HAL库工程模板


  • 作用:方便编写用户代码
  • 开发环境:MDK5
  • 所需软件包:HAL库包

  其步骤如下:

  1. 在电脑的某个目录下面建立一个文件夹,后面所建立的工程都可以放在这个文件夹下面,并新建下面 4 个子文件夹:COREHALLIBOBJUSER
    在这里插入图片描述

  2. 打开 MDK,点击菜单 Project –>New Uvision Project ,然后将目录定位到刚才建立的文件夹下的 USER 子目录,工程取名为 Template 之后点击保存,工程文件就都保存到 USER文件夹下面。
    在这里插入图片描述
    接下来会出现一个选择 Device 的界面,就是选择我们的芯片型号。这里我们选择 STMicroelectronics->STM32F4 Series->STM32F429->STM32F429IG->STM32F429IGTx
    在这里插入图片描述
    点击 OK,MDK 会弹出 Manage Run-Time Environment 对话框,
    在这里插入图片描述
    这是 MDK5 新增的一个功能,在这个界面,我们可以添加自己需要的组件,从而方便构建开发环境,不过这里我们不做介绍。我们直接点击 Cancel即可,

  3. USER目录内容如下图
    在这里插入图片描述
    这里我们说明一下, Template.uvprojx 是工程文件,非常关键,不能轻易删除。DebugConfigListingsObjects 三个文件夹是 MDK 自动生成的文件夹。其中 DebugConfig 文件夹用于存储一些调试配置文件,ListingsObjects 文件夹用来存储 MDK 编译过程的一些中间文件。这里,我们把 ListingsObjects 文件夹删除,我们会在下一步骤中新建一个 OBJ 文件夹,用来存放编译中间文件。当然,我们不删除这两个文件夹也没有关系,只是我们不用它而已。

  4. 接下来我们将从官方 stm32cubeF4 包里面复制一些我们新建工程需要的关键文件到我们的工程目录中。首先,我们要将 STM32CubeF4 包里的源码文件复制到我们的工程目录文件夹下面。打开官方 STM32CubeF4 包,定位到我们之前准备好的 HAL 库包的目录:\STM32Cube_FW_F4_V1.10.0\Drivers\STM32F4xx_HAL_Driver 下面,将目录下面的 Src,Inc 文件夹复制到我们刚才建立的 HALLIB 文件夹下面。Src 存放的是固件库的.c 文件,Inc 存放的是
    对应的.h 文件
    在这里插入图片描述

  5. 接下来,我们要将 STM32CubeF4 包里面相关的启动文件以及一些关键头文件复制到我们的工程目录 CORE 之下。打开 STM32CubeF4 包,定位到目录\STM32Cube_FW_F4_V1.11.0\Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm 下面,将文件startup_stm32f429xx.s 复制到 CORE 目录下面 。然后定位到目录\STM32Cube_FW_F4_V1.11.0\Drivers\CMSIS\Include,将里面的五个头文件:cmsis_armcc.h
    core_cm4.hcore_cmFunc.hcore_cmInstr.hcore_cmSimd.h 同样复制到 CORE 目录下面。
    现在看看我们的 CORE 文件夹下面的文件,
    在这里插入图片描述

  6. 接下来,我们要复制工程模板需要的一些其他头文件和源文件到我们工程。首先定位到目录:\STM32Cube_FW_F4_V1.11.0\Drivers\CMSIS\Device\ST\STM32F4xx\Include 将里面的 3 个文件stm32f4xx.hsystem_stm32f4xx.hstm32f429xx.h 复制到 USER 目录之下。这三个头文件是STM32F4 工程非常关键的头文件。然后进入目录\STM32Cube_FW_F4_V1.11.0\Projects\STM32F429I-Discovery\Templates 目录下,我们需要从 SrcInc 文件夹下面复制我们需要的文件到 USER 目录。首先我们打开Inc目录,将目录下面的3个头文件stm32f4xx_it.hstm32f4xx_hal_conf.hmain.h全部复制到USER目录下面。然后我们打开 Src 目录,将下面的四个源文件 system_stm32f4xx.cstm32f4xx_it.c, stm32f4xx_hal_msp.cmain.c 同样全部复制到 USER 目录下面。
    在这里插入图片描述

  7. 接下来,我们还需要复制 ALIENTEK 编写的 SYSTEM 文件夹内容到工程目录中。
    在这里插入图片描述
    到这里,工程模板所需要的所有文件都已经复制进去。接下来,我们将在 MDK 中将这些文件添加到工程。

  8. 下面我们将前面复制过来的文件加入我们的工程中。右键点击 Target1,选择 Manage Project Items
    在这里插入图片描述

  9. 建立四个 GroupsUSERSYSTEMCORE,和 HALLIB
    在这里插入图片描述
    在这里插入图片描述

  10. 下面我们往 Group 里面添加我们需要的文件。第一步我们选择HALLIB,然后点击右边的 Add Files,定位到我们刚才建立的目录\HALLIB\Src 下面,将里面所有的文件选中(Ctrl+A),然后点击 Add,然后 Close。可以看到 Files 列表下面包含我们添加的文件。这里有 几 个 文件比较特殊 , 例 如 stm32f4xx_hal_dsc.cstm32f4xx_hal_iptim.cstm32f4xx_hal_msp_template.c 三个文件不需要引入工程。stm32f4xx_hal_dsi.cmipi 接口相关函数,STM32F429 没有这个接口,所以这个文件可以不用引入。stm32f4xx_hal_iptim.c 文件是低功耗定时器相关函数, STM32F429 也没有这 个功能,也不需要引入。stm32f4xx_hal_msp_template.c 文件内容是一些空函数,一般也不需要引入。
    在这里插入图片描述

  11. 用上面同样的方法,将 Groups 定位到 COREUSERSYSTEM 分组之下,添加需要的文件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  12. 接下来我们要在 MDK 里面设置头文件存放路径。也就是告诉 MDK 到那些目录下面去寻找包含了的头文件。这一步骤非常重要。如果没有设置头文件路径,那么工程会出现报错头文件路径找不到
    在这里插入图片描述
    在这里插入图片描述

  13. 接下来,对于 STM32F429 系列的工程,还需要添加全局宏定义标识符,所谓全局宏定义标识符,就是在工程中任何地方都可见。添加方法是点击魔术棒之后,进入C/C++选项卡,然后在 Define 输入框连输入:USE_HAL_DRIVER,STM32F429xx
    在这里插入图片描述

  14. 接下来我们要编译工程,在编译之前我们首先要选择编译中间文件编译后存放目录。MDK 默认编译后的中间文件存放目录为 USER 目录下面的 ListingsObjects子目录,这里为了和我们 ALIENTEK 工程结构保持一致,我们重新选择存放到目录 OBJ 目录之下。
    在这里插入图片描述
    在这里插入图片描述
    这里我们还要勾上“Create HEX File”选项和 Browse Information 选项。Create HEX File 选项选上是要求编译之后生成 HEX 文件。

  15. 接下来,在编译之前,我们先把 main.c 文件里面的内容替换为如下内容:

    #include "sys.h"
    #include "delay.h"
    #include "usart.h"
    
    
    void Delay(__IO uint32_t nCount);
    
    void Delay(__IO uint32_t nCount)
    {
      while(nCount--){}
    }
    
    int main(void)
    {
    
    	GPIO_InitTypeDef GPIO_Initure;
         
        HAL_Init();                     //初始化HAL库    
        Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
    
        __HAL_RCC_GPIOB_CLK_ENABLE();           //开启GPIOB时钟
    	
        GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1; //PB1,0
        GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
        GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
        GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
        HAL_GPIO_Init(GPIOB,&GPIO_Initure);
    
    	while(1)
    	{
    		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);	//PB1置1 
    		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);	//PB0置1  			
    		Delay(0x7FFFFF);
    		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);	//PB1置0
    		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);	//PB0置0  
    		Delay(0x7FFFFF);
    	}
    }
    
  16. 点击编译按钮编译工程,可以看到工程编译通过没有任何错误和警告。
    在这里插入图片描述

  17. 到这里,一个基于 HAL 库的工程模板就建立完成,同时在工程的 OBJ 目录下面生成了对应的 hex 文件。

  18. 这里还一个地方需要修改一下,那就是关于系统初始化之后的中断优先级分组组号的设置。默认情况下调用 HAL 初始化函数 HAL_Init 之后,会设置分组为组 4,这里正点原子所有实验使用的是分组 2,所以我们修改 HAL_Init 函数内部,重新设置分组为组 2 即可。具体方法是:打开 HALLIB 分组之下的 stm32f4xx_hal.c 文件,搜索函数 HAL_Init,找到函数体,里面默认有这样一行代码:

    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
    

    我们将入口参数 NVIC_PRIORITYGROUP_4 修改为 NVIC_PRIORITYGROUP_2 即可。

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

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

相关文章

【UE5】多用户协同编辑

UE5新出了一个多用户协同功能所以想搭一个来玩玩。 Epic已经将流程极度的简化了&#xff0c;在B站虚幻官方也放出了教程视频&#xff0c;[官方文档](多用户编辑入门 | 虚幻引擎文档 (unrealengine.com))也有教程。 这里做一下简要记录。 1.启用插件 首先打开Multi-User Edi…

SoftPerfect NetWorx中管理流量和宽带设备工具

SoftPerfect NetWorx中管理流量和宽带设备工具 NetWorx是用于在Windows中管理流量和宽带设备的简单工具和实用程序。如果我们利用交通设施&#xff0c;毫不拖延地利用教育系统&#xff0c;以及与各种驾驶员相关的学习&#xff0c;那么当加载互联网时&#xff0c;通过软件秘密使…

[附源码]计算机毕业设计酒店客房管理系统Springboot程序

项目运行 环境配置&#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…

BaiqiSoft MstHtmlEditor for .NET负责编辑的控制器

BaiqiSoft MstHtmlEditor for .NET负责编辑的控制器 BaiqiSoft MstHtmlEditor获取.NET for win表单被认为是一个元素,用户可以轻松灵活地将其融入到C#、VB.NET甚至WPF软件中。负责编辑的控制器,.NET Win Forms的MstHtmlEditor,允许用户和开发人员,甚至非技术用户使用该系列…

Docker入门第二期

写目一、宿主机与容器之间的文件拷贝二、数据卷三、数据卷容器四、Dockerfile一、宿主机与容器之间的文件拷贝 docker run -p 3307:3306 --name mysql1 -di -v /home/javaxl/data/mysql/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /home/javaxl/data/mysql/data/:/var/lib/…

用Python把附近的足浴店都给采集了一遍,好兄弟:针不戳~

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的小编 又到了学Python时刻~ &#xff08;文末送读者福利&#xff09; 我又来了&#xff01;今天整个好玩的&#xff0c;你们肯定喜欢~ 咱们上班累了&#xff0c;不得好好犒劳一下自己&#xff0c;是吧 &#xff01; 于是我整…

相控阵天线(十三):天线校准技术仿真介绍之换相法

目录简介换相法算法简介换相法校准对方向图的影响Hadamard控制矩阵的换相法仿真循环移相控制矩阵的换相法仿真简介 传统方法按照测试区域分&#xff0c;可分为远场、中场和近场测量。远场测量发展成熟&#xff0c;可直接测量方向图&#xff0c;但对条件要求较高&#xff0c;且…

SpringMVC从入门到精通(二)

文章目录6. 响应视图和结果数据6.1 返回值类型6.2 springmvc作用域传值6.3 转发和重定向6.4 json数据格式的请求与响应7.SpringMVC 实现文件上传7.1 文件上传三要素7.2 文件上传依赖7.2 文件上传示例&#xff08;后端需要配置文件解析器&#xff09;8. SpringMVC 中的异常处理8…

FMT航点飞行(一)

一、航点飞行前检查&#xff1a; &#xff08;1&#xff09;将飞行器在position模式下启动飞行&#xff0c;移动一个距离&#xff1b;在qgc地面站地图上观察移动的距离&#xff0c;记录大概移动的距离为D&#xff1b;打航向&#xff0c;观察地磁计转向是否正常&#xff1b; &a…

Redisson的看门狗机制究竟有什么用?

Redisson的看门狗机制究竟有什么用&#xff1f; 一、普通的Redis分布式锁的缺陷 基于Redis的分布式锁 Redis Lua 脚本实现分布式锁 二、watchDog的自动延期机制 调用链关系 源码解析 tryLock() tryAcquire() tryAcquireAsync() scheduleExpirationRenewal() 锁…

Nginx+tomcat集群

Nginxtomcat集群 定义&#xff1a;在测试环境中有多个tomcat运行这一个项目&#xff0c;需要nginx管理 2特点&#xff1a;1&#xff0c;增加项目访问能力 2&#xff0c;增加服务器性能 3&#xff0c;实现不同负载均衡 3负载均衡&#xff1a;根据每台服务器的性能分配其能承受住…

【Linux】程序地址空间

目录 地址空间是什么 写时拷贝 地址空间存在的意义 如何管理进程地址空间 地址空间是什么 这是我们常说的c/c程序地址空间&#xff0c;但是这里的空间具体指的是哪里的空间&#xff0c;举一个例子方便理解&#xff1a; 运行结果&#xff1a; 代码运行十秒后子进程修改了全局…

目标检测—DiffusionDet:用于检测的概率扩散模型笔记—DDPM

目录 一、Introduction 二、相关工作 三、方法 1.准备工作 2.架构 3、训练 4.预测过程 四. 实验 1.训练策略 2.main property 3.消融实验 五、代码分析 1.测试 demo.py 2.训练 train-net.py 总结 DiffusionDet&#xff1a;将目标检测问题构建为一个从带噪框到目…

安卓APP源码和设计报告——麻雀笔记

目录 一 安卓应用程序开发背景3 1.1开发背景3 1.2开发环境4 二 安卓应用程序开发理论与方法4 三 记事本应用程序的设计与实现5 3.1 拟解决的问题及目标5 3.2 总体设计6 3.3 详细设计与编码实现6 四 总结23 一 安卓应用程序开发背景 1.1开发背景 1.智能手机的市场 …

四年一次的世界杯来了,看看还剩下哪些赛程呢?

足球世界杯的由来2022年的世界杯目前世界杯的赛程看看排在前十的球员几个疑问&#xff1f;世界杯的由来 足球大家应该知道&#xff0c;是一项体育运动&#xff0c;而且是一项多人的体育运动。 世界杯的诞生&#xff0c;源于1950年的南非公开赛&#xff0c;在当时只有5支队伍参…

微信视频播放点播小程序毕业设计,在线教育视频学习小程序系统设计与实现,微信小程序毕业设计论文怎么写毕设源码开题报告需求分析怎么做

基于微信小程序的毕业设计题目&#xff08;12&#xff09;php在线教育视频点播学习小程序(含开题报告、任务书、中期报告、答辩PPT、论文模板) 项目背景和意义 目的&#xff1a;本课题主要目标是设计并能够实现一个基于微信小程序视频点播系统&#xff0c;前台用户使用小程序&a…

理解Nodejs中的进程间通信

前置知识 文件描述符 在 Linux 系统中&#xff0c;一切都看成文件&#xff0c;当进程打开现有文件时&#xff0c;会返回一个文件描述符。 文件描述符是操作系统为了管理已经被进程打开的文件所创建的索引&#xff0c;用来指向被打开的文件。 当我们的进程启动之后&#xff0c…

Python学习-8.1.2 标准库(random库的基础与实例)

2.2 random库 使用random库的主要目的是生成随机数 2.2.1 产生随机数 random()函数&#xff1a;生成一个[0.0,1.0)之间的随机小数&#xff0c;左开右闭。 import random print(random.random())#生成一个[0.0,1.0)之间的随机小数 #每次运行random()函数都会产生不同的数据 …

Layer2代币经济学:除了治理 还应该具备什么价值?

为什么我们需要L2&#xff1f; 任何在2021年期间使用以太坊的人都知道&#xff0c;该区块链可能会变得非常拥堵。这是一个典型的问题——需求太多而供应不足。因此&#xff0c;gas费用&#xff08;交易费&#xff09;变得相当昂贵。在牛市高峰期&#xff0c;使用以太坊区块链发…

基于Jenkins的开发测试全流程持续集成实践

今年一直在公司实践CI&#xff0c;本文将近半年来的一些实践总结一下&#xff0c;可能不太完善或优美&#xff0c;但的确初步解决了我目前所在项目组的一些痛点。当然这仅是一家之言也不够完整&#xff0c;后续还会深入实践和引入Kubernetes进行容器编排&#xff0c;以及通过阿…