STM32F103标准外设库——寄存器 (二)

news2024/11/15 17:59:15

 个人名片:

🦁作者简介:一名喜欢分享和记录学习的在校大学生
🐯个人主页:妄北y

🐧个人QQ:2061314755

🐻个人邮箱:2061314755@qq.com
🦉个人WeChat:Vir2021GKBS
🐼本文由妄北y原创,首发CSDN🎊🎊🎊
🐨座右铭:大多数人想要改造这个世界,但却罕有人想改造自己。

专栏导航:

妄北y系列专栏导航:

C/C++的基础算法:C/C++是一种常用的编程语言,可以用于实现各种算法,这里我们对一些基础算法进行了详细的介绍与分享。🎇🎇🎇

C/C++刷题库:分享一些关于编程的练习基础题,也会后续加入一系列的算法题,分享自己的解题思路和方法。🥰🥰🥰

计算机网络:对计算机网络的基础知识框架有一个简单的学习与认识,对计算机网络中常见的题型进行一个总结与归纳。🍾🍾🍾

QT基础入门学习:对QT的基础图形化页面设计进行了一个简单的学习与认识,利用QT的基础知识进行了翻金币小游戏的制作🤹🤹🤹

Linux基础编程:初步认识什么是Linux,为什么学Linux,安装环境,进行基础命令的学习,入门级的shell编程。🍻🍻🍻

Linux的系统编程+网络编程:IO编程、进程、线程、进程间通讯(包括管道、信号、信号量、共享内存等)网络编程主要就是socket,poll,epoll,以及对TCP/IP的理解,同时要学会高并发式服务器的编写。🙌🙌🙌

Linux应用开发基础开发:分享Linux的基本概念、命令行操作、文件系统、用户和权限管理等,网络编程相关知识,TCP/IP 协议、套接字(Socket)编程等,可以实现网络通信功能。💐💐💐

Linux项目开发:Linux基础知识的实践,做项目是最锻炼能力的一个学习方法,这里我们会学习到一些简单基础的项目开发与应用,而且都是毕业设计级别的哦。🤸🤸🤸


非常期待和您一起在这个小小的互联网世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨ 

文章介绍:

🎉本篇文章对STM32学习的相关知识进行分享!🥳🥳🥳

如果您觉得文章不错,期待你的一键三连哦,你的鼓励是我创作动力的源泉,让我们一起加油,一起奔跑,让我们顶峰相见!!!💪💪💪

🎁感谢大家点赞👍收藏⭐评论✍️

目录:

一、什么是寄存器

1.STM32 长啥样

 2.芯片里面有什么

(1)ICode 总线

(2)驱动单元

(3)被动单元

内部的闪存存储器

内部的 SRAM

FSMC

AHB 到 APB 的桥

3.存储器映射

4. 寄存器映射

二、寄存器映射

1. STM32 的外设地址映射

(1)名称

(2) 偏移地址

(3)寄存器位表

(4)位功能说明

2.C 语言对寄存器的封装 

(1)封装总线和外设基地址

(2)封装寄存器列表


一、什么是寄存器

1.STM32 长啥样

        我们开发板中使用的芯片是 100pin 的 STM32F103VET6,具体见图 STM32F103VET6 实物图 。这个就是我们接下来要学习的 STM32,它将带领我们进入嵌入式的殿堂。

        芯片正面是丝印,ARM 应该是表示该芯片使用的是 ARM 的内核,STM32F103VET6 是芯片型号, 后面的字应该是跟生产批次相关,最上面的是 ST 的 LOGO。

        芯片四周是引脚,左下角的小圆点表示 1 脚,然后从 1 脚起按照逆时针的顺序排列(所有芯片 的引脚顺序都是逆时针排列的)。开发板中把芯片的引脚引出来,连接到各种传感器上,然后在 STM32 上编程(实际就是通过程序控制这些引脚输出高电平或者低电平)来控制各种传感器工 作,通过做实验的方式来学习 STM32 芯片的各个资源。

 2.芯片里面有什么

        我们看到的 STM32 芯片是已经封装好的成品,主要由内核和片上外设组成。若与电脑类比,内核与外设就如同电脑上的 CPU 与主板、内存、显卡、硬盘的关系。

        STM32F103 采用的是 Cortex-M3 内核,内核即 CPU,由 ARM 公司设计。ARM 公司并不生产芯片,而是出售其芯片技术授权。芯片生产厂商 (SOC) 如 ST、TI、Freescale,负责在内核之外设计部件并生产整个芯片,这些内核之外的部件被称为核外外设或片上外设。

        如 GPIO、USART(串 口)、I2C、SPI 等都叫做片上外设。

         芯片(这里指内核,或者叫 CPU)和外设之间通过各种总线连接,其中驱动单元有 4 个,被动单元也有 4 个,具体见图 STM32F10xx 系统框图 。

(1)ICode 总线

        ICode 中的 I 表示 Instruction,即指令。我们写好的程序编译之后都是一条条指令,存放在 FLASH 中,内核要读取这些指令来执行程序就必须通过 ICode 总线,它几乎每时每刻都需要被使用,它 是专门用来取指的。

(2)驱动单元

DCode 总线

         DCode 中的 D 表示 Data,即数据,那说明这条总线是用来取数的。我们在写程序的时候,数据有常量变量两种,常量就是固定不变的,用 C 语言中的 const 关键字修饰,是放到内部的 FLASH 当中的,变量是可变的,不管是全局变量还是局部变量都放在内部的 SRAM。因为数据可以被 Dcode 总线和 DMA 总线访问,所以为了避免访问冲突,在取数的时候需要经过一个总线矩阵来 仲裁,决定哪个总线在取数。

System系统总线

        系统总线主要是访问外设的寄存器,我们通常说的寄存器编程,即读写寄存器都是通过这根系统 总线来完成的。

DMA 总线

        DMA 总线也主要是用来传输数据,这个数据可以是在某个外设的数据寄存器,可以在 SRAM, 可以在内部的 FLASH。因为数据可以被 Dcode 总线和 DMA 总线访问,所以为了避免访问冲突, 在取数的时候需要经过一个总线矩阵来仲裁,决定哪个总线在取数。

(3)被动单元

内部的闪存存储器

        内部的闪存存储器即 FLASH,我们编写好的程序就放在这个地方。内核通过 ICode 总线来取里面的指令。

内部的 SRAM

        内部的 SRAM,即我们通常说的 RAM,程序的变量,堆栈等的开销都是基于内部的 SRAM。内核通过 DCode 总线来访问它。

FSMC

         FSMC 的英文全称是 Flexible static memory controller,叫灵活的静态的存储器控制器,是 STM32F10xx 中一个很有特色的外设,通过 FSMC,我们可以扩展内存,如外部的 SRAM,NAND-FLASH 和 NORFLASH。但有一点我们要注意的是,FSMC 只能扩展静态的内存,即名称里面的 S:static,不能是动态的内存,比如 SDRAM 就不能扩展。

AHB 到 APB 的桥

         从 AHB 总线延伸出来的两条 APB2 和 APB1 总线,上面挂载着 STM32 各种各样的特色外设。我们经常说的 GPIO、串口、I2C、SPI 这些外设就挂载在这两条总线上,这个是我们学习 STM32 的重点,就是要学会编程这些外设去驱动外部的各种设备。

3.存储器映射

        在图 STM32F10xx 系统框图中,被控单元的 FLASH,RAM,FSMC 和 AHB 到 APB 的桥(即片上外设),这些功能部件共同排列在一个 4GB 的地址空间内。我们在编程的时候,可以通过他们地址找到他们,然后来操作他们(通过 C 语言对它们进行数据的读和写)。

        存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就称为存储器映射,具体见图存储器映射 。如果给存储器再分配一个地址就叫存储器重映射。

存储器区域功能划分

 储存器 Block2 内部区域功能划分

        Block2 用于设计片内的外设,根据外设的总线速度不同,Block 被分成了 APB 和 AHB 两部分, 其中 APB 又被分为 APB1 和 APB2,具体见表格存储器 Block2 内部区域功能划分 。

4. 寄存器映射

        在存储器 Block2 这块区域,设计的是片上外设,它们以四个字节为一个单元,共 32bit,每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。我们可以找到每个单元的起始地址,然后通过 C 语言指针的操作方式来访问这些单元,如果每次都是通过这种地址的方式来访问,不仅不好记忆还容易出错,这时我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射

 

//寄存器-1 通过绝对地址访问内存单元
// GPIOB 端口全部输出 高电平
 *(unsigned int*)(0x4001 0C0C) = 0xFFFF;

        0x4001 0C0C 在我们看来是 GPIOB 端口 ODR 的地址,但是在编译器看来,这只是一个普通的变量,是一个立即数,要想让编译器也认为是指针,我们得进行强制类型转换,把它转换成指针, 即 (unsigned int *)0x4001 0C0C,然后再对这个指针进行 * 操作。 

//寄存器-2 通过寄存器别名方式访问内存单元
// GPIOB 端口全部输出 高电平
#define GPIOB_ODR (unsigned int*)(GPIOB_BASE+0x0C)
 * GPIOB_ODR = 0xFF;

 为了方便操作,我们干脆把指针操作“*”也定义到寄存器别名里面

//寄存器-3 通过寄存器别名访问内存单元
// GPIOB 端口全部输出 高电平
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE+0x0C)
 GPIOB_ODR = 0xFF;

二、寄存器映射

1. STM32 的外设地址映射

        片上外设区分为三条总线,根据外设速度的不同,不同总线挂载着不同的外设,APB1 挂载低速外设APB2 和 AHB 挂载高速外设。相应总线的最低地址我们称为该总线的基地址,总线基地 址也是挂载在该总线上的首个外设的地址。其中 APB1 总线的地址最低,片上外设从这里开始, 也叫外设基地址。

总线基地址

外设基地址 

         总线上挂载着各种外设,这些外设也有自己的地址范围,特定外设的首个地址称为“XX 外设基 地址”,也叫 XX 外设的边界地址。

外设寄存器 

        GPIO 有很多个寄存器,每一个都有特定的功能。每个寄存器为 32bit,占四个字节,在该外设的 基地址上按照顺序排列,寄存器的位置都以相对该外设基地址的偏移地址来描述。这里我们以 GPIOB 端口为例,来说明 GPIO 都有哪些寄存器。

这里我们以“GPIO 端口置位/复位寄存器”为例,教大家如何理解寄存器的说明 

(1)名称

        寄存器说明中首先列出了该寄存器中的名称,“(GPIOx_BSRR)(x=A…E)”这段的意思是该寄存器名为“GPIOx_BSRR”其中的“x”可以为 A-E,也就是说这个寄存器说明适用于 GPIOA、GPIOB 至 GPIOE,这些 GPIO 端口都有这样的一个寄存器。

(2) 偏移地址

        偏移地址是指本寄存器相对于这个外设的基地址的偏移。本寄存器的偏移地址是 0x10,从参考手册中我们可以查到 GPIOA 外设的基地址为 0x4001 0800 ,我们就可以算出 GPIOA 的这个 GPIOA_BSRR 寄存器的地址为:0x4001 0800+0x10;同理,由于 GPIOB 的外设基地址为 0x4001 0C00,可算出 GPIOB_BSRR 寄存器的地址为:0x4001 0C00+0x10 。其他 GPIO 端口以此类推即可。

(3)寄存器位表

        紧接着的是本寄存器的位表,表中列出它的 0-31 位的名称及权限。表上方的数字为位编号,中间为位名称,最下方为读写权限,其中 w 表示只写,r 表示只读, rw 表示可读写。本寄存器中的位权限都是 w,所以只能写,如果读本寄存器,是 无法保证读取到它真正内容的。而有的寄存器位只读,一般是用于表示 STM32 外设的某种工作状态的,由 STM32 硬件自动更改,程序通过读取那些寄存器位来判断外设的工作状态。

(4)位功能说明

        位功能是寄存器说明中最重要的部分,它详细介绍了寄存器每一个位的功能。例如本寄存器中有两种寄存器位,分别为 BRy 及 BSy,其中的 y 数值可以是 0-15, 这里的 0-15 表示端口的引脚号,如 BR0、BS0 用于控制 GPIOx 的第 0 个引脚,若 x 表示 GPIOA,那就是控制 GPIOA 的第 0 引脚,而 BR1、BS1 就是控制 GPIOA 第 1 个引脚。

        其中 BRy 引脚的说明是“0:不会对相应的 ODRx 位执行任何操作;1:对相应 ODRx 位进行复位”。这里的“复位”是将该位设置为 0 的意思,而“置位”表示将该位设置为 1;说明中的 ODRx 是另一个寄存器的寄存器位,我们只需要知道 ODRx 位为 1 的时候,对应的引脚 x 输出高电平,为 0 的时候对应的引脚输出低 电平即可 (感兴趣的读者可以查询该寄存器 GPIOx_ODR 的说明了解)。所以,如 果对 BR0 写入“1”的话,那么 GPIOx 的第 0 个引脚就会输出“低电平”,但是 对 BR0 写入“0”的话,却不会影响 ODR0 位,所以引脚电平不会改变。要想该 引脚输出“高电平”,就需要对“BS0”位写入“1”,寄存器位 BSy 与 BRy 是相 反的操作。

2.C 语言对寄存器的封装 

(1)封装总线和外设基地址

/* 外设基地址 */
#define PERIPH_BASE ((unsigned int)0x40000000)

/* 总线基地址 */
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000)
#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000)


/* GPIO 外设基地址 */
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400)
#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800)
#define GPIOF_BASE (APB2PERIPH_BASE + 0x1C00)
#define GPIOG_BASE (APB2PERIPH_BASE + 0x2000)


/* 寄存器基地址,以 GPIOB 为例 */
#define GPIOB_CRL (GPIOB_BASE+0x00)
#define GPIOB_CRH (GPIOB_BASE+0x04)
#define GPIOB_IDR (GPIOB_BASE+0x08)
#define GPIOB_ODR (GPIOB_BASE+0x0C)
#define GPIOB_BSRR (GPIOB_BASE+0x10)
#define GPIOB_BRR (GPIOB_BASE+0x14)
#define GPIOB_LCKR (GPIOB_BASE+0x18)

         首先定义了“片上外设”基地址 PERIPH_BASE,接着在 PERIPH_BASE 上加入各个总线的地址偏移,得到 APB1、APB2 总线的地址 APB1PERIPH_BASE、APB2PERIPH_BASE, 在其之上加入外设地址的偏移,得到 GPIOA-G 的外设地址,最后在外设地址上加入各寄存器的地址偏移,得到特定寄存器的地址。一旦有了具体地址,就可以用指针读写。

/* 控制 GPIOB 引脚 0 输出低电平 (BSRR 寄存器的 BR0 置 1) */
*(unsigned int *)GPIOB_BSRR = (0x01<<(16+0));

/* 控制 GPIOB 引脚 0 输出高电平 (BSRR 寄存器的 BS0 置 1) */
*(unsigned int *)GPIOB_BSRR = 0x01<<0;

unsigned int temp;
/* 读取 GPIOB 端口所有引脚的电平 (读 IDR 寄存器) */
temp = *(unsigned int *)GPIOB_IDR

        该代码使用 (unsigned int *) 把 GPIOB_BSRR 宏的数值强制转换成了地址,然后再用“*”号做取 指针操作,对该地址的赋值,从而实现了写寄存器的功能。同样,读寄存器也是用取指针操作, 把寄存器中的数据取到变量里,从而获取 STM32 外设的状态。 

(2)封装寄存器列表

        用上面的方法去定义地址,还是稍显繁琐,例如 GPIOA-GPIOE 都各有一组功能相同的寄存器, 如 GPIOA_ODR/GPIOB_ODR/GPIOC_ODR 等等,它们只是地址不一样,但却要为每个寄存器都定义它的地址。为了更方便地访问寄存器,我们引入 C 语言中的结构体语法对寄存器进行封装

typedef unsigned int uint32_t; /* 无符号 32 位变量 */
typedef unsigned short int uint16_t; /* 无符号 16 位变量 */

/* GPIO 寄存器列表 */
typedef struct {
uint32_t CRL; /*GPIO 端口配置低寄存器 地址偏移: 0x00 */
uint32_t CRH; /*GPIO 端口配置高寄存器 地址偏移: 0x04 */
uint32_t IDR; /*GPIO 数据输入寄存器 地址偏移: 0x08 */
uint32_t ODR; /*GPIO 数据输出寄存器 地址偏移: 0x0C */
uint32_t BSRR; /*GPIO 位设置/清除寄存器 地址偏移: 0x10 */
uint32_t BRR; /*GPIO 端口位清除寄存器 地址偏移: 0x14 */
uint16_t LCKR; /*GPIO 端口配置锁定寄存器 地址偏移: 0x18 */
} GPIO_TypeDef;

        这段代码用 typedef 关键字声明了名为 GPIO_TypeDef 的结构体类型,结构体内有 7 个成员变量, 变量名正好对应寄存器的名字。C 语言的语法规定,结构体内变量的存储空间是连续的,其中 32 位的变量占用 4 个字节,16 位的变量占用 2 个字节。

        也就是说,我们定义的这个 GPIO_TypeDef ,假如这个结构体的首地址为 0x4001 0C00(这也是第一个成员变量 CRL 的地址),那么结构体中第二个成员变量 CRH 的地址即为 0x4001 0C00 +0x04 ,加上的这个 0x04,正是代表 CRL 所占用的 4 个字节地址的偏移量,其它成员变量相对于结构体首地址的偏移。

        这样的地址偏移与 STM32 GPIO 外设定义的寄存器地址偏移一一对应,只要给结构体设置好首地址,就能把结构体内成员的地址确定下来,然后就能以结构体的形式访问寄存器。

GPIO_TypeDef * GPIOx; //定义一个 GPIO_TypeDef 型结构体指针 GPIOx
GPIOx = GPIOB_BASE; //把指针地址设置为宏 GPIOB_BASE 地址
GPIOx->IDR = 0xFFFF;
GPIOx->ODR = 0xFFFF;


uint32_t temp;
temp = GPIOx->IDR; //读取 GPIOB_IDR 寄存器的值到变量 temp 中

         这段代码先用GPIO_TypeDef类型定义一个结构体指针GPIOx, 并让指针指向地址 GPIOB_BASE(0x4001 0C00),使用地址确定下来,然后根据 C 语言访问结构体的语法,用 GPIOx- >ODR 及 GPIOx->IDR 等方式读写寄存器。

        最后,我们更进一步,直接使用宏定义好 GPIO_TypeDef 类型的指针,而且指针指向各个 GPIO 端口的首地址,使用时我们直接用该宏访问寄存器即可

/* 使用 GPIO_TypeDef 把地址强制转换成指针 */
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)
#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE)



 /* 使用定义好的宏直接访问 */
 /* 访问 GPIOB 端口的寄存器 */
 GPIOB->BSRR = 0xFFFF; //通过指针访问并修改 GPIOB_BSRR 寄存器
 GPIOB->CRL = 0xFFFF; //修改 GPIOB_CRL 寄存器
 GPIOB->ODR =0xFFFF; //修改 GPIOB_ODR 寄存器

 uint32_t temp;
 temp = GPIOB->IDR; //读取 GPIOB_IDR 寄存器的值到变量 temp 中

 /* 访问 GPIOA 端口的寄存器 */
 GPIOA->BSRR = 0xFFFF;
 GPIOA->CRL = 0xFFFF;
 GPIOA->ODR =0xFFFF;

 uint32_t temp;
 temp = GPIOA->IDR; //读取 GPIOA_IDR 寄存器的值到变量 temp 中

这部分工作都由固件库帮我们完成了,这里我们只 是分析了下这个封装的过程 。

大佬觉得有用的话点个赞 👍🏻 呗。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥任务在无形中完成,价值在无形中升华,让我们一起加油吧!🌙🌙🌙

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

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

相关文章

C语言中对变量的理解

变量(variable)是程序中不可或缺的组成单位&#xff0c;是最基本的存储单元。 1.什么是变量&#xff1f; Ⅰ.概念&#xff1a; 内存中的一个存储区域&#xff0c;该区域的数据可以在同一类型范围内不断变化。 通过变量名&#xff0c;可以访问这块内存区域&#xff0c;获取里…

翻译: Streamlit从入门到精通 部署一个机器学习应用程序 四

Streamlit从入门到精通 系列&#xff1a; 翻译: Streamlit从入门到精通 基础控件 一翻译: Streamlit从入门到精通 显示图表Graphs 地图Map 主题Themes 二翻译: Streamlit从入门到精通 构建一个机器学习应用程序 三 1. 5. 如何部署一个Streamlit应用 部署是将应用程序从开发…

Linux中文件名修改的多种方法

找一个不算漂亮的普通女孩&#xff0c;一起柴米油盐&#xff0c;一起日出日落&#xff0c;一起田间地头&#xff0c;一起春花冬雪&#xff01;要一个不算大的小房子&#xff0c;生两个健康可爱的宝宝&#xff0c;这样就很好。。。。。。 简介&#xff1a; 在Linux系统中&#x…

nvcc -V显示command not found

出现这个问题&#xff0c;不仅是 nvcc -V会显示command not found,nvidia-smi同样也会显示 解决方法如下&#xff1a; 1&#xff09;这里首先转换到CUDA所在位置&#xff0c;一般是在这个位置 cd /usr/local 2&#xff09;打开、编辑环境变量的配置文件 vim ~/.bashrc …

使用NI VeriStand构建分布式系统

使用NI VeriStand构建分布式系统 - NI 概览 本文探讨了如何使用NI VeriStand来构建分布式处理和I/O系统&#xff0c;并提供诸多功能来帮助工程师更高效地开发强大的分布式系统。 飞机、汽车或其他工业项目中的控制系统由于需要执行监测、测试或仿真任务&#xff0c;其所需的计…

【MATLAB】EEMD+FFT+HHT组合算法

代码原理 EEMD&#xff08;经验模态分解&#xff09;FFT&#xff08;快速傅里叶变换&#xff09;HHT&#xff08;希尔伯特-黄变换&#xff09;组合算法是一种常用的信号处理和分析方法。这个组合算法包含了EEMD、FFT和HHT三个步骤&#xff0c;可以用于处理非线性和非平稳信号。…

IO网络2.0

思维导图 机械臂 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <myhead.h> #define SER_PORT 8888 #define SER_IP "192.168.122.68" //服务端//TCP客户端 int main(int argc, const char *argv[]) {//创建套接字…

20240115寻找两数之和

代码 class Solution:def getSumIndex(self, nums: List[int], target: int) -> List[int]:records dict()for index, value in enumerate(nums): if target - value in records: # 遍历当前元素&#xff0c;并在map中寻找是否有匹配的keyreturn [records[target- valu…

8个 Python 开发者必备的 PyCharm 插件

这8个顶级插件保证了更快、更轻松、更愉悦的开发过程。 在 PyCharm 插件列表中&#xff0c;我们发现了几个瑰宝插件&#xff0c;它们各自以独特的方式帮助开发者快速、简便、愉悦地开发。 今天我就给大家逐个介绍它们。 1. Key Promoter X 【下载链接】&#xff1a;https://…

transbigdata笔记:可视化

1 可视化轨迹 transbigdata.visualization_trip(trajdata, col[Lng, Lat, ID, Time], zoomauto, height500) 例子见transbigdata 笔记&#xff1a;官方文档案例1&#xff08;出租车GPS数据处理&#xff09;-CSDN博客 2 可视化od transbigdata.visualization_od(oddata, col…

MySQL篇—通过Clone插件进行本地克隆数据(第二篇,总共三篇)

在上一篇文章中&#xff0c;我们深入探讨了Clone技术的多种用途&#xff0c;以及使用它所需满足的前提条件。我们也详细分析了Clone存在的限制&#xff0c;并深入了解了其背后的备份原理。今天&#xff0c;我们将继续探索MySQL Clone Plugin的强大功能&#xff0c;Clone其实最重…

实践学习PaddleScience飞桨科学工具包

实践学习PaddleScience飞桨科学工具包 动手实践&#xff0c;在实践中学习&#xff01;本项目可以在AIStudio平台一键运行&#xff01;地址&#xff1a;https://aistudio.baidu.com/projectdetail/4278591 本项目第一次执行会报错&#xff0c;再执行一次即可。若碰到莫名其妙的…

JSP-概念

一、引子 很多读者可能听过JSP&#xff0c;并且知道这是一门过时的技术了。在Spring&#xff0c;SpringBoot已经成为主流的今天&#xff0c;笔者为什么还要介绍JSP的相关内容呢&#xff1f;笔者常常提到一个概念&#xff1a;理解一门技术&#xff0c;要理解这个技术为什么产生…

基于Spring Boot+vue的云上新鲜水果超市商城系统

本云上水果超市是为了提高用户查阅信息的效率和管理人员管理信息的工作效率&#xff0c;可以快速存储大量数据&#xff0c;还有信息检索功能&#xff0c;这大大的满足了用户、员工信息和管理员这三者的需求。操作简单易懂&#xff0c;合理分析各个模块的功能&#xff0c;尽可能…

电阻表示方法和电路应用

电阻 电阻的表示方法 直标法 直标法是将电阻器的类别及主要技术参数的数值直接标注在电阻器表面上 通常用3位阿拉伯数字来标注片状电阻的阻值&#xff0c;其中第1位数代表阻值的第1位有效数&#xff1b;第2位数代表阻值的第二位有效数字&#xff1b;第3位数代表阻值倍率&…

HNU-算法设计与分析-实验1

算法设计与分析实验1 计科210X 甘晴void 202108010XXX 目录 文章目录 算法设计与分析<br>实验1&#xff08;1&#xff09;分治法查找最大最小值问题描述想法代码评测算法分析 &#xff08;2&#xff09;分治法实现合并排序问题描述想法代码评测算法分析 &#xff08;3…

SpringCloud Nacos服务注册中心和配置中心

一、什么是Nacos&#xff1f; 官方介绍是这样的&#xff1a; Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集&#xff0c;帮助您实现动态服务发现、服务配置管理、服务及流量管理。 Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Na…

WEB 3D技术 three.js 3D贺卡(1) 搭建基本项目环境

好 今天 我也是在网上学的 带着大家一起来做个3D贺卡 首先 我们要创建一个vue3的项目、 先创建一个文件夹 装我们的项目 终端执行 vue create 项目名称 例如 我的名字想叫 greetingCards 就是 vue create greetingcards因为这个名录 里面是全部都小写的 然后 下面选择 vue3 …

全网最细RocketMQ源码四:消息存储

看完上一章之后&#xff0c;有没有很好奇&#xff0c;生产者发送完消息之后&#xff0c;server是如何存储&#xff0c;这一章节就来学习 入口 SendMessageProcessor.processRequest private CompletableFuture<RemotingCommand> asyncSendMessage(ChannelHandlerCont…

低频信号发生器

前言 最近我快期末考试了&#xff0c;有点忙着复习。没时间写文章&#xff0c;不过学会了焊接 挺开心的所以买几套。 焊得怎么样这就是我们今天故事的主角“低频信号发生器”&#xff08;由于要用到所以这是购买链接&#xff09; 好&#xff0c;故事开始&#xff1a; 如何将…