二、点亮希望之光:寄存器与库函数驱动 LED 灯

文章目录

  • 一、寄存器
    • 1、存储器映射
    • 2、存储器映射表
    • 3、寄存器
    • 4、寄存器映射
    • 5、寄存器重映射
    • 6、总线基地址、外设基地址、外设寄存器地址
    • 7、操作寄存器(以操作一个GPIO口为例)
      • 1. 寄存器地址定义部分
      • 2. `GPIOD_Configuration` 函数部分
      • 3. `main` 函数部分
  • 二、库函数
    • 1、为什么要使用库函数
    • 2、什么是库函数
    • 3、库函数的详解(以GPIO为例)
    • 4、如何操作库函数(以点亮LED连接到PD7为例)
  • 三、寄存器和库函数的区别
    • 1、寄存器与库函数的区别
    • 2、寄存器操作的优势和劣势
    • 3、库函数的优势和劣势
  • 四、GD32F4xx 系列器件的存储器映射表

一、寄存器

  • GD32F450ZG 单片机的寄存器是用于控制和配置芯片内部各种硬件资源的存储单元。它们就像是一组开关和控制器,通过对这些寄存器进行读写操作,可以实现对单片机的功能配置、数据传输、中断处理等多种操作。

1、存储器映射

  • 概念:存储器映射是将芯片中的各种存储器(如闪存、SRAM等)和外设(如定时器、GPIO等)统一编址,把它们看成一个连续的地址空间。就好像一个大仓库,不同的区域存放着不同的东西,这个大仓库的每个存储单元都有一个唯一的地址。这样CPU可以通过这个统一的地址来访问不同的资源。
  • 举例:在GD32F450ZG单片机中,整个存储区域可能从0x00000000开始,一直到某个较大的地址,其中不同的段分配给了不同的用途。例如,一部分地址范围是闪存(程序存储区),用来存放程序代码;另一部分是SRAM(数据存储区),用于存放程序运行时的数据。

2、存储器映射表

  • 概念:存储器映射表是一张详细的“地图”,它记录了存储区域中每个地址段对应的具体资源。它告诉用户从哪个地址开始到哪个地址结束是闪存、从哪个地址开始是SRAM、哪个地址范围是某个外设(如UART、SPI等)的寄存器等信息。
  • 用途:通过查看存储器映射表,开发者可以准确地找到想要访问的资源的地址范围。例如,在编写程序时,如果要访问某个外设的寄存器,就需要根据这个表来确定正确的地址。详细可见文章末尾存储器映射表。

3、寄存器

  • 概念:寄存器是一种特殊的存储单元,它位于芯片内部,用于控制和监视芯片的各种功能。可以把寄存器想象成一个个小的“控制盒”,每个“控制盒”负责一个特定的功能。例如,对于GPIO(通用输入输出端口),有控制引脚方向(输入或输出)的寄存器、控制引脚输出电平(高或低)的寄存器等。
  • 功能分类
    • 控制寄存器:用于控制外设的工作模式。比如,定时器的控制寄存器可以设置定时器的计数模式(向上计数、向下计数等)、是否使能定时器等。
    • 状态寄存器:用于反映外设的当前状态。以UART为例,状态寄存器可以指示是否有数据接收完成、是否有数据发送缓冲区为空等状态。
    • 数据寄存器:用于存储要发送或接收的数据。在SPI通信中,数据寄存器用于存放要发送出去的数据,或者读取接收到的数据。

4、寄存器映射

  • 概念:寄存器映射是将寄存器的物理地址映射到一个便于编程访问的虚拟地址空间。这样,在编程时就可以通过简单的地址操作来访问寄存器,而不需要关心寄存器的实际物理位置。
  • 举例:GD32F450ZG单片机可能将一些外设寄存器映射到特定的地址范围,比如将GPIOA的寄存器映射到从地址A开始的一段连续地址,这样在程序中通过访问这个地址范围就相当于访问GPIOA的寄存器。

5、寄存器重映射

  • 概念:寄存器重映射是改变寄存器的默认映射地址,将其映射到另外一个地址空间。这样做的目的通常是为了方便布线、解决资源冲突或者满足特定的应用需求。
  • 举例:在某些情况下,默认的GPIO引脚对应的寄存器地址可能在布线时不太方便访问,通过寄存器重映射,可以将这些寄存器映射到一个更容易访问的地址,从而方便对GPIO进行操作。

6、总线基地址、外设基地址、外设寄存器地址

  • 总线基地址:它是整个存储系统中某条总线(如APB总线、AHB总线)的起始地址。就像一条街道的起点门牌号,所有连接在这条总线上的外设的地址都是基于这个总线基地址来确定的。
  • 外设基地址:是某个外设在总线上的起始地址。例如,GPIOA这个外设在总线上有一个基地址,从这个地址开始的一段连续地址空间就是GPIOA的寄存器地址范围。
  • 外设寄存器地址:是外设中每个具体寄存器的地址。以GPIOA为例,有控制引脚方向的寄存器地址、控制引脚输出电平的寄存器地址等,这些都是基于GPIOA的外设基地址来确定的。

7、操作寄存器(以操作一个GPIO口为例)

以下是基于GD32F450ZG芯片,通过操作寄存器的方式来控制GPIOD的第7引脚输出高电平以点亮LED的示例代码(假设LED阳极接该引脚,阴极接地这种常见连接方式),以下代码使用C语言编写,且是示意性代码,你可能需要根据实际的编译环境等做适当调整:

// 首先定义寄存器相关的地址,这些地址可以从芯片手册中获取对应的值
#define RCC_AHB1ENR    (*(volatile unsigned int *)0x40023830)  // 时钟使能寄存器地址
#define GPIOD_MODER    (*(volatile unsigned int *)0x40020C00)  // GPIOD 模式寄存器地址
#define GPIOD_OTYPER   (*(volatile unsigned int *)0x40020C04)  // GPIOD 输出类型寄存器地址
#define GPIOD_OSPEEDR  (*(volatile unsigned int *)0x40020C08)  // GPIOD 输出速度寄存器地址
#define GPIOD_PUPDR    (*(volatile unsigned int *)0x40020C0C)  // GPIOD 上拉下拉寄存器地址
#define GPIOD_ODR      (*(volatile unsigned int *)0x40020C14)  // GPIOD 输出数据寄存器地址// 函数用于初始化GPIOD的相关配置
void GPIOD_Configuration(void)
{// 使能GPIOD时钟,对应RCC_AHB1ENR寄存器中相关位设置为1RCC_AHB1ENR |= (1 << 3);  // 配置GPIOD的第7引脚为通用输出模式(01),参考芯片手册对MODER寄存器的描述GPIOD_MODER &= ~(3 << 14);  // 先清除原来的设置GPIOD_MODER |= (1 << 14);  // 设置为输出模式// 设置输出类型为推挽输出(0),对应OTYPER寄存器设置,默认就是推挽输出,这里做下示意性设置GPIOD_OTYPER &= ~(1 << 7);  // 设置输出速度,这里设置为高速(11),可根据实际需求调整,参考OSPEEDR寄存器说明GPIOD_OSPEEDR &= ~(3 << 14);GPIOD_OSPEEDR |= (3 << 14);// 设置上拉下拉电阻,这里设置为无上下拉(00),参考PUPDR寄存器GPIOD_PUPDR &= ~(3 << 14);
}int main()
{// 进行GPIOD引脚的初始化配置GPIOD_Configuration();// 将GPIOD的第7引脚输出数据寄存器对应位置1,输出高电平GPIOD_ODR |= (1 << 7);  while(1){// 可以在这里添加其他需要循环执行的代码,如果不需要可以为空循环}
}

下面详细解释一下代码各部分的含义:

1. 寄存器地址定义部分

通过 #define 宏定义了一系列寄存器的地址,使用 volatile 关键字修饰是为了告诉编译器该变量(实际代表的寄存器内容)可能会被硬件等外部因素改变,编译器不要对其访问做优化,要每次都从实际的内存地址(寄存器所在地址)读取其值。

例如 RCC_AHB1ENR (*(volatile unsigned int *)0x40023830) 就定义了 RCC_AHB1ENR 这个寄存器对应的内存地址是 0x40023830,后续可以通过对这个定义好的变量进行读写操作来操作对应寄存器。

2. GPIOD_Configuration 函数部分

  • 时钟使能
    首先在函数内通过 RCC_AHB1ENR |= (1 << 3); 操作 RCC_AHB1ENR 寄存器来使能GPIOD的时钟。在芯片中,各个外设模块(比如这里的GPIOD端口)都需要时钟才能正常工作,将该寄存器对应位(第3位对应GPIOD的时钟使能位,具体参考芯片手册的寄存器说明)置1就是开启其时钟。
    在这里插入图片描述

  • 引脚模式配置

    • 对于 GPIOD_MODER 寄存器,它用来设置每个引脚的工作模式(比如输入、输出、复用功能等)。先通过 GPIOD_MODER &= ~(3 << 14); 清除原来对应引脚(第7引脚,对应寄存器的位是从低位开始算,第7引脚对应的位在第14、15两位控制,因为每两位控制一个引脚的模式,所以左移14位)的模式设置,然后 GPIOD_MODER |= (1 << 14); 将其设置为通用输出模式(01表示输出模式,参考芯片手册的模式编码定义)。
      在这里插入图片描述
  • 输出类型配置
    GPIOD_OTYPER 寄存器用于设置引脚是推挽输出还是开漏输出,这里 GPIOD_OTYPER &= ~(1 << 7); 表示将第7引脚设置为推挽输出(默认一般就是推挽输出,这里做明确设置),也就是可以输出高低电平且具有一定的驱动能力。
    在这里插入图片描述

  • 输出速度配置
    通过操作 GPIOD_OSPEEDR 寄存器来设置引脚的输出速度,这里 GPIOD_OSPEEDR &= ~(3 << 14); 先清除原来的速度设置,然后 GPIOD_OSPEEDR |= (3 << 14); 将其设置为高速输出(速度等级的编码同样参考芯片手册定义,这里设置为11表示高速),根据实际电路和对速度的需求可以选择不同的速度等级。
    在这里插入图片描述

  • 上拉下拉电阻配置
    最后使用 GPIOD_PUPDR 寄存器设置引脚的上拉下拉情况,GPIOD_PUPDR &= ~(3 << 14); 操作是将第7引脚设置为无上下拉状态(00表示无上下拉,不同编码对应不同的上拉下拉设置,参考芯片手册)。
    在这里插入图片描述

3. main 函数部分

  • 首先调用 GPIOD_Configuration 函数对GPIOD的第7引脚进行初始化配置,使其具备合适的输出条件。

  • 然后通过 GPIOD_ODR |= (1 << 7); 操作 GPIOD_ODR 寄存器,将第7引脚对应的位(第7位)置1,这样就使得该引脚输出高电平,从而如果连接的LED电路正确(阳极接该引脚,阴极接地),就可以点亮LED。

  • 最后的 while(1) 循环可以根据实际需求添加其他要不断执行的代码逻辑,如果暂时不需要额外逻辑,空循环即可保证程序持续运行并维持引脚的输出电平状态。

请注意,以上代码只是基于芯片手册对寄存器操作的常规实现示例,实际应用中可能需要考虑更多如系统初始化等完整的环境搭建内容,并且要严格对照芯片手册确保寄存器地址、位操作等都符合芯片的具体规定。

二、库函数

1、为什么要使用库函数

  • 提高开发效率:直接操作寄存器来控制芯片的功能是非常繁琐的。例如,配置一个通用输入输出(GPIO)引脚,需要对多个寄存器进行位操作,包括配置模式寄存器、输出数据寄存器等。使用库函数可以避免这些复杂的底层寄存器操作,减少代码编写量和出错的概率。
  • 增强代码的可移植性:不同的芯片可能有不同的寄存器地址和操作方式。如果使用库函数,只要库函数的接口不变,在不同的同系列芯片或者经过适当修改的其他芯片之间移植代码会更加方便。
  • 便于代码维护:库函数将复杂的硬件操作封装起来,使代码结构更加清晰。当需要修改功能时,例如改变GPIO引脚的功能或者更新芯片的某些配置,只需要调用相应的库函数或者修改库函数的参数,而不需要在大量的寄存器操作代码中寻找和修改。

2、什么是库函数

  • 库函数是芯片厂商或者第三方为了方便开发者使用芯片的功能而编写的一组函数。这些函数封装了对芯片内部寄存器的操作,为开发者提供了一个更高级的编程接口。以GD32F450ZG为例,它的库函数可以实现诸如GPIO配置、定时器设置、中断处理等各种功能。库函数通常是基于芯片的硬件手册编写的,它准确地反映了芯片的功能和特性。

3、库函数的详解(以GPIO为例)

  • 函数分类
    • 初始化函数:用于配置GPIO引脚的模式(输入、输出、复用等)、速度等参数。例如,gpio_mode_set()函数用于设置GPIO引脚的模式,它会根据传入的参数配置相应的寄存器。
    • 读写函数:用于读取GPIO引脚的输入状态或者写入输出状态。像gpio_output_bit_set()gpio_output_bit_reset()函数可以分别设置和清除GPIO引脚的输出电平。
  • 参数含义
    • gpio_mode_set()函数为例,它通常需要传入GPIO端口(如GPIOD)、引脚号(如GPIO_PIN_7)、模式(如GPIO_MODE_OUTPUT)等参数。这些参数明确了要操作的具体引脚和要设置的功能。

4、如何操作库函数(以点亮LED连接到PD7为例)

  • 步骤一:包含头文件
    • 首先需要包含相关的头文件,这些头文件包含了库函数的声明。对于GD32F450ZG的GPIO操作,通常需要包含gd32f4xx_gpio.h头文件。在C语言中,使用#include "gd32f4xx_gpio.h"语句将头文件包含到源文件中。
  • 步骤二:初始化GPIO时钟
    • 芯片的GPIO模块需要时钟才能正常工作。可以使用rcu_periph_clock_enable()函数来使能GPIOD的时钟。例如:
rcu_periph_clock_enable(RCU_GPIOD);
  • 步骤三:配置GPIO引脚模式
    • 使用gpio_mode_set()函数将PD7配置为输出模式。示例代码如下:
gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
 - 这里`GPIOD`表示要操作的是D端口,`GPIO_MODE_OUTPUT`表示设置为输出模式,- `GPIO_PUPD_NONE`表示不使用上下拉电阻,`GPIO_PIN_7`表示操作的是第7个引脚。
  • 步骤四:点亮LED(设置高电平)
    • 使用gpio_output_bit_set()函数将PD7引脚设置为高电平来点亮LED。代码如下:
gpio_output_bit_set(GPIOD, GPIO_PIN_7);
  • 完整示例代码如下
#include "gd32f4xx.h"
#include "gd32f4xx_gpio.h"
int main()
{rcu_periph_clock_enable(RCU_GPIOD);gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7);gpio_output_bit_set(GPIOD, GPIO_PIN_7);while (1);return 0;
}
  • 在上述代码中,while(1)语句用于让程序保持运行状态,这样可以持续保持LED点亮。如果没有这个循环,程序执行完后可能会导致LED熄灭或者出现其他不可预期的行为。

请注意,以上代码可能需要根据具体的开发环境和工程配置进行适当的调整,如添加启动文件、正确配置链接脚本等。

三、寄存器和库函数的区别

1、寄存器与库函数的区别

  • 操作层次不同
    • 寄存器:是芯片内部的存储单元,直接与硬件电路相关联。例如,在GD32F450ZG芯片中,GPIO(通用输入输出)寄存器用于控制引脚的输入输出模式、电平状态等。每个寄存器都有特定的地址和位定义,开发者需要直接对这些寄存器进行读写操作来控制硬件。比如,通过向GPIO端口的控制寄存器写入特定的值来设置引脚为输入或输出模式。
    • 库函数:是对寄存器操作的封装。它提供了一种更高级的编程接口,隐藏了寄存器操作的细节。例如,库函数内部会根据传入的参数(如设置引脚为输出模式)自动对相应的寄存器进行正确的读写操作,开发者只需要调用库函数并传入合适的参数,而不需要了解具体是哪个寄存器以及如何对其进行位操作。
  • 代码形式不同
    • 寄存器操作:代码通常涉及直接访问寄存器地址。在C语言中,可能会使用指针来访问寄存器。例如,*(volatile uint32_t *)0x40021000 = 0x00000001;(这只是一个简单示例,实际地址和值根据芯片手册确定),这里将值0x00000001写入到地址为0x40021000的寄存器中,这种代码比较底层,不易理解。
    • 库函数调用:代码看起来更加简洁明了。以设置GPIO引脚模式为例,可能会有类似gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7);这样的函数调用。其中gpio_mode_set是库函数,后面的参数用于指定端口、模式、上下拉电阻状态和引脚号等信息。

2、寄存器操作的优势和劣势

  • 优势
    • 高度灵活性:可以实现对芯片硬件的最精细控制。开发者能够根据自己的需求精确地设置每个寄存器位,以实现特殊的功能或者对硬件进行优化。例如,在某些低功耗应用中,可以通过对特定寄存器的位操作来精确控制芯片各个模块的功耗状态。
    • 资源占用少:由于直接操作寄存器,没有额外的代码封装层,所以生成的代码体积可能相对较小。这在资源受限的嵌入式系统中,如一些小型的传感器节点或者简单的微控制器应用中,是一个重要的优势。
    • 执行效率高:没有函数调用的开销,直接对寄存器进行读写,在一些对实时性要求极高的应用场景中,能够更快地响应硬件事件。例如,在高速数据采集系统中,直接操作寄存器可以更快地获取和处理数据。
  • 劣势
    • 开发难度大:需要开发者深入了解芯片的寄存器手册,包括寄存器的地址、位定义、复位值等信息。对于复杂的芯片,寄存器数量众多,操作起来容易出错。例如,在配置一个复杂的通信接口(如SPI或I2C)时,需要正确设置多个相关寄存器的多个位,这对开发者的硬件知识和耐心是一个很大的考验。
    • 代码可读性差:直接操作寄存器的代码通常是一些十六进制或二进制的常量赋值,以及指针操作,这些代码对于其他开发者或者后期维护代码的人员来说,理解起来非常困难。而且,代码缺乏高层次的抽象,使得业务逻辑被底层硬件操作细节所掩盖。
    • 可移植性差:不同芯片的寄存器布局和功能定义不同。如果要将基于某个芯片寄存器操作的代码移植到另一个芯片上,几乎需要重新编写大部分代码。例如,从GD32F450ZG移植到另一个型号的微控制器,由于寄存器地址和功能可能完全不同,原有的寄存器操作代码无法直接使用。

3、库函数的优势和劣势

  • 优势
    • 易于开发:降低了开发难度,开发者不需要深入了解芯片的每个寄存器细节。只需要熟悉库函数的接口和功能,就可以快速实现对芯片硬件的控制。例如,使用库函数来配置定时器,只需要按照函数的参数要求传入定时时间、计数模式等信息,就可以完成定时器的配置,而不需要了解定时器相关寄存器的具体操作。
    • 代码可读性好:库函数的调用使得代码更具有逻辑性和可读性。代码能够清晰地表达其功能,例如gpio_output_bit_set(GPIOD, GPIO_PIN_7);很容易理解是设置GPIOD端口的第7引脚为输出高电平。这种高层次的抽象使得代码的维护和协作开发更加方便。
    • 可移植性强:在同一系列芯片或者具有相似库函数接口的芯片之间,代码移植相对容易。只要库函数的接口和功能没有大的变化,就可以在不同芯片上使用相同的代码逻辑。例如,在GD32系列的不同型号芯片中,如果库函数接口保持一致,就可以方便地移植GPIO控制代码。
  • 劣势
    • 灵活性相对较低:库函数提供了一种标准化的操作方式,可能无法满足一些特殊的硬件控制需求。例如,在某些非常特殊的硬件调试或者优化场景下,需要对寄存器进行一些非标准的位操作,而库函数可能没有提供这样的功能接口。
    • 资源占用可能较多:由于库函数是对寄存器操作的封装,内部可能会包含一些额外的代码来处理参数检查、错误处理等功能。这可能导致生成的代码体积比直接操作寄存器的代码要大,在资源受限的系统中可能会受到限制。
    • 执行效率可能稍低:库函数调用会带来一定的函数调用开销,包括参数传递、栈操作等。在对性能要求极高的场景下,可能会影响系统的实时响应速度。不过,在大多数嵌入式应用中,这种效率损失通常是可以接受的。

四、GD32F4xx 系列器件的存储器映射表

在这里插入图片描述

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

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

相关文章

梯度下降法求解局部最小值深入讨论以及 Python 实现

文章目录 0. 前期准备1. 局部最小值2. 例子3. 讨论3.1 增加迭代次数3.2 修改学习率 η \eta η3.3 修改初始值 x 0 x^0 x0 4. 总结参考 0. 前期准备 在开始讲梯度下降法求解函数的局部最小值之前&#xff0c; 你需要有梯度下降法求解函数的最小值的相关知识。 如果你还不是…

css部分

前面我们学习了HTML&#xff0c;但是HTML仅仅只是做数据的显示&#xff0c;页面的样式比较简陋&#xff0c;用户体验度不高&#xff0c;所以需要通过CSS来完成对页面的修饰&#xff0c;CSS就是页面的装饰者&#xff0c;给页面化妆&#xff0c;让它更好看。 1 层叠样式表&#…

7-zip如何分卷压缩文件并加密?

想要压缩的文件过大&#xff0c;想要在压缩过程中将文件拆分为几个压缩包并且同时为所有压缩包设置加密应该如何设置&#xff1f; 想要分卷压缩文件并加密一起操作就可以完成了&#xff0c;设置方法如下&#xff1a; 打开7-zip&#xff0c;选中需要压缩的文件&#xff0c;选择…

14.在 Vue 3 中使用 OpenLayers 自定义地图版权信息

在 WebGIS 开发中&#xff0c;默认的地图服务通常会带有版权信息&#xff0c;但有时候我们需要根据项目需求自定义版权信息或添加额外的版权声明。在本文中&#xff0c;我们将基于 Vue 3 的 Composition API 和 OpenLayers&#xff0c;完成自定义地图版权信息的实现。 最终效果…

【游戏】超休闲游戏:简单易上手的游戏风潮

1. 什么是超休闲游戏&#xff1f; 超休闲游戏&#xff08;Hyper-Casual Games&#xff09; 是一种专注于简单玩法、快速上手、短时间内能完成的游戏类型。这类游戏通常具有以下特点&#xff1a; 玩法简单&#xff1a;规则直观&#xff0c;用户无需教程即可上手。碎片化体验&a…

无法找到 msvcr120.dll,无法执行程序要怎么处理?修改msvcr120.dll文件

遇到“无法找到 msvcr120.dll&#xff0c;无法执行程序”这类错误通常指示着你的计算机缺少了一个核心组件&#xff0c;即 Microsoft Visual C 2013 Redistributable 的一部分&#xff1a;msvcr120.dll 文件。这个文件是许多依赖 Visual C 的应用程序运行的基础。目前修复此类问…

Kruskal 算法在特定边权重条件下的性能分析及其实现

引言 Kruskal 算法是一种用于求解最小生成树(Minimum Spanning Tree, MST)的经典算法。它通过逐步添加权重最小的边来构建最小生成树,同时确保不会形成环路。在本文中,我们将探讨在特定边权重条件下 Kruskal 算法的性能,并分别给出伪代码和 C 语言实现。特别是,我们将分…

实战 | C# 中使用GPU加速YOLOv11 推理

导 读 本文主要介绍如何在C#中使用GPU加速YOLOv11推理。 YOLOv11介绍 C# 中使用YOLOv11 (GPU版本) 【1】环境和依赖项。 下载安装CUDA12.6和CUDNN9.6,截止文章日期最新版本,注意选择自己的版本,我的系统是win11 64位。

大数据-244 离线数仓 - 电商核心交易 ODS层 数据库结构 数据加载 DataX

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…

C# 高效编程指南:从命名空间到异常处理的技巧与最佳实践

在这条成长的路上&#xff0c;有一些核心概念将成为你开发过程中的得力助手—命名空间、预处理指令、正则表达式、异常处理和文件输入输出&#xff0c;这些看似独立的技术&#xff0c;实际上在大多数应用中都紧密相连&#xff0c;共同构成了C#开发的基础。 目录 C#命名空间 C…

gitee常见命令

目录 1.本地分支重命名 2.更新远程仓库分支 3.为当前分支设置远程跟踪分支 4.撤销已经push远程的代码 5.idea->gitee的‘还原提交’ 需要和本地当前的代码解决冲突 解决冲突 本地工作区的差异代码显示 本地commit和push远程 6.idea->gitee的‘将当前分支重置到此…

简易图书管理系统

javawebjspservlet 实体类 package com.ghx.entity;/*** author &#xff1a;guo* date &#xff1a;Created in 2024/12/6 10:13* description&#xff1a;* modified By&#xff1a;* version:*/ public class Book {private int id;private String name;private double pri…

什么是甘特图?使用甘特图制定项目计划表的步骤

在项目管理中&#xff0c;项目计划是项目的核心要素&#xff0c;它详细记录了项目任务详情、责任人、时间规划以及所需资源。 这份计划不仅为项目推进提供指引&#xff0c;更是控制范围蔓延、争取更多支持的有力工具。 在项目管理中&#xff0c;项目计划是项目的核心要素&…

mock.js介绍

mock.js http://mockjs.com/ 1、mock的介绍 *** 生成随机数据&#xff0c;拦截 Ajax 请求。** 通过随机数据&#xff0c;模拟各种场景&#xff1b;不需要修改既有代码&#xff0c;就可以拦截 Ajax 请求&#xff0c;返回模拟的响应数据&#xff1b;支持生成随机的文本、数字…

16.[极客大挑战 2019]Upload1

进入靶场 是文件上传类题目 随便传个图片 制作个含木马的 算了&#xff0c;直接抓包只传文件改格式好了 第一次传的是<?php eval($_POST[attack]);?> 第二次传的是GIF89a? <script language"php">eval($_REQUEST[1])</script> "GIF89a&…

标书里的“废标雷区”:你踩过几个?

在投标领域&#xff0c;标书的质量不仅决定了中标的可能性&#xff0c;更是体现企业专业度的关键。但即便是经验丰富的投标人&#xff0c;也难免会在标书编制过程中踩中“废标雷区”。这些雷区可能隐藏在技术方案的细节中&#xff0c;也可能是投标文件格式的规范问题。以下&…

电脑投屏到电脑:Windows,macOS及Linux系统可以相互投屏!

本篇其实是电脑远程投屏到另一台电脑的操作介绍。本篇文章的方法可用于Windows&#xff0c;macOS及Linux系统的相互投屏。 为了避免介绍过程中出现“这台电脑”投屏到“那台电脑”的混乱表述&#xff0c;假定当前屏幕投出端是Windows系统电脑&#xff0c;屏幕接收端是Linux系统…

单片机上各种输出模式和寄存器讲解

零、目录 1&#xff0c;什么是寄存器 2&#xff0c;单片机各种输出模式及其应用 一、什么是寄存器 我们直接以STM32芯片的架构为例子 单片机芯片组成两部分&#xff1a;内核&#xff0c;外设&#xff08;相当于电脑的CPU和其他一件主板&#xff0c;键盘显示器等&#xff09;…

基于内核DWT延时

1.软件延时缺点 2.硬件延时&#xff0c;利用系统提供的嘀嗒定时器。1ms进一次。 3.内核架构。该监视只有Cortex3以上的才有。 4.DWT硬件延时方案 5.使用步骤

文件操作---文件IO与标准IO

目录 一、带参数的main函数 带参main函数的格式 带参main的示例 二、文件操作 1、文件结构 2、文件操作的方式 3、文件IO和标准IO区别 ①概念介绍 ②主要区别 三、文件IO 1、特性 2、操作流程 3、相关函数 open close write read lseek 4、综合示例…