0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

教你如何轻松写单片机的指针

凡亿PCB 来源:果果小师弟 作者:果果小师弟 2021-06-17 16:08 次阅读

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

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

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

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

1、变量1.定义一个int型的变量,通过打印可以看到这个变量存储的地址是:0x20000000。这也证明了我们内存的首地址是0x20000000。我们定义的value变量就放在这里。

3aea0c10-ca98-11eb-9e57-12bb97331649.png

3b100280-ca98-11eb-9e57-12bb97331649.png

2.再定义一个变量

通过打印可以看到这个变量存储的地址是:0x20000004。因为int类型在内存中占据4个字节,所以第二个变量就存放在0x20000004这个地方。

3b1f7e2c-ca98-11eb-9e57-12bb97331649.png

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

0x2000 0000地址里面存储的是 0

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

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

下面就定义一个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

”,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

”,q);//打印下这个指针指向的地址

while(1)

{

}

}

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

3、指针有啥用?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

”,value);

printf(“Address of b: %d

”,*p);

while(1)

{

}

}

3bdfdb54-ca98-11eb-9e57-12bb97331649.png

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

有人觉得多此一举?

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

既然 * 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

”,value);

*p=520;

printf(“value of b: %d

”,value);

while(1)

{

}

}

还是没感觉到指针有啥用?别着急,先把基本的知识点学完哈。没有最基本的知识储备是不可以的,因为厚积而薄发!

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

4、函数指针先看一下,如果感觉不理解就接着往下看

#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

”,&value);//打印value的地址

printf(“Address2 of a: %p

”,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

”,&value);//打印value的地址

printf(“Address2 of a: %p

”,q);//打印p所代表的地址

while(1)

{

}

}

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

咱们都知道这样调用函数

#include “sys.h”#include “led.h”#include “delay.h”#include “usart.h”void function()

{

printf(“zhiguoxin

”);

}

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

”);

}

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

”,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

”,*p); //p就代表数组的第一个数据的地址

printf(“value1 = %d

”,*(p+1));//p+1就代表数组的第二个数据的地址

printf(“value2 = %d

”,*(p+2));//p+2就代表数组的第三个数据的地址

printf(“temp[0] = %d

”,p[0]);//p[0]等同于temp[0]

printf(“temp[1] = %d

”,p[1]);//p[1]等同于temp[1]

printf(“temp[2] = %d

”,p[2]);//p[2]等同于temp[2]

while(1)

{

}

}

5、函数的形参是一个指针#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

”,value[0]);

printf(“value1 = %d

”,value[1]);

printf(“value2 = %d

”,value[2]);

}

int main(void)

{

uart_init(115200);//串口初始化

delay_init();

function(temp);

while(1)

{

}

}

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

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

本文编辑转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。版权归原作者所有,如涉及作品内容、版权和其它问题,请联系我们第一时间删除内容!

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6032

    文章

    44513

    浏览量

    632739
  • RAM
    RAM
    +关注

    关注

    8

    文章

    1367

    浏览量

    114517
  • STM32
    +关注

    关注

    2265

    文章

    10870

    浏览量

    354716
  • 函数
    +关注

    关注

    3

    文章

    4304

    浏览量

    62413
  • 代码
    +关注

    关注

    30

    文章

    4741

    浏览量

    68326

原文标题:干货|手把手教你写单片机的指针

文章出处:【微信号:FANYPCB,微信公众号:凡亿PCB】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    单片机怎么写入程序

    单片机(Microcontroller Unit,MCU)是一种集成电路芯片,它将计算机的CPU、存储器、输入/输出接口等功能集成在一个芯片上。单片机广泛应用于嵌入式系统和物联网设备中。编写单片机
    的头像 发表于 10-21 11:21 254次阅读

    把esp8266加入到c51单片机单通道程序怎么

    要将ESP8266模块加入到C51单片机的单通道程序中,您需要了解如何通过串行通信(UART)与ESP8266进行通信。以下是如何实现这一点的步骤和示例代码。 步骤 1:硬件连接 首先,您需要
    的头像 发表于 10-18 11:32 371次阅读

    单片机的中断机制

    单片机的中断机制是一种重要的处理方式,它允许单片机在执行主程序的过程中,能够暂停当前任务,转而处理外部或内部紧急事件。这种机制极大地提高了系统的响应速度和处理能力,使得单片机在各种应用领域中得到广泛应用。以下是对
    的头像 发表于 10-17 18:03 340次阅读

    单片机STM32可以用Python吗?可以的开发板有哪些?

    近年来,随着嵌入式技术的发展,Python语言逐渐被引入到单片机开发中,尤其是一些高性能的单片机上。这一趋势给开发者带来了极大的便利,尤其是在快速原型设计和实验中。本文将详细探讨STM32单片机是否
    的头像 发表于 09-05 08:00 2397次阅读
    <b class='flag-5'>单片机</b>STM32可以用Python<b class='flag-5'>写</b>吗?可以的开发板有哪些?

    单片机烧录程序的基本步骤是什么

    单片机烧录程序是单片机开发过程中非常重要的一步,它涉及到将编写好的程序代码通过一定的方式传输到单片机内部的存储器中,使单片机能够按照预定的逻辑执行任务。 一、硬件准备
    的头像 发表于 09-02 09:47 765次阅读

    STM32F0系列单片机,指针取整型值错误的原因?

    STM32F0系列单片机,指针取整型值错误,用F0的进来看下,代码如下,附件里也有个工程可以下来单步运行下,这是什么问题如何解决. uint8_t a
    发表于 05-15 07:46

    如何系统、科学地自学单片机

    很多初学者都会面临这个问题,我想学习单片机、我也想学好单片机、我也想系统地学习单片机,但是单片机涉及到的学科多且杂根本不是三天两天就能学完的,很多人都逃脱不了从入门到放弃的怪圈?那么我
    的头像 发表于 03-28 08:03 993次阅读
    如何系统、科学地自学<b class='flag-5'>单片机</b>?

    单片机的最小系统由什么组成 单片机的最小系统包括哪些

    单片机(Microcontroller Unit,MCU)的最小系统包括以下几个主要组成部分: 单片机芯片:单片机是整个最小系统的核心部分,它集成了中央处理器(Central Processing
    的头像 发表于 02-02 11:27 9854次阅读

    基于单片机控制的交通灯设计

    本课程设计是在学完单片机原理及课程之后综合利用所学单片机知识完成一个单片机应用系统设计并在实验室实现。
    的头像 发表于 01-22 15:31 1837次阅读
    基于<b class='flag-5'>单片机</b>控制的交通灯设计

    AvR单片机1us延时函数数怎么

    在编写AvR单片机的1us延时函数之前,我们首先需要了解几个关键概念。 单片机的延时函数是通过控制器在特定的时间间隔内执行一系列的指令来实现的。在单片机中,我们通常使用定时器来实现延时功能。定时器
    的头像 发表于 12-26 14:02 1137次阅读

    单片机boot脚干嘛的

    单片机boot脚是单片机的引导脚,用于控制单片机的启动和引导过程。在单片机系统中,boot脚的作用十分重要,它影响着整个单片机的工作状态和功
    的头像 发表于 12-19 09:47 9506次阅读

    单片机如何检测电流?

    单片机如何检测电流? 随着科技的发展,单片机技术在电子设备中得到了广泛应用。其中,电流检测是单片机的一个重要功能之一。本文将详细介绍单片机电流检测技术的原理与应用,并着重探讨了A/D转
    的头像 发表于 12-07 15:37 3659次阅读

    单片机复位电路工作原理

    单片机复位电路工作原理  单片机是一种集成电路,通常用于嵌入式系统中。单片机复位电路是单片机可靠工作的保证,它负责在出现故障或者异常情况时将单片机
    的头像 发表于 12-07 15:17 4100次阅读

    单片机的烧次数是不是无限的呢?单片机能烧录多少次?

    单片机的烧次数是不是无限的呢?单片机能烧录多少次? 单片机的烧次数是有限的,每款单片机都有一
    的头像 发表于 12-07 13:46 3854次阅读

    你用过哪些编程语言开发单片机

    C语言是最常用的一种用于单片机的开发语言,也是一种高级编程语言,具有较好的可移植性和可读性。对于单片机,通常使用嵌入式C来进行开发。 举例:用C语言一段STM32单片机点灯程序。
    发表于 12-04 10:18 1274次阅读