资讯详情

c语言指针用法及实际应用详解,通俗易懂超详细

c详细说明语言指针的用法和实际应用,通俗易懂,超详细!

\\\插播:文末有惊喜~///

今天给大家讲解一下指针。

我会从浅到深,最后结合实际应用讲解,让大家学会指针,知道老板用指针做什么!

长文预警!全文5200字左右,学指针看这篇文章就够了!

像我刚学习C语言一样,很多人害怕指针。

后来做了一些物联网网关才知道,指针是c语言的灵魂,这句话的真谛。

没有指针,实现很多功能真的很不方便,如果不能真正模块化编程。

Ok,废话不多说,下面正式进入主题。

一、通过本文可以掌握以下知识:

指针的相关概念

掌握指针与数组的关系

00003.掌握指针指向的指针

掌握如何使用指针变量作为函数参数

掌握如何使用指针函数

0006.掌握如何使用数组指针函数

所以这篇文章对应于视频教程。如果你不喜欢看文章,你可以看视频。教程可以在小破站搜索无尽的单片机编程,也可以找到我们。

二、指针的作用:

指针是C语言中更重要的东西。有人说指针是C语言的灵魂。

如果系统地动态分配内存、音频机制、任务调度、灵敏矩阵定时等,正确灵敏地使用它可以有效地表达一些复杂的数据结构。

掌握指针可以使你的程序更简洁、紧凑、高效。

所以在单片机领域,如果是稍大一点的项目,每个功能都必须模块化,硬件驱动层和应用层分别独立运行。

即使更换单片机型号,也不需要修改应用层程序,即移植性很强,离不开指针。

即使没有指针,也很难实现代码的可移植性也很差。

三、指针的概念

前面讲了指针的作用,这里再强调一点,指针是一把双刃剑。

充分利用可以非常敏感,提高程序效率,但如果使用不当,就会出现程序死机等致命问题。

这些问题通常是由错误使用指针引起的,最常见的是内存溢出错误,指针指向未知地址。

1.地址和指针

指针是一个抽象的概念。如果你想真正理解指针,你应该从如何存储数据开始。让我们通过一张图片来看看存储在内存中的数据。

在这张图中,它们都以16进制显示。

红色标注的0x0000400代表地址内存地址,绿色3730代表数据,橙色标记00 01代表地址增量,即0x00000400和0x每个地址存储一个字节数据。

然后我们把这张图作为内存中数据的存储形式,0x内存地址存储数据37,00000400x存储数据30的0000401。

当我们在程序中定义字节变量时,我们将在编译器编译时分配这样的内存地址进行存储。

假设我们定义以下变量

unsigned char a;

a = 0x37;

相应的图片是,编译器将为变量a分配一个字节的内存空间,并在编译过程中使用0x37存储数据,将变量名a改为地址0x00000400,以便CPU的访问。

变量a数据的存储位置可以通过该地址找到,该地址0x0000400实际上是指针,它可以访问变量a的数据。

2.指针变量

通过以上解释,我们了解到可以通过地址访问内存的数据。这个地址是指针。

所以指针和指针变量是不同的概念,我们必须记住。

指针是概念和指针变量的详细应用之一。让我们来看看如何在C语言中定义指针变量。

指针变量定义的一般形式:

变量类型*变量名

unsigned char *p;

通过这种语法,我们可以定义指针变量p。

指针变量赋值

指针和指针变量是两个概念,指针变量和普通变量一样,在使用前必须定义和赋值(指向地址)。

给指针变量赋值不同于普通变量,给指针变量赋值只能给地址,不能给其他任何值,否则会造成错误。

那么如何获得普通变量的地址,可以用C语言&获取普通变量的地址通常用以下格式表示:

&变量名

那么通过&在获得变量地址后,变量名可以赋值指针变量。

举例:

unsigned char a;

unsigned char *p

int main()

{

p = &a;}

在这个代码中,我们定义了一个变量a,定义指针变量p。

我们通过运算符&将变量a的内存地址赋值给变量p,因此,p指向变量a的存储地址。

上面提到了指针变量赋值的问题,那么如何获取和改变指针变量指向内存地址的数据呢?我们可以通过:

*指针变量 =数值

如:*p = 10;

这种操作可以改变指针变量指向内存地址的数据。

通过:

a = *p;

获取指针变量指向内存地址的数据。

我们以代码实验为例。

在这里,我们定义了变量a和指针变量p,然后a的值初始化为10。

将a的地址赋值给指针变量p,然后我们输出a的地址是0x60ff33。

因为我们之前给指针变量赋值了a的地址p,所以p指向的地址也是0x60ff33。

那么我们再来看一下,指针变量的在内存里的存储地址是0x60ff2c。

所以大家这里要注意了,我们定义指针变量时,即便指针变量是指向地址用的,但是编译器也会分配一块内存地址来存储指针变量。

我们接着来看下变量a的输出值。

a=10, *p是获取指针指向内存地址的数据,所以也是10。

下面就是通过指针变量来变更变量a的值,由于指针变量p指向的是变量a的地址,所以变更指针变量p指向内存地址的数据就能够变更变量a的值。

那么通过这么原理,我们是不是不用指针变量,也不用a即是多少来变更a的值呢?当然能够!

我们看下面通过内存地址变更变量a的值,我们前面知道a的地址是0x60ff33,那我们能够直接写0x60ff33=12来变更变量a的值。

当然这里要注意,编译器编译时并不知道0x60ff33是什么东西,所以要把这个整形地址转换成指针类型。

最后通过*+地址语法变更这个地址里面的数据。

我们看输出结果,能够发现a的值已经成功被改成了12。

其实通过指针变量变更某个内存地址的数据就是这个原理,但是指针变量益处能够任意起名字。

也不用像这样先把变量a的地址读出来,然后通过地址去变更它的值,用起来就很方便,所以通过指针变量来替代了这种做法。

四、数组与指针

一般系统或编译器会分配不间断地址的内存来存储数组里的元素,假如把数组地址赋值给指针变量,那么就能够通过指针变量来引用数组,读写数组里的元素了。我们来做个实验:

从这个代码来看,定义了一个数组buff并初始化为1,2,3,4,5。

定义了2个指针变量p1和p1,分别指向buff, &buff[0]。

buff默认的是数组下标为0元素的存储地址。

所以这里buff和&buff[0]是同一个内存地址,只是写法不一样。

我们从输出结果能够看的出来,数组和指针变量的地址都是一样的,所以大家用这几种写法都是能够的。

那么我们来看下输出结果,都是1,说明操作是对的。

指针自加自减运算

指针变量除了能够用来获取内存地址的值以外,还能够用来进行加减运算。

但是这个加减呢跟普通变量加减不一样,普通变量加减的是数值,而指针变量加减的是地址,我们来通过代码来讲解下。

同样这里定义了数组buff并初始化为1,2,3,4,5。

我们把指针变量p1指向数组第一个元素的地址,即0x402000。

然后我们直接看p1++的操作,p1++后我们看到p=0x402001,所以指针变量的加减等运算是指向地址的运算。

其他减法乘除法也是基于地址的运算。

如何攻克单片机下载程序失败的问题

作为一个单片机开发人员,每天跟我们打交道的工具没非两种,一种是PC机上的开发环境,假如Keil MDK、IAR Embedded Workbench等等;而另外一种呢,没非就是集程序下载、调试功能于一体的编程器、这个叫法比较混乱、也能够叫编程器、下载器、仿真器(但我认为不叫烧录器,烧录器一般值批量烧录阶段所用的那种能够快捷完成芯片批量烧录的玩意)。后文统称编程器。

常见的编程器有以下几种:

1、自然是老牌Jlink了;

其实拆开市面上常见的jlink,能够看到各种各样的板子:

这都是从某宝上买的,标注着正版、永不掉固件的jlink,这样的东西在我手里坏了2个,一初始我还有毅力去找个XP系统刷一下固件,但是刷了没几天就又坏了,而且身边的XP是越来越少了,想着再买一个也才几十块,完全没必要浪费这个时长去刷了。当然很多人喜爱动手挑战一下,但是当你的项目忙的不可开交,而这个时候你的编程器固件掉了,你还要跑去找个XP给他刷固件,想想都不爽。

有朋友告诉我,自己经常要去其他城市出差,调试自己的板子,SEGGER的原版太贵,只好从某宝买几十块的用,而且买一个又担忧坏了耽搁事,所以每次出差至少都带两个,然而这个硕大的体积是在让人不爽,出差的时候要在极其宝贵的行李空间里放两个jlink,也是够了。

也有人埋怨,jlink的接口太不方便了,虽然大多数时候调试的时候,只用了四五根杜邦线截出来,然而他的接口却保留了20脚,其中有一整排除了一个脚全是GND了。做个板子,入股只留几个排针,那样不好插线调试,假如想留一个和jlink一样的接口,又觉得会显得板子笨重,而且在一些对尺寸有严格要求的产品里,压根没有空间放下这个20脚的接口。

这时候有人提出了攻克方案,也就是下文的第二种编程器:

2、ST-LINK

可是仔细看看这个并没有攻克JLINK的一些缺少点,接口还是笨,体积还是不小。那么万能的某宝上还有一种攻克方案;

各种各样的颜色,而且价格比较便宜,十五块左右就能搞到,尝鲜买个试试,发现挺好用。和优盘一样大小的身板,出差带着也方便。但是某一天它忽然不工作了,插上之后电脑没有人任何反应,我经过一系列的诊断,最后怀着沉重的心情给它下了死亡通知书。

然后再去买下载器,我又不想买太贵的,又想买个小体积的,想来想去,最终一次买了三四个这种小的STLINK,我知道他会坏,但是一次买好几个就不怕他坏了,而且好几个的价格也就是一个某版的jlink价格。

接下来没意发现了淘宝上有一款叫做elink的玩意:

3、elink32-pro

这个东西看起来很棒,由于它集成了串口调试,而且貌似速度很快,正好我和合泰半导体这个公司有业务往来,就请合泰的相关负责人寄我一个样品试用,试用效果很棒,唯二的缺少点就是体积太大(和jlink差不多)、价格太贵。

那么有没有可能和合泰达成一个协议,共有作出一款合乎以下需求的编程器(下载器、仿真器、调试器)呢?

a、能支持简直所有32位ARM-CortexM内核单片机

b、小巧便携

c、不掉固件

d、去掉多余接口,只保留swd

e、增加虚拟串口功能

f、可对外供电、电流过大自动切断

g、低老本,大多数人买得起

h、没需驱动,即插即用

于是我和合泰的相关人员进行沟通(这个沟通大略是16年10月初始的)。

经过屡次沟通,最终确定:以elink32-pro为原型,去掉一些没用的东西、增加相关功能、由合泰半导体提供固件,我提供硬件及出产。

沟通中争议最多的一个问题是RST引脚是否保留。由于我们使用stlink,jlink等时经常会发生以下问题:

这个问题能够通过一下方式攻克:

但是还有很多问题是通过开发环境配置修改所不能攻克的,这时候就须要保留RST,然后把RST接在开发板上,就能完成下载,这个功能主要是波及以下几种使用场景:

1、swd引脚复用(例如STM32F103的PA13和PA14在程序中被设置为其他功能),这时候须要编程器能对开发板进行硬件复位。

2、芯片工作状态为低功耗或者睡眠模式,这时候须要编程器能对开发板进行硬件复位。

所以最终探讨结果是依照合泰半导体厂商提供的方案来,毕竟他们是半导体厂商,考虑问题很严谨、完善。

方案定稿之后,签订了软件使用合同与保密合同,接下来是合泰提供带固件的芯片,我来做整体设计并完成PCB设计、焊接调试等详细的工作。经过一个月的时长、出了几个样品,经过测试发现使用不顺手,等各种问题。假如第一次构思的是直接在板子上加一个usb公头,然后就能够插在电脑上了,但是后续使用发现,这样不是很方便,由于这样的话就会导致宗旨板距离电脑独有杜邦线长度的距离,假如杜邦线太短,挪动不太方便,甚至此时有些电脑的USB口在后面,这样不方便用户下载程序后观察现象。而杜邦线太长则会不稳定,很多情况下,程序没法下载是与杜邦线连接不稳定有关系的(在使用优盘状的STLINK时,经常由于杜邦线太长或者接触不良导致下载失败,后来换成航空线直接焊接上去就能够下载,说明这种stlink的io口驱动才能欠佳)。

考虑以上的缺少点,我决定使用此时最常见的micro-USB线来连接e-Link32和PC机。于是经过改版,e-Link32变成了下面这样(手工焊接调试版):

其中白色的SH1.0端子和右侧的5P弯针都是SWD接口。为啥要增加一个SH1.0端子呢,由于在有些电路里,保留2.54的插针都是对空间的浪费,而且插针是要占用PCB的双面,对其他布线造成了影响。所以增加了SH1.0端子接口,以后大家做板也能够使用这样的端口、减小板子面积,方便调试。

这个版本e-Link32我赠送给五个人进行测试,大略是从16年12月份初始测试的、到17年8月份没有人任何问题,所以我才批量了1000个。选用的是最可靠的PCB提供商和贴片厂商,做出的板子如下:

一个产品必需有完善的文档。在量产的阶段我也进行了相关文档的编写

详细文档能够在淘宝宝贝详情下载。大略详细内容如下:

另外清晰的阐述了elink32如何连接开发板和电脑:

以及如何用elink32给带20脚jtag接口的开发板下载程序:

此时能够说完成了当时提出的这个需求,实现了具有以下功能的调试器:

经测试,可用于但不局限于以下芯片的调试:

STM32F0,STM32F1,STM32F2,STM32F3,STM32F4,STM32F7

STM32L0,STM32L4

LPC800XX,LPC1100XXX,LPC1200XXX,LPC1300XXX,LPC1500XXX,LPC1700XXX,LPC1800XXX,LPC4000XXX,LPC4300XXX,LPC5400XXX,

K60

HT32F16XX,HT32F52XXX

NV32F100XXX

EFM32XXX

W7500

列表有待完善。

有人提出了:带串口的东西其实早有了,那么你能够去看看,网络上也有很多教程教大家做这样的下载器的,我能够花一两天时长依据教程完成这么一个下载器,但我肯定没有勇气把他批量了放在市场上给大家用。一款工具性的东西须要经过长期的稳定性测试、还须要对加工工艺进行测试、这些流程都增加了产品的老本,但是却是保证用户买到有保证的产品的一个必需的投入。

兼容市面上绝大多数ARM Cortex-M系列单片机。

500ma3.3v对外供电电流,加自恢复二极管保驾护航。

半导体原厂提供固件与技术支持。

一个USB口完成下载调试串口通讯,一遍单步一遍查看串口数据,为你的电脑节省一个宝贵的USB口。

从16年测试,到17年初始量产,此时已经销售了3000多个了,经测试非常稳定。

01首先聊一聊大家都知道进行单片机编程和计算机编程有个最大的差别就是单片机的资源非常的有限,并且对于大局部低端单片机而言都没有操作系统。除了一些嵌入式级的芯片用了Linux系统外,?

彩蛋:最近有同学跟我要单片机的资料,我特意花几个月时间,总结了我10年产品研发经验,资料包几乎覆盖了C语言、单片机、模电数电、原理图和PCB设计、单片机高级编程等等,非常适合初学者入门和进阶。除此以外,再含泪分享我压箱底的22个热门开源项目,包含源码+原理图+PCB+说明文档,不是市面上打包卖的那种课程,我认为教程多未必是好事,10年前我自学快,除了自身执行力以外,还有就是教程少。不要害羞做伸手党,等你一个小红点。后期我也会组建一些纯技术交流的小圈子,让大家能认识更多的大佬,有个好的圈子,你对行业的认知一定是最前沿的。306b0d0694900702fd1a768fd9b9022e.png

标签: 二极管sp3100的参数11弯针连接器二极管efmht7327集成电路

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台