干货|手把手教你写单片机的结构体

摘要:你们想过没有咱们用keil写单片机的代码,你的函数啊、变量啊最终都放在了哪里?咱们一直说的内存五区,究竟是哪五区?到底放在芯片的那个地方呢?还有为何你学完C语言指针和结构体32单片机里面的关于结构体指针的内容仍是搞不清楚呢?若是你有这些问题,今天就带你研究研究!程序员

这张图学过STM32单片机的小伙伴应该都不陌生,咱们看到的STM32芯片已是已经封装好的成品,主要由内核和片上外设组成。若与电脑类比,内核与外设就如同电脑上的CPU与主板、内存、显卡、硬盘的关系。芯片和外设之间经过各类总线链接。链接被控总线的是FLASH,RAM和片上外设,这些功能部件共同排列在一个4GB的地址空间内。上面这些张图是STM32F40XXX系列单片机的内存地址映射图。数组

咱们的代码就是放在Flash里面(0x8000000~0x80FFFFF)。代码就是你写得各类函数,而在程序或者中声明的各类变量都放在RAM中,局部变量就是在函数运行完空间就释放了,全局变量就是程序运行完了再释放,能够这样简单的理解。markdown

CPU使用的变量是存储在RAM里面的,要问我RAM是啥,RAM就是个芯片。就是上图的Block1的SRAM区。CPU是经过导线和RAM芯片链接的,而后能够经过导线往RAM芯片里面存储数据和读数据。首先RAM须要有个一开始的地址,对于STM32单片机来讲开始地址是0x20000000,要问我为啥要规定地址。只有规定了地址CPU才好对数据进行存储,要是没有地址,瞎几把存,瞎几把取......函数

一、变量

1.定义了一个int型的变量,经过打印能够看到这个变量存储的地址是:0x20000000。这也证实了咱们内存的首地址是0x20000000。咱们定义的value变量就放在这里。ui

2.再定义一个变量spa

经过打印能够看到这个变量存储的地址是:0x20000004。由于int类型在内存中占据4个字节,因此第二个变量就存放在0x20000004这个地方。3d

综上所述,定义的两个变量在内存里面是下面这样子。指针

0x2000 0000地址里面存储的是 0 0x2000 0004地址里面存储的是 1code

二、指针变量

定义指针其实和定义变量同样同样的,只不过变量名前头有个*orm

下面就定义了一个int型的指针变量,变量的名字是p。而后有人会问,为啥变量名字前面加个*就是指针了?

答:搞C语言那帮家伙们规定的。

定义指针和定义变量同样哈,而后能够定义各类类型的。

而后记住一句话:

指针这个变量是存变量的地址的!

指针这个变量是存变量的地址的! 指针这个变量是存变量的地址的!

因此给指针赋值天然是把变量的地址给它。

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

int value = 0;
int value2 = 1;
int *p;

int main(void) {	
	uart_init(115200);
	delay_init();
	p=&value;//把变量value的地址复制给这个指针
	printf("Address of a: %p\n",p);//打印下这个指针指向的地址
  while(1)
	{	
	}	
}
复制代码

通常什么类型的指针变量就应该赋值什么类型变量的地址。如再定义个char型

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

int value = 0;
int value2 = 1;
int *p;//定义一个指针

char value3=1;
char *q;
	
int main(void) {	
	uart_init(115200);//串口初始化
	delay_init();
	
	p=&value;//把变量value的地址复制给这个指针
	q=&value3;//把变量value的地址复制给这个指针
	
	printf("Address of a: %p\n",q);//打印下这个指针指向的地址
    while(1)
	{	
	}	
}
复制代码

那些规定C语言的大佬弄出来指针这个玩意有啥用?

三、指针有啥用?

1.咱先使用感觉下指针,而后具体有啥用就本身体会了。前面咱把一个变量的地址赋值给了指针了,而后搞C语言的那帮家伙们又规定。*{指针变量名} :表明了这个指针所指向的变量。

啥意思呢?

对照下面的程序 p=&value, p记录的就是变量value的地址, 而后*p就表明value。

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

int value = 0;
int *p;//定义一个指针
	
int main(void) {	
	uart_init(115200);//串口初始化
	delay_init();
	
	p=&value;//把变量value的地址复制给指针变量p
	
	printf("Address of a: %d\n",value);
	printf("Address of b: %d\n",*p);
  while(1)
	{	
	}	
}
复制代码

有人会想......就这?

这不是脱了裤子放屁

画蛇添足?

其实我一开始也是这样想的......

既然 * p就表明value 那么 * p=XXXX,不就是至关于value=XXXX

看看下面这个例子

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
int value = 0;
int *p;//定义一个指针 
int main(void) {	
	uart_init(115200);//串口初始化
	delay_init();
	
	p=&value;//把变量value的地址复制给指针变量p
	printf("value of a: %d\n",value);
	
	*p=520;	
	
	printf("value of b: %d\n",value);
    while(1)
	{	
	}	
}

复制代码

仍是没感受到指针有啥用?别着急,先把基本的知识点学完哈。没有最基本的知识储备是不能够的,由于厚积而薄发!

见过返回值是指针的函数没?

四、函数指针

先看一下,若是感受不理解就接着往下看

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

int value = 0;
int *p;//定义一个指针
	
int *function(void) {
   return &value;//把value的地址返回
}
	
int main(void) {	
	uart_init(115200);//串口初始化
	delay_init();
	
	p=function();//调用函数,其实就是把value的地址赋值给了p
	
	printf("Address1 of a: %p\n",&value);//打印value的地址
	printf("Address2 of a: %p\n",p);//打印p所表明的地址
	
    while(1)
	{	
	}	
}
复制代码

不少人用过返回值是int、char 等等的函数,可是在int,char 后面加个*

估计对于初学者没有用过。看下面的,其实就是指针之间赋值。下面就是把p(int*类型的指针) 表明的地址赋值给q

变量之间能够互相赋值吧,指针之间也同样,能够互相之间赋值。

其实和上面是同样的道理,那个函数function返回值是一个int*类型的指针,而后赋值给了p而已

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

int value = 0;
int *p;//定义一个指针
int *q;//定义一个指针
	
int main(void) {	
	uart_init(115200);//串口初始化
	delay_init();
	
	p=&value;//把value的地址赋值给了p 
	q=p;//把p表明的地址给q
	
	printf("Address1 of a: %p\n",&value);//打印value的地址
	printf("Address2 of a: %p\n",q);//打印p所表明的地址
	
  while(1)
	{	
	}	
}
复制代码

姑且再问一句,函数名字是啥?

我们都知道这样调用函数

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

void function() {
  printf("zhiguoxin\n");
}
int main(void) {	
	uart_init(115200);//串口初始化
	delay_init();	
	
  function();	
    
  while(1)
	{	
	}	
}
复制代码

可是这样的见过没

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

void (*fun)();

void function() {
  printf("zhiguoxin\n");
}

int main(void) {	
	uart_init(115200);//串口初始化
	delay_init();
	
	fun = function;
  fun();
		
  while(1)
	{	
	}	
}
复制代码

这里采用了函数指针

先记住一句话

函数名就是这个函数的地址!

函数名就是这个函数的地址! 函数名就是这个函数的地址!

既然是地址,那么这个地址应该能够赋值给一个指针。由于是函数的地址,因此咱定义的指针也必定是一个函数类型的。

上面的函数void function()是一个没有返回值,没有形参的函数。那么咱须要定义一个这种的指针类型,其实就是void (*指针变量名字,随意写) ()。上面写的是 void (*fun)(); fun就是一个函数类型的指针,是一个没有返回值,没有形参的函数指针。

咱能够把这种函数赋值给这个指针变量。就是上面的fun=function。那么这个函数指针便表明了那个函数fun就等同于function。因此调用 fun(); 就等同于调用function()。

若是函数有形参怎么办? 好办,它有咱就加

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

void (*fun)(int a);

void function(int value) {
  printf("value= %d\r\n",value);
}

int main(void) {	
	uart_init(115200);//串口初始化
	delay_init();
	
	fun = function;//把function赋值给fun
  fun(520);//fun就等同于function
		
  while(1)
	{	
	}	
}
复制代码

若是函数有返回值怎么办?照加不误

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

int res;

int (*fun)(int a);

int function(int value) {
  return value;
}
int main(void) {	
	uart_init(115200);//串口初始化
	delay_init();
	
	fun = function;//把function赋值给fun
  res = fun(520);//fun就等同于function
		
	printf("res = %d",res);
  while(1)
	{	
	}	
}
复制代码

小总结一下

指针呢其实基本的也就是上面那些,指针就是用来记录变量的地址的。或是作地址之间的传递的。

&表明取地址符。

*表明取数据。 &{变量名} :就是把这个变量的地址取出来。 *{指针变量名} :就是把这个指针所表明的地址里面的存的值取出来

下面看一些比较常见的应用。把数组的地址赋值给指针,而后用指针操做数组

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

char temp[3]={1,2,3};
char *p;

int main(void) {	
	uart_init(115200);//串口初始化
	delay_init();
	
  p=temp;//将数组名赋值给指针变量p,p就指向数组temp的首地址
		
	printf("value0 = %d\r\n",*p);    //p就表明数组的第一个数据的地址
	printf("value1 = %d\r\n",*(p+1));//p+1就表明数组的第二个数据的地址
	printf("value2 = %d\r\n",*(p+2));//p+2就表明数组的第三个数据的地址
	
	printf("temp[0] = %d\r\n",p[0]);//p[0]等同于temp[0]
	printf("temp[1] = %d\r\n",p[1]);//p[1]等同于temp[1]
	printf("temp[2] = %d\r\n",p[2]);//p[2]等同于temp[2] 
  while(1)
	{	
	}	
}
复制代码

五、函数的形参是一个指针

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

char temp[3]={1,2,3};

void function(char *value) {
	printf("value0 = %d\r\n",value[0]);
	printf("value1 = %d\r\n",value[1]);
	printf("value2 = %d\r\n",value[2]);
}
int main(void) {	
	uart_init(115200);//串口初始化
	delay_init();
	
	function(temp);

  while(1)
	{	
	}	
}
复制代码

以上的指针的基本知识多练习几遍就能够。指针真正的应用是在于代码的封装。可能对于初学者感觉不到其做用,可是当你成为真正的开发人员。你会发现把好多功能函数封装起来,而后留出接口来调用是之后必不可少的。

封装的时候会大量的使用指针,函数指针、结构体指针等,怎么说呢!90%的程序员敲的是字母,写的是代码。当你开始封装的时候,你写的即是思想,可是须要必定的基础知识储备才能达到。

默认标题_横版二维码_2021-05-29-0.png

相关文章
相关标签/搜索