Keil C51中函数指针使用注意事项
c51指针用法

c51指针用法
C51是一种常用的单片机,使用指针可以更灵活地操作内存和外设。
在C51中,指针可以用于访问和操作内存中的数据,也可以用于操作外设寄存器。
首先,我们可以使用指针来访问和操作内存中的数据。
在C51中,内存被分为不同的存储区域,如代码区、数据区和堆栈区。
通过使用指针,我们可以直接访问和修改这些存储区域中的数据。
例如,我们可以使用指针来读取和修改数组中的元素,而不需要使用数组索引。
这种方法可以提高程序的执行效率。
其次,指针还可以用于操作外设寄存器。
在单片机编程中,外设寄存器用于控制和配置外部设备,如GPIO(通用输入输出)、定时器和串口等。
通过使用指针,我们可以直接访问和修改这些寄存器的值,从而控制外部设备的行为。
例如,我们可以使用指针来设置GPIO引脚的状态,或者配置定时器的工作模式。
除了访问和操作内存和外设寄存器,指针还可以用于动态内存分配和数据结构的操作。
在C51中,我们可以使用指针来动态分配内存,并在运行时根据需要分配和释放内存。
这种灵活的内存管理方式可以提高程序的效率和灵活性。
此外,指针还可以用于创建和操作复杂的数据结构,如链表和树等。
通过使用指针,我们可以方便地插入、删除
和修改数据结构中的元素。
总之,C51中的指针用法非常重要,可以帮助我们更灵活地操作内存和外设。
通过使用指针,我们可以提高程序的执行效率,实现动态内存分配,以及创建和操作复杂的数据结构。
因此,熟练掌握C51指针的用法对于单片机编程非常重要。
C51 指针问题

C51 指针问题一般指针一般指针的声明和使用均与标准C 相同,不过同时还可以说明指针的存储类型,例如:long * state;为一个指向long 型整数的指针,而state 本身则依存储模式存放。
char * xdata ptr;ptr 为一个指向char 数据的指针,而ptr本身放于外部RAM 区,以上的long,char 等指针指向的数据可存放于任何存储器中。
一般指针本身用3 个字节存放,分别为存储器类型,高位偏移,低位偏移量。
2.存储器指针基于存储器的指针说明时即指定了存贮类型,例如:chardata * str;str 指向data 区中char 型数据int xdata * pow; pow 指向外部RAM 的int 型整数。
这种指针存放时,只需一个字节或2 个字节就够了,因为只需存放偏移量。
/*.........................................................................................char * xdata ptr;//ptr 本身放在Xdata(XRAM)区char xdata * ptr;//ptr 指向的数据放在Xdata(XRAM)区........................................................................................*/char xdata * pxchar xdata * data pxdata char xdata * px 这3 者有什么不同??char xdata * pxpx 本身存在于自动分配的空间,一般位于data 中,指向的内容位于xdatachar xdata * data pxpx 本身存在于data 空间,指向的内容位于xdatadata char xdata * px =char xdata *data pxdata:固定指前面0x00-0x7f 的128 个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。
[计算机软件及应用]Keil C51软件使用说明
![[计算机软件及应用]Keil C51软件使用说明](https://img.taocdn.com/s3/m/be9215d4dbef5ef7ba0d4a7302768e9951e76ef9.png)
* ——表示是指针类型,此处*不含取内容之意;
数据类型——声明指针所指变量的类型;
[存储器类型1]——声明指针所指变量的存储类型,若默认则定义
为一般指针;
[存储器类型2]——声明该指针变量本身的存储类型;
标识符——声明指针变量本身的数据类型和名称.
22
MCS-51单片机原理、接口及应用
第6章 单片机的C51语言编程
6
MCS-51单片机原理、接口及应用
第6章 单片机的C51语言编程
6.1.2 C51中常用的头文件
reg51.h、reg52.h、math.h、ctype.h、stdio.h、stdlib.h、 absacc.h和intrins.h. 〔1〕reg51.h和reg52.h
〔定义51或52子系列单片机特殊功能寄存器和特殊位〕 reg52.h比reg51.h多了几行定义T2寄存器的内容.
第6章 单片机的C51语言编程
汇编语言:
优点:面向机器、目标代码短、占用存储器空间少、运行
快. 缺点:指令助记符多、编程灵活性差.
C语言: 优点:具有面向机器和面向用户的特点,良好的可读性﹑易
维护性和可移植性,对硬件的控制能力也很强, C语言的数据类 型及运算符丰富,具有良好的程序结构.
缺点:代码效率稍低〔同汇编语言相比〕,占用存储空间较 大. 解决方法:单片机内部都嵌入了大容量的Flash ROM,有效的 弥补了这个缺陷.
{
局部变量说明
执行语句〔包括子函数的调用语句〕
}
4
MCS-51单片机原理、接口及应用
第6章 单片机的C51语言编程
func1<形式参数及说明>
//子函数1
{ 局部变量说明
Keil C51使用详解

Keil C51使用详解keilc51使用详解v1.0电子设计世界!版权所有,热烈欢迎贴文,切勿修正并标明原文。
留存一切权利。
第一章keilc51开发系统基本知识 (6)1第一节系统概述 (6)第二节keilc51单片机软件开发系统的整体结构...6第三节keilc51工具包的加装...71.c51fordos72.c51forwindows的安装及注意事项:...7第四节keilc51工具包各部分功能及使用简介...71.c51与a51.72.l51和bl51.83.dscope51,tscope51及monitor51.84.ishell及uvision.9第二章keilc51软件使用详解 (10)第一节keilc51编译器的控制指令...101.源文件掌控类 (10)2.目标文件(object)控制类:...103.列表文件(listing)控制类:...10第二节dscope51的使用...111.dscope51fordos112.dscopeforwindows12第三节monitor51及其使用...131.monitor51对硬件的要求...132.mon51的使用...133.mon51的配置...134.串口连接图:...135.mon51命令及使用...14第四节集成开发环境(ide)的使用...141.ishellfordos的使用 (14)22.uvisionforwindows的使用 (15)第三章keilc51vs标准c..15第一节keilc51扩展关键字...15第二节内存区域(memoryareas):...161.pragramarea:...162.internaldatamemory:163.externaldatam emory.162.可位串行区表明20h-2fh..18第七节keilc51指针...181.通常指针...182.存储器指针...183.指针切换...18第八节keilc51函数...191.中断函数声明:...192.通用型存储工作区 (19)3.选通用存储工作区由usingx声明,见上例。
关于Keil C51指针的使用

关于KeilC51指针的使用(参见page106-113,keiluv2user'sguide09,2001)Keil中的指针分为两种:一种是普通指针,兼容标准C语言的指针;另一种我翻译成内存特殊指针(memory-specific pointers,翻译得不好:>)一.普通指针普通指针的定义方式如下:char * ptr;跟标准C的定义方式一样。
这种指针占三个字节,第一个字节是标识存储类型,是指针指向的变量的数据类型;第二个字节是指针存储地址的高位字节;第三个字节是指针存储地址的低位字节。
普通指针默认存储在内部存储器data,即片上RAM,如果想指定指针的存储位置,可以在*后加上存储类型,如下面几种定义方式:char * data ptr; //与char * ptr;等价,即默认的定义方式char * xdata ptr; //指针存储在片外RAMchar * idata ptr; //指针存储在idatachar * pdata ptr; //指针存储在pdata由定义普通指针写的程序最终代码比较长,运行速度相对较慢,因为Keil 在编译的时候不知道这个指针将要指向的变量的存储位置,只有当程序执行的时候才能知道,所以编译器不能对这段代码进行优化,不过,这样做的优点是此指针可以指向存储在任何位置的变量。
二.内存特殊指针内存特殊指针的定义方式为:char xdata * ptr;这个指针存储的时候占的字节数是不一定的,占一个字节的变量类型为:idata,data, pdata, bdata;占两个字节的变量类型为:code,xdata。
注意:char xdata * ptr;这里定义的ptr所指向的变量存储在xdata中,即外部变量,这样的话指针变量ptr占两个字节,我们再定义一个外部变量。
char xdata variable1;ptr=&variable1; //这样是正确的这段程序中,变量variable1存储在外部存储器中,是最合适的。
keil c51函数指针

Keil C51 中的函数指针和再入函数,函数指针与overlay=====调用树的保存C51不把函数参数压栈(除非使用再入函数)。
函数参数和全局变量被存入寄存器或固定的存储空间。
这样阻止函数的再入。
例如,一个函数调用它自己,它将覆盖它自己的参数或存储空间。
函数的再入问题通过关键字“reentrant”来解决。
函数指针的非再入函数的副作用,在执行中出现问题。
MAIN函数调用FUNC和FUNC_CALLER(根据调用树)。
用函数的指针来传递参数,调用树往往会出错。
=====转这篇文章是由Keil C51 的英文文档翻译过来的,很多语句都是根据自己的理解翻译的,肯定还有许多地方需要推敲。
希望读者能吸取到有用的部分,不要被误解了,自己多理解。
Overlay修改用于数据覆盖的调用树。
如果在用户程序里使用了函数指针,或者使用了像实时操作系统中调度器那样的跳转(k 指的是指针方式的调用吗?),那么,修改程序调用树将是很有必要的。
混合编程:函数名符号名解释viod func(void) FUNC 无参数传递,或不含寄存器参数的函数名不作改变转入目标文件中,名字只是简单地转为大写形式viod func(char) _FUNC 带寄存器参数的函数名加入“_”字符前缀,它表明这类函数包含寄存器内的参数传递viod func(viod) reentrant _?FUNC “_?”表示可重入,它表明该行数包含栈内的参数传递。
====将下面这篇的难点内容提到前面使用函数指针的附加说明如果你在C51中使用函数指针编程,有几个附加的说明你必须注意。
参数列表的限制通过函数指针传递参数给函数必须把所有的参数存入寄存器。
在大部分情况下,3个参数能够自动通过寄存器传递。
在C51的用户手册中能找到传递参数进入寄存器的运算法则。
但是并不保证,任何的3个数据类型可以传递。
因为C51在寄存器中传递3个参数,用于传递参数的存储空间是不被分配的,除非函数指向一个要求更多参数的函数。
C51语言的指针详解

单片机接口技术(C51版)第五章指针、结构、联合和枚举内容概述指针是C51语言的精华也是难点。
本章主要介绍指针的概念、定义指针的方法,介绍指向一维数组、二维数组、字符数组的指针使用方法,指针数组的概念以及指针作为函数参数的使用方法。
结构、联合和枚举是另外的构造型数据,本章介绍了这三种类型数据的定义、初始化以及使用方法。
教学目标1.理解指针的概念,掌握指针与地址的关系,能区别指针变量与变量的指针,根据需要定义并使用指针变量,理解地址运算的方法。
2.理解指针与数组的关系,熟练使用指针指向一维数组、二维数组,理解并掌握利用指针表达数组元素的几种表现形式。
3. 能利用指针指向字符数组,处理字符串。
4.理解指针数组的概念,该数组的元素是指针。
5.掌握指针作为函数形参的使用方法,理解指针作为函数形参传递整个数组的作用。
6.了解结构体的作用及应用场合,能定义并使用结构体变量,掌握结构变量成员的引用方法。
能定义并使用结构数组,会引用结构数组元素成员,7.掌握结构指针的定义方法,利用结构指针访问结构变量的成员。
8. 了解结构变量的作为结构成员的结构嵌套定义方法以及位结构的概念。
9. 理解联合的概念,能定义并使用联合体变量,掌握联合与结构的区别。
10. 能定义并使用枚举变量。
5.1指针5.1.1 指针和地址5.1.1.1 指针变量的定义⏹C51语言中, 对于变量的访问形式之一, 就是先求出变量的地址,然后再通过地址对它进行访问, 这就是这里所要论述的指针及其指针变量。
⏹所谓变量的指针, 实际上指变量的地址⏹变量的地址虽然在形式上好象类似于整数, 但在概念上不同于以前介绍过的整数, 它属于一种新的数据类型, 即指针类型。
⏹C51中, 一般用“指针”来指明这样一个表达式&x的类型,而用“地址”作为它的值, 也就是说, 若x为一整型变量, 则表达式&x的类型是指向整数的指针, 而它的值是变量x的地址。
⏹同样, 若double d;则&d的类型是指向双精度数d的指针, 而&d的值是双精度变量d的地址。
KeilC51中函数指针的使用

Keil C51中函数指针的使用3■江西理工大学 朱博 许伦辉 函数指针在C语言中应用较为灵活。
在单片机系统中,嵌入式操作系统、文件系统和网络协议栈等一些较为复杂的应用都大量地使用了函数指针。
K eil公司推出的C51编译器是事实上80C51C编程的工业标准,它针对8051系列CPU硬件在标准ANSI C的基础上进行了扩展;但由于编译器及8051体系结构的限制,造成了在使用函数指针时有很多与ANSI C不同的地方。
下面举例说明在不同的情形下函数指针的使用。
以下代码均在K eilμVision3、v8.08 C51、默认优化等级的开发环境下验证通过。
1 指向固定地址的指针在程序设计中,常需要跳转到某一特定的地址上执行,如引导程序的设计。
可通过如下C语言实现: int main(void){((void(code3)(void))0x2000)();return0;}此代码使得主函数执行位于0x2000地址的程序代码。
其中((void(code3)(void))是一种数据类型,表示一指向代码段函数的指针,该函数无参数和无返回值。
它对数据0x2000进行了强制类型转换,使函数指针指向地址为0x2000的代码段地址。
关于复杂类型的声明详见参考文献[1]。
通过反汇编窗口可看到编译器生成了如下汇编代码: C:0x000F 122000 LCALL C:2000由上可以看出,Keil C51是非常高效的编译器,产生了非常简洁的输出。
这正是我们所期望的。
2 无参数的函数指针Keil C51中不带参数的函数指针的使用方法与ANSI3国家自然科学基金项目(No:60664001):基于分布式多智能体的城市交通协调控制理论及应用研究。
C基本相同。
示例如下: void foo(void){ return;}int main(void){ void(3pfoo)(void);//声明函数指针pfoo pfoo=foo;//对该指针赋值,使该指针指向某一函数 (3pfoo)();//通过指针调用其指向的函数 return0;}3 带参数的函数指针一般来说,函数参数是通过堆栈来传递,用PUSH和POP汇编指令来实现的;但由于8051体系及其编译器的一些限制,使得其函数参数的传递需要一些特殊的方法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Keil C51中函数指针使用注意事项
在我们的代码中大量使用了函数指针。
当函数指针用在Keil C51中时,一定要注意编译器自动生成的函数调用树通常是不正确的,需要手动调整。
否则可能造成无法预知的后果。
这是因为,Keil C51编译器并不把函数参数和局部变量压入堆栈中,而是放在寄存器或固定的内存位置。
C51的编译器监视函数调用的嵌套顺序,把几个函数的变量放在同样固定的位置。
在C51编译器中连接器会搜索所有函数中变量占用存储区间最多的函数,然后以这个函数的变量的占用空间开辟一片空间,其他函数的变量也放在该空间中,同时实现了变量的覆盖(无相互调用)与地址的共享。
例如函数A占10个字节,函数B占20个字节,函数C占15个字节,如果它们之间没有相互调用则仅需20个字节就可以满足45个字节的变量需要。
正是由于所有函数的参数和局部变量的共享一个覆盖区,函数没有相互的调用时,在执行一个函数时,会将另一个函数的变量的存储区覆盖。
如果函数有调用,那么不会覆盖原来函数的局部变量的区间。
调用树(call tree)是由Keil链接器自动生成的,用于描述函数的调用关系(调用树可通过编译生成的*.M51文件的OVERLAY MAP OF MODULE部分查看,该部分详细的说明了函数的调用关系以及对覆盖存储区的使用情况)。
链接器通过分析调用树来确定哪些寄存器或内存位置是可安全覆盖的。
这样两个不同时调用的函数就可以共享同一块内存用于传递参数和存储局部变量。
但对于函数指针来说,编译器并不知道函数指针将指向哪个函数。
这导致了调用树构造出错的可能,函数的参数和局部变量也可能被错误覆盖(例如,函数A通过函数指针调用了函数B,但编译器并不知道它们之间存在调用关系,所以认为它们是可以共享同一块内存的。
这样当函数A调用了函数B,回到函数A后,函数A的参数和局部变量可能已经被改变了,再往下运行就出错了)。
对此,Keil提供了链接器OVERLAY伪指令,可让用户自行修改调用树,调整函数的调用关系。
删除调用关系,命令格式:
OVERLAY (sfname-caller ~ sfname-callee)
OVERLAY (sfname-caller ~ (sfname-callee, sfname-callee))
举例:OVERLAY(?PR?_FUNC?DMAIN ~ (?PR?_FUNC_A?DMAIN,?PR?_FUNC_B?DMAIN)) 意思是从FUNC函数中删除对FUNC_A和FUNC_B的调用。
添加调用关系,命令格式:
OVERLAY (sfname-caller ! sfname-callee)
OVERLAY (sfname-caller ! (sfname-callee, sfname-callee))
举例:OVERLAY(?PR?_MAIN?DMAIN ! (?PR?_FUNC_A?DMAIN,?PR?_FUNC_B?DMAIN)) 意思是添加FUNC函数对FUNC_A和FUNC_B的调用。
可在链接命令行输入命令。
或在Keil集成开发环境中,在“BL51 Misc”-“Overlay”中填入()中的内容。