零基础自学STM32-野火——GPIO复习篇——使用绝对地址操作GPIO

2023-05-16

今天主要是复习一下。
结合野火的《零基础开发指南》名字没记住大概是这个
先放一张结构图
在这里插入图片描述

存储器映射(初学重点):
我们的片内外设比如:Flash,Sram,Fsmc,以及挂在AHB 总线上的外设,我们都需要知道他的地址来操作这些器件。而这些外设的地址都被分配在一个4g的内存空间里(4g的存储器,下文中的)。
为什么是4g的?
2的32次方就是4g-byte。
存储器映射
存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就称为存储器映射,具体见图存储器映射。如果给存储器再分配一个地址就叫存储器重映射。
在这里插入图片描述
注意看4g的存储空间分位8个部分,每部分都给分配了各自的起始地址和末尾的地址信息。每块占用512MByte
显然8*512=4096MByte 4096MByte/1024=4g
拿其中几个举个例子:
在这里插入图片描述
第一部分就包含了Flash
在这里插入图片描述
第二部分就包含了Sram我的板子买的霸道,也就是F103zet6 64k的SRAM
第三部分就是FSMC
在这里插入图片描述
我是初学,咱时不管这部分(用到啥学啥,你没那么好的记性和时间)
其余的暂时不列出来。

重点来了!!!!!!!
我们操作的主要部分时在BLOCK2
在这里插入图片描述
我们首先得明白,分配的这些地址首先他是连续的。这一点很重要。
那么BLOCK2包含了哪些??
在这里插入图片描述
眼神好的自己看
《STMF103X英文数据手册》
在这里插入图片描述
简言之,这部分详细的描述了我们的外设及其分配到的地址信息。(有大用)
在这里插入图片描述
以端口举例,详细的描述了各端口的起始地址和终止地址,同样也是连续的。可以数数看。
在这里插入图片描述
对于这8个块,主要看三块就可以,BLOCK0对应的FLASH,BLOCK1对应的SRAM,BLOCK2对应的片上外设。
我们先直接看BLOCK2部分
BLOCK2上有两个总线,AHB和APB,这两个总线主要区别在于其速度不同。
在这里插入图片描述
APB又被分为APB1和APB2
而APB2和AHB被称为高速总线,挂高速外设,APB1是低速总线,挂低低速外设。
寄存器的映射
在存储器 Block2 这块区域,设计的是片上外设,它们以四个字节为一个单元,共 32bit,每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作(实际就是每32个位也就是4个字节为一个寄存器,而每一个寄存器负责一个具体的功能。巧了我们的单片机正好就是32位的,他正好能一次处理32位的数据)。
我们可以找到每个单元的起始地址,然后通过 C 语言指针的操作方式来访问这些单元,如果每次都是通过这种地址的方式来访问,不仅不好记忆还容易出错,这时我们可以根据每个单元功能的不同,以功能为名给这个
内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。(了解一下,后面在代码中一下就能明白)。
比如:
我们找到 GPIOB 端口的输出数据寄存器 ODR 的地址是 0x40010C0C(至于这个地址如何找到可以先跳过,后面我们会有详细的讲解),ODR 寄存器是 32bit,低 16bit 有效,对应着 16 个外部 IO,写 0/1 对应的的 IO 则输出低/高电平。现在我们通过 C 语言指针的操作方式,让 GPIOB的 16 个 IO 都输出高电平。

操作寄存器的方法一:通过绝对地址访问内存单元

// GPIOB 端口全部输出 高电平
 *(unsigned int*)(0x4001 0C0C) = 0xFFFF;

简单解释一下
0x4001 0C0C是GPIOB的ODR寄存器的地址,先别管他怎么来的。只需要知道我们操作这个地址就可以控制寄存器对应的GPIO输出
只不过对于单片机来说这个地址是一个变量,是一个立即数,而不是地址。(这里我没太明白。上网查了一下,我的理解就是说这个只是个数据而无实际意义,我们将他给Int变量那么这个就是int型数据,把他给指针变量那他就是地址,如果不赋值给一个具体的变量类型那他就啥也不是)。
我们需要强制转化为地址才行,所以使用了(unsigned int),也就是说这个地址是一个32位无符号整型的指针(指针就是地址)。*
对于这个地址空间其存储了一个数据0xFFFF。(一定要懂)
说明一下0xFFFF,我们知道对于一个16进制数 来说,一个F对应的4位。那么4个F对应的正好就是16位,而我们的ODR寄存器也正好能够操作的就只有16位。(后面针对ODR寄存器讲解的时候能用到)
而unsigned int 是32位的,对于0x4001 0C0C 是够用的!

那么使用绝对地址访问寄存器的方式缺点就很明显,地址不好记啊,也不好写啊。
操作寄存器的方法二:通过寄存器别名的方式访问寄存器

// GPIOB 端口全部输出 高电平
 #define GPIOB_ODR (unsigned int*)(GPIOB_BASE+0x0C)
* GPIOB_ODR = 0xFF;

使用宏定义#define 给寄存器的地址重新命名为GPIOB_ODR
然后使用* 号去操作ODR的值
这就是基本的指针操作,不做解释对于(GPIOB_BASE+0x0C)暂时不必纠结。只需要知道他是寄存器ODR的地址。

上面通过寄存器别名访问寄存器更换好的写法是

// GPIOB 端口全部输出 高电平
 #define GPIOB_ODR  *(unsigned int*)(GPIOB_BASE+0x0C)//将* 号也封装在//宏定义里
 GPIOB_ODR = 0xff;   //直接操作即可

下面介绍STM32的外设地址映射
片上外设区分为三条总线AHB总线和APB1,APB2(APB1和APB2共同构成APB总线),根据外设速度的不同,不同总线挂载着不同的外设,APB1 挂载低速外设,APB2 和 AHB 挂载高速外设。
相应总线的最低地址我们称为该总线的基地址,总线基地址也是挂载在该总线上的首个外设的地址。(这句就很有用,记住要考)
其中 APB1 总线的地址最低,片上外设从这里开始,也叫外设基地址。

在这里插入图片描述
表格总线基地址 的“相对外设基地址偏移”即该总线地址与“片上外设”基地址 0x4000 0000 的差值。(这个差值就是相对总线基地址的偏移量)
这里还不够直观我重新描述一下(对比以下三张图)
在这里插入图片描述
在STM32F103x的中文参考手册里能够找到

在STM32F03Xz在这里插入图片描述在这里插入图片描述

我们知道TM2是属于APB1总线的,并且与APB1总线的基地址的值是一样的。那么GPIOB是属于APB2总线的,而APB2总线的基地址是
在这里插入图片描述
对比APB1和APB2的地址,就能得到地址的差值(就是偏移量),0x0001 0000

外设基地址
我们知道总线地址的范围,还需要知道具体要操作的外设的地址。将目标进一步的细化。
这里以GPIO为例子。
在这里插入图片描述
在这里插入图片描述
我们可以对照一下这两张图。第一个是野火给出的,第二个来自数据手册
很显然我们的GPIO的外设地址范围是0x4001 0800到0x4001 23FF这个范围内
有ABCDEFG这几个端口。
在这里插入图片描述
查看参考手册知道了这几个GPIO端口都是挂接在APB2这个总线上的。
而APB2是高速总线,总线基地址是
在这里插入图片描述
我们的APB2的总线基地址是0x4001 0000
这么一来就能知道端口相对与APB2总线基地址的偏移量
在这里插入图片描述
我们知道了外设的基地址还没结束,我们知道最终我们是需要操作寄存器的,所以我们接下来就要去找对应外设的寄存器的地址信息。
以GPIOB为例子
在这里插入图片描述
我们在知道了外设基地址的时候比如GPIOB为0x4001 0C00
每个GPIO都 有很多个寄存器,而每一个寄存器都有特定的功能。
每个寄存器为 32bit,占四个字节,在该外设的基地址上按照顺序排列,寄存器的位置都以相对该外设基地址的偏移地址来描述。

然后我们就找到的最终的目标,寄存器地址。
在这里插入图片描述
野火指南里给出了分析寄存器功能的方法,这里以端口位设置清零寄存器为例子。
在这里插入图片描述
名称
寄存器说明中首先列出了该寄存器中的名称,“(GPIOx_BSRR)(x=A…E)”这段的
意思是该寄存器名为“GPIOx_BSRR”其中的“x”可以为 A-E,也就是说这个寄
存器说明适用于 GPIOA、GPIOB 至 GPIOE,这些 GPIO 端口都有这样的一个寄存
器。(注意区分,这里说GPIOA到GPIOE都有这样的一个寄存器,别忘了他们各自的GPIO的基地址是不同的,虽然偏移量是相同的)
偏移地址
偏移地址是指本寄存器相对于这个外设的基地址的偏移。本寄存器的偏移地址是
0x10,从参考手册中我们可以查到 GPIOA 外设的基地址为 0x4001 0800 ,我们就
可以算出 GPIOA 的这个 GPIOA_BSRR 寄存器的地址为:0x4001 0800+0x10;同
理,由于 GPIOB 的外设基地址为 0x4001 0C00,可算出 GPIOB_BSRR 寄存器的
地址为:0x4001 0C00+0x10。其他 GPIO 端口以此类推即可。
③ 寄存器位表
紧接着的是本寄存器的位表,表中列出它的 0-31 位的名称及权限。**表上方的数
字为位编号,中间为位名称,最下方为读写权限,其中 w 表示只写,r 表示只读,
rw 表示可读写。**本寄存器中的位权限都是 w,所以只能写,如果读本寄存器,是
无法保证读取到它真正内容的。而有的寄存器位只读,一般是用于表示 STM32
外设的某种工作状态的,由 STM32 硬件自动更改,程序通过读取那些寄存器位
来判断外设的工作状态。
位功能说明
位功能是寄存器说明中最重要的部分,它详细介绍了寄存器每一个位的功能。例
如本寄存器中有两种寄存器位,分别为 BRy 及 BSy,其中的 y 数值可以是 0-15,
这里的 0-15 表示端口的引脚号,如 BR0、BS0 用于控制 GPIOx 的第 0 个引脚,若
x 表示 GPIOA,那就是控制 GPIOA 的第 0 引脚,而 BR1、BS1 就是控制 GPIOA
第 1 个引脚。

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

使用C语言对寄存器进行封装(重点)
总线和外设基地址宏定义

/*片内外设基地址(BLOCK2 的起始地址) */
#define PERIPH_BASE ((unsigned int)0x40000000)//peripheral就是外设的意思
//注意这里使用了强制类型转化,将0x4000 0000转化为一个unsigned int 型的整数



 /* 总线基地址 */
 #define APB1PERIPH_BASE PERIPH_BASE   //TIM2的外设基地址实际上就是我们的BLOCK2 512M内存空间的起始地址
 #define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000)//这是APB2总线外设基地地址,注意相对于片内外设基地址加了偏移量
 #define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000)//这是AHB外设总线基地址,注意是相对片内于外设基地址加了偏移量
 //这里的片内外设就是指BLOCK2的起始地址,我们知道BLOCK2上主要挂的就是我们的外设


 /* 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)

这里总共提到了4部分
第一部分是8个分区其中的片内外设地址:
一个是最外层的BLOCK2的片内外设基地值,我们所有的外设都在这512m字节的空间内部。(如果忘记8个分区时什么,请往前面找)

第二部分是总线基地址:
而在BLOCK2的内部总共分为APB1,APB2,AHB三个总线。所以我们就在片内外设基地址的基础之上加上偏移量,就能得到APB1,或者APB2,或者AHB的总线的地址。

第三部分是外设地址:
然后我们在这三个总线的基地址上加上偏移量就能够找到具体的外设。

第四个部分是寄存器地址:
然后在具体的外设的地址上加上偏移量就能找到具体的寄存器。

下面我将以代码的形式展现如何通过操作寄存器的地址来实现控制GPIO口
头文件

//用来存放stm32寄存器映射的代码
//外设基地址 peripheral

# define PERIPHBASE  ((unsigned int)0x40000000)   //片内外设基地址(属于BLOCK2区的起始地址)
//使用unsigned int 强制转化0x4000 0000,将其作为一个32位的整形去存储
	
//总线基地址

# define APB1PERIPH_BASE	PERIPHBASE   //APB1总线基地址与片内外设基地址是一样的
# define APB2PERIPH_BASE  (PERIPHBASE + 0x10000)   //APB2总线基地址,相对于片内外设基地址的偏移
//这里为什么可以直接使用加号而不用强制转化,应该是与之前使用强制转化PERIPHBASE的缘故,暂时不扩展往下继续
# define AHBPERIPH_BASE   (PERIPHBASE + 0x20000)    //AHB总线基地址(为了后面操作RCC时钟),这里实际采用的DMA1的地址作为基地址
//DMA1的地址是0x4002 0000
//RCC的地址是0x4002 1000  显然用DMA1的地址更方便一点

# define RCC_BASE	(AHBPERIPH_BASE + 0x1000)	//RCC复位时钟控制地址
# define GPIOB_BASE	(APB2PERIPH_BASE + 0x0C00)	//GPIOB地址

//以上的内容只是通过总线基地址加偏移量找到了外设的地址
//下面就是具体的寄存器的地址
# define RCC_APB2ENR	*(unsigned int* )(RCC_BASE + 0x18)  //APB2外设时钟使能寄存器
//这个寄存器的第3位控制IO端口B的时钟使能,0是关闭,1是开启


# define GPIOB_CRL	*(unsigned int*)(GPIOB_BASE  + 0x00)	//端口配置低寄存器,控制着0-7位的模式和速度
# define GPIOB_CRH 	*(unsigned int*)(GPIOB_BASE  + 0x04)	//端口配置高寄存器,控制着8-15位的模式和速度
# define GPIOB_ODR  *(unsigned int*)(GPIOB_BASE  + 0x0C)	//数据输出寄存器

接下来就是main.c

//类比51部分
#if 0
# include <reg51.h>
sbit LED = P0^0;  //51是直接使用位定义操作IO口输出高/电平的

void main ()
{
	
	P0 = 0xFE;//总线操作  //
	LED = 0;//位操作
	
}

#endif




//32部分
#include "stm32f10x.h"

void SystemInit(void);//不用管整个

int main (void)
{
	
	
	# if 0
	
	//使用指针控制寄存器
	*(unsigned int *)0x40021018 |=((1)<<3);        //控制RCC寄存器,打开gpiob端口的时钟,清零IO关闭,置1端口打开
	//为什么使用的是左移三位?
	//因为GPIOB的端口时钟使能位,正好就在第三位(从第0位开始数),所以左移三位
	
	*(unsigned int *)0x40010C00 |=((1)<<(4*0));    //控制CRL寄存器, Set_Output   ODR_REG
	//*(unsigned int *)0x40010C0C &=~(1<<0);       //控制ODR寄存器, Data_Output  CRL_REG
	
	*(unsigned int *)0x40010C0C &=~((1)<<0);	     //控制ODR寄存器, Data_Output  CRL_REG
	

	
	#else
	
	RCC_APB2ENR |= ((1)<<3);          //GPIOB时钟使能

	GPIOB_CRL |= ((1)<<(4*0));         //端口配置低寄存器
	//GPIOB_ODR &= ~(1<<0);   			//数据输出寄存器
	GPIOB_ODR |= (1<<0); 
	
	
	
	#endif
}
//置位  |=
//清零  &=~

void SystemInit(void)//不用管这个
{
	//函数体为空
}



对寄存器配置部分代码的说明:

//置一操作:
//配置RCC寄存器
*(unsigned int *)0x40021018 |=((1)<<3);
//说明一下使用|=的目的就是按位或,我们将想要配置为1的位使用|操作配置上去。|操作就是有1|1就是1,1|0也是1。

//置一操作:
//配置CRL寄存器
*(unsigned int *)0x40010C00 |=((1)<<(4*0));

//清零操作:
//配置ODR寄存器
*(unsigned int *)0x40010C0C &=~((1)<<0);
//说明一下是用&=的目的就是按位与,我们先将需要配置的位按位&1,然后取反就是0了。按位与是1&0是0,1&1是1。

下面详细介绍一下,这段代码中使用到的三个寄存器:
第一个是:RCC下面的APB2外设时钟使能寄存器(RCC_APB2ENR)
在这里插入图片描述
我们知道在GPIOB是挂接到APB2这条总线上的,而与51不同的是,32在操作GPIO是需要使能他的IO时钟的。
在这里插入图片描述
IO端口B的时钟使能是1打开,0关闭。
所以才有了下面的使能操作

//置一操作:
//配置RCC寄存器,使能IOB的时钟
*(unsigned int *)0x40021018 |=((1)<<3);
//说明一下使用|=的目的就是按位或,我们将想要配置为1的位使用|操作配置上去。|操作就是有1|1就是1,1|0也是1。

第二个是端口配置低寄存器(GPIOxCRL)
CRL寄存器决定了IO端口是工作在输入还是输出模式
另外他还决定了速度
在这里插入图片描述
我们此处使用的是通用推挽输出,和10Mhz的速度
手册中规定了CNF0和MODE0控制着端口位0。
通用推挽输出要求CNFNy为00,MODEy为01

//清零操作:
//配置CRL寄存器
*( unsigned int * )0x40010C00 &=  ~( (0x0f) << (4*0) );//这个下面我会解释为什么要加这一句
*( unsigned int * )0x40010C00 |=  ( (1) << (4*0) );
//说明一下是用&=的目的就是按位与,我们先将需要配置的位按位&1,然后取反就是0了。按位与是1&0是0,1&1是1。
//CRL寄存器的复位值是0x4444 4444 转化为2进制就是
//0100 0100 0100 0100 0100 0100 0100 0100
//而低四位正好是0100显然这个状态是在浮空输入模式,这就需要我们留意寄存器在复位后的初始状态,而且要做好处理。如果我们直接使用|=操作去置位最低位位1,也得不到我们想要的结果。所以就需要下面这句
*( unsigned int * )0x40010C00 &=  ~( (0x0f) << (4*0) );
//将我们的寄存器重复位后的输入状态下的低四位0100全部清零
//然后使用|=的操作去置位最低位,从而达到通用输出的模式,复位后的初始状态对于操作的影响这点很重要,需要留心。

第三个是端口输出数据寄存器(GPIOx_ODR)
在这里插入图片描述
端口输出数据寄存器显然只有16位而已
我们需要操作ODR的具体某一个位只需要直接赋值为1或者0即可。

//将最低位清零的操作
*(unsigned int *)0x40010C0C &=~((1)<<0);
//将最低位置一的操作
*(unsigned int *)0x40010C0C |=((1)<<0);

//另外我需要说明一下上面的代码
//指针是unsigned int的,意味着0x40010C0C是一个真正意义上的16进制的32位的地址。
//这样一来我们后面的1可以看作是一个32位十六进制的0x0000 0001其实还是1而已,通过<<0。也就是左移动0位然后或等于的操作来实现按位操作。
//

在这里插入图片描述
我们操作的就是PB0(端口B的第0位,PortB_0)
好了,通过基本的寄存器的绝对地址指针,实现点亮LED的操作就是这样

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

零基础自学STM32-野火——GPIO复习篇——使用绝对地址操作GPIO 的相关文章

  • ROS2学习笔记(十)-- ROS2 launch启动文件

    简介 xff1a 接触过ROS1的同学对launch肯定不陌生 xff0c 在ROS1中 xff0c 我们常用launch实现node和master同时启动 多节点同时启动配置等功能 xff0c ROS2中的launch也是用于多节点启动
  • C++vector的使用总结及常用vector操作

    一 C vector类为内置数组提供了一种替代表示 与string类一样 vector 类是随标准 C 引入的标准库的一部分 使用时需包含头文件 include lt vector gt 二 C vector类有两种使用方式 第一种 STL
  • cc2640 基于官方从机修改的通过手机实现蓝牙点灯例程

    在TI官方从机例程中的simpleBLEPeripheral c进行代码修改 添加引脚驱动头文件 xff1a include lt ti drivers pin PINCC26XX h gt PIN driver 添加全局变量 xff1a
  • cadence 17.0 生成钻孔文件 cam350打不开的问题解决

    17 0生成钻孔文件后 xff0c cam350打不开 这时用记事本打开钻孔文件 对比发现相较于16 6的版本 xff0c 多了以下一行红色高亮的的代码 将其删除就可以用cam350打开了 LEADER 12 HEADER CODE ASC
  • matlab 串口读取设置

    本例代码运行于 MATLAB2015b xff0c 参照网上的代码修改而成 xff0c 可以自定义一次读取的数据 xff0c 并做简单处理 xff0c 随后绘图 实测可用 实用 读串口 clear clc obj 61 serial 39
  • 室内定位综述

    本篇文章是作者研究生毕设的前稿 xff0c 每周更新补充 xff0c 主要是中外关于室内定位的论文综述 xff0c 偏向于TDOA方向 xff0c 也会更新些其他的方向 有不当的地方欢迎有人指正 61 2016 7 20 1 Contrib
  • CC2630 TIMAC协议栈低功耗问题

    项目功能 采集5s数据发送 休眠5s 采集5s数据发送 xff0c 循环往复 平台 CC2630 协议栈 xff1a timac 1 05 02 43299 问题描述 在休眠5s的过程中 xff0c 整体电流在7 8ma xff0c 只比数
  • c++ 大小写转换&&字符转数字

    大小写转换 amp amp 字符转数字 xff0c 实验笔记 int main 其实就是对ASCii表的操作 string s char a 61 39 a 39 int b 61 a 39 0 39 字符转成数字 int c 61 int
  • 数组方式赋值字符串及字面值常量赋值字符串的区别

    c 43 43 实验笔记 数组赋值字符串时需要显示 39 0 39 xff0c 否则在某些时候会有问题 int main const char a 61 39 a 39 39 v 39 39 b 39 39 b 39 39 0 39 数组需
  • STL:: allocator之deallocate & destory的区别与联系

    c 43 43 中的allocator是标准库中的一个类 xff0c 负责内存分配管理 下面是 STL源码剖析 中一个简单allocator实现的部分源代码 xff1a deallocate xff1a template lt class
  • allocator简单实现

    allocator是c 43 43 标准库中用于管理内存的一个类 主要包括以下类方法 xff1a 代码如下 xff08 来源于 STL源码剖析 xff09 xff1a ifndef JJALLOC define JJALLOC includ
  • ROS2学习笔记(十一)-- ROS2 bag数据记录与回放

    简介 xff1a ROS2提供了ros2 bag命令 xff0c 可以记录指定主题的数据到文件中 xff0c 也可以将记录下的内容再发布出来 xff0c 相当于是数据的回放 xff0c 除了通过命令行的方式实现数据记录以外 xff0c 也可
  • Altium Designer 10 导出文件(PDF,gerber,BOM)

    作者 xff1a 卢老师 华清远见嵌入式学院讲师 5 导出原理图文档 GERBER 文件 xff0c BOM对于导出 PDF 文档 xff0c 多人分析时 xff0c 不能保证所有的电脑都安装有 AD10 软件 xff0c 这个也很有必要
  • 纯C++的Socket访问Http封装类

    纯C 43 43 的Socket访问Http封装类 1 项目中要使用c 43 43 43 43 来访问Web服务器 xff0c 从网上找了个C 43 43 的封装类 xff0c 其中调用了MFC xff0c 在VC2005上用能用 xff0
  • 一个C++解析HTML的库

    HTTP协议使用广泛 xff0c 相应的 xff0c C 43 43 在这块需求也开始增加 一个好的解析库可以达到事半功倍的效果 xff0c 在此贴出我的解析库的代码 xff0c 方便新手朋友们使用 hHttpParse h ifndef
  • Intel Realsense D435i SDK Install

    Intel Realsense D435i 0 引言1 参考2 Install3 Other 0 引言 自己买的还没到 xff0c 借的同学 xff0c 生怕给他搞坏了 1 参考 ref0 官方giahubref1 官方Installref
  • OBVP问题推导

    OBVP问题推导 0 引言1 推导2 code 0 引言 记录一下 时间紧张 xff0c 不整理了 xff0c 直接上草稿纸 一元四次方程求解参考博客 1 推导 2 code 代码完全按照推导书写 xff0c 包括变量的命令 span cl
  • CMakeLists中的add_definitions()函数

    CMakeLists中的add definitions函数 0 引言1 add definitions 2 应用 0 引言 其实这个函数在安装一些库的时候 xff0c 它的CMakeLists里面就有这样的函数 典型的就是opencv了 o
  • Intel Realsense D435i&L515 驱动安装

    Intel Realsense D435i amp L515 驱动安装 0 引言1 D435i amp L515固件更新1 1 D435i固件更新1 2 L515固件更新 2 Intel Realsense驱动安装3 ROS Wrapper
  • 位置编码Positional Encoding

    位置编码Positional Encoding 1 Transformers中的PE2 什么是Transformer位置编码2 1 表格型2 2 相对位置的关系 函数型 3 为什么可以表示相对距离 xff1f 4 其他参考 内容全来自于网络

随机推荐

  • vscode 调试 Python 代码

    vscode 调试 Python 代码 0 引言1 插件2 环境布置3 parser解析 0 引言 参考0参考1 1 插件 官方的python插件代码助手 xff0c 自动补全 xff1a 解释器选择 xff0c 在窗口右下角选择解释器 x
  • OpenCV 相机转换为 OpenGL 相机

    OpenCV 相机转换为 OpenGL 相机 0 引言1 预备知识和概述2 资源3 OpenCV和OpenGL中的图像坐标系统3 1 OpenCV H Z和OpenGL中的主轴3 2 齐次坐标和OpenGL中的归一化设备坐标 4 OpenC
  • 两轮差速小车循线控制原理分析

    硬件资料设定 xff1a 小车驱动来自于两个相同的电机 xff0c 转向依靠两轮差速实现 xff0c 小车前后左右安装超声波传感器 xff0c 前后各一个 xff0c 左右各两个 xff1b 功能目标 xff1a 假设小车左侧有墙壁 xff
  • ch06-Pytorch的正则化与归一化

    ch06 Pytorch的正则化与归一化 0 引言1 weight decay 和 dropout1 1 Regularization1 2 Dropout 2 Normalization2 1 Batch Normalization2 2
  • ch07-Pytorch的训练技巧

    ch07 Pytorch的训练技巧 0 引言1 模型保存与加载1 1 序列化与反序列化1 2 PyTorch 中的模型保存与加载1 3 模型的断点续训练 2 模型 Finetune2 1 Transfer Learning amp Mode
  • opencv-contrib-Python编译module 'cv2.cv2' has no attribute 'xfeatures2d'

    opencv contrib Python编译module 39 cv2 cv2 39 has no attribute 39 xfeatures2d 39 引言解决步骤一解决步骤二 引言 opencv contrib Python编译出现
  • find_package()函数

    find package函数 引言1 find package用法2 find package原理3 A required library with LAPACK API not found 错误解决4 添加findpackage查询路径
  • py安装文件时报错usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]

    py安装文件时报错usage setup py global opts cmd1 cmd1 opts cmd2 cmd2 opts 引言solved 引言 报错 xff1a python setup py fastentrypoints u
  • VScode单步调试

    VScode配置 0 快捷键1 安装clang2 VScodeDebug3 Cmake支持gdb调试的方法 0 快捷键 稍大工程在vscode下的调试参考该博客 Ctrl 43 打开默认终端 Ctrl 43 Shift 43 新建新的终端
  • 串口通信简介

    串口通信 串口通信是一种串行异步通信 xff0c 通信双方以字符帧作为数据传输单位 xff0c 字符帧按位依次传输 xff0c 每个位占固定的时间长度 两个字符帧之间的传输时间间隔可以是任意的 xff0c 即传输完一个字符帧之后 xff0c
  • ubuntu16.0 ROS(介绍EAI的YDLIDAR-X4激光雷达在ROS下使用方法)

    YDLIDAR X4激光雷达介绍 YDLIDAR X4激光雷达是深圳越登智能科技有限公司 xff08 YDLIDAR xff0c 这家公司属于EAI xff09 研发的一款 360 度二维测距产品 xff0c 本产品基于三角测距原理 xff
  • php使用http_build_query,parse_url,parse_str创建与解析url

    1 http build query http build query 可以创建urlencode之后的请求字符串 span class hljs keyword string span http build query mixed spa
  • 无人驾驶小车调试笔记(六)-- 车轮校准

    简介 xff1a 小车的动力完全来自于两个电机带动的车轮 xff0c 在理想状态下 xff0c 给两个电机同样的驱动参数 xff0c 两个车轮会以同样的转速带动小车直线行驶 xff0c 而实际情况是每个电机可能都会有个体差异 xff0c 也
  • Nginx HTTP详解

    正文 1 Nginx启动流程 2 HTTP 初始化 新连接建立时的行为 在上次博客的最后可以看到 xff0c 在ngx event accept方法建立连接的最后一步 xff0c 将会调用ngx listening t监听结构体的handl
  • 时钟周期,机器周期,指令周期的相互关系

    1 时钟周期 61 振荡周期 xff0c 名称不同而已 xff0c 都是等于单片机晶振频率的倒数 xff0c 如常见的外接12M晶振 xff0c 那它的时钟周期 61 1 12M 2 机器周期 xff1a 8051系列单片机的机器周期 61
  • 单片机的分频是什么意思?

    分频就是单片机的时钟频率 xff08 也就是晶振的震荡频率 xff09 F经过12分频 xff0c 变换成F 12的频率 简单的来说就是以整数倍降低频率 2分频就是分频前的频率除以2 xff1b 4分频就是分频前的频率除以4 比如 xff1
  • NMOS和PMOS管

    这里我先说一下我自己分辨MOS管的方法 对于NMOS我们看下图中的箭头 xff0c 都是远离源头 对于PMOS我们看箭头 xff0c 都是指向源头 P xff1a POSITIVE积极的寻找自己的起源 N xff1a NEGTIVE消极的远
  • 基本运算放大电路

    我先说明 下面的内容应该很多人都看到过 xff0c 但是我建议还是细看 xff0c 最好自己推一下 我就是这么做的 运算放大器工作原理综述 xff1a 运算放大器组成的电路五花八门 xff0c 令人眼花瞭乱 xff0c 在分析运算放大器工作
  • PCB板框的绘制——AD19

    pcb板框的绘制当然首先要切换到keep out 层才行 找到设置 xff0c 找到keep out 假如我们要绘制一个矩形的板框 xff0c 我们选择线径就可以 手动绘制一个矩形的板框 我们需要让我们的板子边框按照我们所绘制的走线来定义
  • 零基础自学STM32-野火——GPIO复习篇——使用绝对地址操作GPIO

    今天主要是复习一下 结合野火的 零基础开发指南 名字没记住大概是这个 先放一张结构图 存储器映射 xff08 初学重点 xff09 xff1a 我们的片内外设比如 xff1a Flash Sram Fsmc 以及挂在AHB 总线上的外设 x