零基础自学STM32-复习篇2——使用结构体封装GPIO寄存器

2023-05-16

我们首先要了解寄存器的一个特点,他不是只针对一个外设,而是所有的外设都。
就拿GPIO的CRL,ODR寄存器来说
对于GPIOA——GPIOE都有一组功能相同的寄存器只是地址不一样而已A(主要是外设地址不同,比如GPIOA的外设地址和GPIOB的外设地址就不一样,即便寄存器的偏移量一样的),没必要每个寄存器都配置一遍。

这里就引入一个基本操作那就是:使用结构体对GPIO寄存器进行一次封装
主要参考:野火的《开发指南》

typedef unsigned  int uint32_t;
typedef unsigned short int uint16_t;
// unsigned int 占32位unsigned short int占16位
//下面使用结构体来封装
/*********************************/
//定义一个结构体变量使用关键字struct,并将这个结构体命名为GPIO_Typdef如下(不懂结构体的可以去找个视频看看看,不必深究会用就行。)
typedef struct  
{
	uint32_t CRL;//GPIO端口配置低寄存器器
	uint32_t CRH;//GPIO端口配置高寄存器
	uint32_t IDR;//GPIO端口输入寄存器
	uint32_t ODR;//GPIO端口输出寄存器
	uint32_t BSRR;//GPIO端口位置位/清除寄存器
	uint32_t BRR;//GPIO端口位清除寄存器
	uint32_t LCKR;//GPIO端口配置锁定寄存器
}GPIO_TypeDef;

这里还使用了typedef关键字命名了所创建的结构体类型为GPIO_TypeDef
其中结构体成员有7个变量,变量名正是所对应的寄存器名字。
C语言规定了结构体变量的存储空间是连续的(这个正好和我们的寄存器的地址是连续的特点相对应起来。这一点很重要,我们在封装的时候一定要按顺序去封装)。

在这里插入图片描述
比如我们定义的这个结构体GPIO_TypeDef。这个结构体的首个寄存器的地址就是CRL寄存器的地址也就是0x4001 0C00(这个地址也是GPIOB这个外设的总线地址),那么结构体第二个成员CRH的地址就是0x4001 0C00再加上一个0x04这个偏移量,为什么?
我们的寄存器是32位的,也就是4个字节为一个寄存器的存储空间,从CRL到CRH加上0x04也就是CRH的地址。其他成员也是相应的去加上偏移量就可以。(注意这个偏移量是相对于总线APB2的基地址的偏移量)

我们这里依然以代码为分析对象

//这里是stm32f103.h头文件
//用来存放stm32寄存器映射的代码
//GPIOB

//外设基地址 peripheral

# define PERIPHBASE  ((unsigned int)0x40000000)   //片内外设基地址
	
//总线基地址

# define APB1PERIPH_BASE	PERIPHBASE   //APB1总线基地址与片内外设基地址是一样的
# define APB2PERIPH_BASE  (PERIPHBASE + 0x10000)   //APB2总线基地址
# define AHBPERIPH_BASE   (PERIPHBASE + 0x20000)    //AHB总线基地址(为了后面操作RCC时钟),这里采用的DMA1的地址作为基地址


# define RCC_BASE	(AHBPERIPH_BASE + 0x1000)	//RCC复位时钟控制地址,想让IO工作必须配置


# define GPIOB_BASE	(APB2PERIPH_BASE + 0x0C00)	//GPIOB地址,操作GPIO的前提是找到总线地址


# define RCC_APB2ENR	*(unsigned int* )(RCC_BASE + 0x18)  //APB2外设时钟使能,想让IO工作必须配置   0x18就是APB2使能寄存器相对于RCC时钟总线的偏移量



//下面的代码使用宏定义重新命名一个指针变量,并通过操作寄存器的绝对地址指针从而操作寄存器工作
//# define GPIOB_CRL	 *(unsigned int*)(GPIOB_BASE  + 0x00)	//端口配置地寄存器
//# define GPIOB_CRH 	 *(unsigned int*)(GPIOB_BASE  + 0x04)	//端口配置高寄存器
//# define GPIOB_ODR   *(unsigned int*)(GPIOB_BASE  + 0x0C)	//数据输出寄存器
//# define GPIOB_IDR   *(unsigned int*)(GPIOB_BASE + 0x08)  //输入数据寄存器
//# define GPIOB_BSRR  *(unsigned int*)(GPIOB_BASE + 0x10)  //端口位设置/清除寄存器
//# define GPIOB_BRR   *(unsigned int*)(GPIOB_BASE + 0x14)  //端口位清除寄存器
//# define GPIOB_LCKR  *(unsigned int*)(GPIOB_BASE + 0x18)  //端口配置锁定寄存器

typedef unsigned int uint32_t;//声明一个32位的变量类型
typedef unsigned short uint16_t;//声明一个16位的变量类型
	
typedef struct
{
	 /*
	这里解释一下为什么可以直接操作而不需要加偏移量
	我们的stm32是32位单片机,每次操作32位数,而寄存器也是每个寄存器占用4个字节,也正好是32位,
创建结构体本身就会分配一个连续的内存空间,而我们定义了每个成员作为32位的变量,那正好跟寄存器本身的地址相对应起来。
	
	
	*/
	uint32_t  CRL;  
	uint32_t  CRH;
	uint32_t  IDR;
	uint32_t  ODR;
	uint32_t  BSRR;
	uint32_t  BRR;
	uint32_t  LCKR;
	
}GPIO_TypeDef;

//让GPIOB的地址GPIOB_BASE转化为一个结构体类类型的变量,并重新命名为GPIOB
# define GPIOB  ((GPIO_TypeDef*)(GPIOB_BASE))



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

void SystemInit(void);//不用管这条代码

int main (void)
{
	
	
	# if 0  //使用这个语句相当于注释掉下面的代码
	//使用寄存器绝对地址操作
	*(unsigned int *)0x40021018 |=((1)<<3);        //打开gpiob端口时钟
	//*(unsigned int *)0x40010C0C &=~(1<<0);          //Data_Output  CRL_REG   通用推挽输出模式
	
	*(unsigned int *)0x40010C0C &=~((1)<<0);	//Data_Output  CRL_REG
	
	*(unsigned int *)0x40010C00 |=((1)<<(4*0));   //Set_Output   ODR_REG  //数据输出寄存器
	
	#elif 0   //注释掉下面的代码
	
	RCC_APB2ENR |= ((1)<<3);          //GPIOB时钟使能,在头文件中用宏定义声明过了

	GPIOB_CRL |= ((1)<<(4*0));         //端口配置低寄存器
	GPIOB_ODR &= ~(unsigned int)(1<<0);   			//数据输出寄存器
	//GPIOB_ODR |= (1<<0); 
	
	#elif 1  //执行这部分代码,使用结构封装好的函数去配置寄存器的值(重点掌握)
	
	RCC_APB2ENR |= ((1)<<3);          //GPIOB时钟使能

	GPIOB->CRL |= ((1)<<(4*0));         //端口配置低寄存器
	GPIOB->ODR &= ~(unsigned int)(1<<0);   			//数据输出寄存器
	//GPIOB->ODR |= (1<<0); 
	
	
	#endif
}
//置位  |=
//清零  &=~

void SystemInit(void)
{
	
	//函数体为空

}

这里不得不重新说明一下,什么是结构体。以便更好的理解和使用它:
这里我看的是B站UP主“杜远超官方频道”的视频,可以直接搜索结构体就能看到。我是很推荐这个视频的,希望帮到你!!
下面声明一个结构体类型:

# include <stdio.h>
//创建结构体使用关键字struct
//下面这种形式是创建了一个结构体类型,并且这个类型名为Student,我们可以将其看作是int这种的数据类型的形式,去创建多个变量。
struct Student   //结构体的名字为Student,建议首字母大写。这个是类型的名字而不是变量名。(这一点很重要)。比如说float是浮点类型的名称,flaot a,中的a是变量的名称。而struct是一个关键字。
{
	int id;//学号
	int age;//年龄
	char*name;//姓名
	float score;//成绩
};

//显然结构体的内容是基本数据类型组而合成
//我们也可以声明一个空的结构体
struct Emptystruct
{
	//空结构体
};


int main ()
{
	//基本数据类型  int,float,long, doubel...
	//如果我们要表示一个学生的信息,而学生的信息有学号信息等
	
	
}

下面声明一个匿名的结构体类型:

# include <stdio.h>
//我们可以创建一个没有名字的结构体,或者说匿名结构体
//匿名结构体的末尾一定跟着结构体变量的名称。
struct
{
	int id;//学号
	int age;//年龄
	char*name;//姓名
	float score;//成绩

}stu1,stu2;//这里声明了两个学生的变量。

int main ()
{
	
	return 0;
}

下面我们引入typedef:
第一种用法

# include <stdio.h>
//我们可以创建一个没有名字的结构体,或者说匿名结构体
//匿名结构体的末尾一定跟着结构体变量的名称。
struct Student
{
	int id;//学号
	int age;//年龄
	char*name;//姓名
	float score;//成绩

};//这里声明了两个学生的结构体变量,一定要注意这里的是变量而不是类型了。


typedef struct Stdent Stdent;
//上面这一行代码的还以是什么?
//说白了就是用最后的Student这个名字取代替我们的struct Student这个结构体,后面我们创建结构体变量的时候可以直接使用Student,而它所代表的含义就是一个结构体类型。

int main ()
{
	//定义变量的基本格式。数据类型+变量名;比如int a;char c
	//我们使用结构体比如上面创建的Student,去创建一个变量的话还需要加上一个变量的名字
	//struct Student stu;//注意这种创建结构体变量的方式中struct是不可以省略掉
	//我们可以使用typedef去定义一个新的数据类
	//我们就可以这样创建一个结构体变量
	Student stu1;//完美,简洁
	
	return 0;
}

第二种用法

# include <stdio.h>
//我们可以创建一个没有名字的结构体,或者说匿名结构体
//匿名结构体的末尾一定跟着结构体变量的名称。
typedef struct Stdent //可以不加结构体的名字,但是建议加上结构体名
{
	int id;//学号
	int age;//年龄
	char*name;//姓名
	float score;//成绩

}Student;
//说明一下,使用typedef就是将我们创建的sturct Student命名为Student,注意这里的STudent依然是类型的名字而不是变量。(重点)




int main ()
{
	//定义变量的基本格式。数据类型+变量名;比如int a;char c
	//我们使用结构体比如上面创建的Student,去创建一个变量的话还需要加上一个变量的名字
	//struct Student stu;//注意这种创建结构体变量的方式中struct是不可以省略掉
	//我们可以使用typedef去定义一个新的数据类
	//我们就可以这样创建一个结构体变量
	Student stu1;//完美,简洁
	
	return 0;
}

下面介绍结构体的嵌套

# include <stdio.h>

typedef struct Birthday
{
	int year;//年
	int month;//月
	int day;//日

}Birthday;



typedef struct Stdent //可以不加结构体的名字,但是建议加上结构体名
{
	int id;//学号
	int age;//年龄
	char*name;//姓名
	float score;//成绩
	Birthday bitthday;  //结构体的嵌套
}Student;
//说明一下,使用typedef就是将我们创建的sturct Student命名为Student,注意这里的STudent依然是类型的名字而不是变量。(重点)




int main ()
{
	Student stu;
	stu.birthday.year = 1996;//这里就是结构体的访问,我们就是在使用.去访问stu这个结构体下的birthday这个结构体下的year
	
	
	return 0;
}

结构体变量
声明结构体变量的方式
方式1

# include <stdio.h>

typedef struct Birthday
{
	int year;//年
	int month;//月
	int day;//日

}Birthday;



typedef struct Stdent //可以不加结构体的名字,但是建议加上结构体名
{
	int id;//学号
	int age;//年龄
	char*name;//姓名
	float score;//成绩
	Birthday bitthday;  //结构体的嵌套
}Student;
//说明一下,使用typedef就是将我们创建的sturct Student命名为Student,注意这里的STudent依然是类型的名字而不是变量。(重点)




int main ()
{
//注意我们如果不使用类型去创建变量的话是不会分配内存空间,说白了就是不占用任何内存。
//那么也就是说我们声明的结构体本身是不占用内存的。只有在声明结构体变量的时候才会分配内存。
Student stu1;
Student stu2;
	
	
	return 0;
}

声明结构体变量的方式
方式2

# include <stdio.h>

typedef struct Birthday
{
	int year;//年
	int month;//月
	int day;//日

}Birthday;



typedef struct Stdent //可以不加结构体的名字,但是建议加上结构体名
{
	int id;//学号
	int age;//年龄
	char*name;//姓名
	float score;//成绩
	Birthday bitthday;  //结构体的嵌套
}Student,stu3;//注意这里就是直接创建了一个stu3结构体变量,不建议这样创建,我是不习惯
//说明一下,使用typedef就是将我们创建的sturct Student命名为Student,注意这里的STudent依然是类型的名字而不是变量。(重点)

int main ()
{

Student stu1;
Student stu2;
	
	
	return 0;
}

结构体变量的赋值

# include <stdio.h>

typedef struct Birthday
{
	int year;//年
	int month;//月
	int day;//日

}Birthday;



typedef struct Stdent //可以不加结构体的名字,但是建议加上结构体名
{
	int id;//学号
	int age;//年龄
	char*name;//姓名
	float score;//成绩
	Birthday bitthday;  //结构体的嵌套
}Student,stu3;//注意这里就是直接创建了一个stu3结构体变量
//说明一下,使用typedef就是将我们创建的sturct Student命名为Student,注意这里的STudent依然是类型的名字而不是变量。(重点)

int main ()
{
	Student stu1 = {1001,26,"李明",100,
					{1996,10,20}};
	//这样就完成了结构体的赋值
	
	Student stu2 = {1002,22,"李华",99,
					{2000,10,20}};
	return 0;
}

如何去创建结构体变量

# include <stdio.h>

typedef struct Birthday
{
	int year;//年
	int month;//月
	int day;//日

}Birthday;



typedef struct Stdent //可以不加结构体的名字,但是建议加上结构体名
{
	int id;//学号
	int age;//年龄
	char*name;//姓名
	float score;//成绩
	Birthday bitthday;  //结构体的嵌套
}Student,stu3;//注意这里就是直接创建了一个stu3结构体变量,不建议这样创建,我是不习惯
//说明一下,使用typedef就是将我们创建的sturct Student命名为Student,注意这里的STudent依然是类型的名字而不是变量。(重点)

int main ()
{

Student stu1;
Student stu2;
	
	
	return 0;
}

结构体成员的调用

# include <stdio.h>

typedef struct Birthday
{
	int year;//年
	int month;//月
	int day;//日

}Birthday;



typedef struct Stdent //可以不加结构体的名字,但是建议加上结构体名
{
	int id;//学号
	int age;//年龄
	char*name;//姓名
	float score;//成绩
	Birthday bitthday;  //结构体的嵌套
}Student,stu3;//注意这里就是直接创建了一个stu3结构体变量
//说明一下,使用typedef就是将我们创建的sturct Student命名为Student,注意这里的STudent依然是类型的名字而不是变量。(重点)

int main ()
{
	Student stu1 = {1001,26,"李明",100,
					{1996,10,20}};
	//这样就完成了结构体的赋值
	
	Student stu2 = {1002,22,"李华",99,
					{2000,10,20}};
	//访问成员变量使用.操作符
	printf("学号:%d 姓名:%s 年龄:%d 成绩:%0.2f 生日:%d-%d-%d",stu1.id,stu1.name,stu1.age,stu1.score,stu1.Birthday.year,stu1.Birthday.month,syu1.Birthday.day);
	return 0;
}

显然,结构体的访问格式就是,“结构体名 . 结构体变量”的形式。
如果是嵌套的话也是使用.去调用。
程序优化:单独定义一个打印函数

# include <stdio.h>

typedef struct Birthday
{
	int year;//年
	int month;//月
	int day;//日

}Birthday;



typedef struct Stdent //可以不加结构体的名字,但是建议加上结构体名
{
	int id;//学号
	int age;//年龄
	char*name;//姓名
	float score;//成绩
	Birthday bitthday;  //结构体的嵌套
}Student,stu3;//注意这里就是直接创建了一个stu3结构体变量
//说明一下,使用typedef就是将我们创建的sturct Student命名为Student,注意这里的STudent依然是类型的名字而不是变量。(重点)



//此函数的目的是打印学生结构体的信息
//我们需要使用形参,传递需要打印的学生信息
void PrintfStudentInfo(Student stu)
{
	printf("学号:%d 姓名:%s 年龄:%d 成绩:%0.2f 生日:%d-%d-%d",stu.id,stu.name,stu.age,stu.score,stu.Birthday.year,stu.Birthday.month,syu.Birthday.day);

}


int main ()
{
	Student stu1 = {1001,26,"李明",100,
					{1996,10,20}};
	//这样就完成了结构体的赋值
	
	Student stu2 = {1002,22,"李华",99,
					{2000,10,20}};
	
	PrintfStudentInfo(Student stu1);
	return 0;
}

上面的代码还是有他的局限性,想想看我们即便是定义了一个打印函数,但是对于系统来说,我仍然是拷贝了一份打印的信息并封存在了函数中。
所以引出下面的使用结构体指针。

使用结构体指针

# include <stdio.h>

typedef struct Birthday
{
	int year;//年
	int month;//月
	int day;//日

}Birthday;



typedef struct Stdent //可以不加结构体的名字,但是建议加上结构体名
{
	int id;//学号
	int age;//年龄
	char*name;//姓名
	float score;//成绩
	Birthday bitthday;  //结构体的嵌套
}Student,stu3;//注意这里就是直接创建了一个stu3结构体变量
//说明一下,使用typedef就是将我们创建的sturct Student命名为Student,注意这里的STudent依然是类型的名字而不是变量。(重点)



//此函数的目的是打印学生结构体的信息
//我们需要使用形参,传递需要打印的学生信息
void PrintfStudentInfo(Student *p_stu)  //这里函数的形参就是一个结构体指针p_stu
{
	printf("学号:%d 姓名:%s 年龄:%d 成绩:%0.2f 生日:%d-%d-%d",p_stu.id,p_stu.name,p_stu.age,p_stu.score,p_stu.Birthday.year,p_stu.Birthday.month,p_stu.Birthday.day);

}


int main ()
{
	Student stu1 = {1001,26,"李明",100,
					{1996,10,20}};
	//这样就完成了结构体的赋值
	
	Student stu2 = {1002,22,"李华",99,
					{2000,10,20}};
	

	Student*pstu = &stu1;//这一步就是创建一个指针结构体pstu并且这个指针指向了stu1这个结构体变量的地址。
	
	
	PrintfStudentInfo(pstu);//注意这里传递的是地址(指针)
	return 0;
}

上面的代码存在一个致命错误!!!!!

void PrintfStudentInfo(Student *p_stu)  //这里函数的形参就是一个结构体指针p_stu
{
	printf("学号:%d 姓名:%s 年龄:%d 成绩:%0.2f 生日:%d-%d-%d",p_stu.id,p_stu.name,p_stu.age,p_stu.score,p_stu.Birthday.year,p_stu.Birthday.month,p_stu.Birthday.day);

}

注意上面这一行代码,我们的c语言规定了,如果我们使用的是结构体指针,要求我们在访问结构体成员的时候不再使用“.”。而是改用“->”
正确的写法如下所示:

void PrintfStudentInfo(Student *p_stu)  //这里函数的形参就是一个结构体指针p_stu
{
	printf("学号:%d 姓名:%s 年龄:%d 成绩:%0.2f 生日:%d-%d-%d",p_stu>id,p_stu->name,p_stu->age,p_stu->score,p_stu->Birthday.year,p_stu->Birthday.month,p_stu->Birthday.day);

}

//注意细节,我们在使用

p_stu->Birthday.month//在Birthday的后面使用的是“.”,因为这里是成员关系而不是指针。

# include <stdio.h>

typedef struct Birthday
{
	int year;//年
	int month;//月
	int day;//日

}Birthday;



typedef struct Stdent //可以不加结构体的名字,但是建议加上结构体名
{
	int id;//学号
	int age;//年龄
	char*name;//姓名
	float score;//成绩
	Birthday bitthday;  //结构体的嵌套
}Student,stu3;//注意这里就是直接创建了一个stu3结构体变量
//说明一下,使用typedef就是将我们创建的sturct Student命名为Student,注意这里的STudent依然是类型的名字而不是变量。(重点)



//此函数的目的是打印学生结构体的信息
//我们需要使用形参,传递需要打印的学生信息
void PrintfStudentInfo(Student *p_stu)  //这里函数的形参就是一个结构体指针p_stu
{
	printf("学号:%d 姓名:%s 年龄:%d 成绩:%0.2f 生日:%d-%d-%d",p_stu.id,p_stu.name,p_stu.age,p_stu.score,p_stu.Birthday.year,p_stu.Birthday.month,p_stu.Birthday.day);

}


int main ()
{
	Student stu1 = {1001,26,"李明",100,
					{1996,10,20}};
	//这样就完成了结构体的赋值
	
	Student stu2 = {1002,22,"李华",99,
					{2000,10,20}};
	

	Student*pstu = &stu1;//这一步就是创建一个指针结构体pstu并且这个指针指向了stu1这个结构体变量的地址。
	
	
	PrintfStudentInfo(pstu);//注意这里传递的是地址(指针)
	
	pstu = &stu2;
	PrintfStudentInfo(pstu);//打印另一个学生的信息
	
	return 0;
}

本篇完。。。

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

零基础自学STM32-复习篇2——使用结构体封装GPIO寄存器 的相关文章

  • 树莓派没有屏幕如何连接WiFi

    Wi Fi 或以太网 如果您想使用本地 lan 的 DHCP 服务器为您的 pi 获取 IP 地址 xff0c 则有两种方法可以将 Pi 连接到互联网 xff1a 首先是使用以太网电缆将 Pi 连接到路由器 在这种情况下 xff0c 您可以
  • 福禄克FLUKE 435-2电能质量分析仪测试瞬态与电压不平衡

    最常影响工业工厂的电功率问题包括电压暂降和暂升 谐波 瞬态 xff0c 以及电压和电流不平衡 在平衡的三相系统中 xff0c 各个相电压应相同或非常接近于相同 不平衡是相电压不相等程度一个度量 电压不平衡是三相系统中各相之间的电压差异指标
  • 在线摄像头

    在线摄像头 2009 07 22 09 49 10人阅读 评论 0 收藏 举报 在Google中输入 inurl 34 ViewerFrame Mode 61 34 或者 inurl 34 MultiCameraFrame Mode 61
  • Docker Desktop的安装

    如果安装了 Docker Desktop xff0c 则已经安装了完整的 Docker xff0c 包括 Compose 一 在 Ubuntu 上安装 Docker Desktop DEB 包 先决条件 要成功安装 Docker Deskt
  • Intel Realsense D435i Firmware Update

    Intel Realsense D435i Firmware Update 0 引言1 更新2 显示设备信息 0 引言 固件下载更新教程 1 更新 固件名称 xff1a Signed Image UVC lt firmware versio
  • Intel RealSense D435i Calibration

    Intel RealSense D435i Calibration 0 引言1 标定工具安装1 1 imu utils Install1 2 kalibr Install 2 IMU标定3 相机标定4 IMU 43 相机联合标定5 VINS
  • G2O优化

    G2O优化 0 引言0 1 参考0 1 G2O的解决问题0 2 G2O整体框架 1 基本使用1 1 构造 g2o 模型1 2 g2o 类图 2 g2o 的顶点 xff08 Vertex xff09 2 1 顶点的格式2 2 自定义顶点2 3
  • Kalman Filter

    Kalman Filter 0 引言1 Kalman Filter1 1 建模1 2 五个重要公式 2 推导3 MatlabDemo 0 引言 卡尔曼滤波 xff08 Kalman filtering xff09 一种利用线性系统状态方程
  • 发一套最完整的直升机原理(绝对完整,绝对精华)

    发一套最完整的直升机原理 xff08 绝对完整 xff0c 绝对精华 xff09 这是找到的最完整 xff0c 最系统介绍直升机的原理及发展史的文章 转到这里 xff0c 送给论坛里喜欢飞行 xff0c 向往蓝天的朋友 xff01 xff0
  • 模拟串口UART的实现

    我所祷告的 xff0c 就是要你们的爱心 xff0c 在知识和见识上 xff0c 多而又多 xff0c 使你们能分辨是非 xff0c 做诚实无过的人 xff0c 直到基督的日子 腓立比书 1 9 10 最近在调的MCU的型号为STM32F0
  • VScode安装git插件使用说明

    VScode创建代码功能目录后 xff0c 可以安装git相关插件查看代码合入历史记录 代码提供 更新 合入等操作 xff0c 使用起来比较方便 1 安装试用Git History 离线安装包 xff1a donjayamanne gith
  • 使用java代码连接RedisCluster集群实现

    Redis5 x集群学习须知 学前须知 xff1a 当前redis的最新版本是5 0以上 xff0c 其搭建cluster的方法与早期的redis4 0以前的不太一样 xff0c 不再使用ruby相关的组件 1 redis集群的常见搭建方式
  • [设计] Doris血缘解析流程

    一 背景 1 1 元数据概述 元数据是凌久中台重要功能模块 xff0c 是数据治理的重要一环 xff0c 元数据治理是一切数据治理的基础 xff0c 主要分为元数据管理和表血缘管理 xff1b 元数据管理主要用来做数据地图 数据资产等 xf
  • [安装] 搭建hadoop集群

    参考资料 xff1a Hadoop集群搭建 xff0c 14张过程截图超详细教程 目录 目录 hadoop集群构建 for ljgk 一 基础环境准备 修改主机名称 配置yum源 1 局域网中配置代理环境 2 或者使用私有的yum源的方式
  • presto和doris查询对比

    本文对比了presto和doris在即席查询场景下的性能对比 1 count 查询数据总条数 例子 xff1a select count from ods tb device point data presto查询结果 presto vas
  • JAVA常用工具类

    JAVA常用工具类 根据GITHUB代码统计 从Google你能搜索到大量的关于Struts Spring Hibernate iBatis等比较大的框架的资料 xff0c 但是很少有人去关注一些小的工具包 xff0c 但是当你真正知道了这
  • Kafka遇到的坑-- Error while fetching metadata with correlation id : {LEADER_NOT_AVAILABLE}

    1 创建topic中出现出现错误 kafka出现 Error while fetching metadata with correlation id LEADER NOT AVAILABLE 表示无法识别kafka hostname 正确处
  • 怎样让Intellij IDEA工程中输出日志信息

    Intellij IDEA中使用log4j日志 一 在pom xml中添加依赖 span class token tag span class token tag span class token punctuation lt span d
  • 面试一般流程

    面试流程 xff1a 个人介绍 gt 技术面试 gt 项目介绍 gt 职业规划 一 个人介绍 xff1a xff08 1 xff09 个人履历 xff1a 你的学校 专业 xff08 突出自己的优势 已经做的项目突出你的个人能力 xff09
  • 31岁之十大拙见

    版权归作者所有 xff0c 任何形式转载请联系作者 作者 xff1a 萧汐汐 xff08 来自豆瓣 xff09 来源 xff1a https www douban com note 696211880 31岁之十大拙见 工作是人生大事 xf

随机推荐

  • Flink日志输出查看方式

    在网上查看flink日志查看方式 xff0c 竟然查询不到 xff0c 因此写下这篇文章 xff0c 给有此困惑的小盆友们 xff0c 也给自己做个总结 xff01 前情提要 xff1a 我是通过flink web ui提交的flink任务
  • 重学C语言之开始

    还记得是大一上学期学习的C语言 xff0c 当时就是为了应付一下考试 xff0c 很多东西其实还没有吃透 虽然大学玩了几年的单片机 xff0c 自己也写了不少的C代码 xff0c 但是总是感觉自己还是没有搞透C语言 xff0c 没有抓住C语
  • 【20-8-7】树莓派上部署英特尔深度相机IntelRealsense T265

    最近在搭建无人机的自主飞行平台 xff0c 无GPS的情况下室内定位的方案除了光流 xff0c 最好的就是配合intel的realsense系列的摄像头 尤其是T265本身带IMU xff0c 可以直接给飞控输出位姿信息 xff0c 不管是
  • 【2020-8-8】ROS软件包自动安装依赖,安装ros_pcl

    最近要把T265部署到无人机平台 xff0c 编译一个软件的时候一直报ros pcl的错误 原因是树莓派安装的ros并不是完整版 xff0c 因为也不需要再树莓派上部署gazebo之类的仿真平台 网上关于安装ros pcl的文章基本上都已经
  • 【2020-8-9】APM,PX4,GAZEBO,MAVLINK,MAVROS,ROS之间的关系以及科研设备选型

    0 概述 无人机自主飞行平台可以分为四个部分 xff1a 动力平台 xff0c 飞行控制器 xff0c 机载电脑和模拟平台 动力平台 xff1a 负责执行飞行任务 xff0c 包括螺旋桨 电机 机架等 xff0c 用于科研的一般都是F380
  • 【8-12】树莓派ubuntu升级Cmake

    树莓派上运行的是Ubuntu Mate18 04的系统 xff0c 自带的cmake版本是3 10 0 xff0c 编译软件的时候要求cmake版本大于3 11 0 需要进行升级 注意网上的教程会让你卸载现在系统里cmake xff0c 就
  • 【8-12】树莓派部署t265+px4飞控实现无人机视觉定位

    在之前的文章中 xff0c 我们已经成功在树莓派 xff08 ubuntu mate 18 04 xff09 上部署了T265的追踪摄像头 本文将利用MAVROS协议 xff0c 将T265测量的位姿信息发送给px4固件 xff0c 实现室
  • 【8-14】树莓派3B+ Ubuntu Mate 18.04使用Intel NCS2做人脸识别

    想要在无人机平台部署CV xff0c 但是无人机的机载电脑需要安装ROS xff0c 而ROS需要在Ubuntu的平台才能方便使用 xff0c 所以树莓派3B 43 上安装的是Ubuntu Mate18 04 Intel Ncs2 xff0
  • 【8-14】virtualenv和virtualenv wrapper的快速入门

    跟conda类似的Python虚拟环境管理工具 xff0c jetson nano暂时无法使用conda 1 virtualenv span class token comment 安装 span span class token func
  • 【20-9-22】Python实现多进程多线程

    简介 对于计算机来说 xff0c 有两种实现多任务的方式 xff1a 并行和并发 并发 xff1a 一段时间内交替执行某些任务 如单核CPU轮流执行一些程序 并行 xff1a 一段时间内同时运行多个任务 多核cpu处理多任务 1 进程 程序
  • 【21-3-28】pvcreate device excluded by a filter

    使用Lvm创建虚拟磁盘时报错的解决方法 xff1a span class token function sudo span pvcreate dev sdd Device dev sdd excluded by a filter 原因是因为
  • BMI指数

    身体质量指数 xff08 Body Mass Index xff0c BMI xff09 是根据人的体重和身高计算得出的一个数字 xff0c BMI对大多数人来说 xff0c 是相当可靠的身体肥胖指标 xff0c 其计算公式为 xff1a
  • 生日悖论的Python实现

    题目 xff1a 如果你的班级中有23个学生 xff0c 那么其中有两个人生日相同的概率为多大 xff1f usr bin env python coding 61 utf 8 import random def has duplicate
  • 二分法查找的Python实现

    代码如下 xff1a usr bin env python coding 61 utf 8 def BinarySearch t x t sort 对列表进行排序 xff0c 列表是有序的 xff0c 是二分法的前提 low 61 0 hi
  • Python中bisect模块用法,及实现方式

    bisect用法 import bisect bisect bisect left t x 在T列表中查找x xff0c 若存在 xff0c 返回x左侧位置 bisect bisect right t x bisect insort lef
  • c++实验六总结(自用)

    实验目的 掌握派生类的声明方法和派生类构造函数的定义方法 掌握不同方式下 xff0c 构造函数与析构函数的执行顺序与构造规则 程序如下 xff1a include lt iostream gt include lt string gt us
  • 光网络知识

    一 WDM网络体系结构注意点 1 波长复用 2 波长转换 3 透明性 4 电路交换 5 生存性 xff1a 当网络出现故障时 xff0c 光路能够自动路由到另一条备份路径上 xff0c 为网络提供了高度的弹性 6 光路拓扑 二 波分复用网络
  • docker镜像更新后 如何正确更新对应的容器 避免数据丢失

    容器的更新大致分为以下两种方法 1 容器并未存储任何应用程序的数据 在这种情况下 您可以在任何时候使用它的更新版本替换APP容器 方法是执行如下所示 span class token function docker span pull my
  • netconn_accept返回值为0,OSQCreate出错 lwip uocsii

    我是在main中有创建信号量的函数 led event 61 OSQCreate amp led q 0 MSGSIZE 这个因为配置中信号量上限较小 而在sys arch c中有一个创建消息邮箱的函数 err t sys mbox new
  • 零基础自学STM32-复习篇2——使用结构体封装GPIO寄存器

    我们首先要了解寄存器的一个特点 xff0c 他不是只针对一个外设 xff0c 而是所有的外设都 就拿GPIO的CRL xff0c ODR寄存器来说 对于GPIOA GPI xff2f E都有一组功能相同的寄存器只是地址不一样而已 xff21