PICC编译指针详解

2020-02-14来源: eefocus关键字:PICC  编译指针  指针寻址

指向 RAM 的指针


如果是汇编语言编程,实现指针寻址的方法肯定就是用 FSR 寄存器,PICC 也不例外。www.1720.com_【官方首页】-澳门美高梅为了生成高效的代码,PICC 在编译C原程序时将指向 RAM 的指针操作最终用 FSR 来实现间接寻址。这样就势必产生一个问题:FSR 能够直接连续寻址的范围是 256 字节(bank0/1或 bank2/3),要覆盖最大 512 字节的内部数据存储空间,又该如何让定义指针?PICC 还是将这一问题留给编程员自己解决:在定义指针时必须明确指定该指针所适用的寻址区域,例如:

unsigned char *ptr0; //①定义覆盖bank0/1的指针

bank2 unsigned char *ptr1; //②定义覆盖bank2/3的指针

bank3 unsigned char *ptr2; //③定义覆盖bank2/3的指针

上面定义了三个指针变量,其中①指针没有任何 bank 限定,缺省就是指向 bank0和 bank1;②和③一个指明了 bank2,另一个指明了 bank3,但实际上两者是一样的,因为一个指针可以同时覆盖两个 bank 的存储区域。另外,上面三个指针变量自身都存放在 bank0 中。我们将在稍后介绍如何在其它 bank 中存放指针变量。


指向函数的指针

单片机编程时函数指针的应用相对较少,但作为标准 C 语法的一部分,PICC 同样支持函数指针调用。如果你对编译原理有一定的了解,就应该明白在 PIC 单片机这一特定的架构上实现函数指针调用的效率是不高的:PICC 将在 RAM 中建立一个调用返回表,真正的调用和返回过程是靠直接修改 PC 指针来实现的。www.1720.com_【官方首页】-澳门美高梅因此,除非特殊算法的需要,建议大家尽量不要使用函数指针。


bank 修饰词的位置含义

前面介绍的一些指针有的作用于 bank0/1,有的作用于 bank2/3,但它们本身的存放位置全部在 bank0。显然,在一个程序设计中指针变量将有可能被定位在任何可用的地址空间,这时,bank修饰词出现的位置就是一个关键,看下面的例子:

//定义指向bank0/1的指针,指针变量为于bank0 中

unsigned char *ptr0;

//定义指向bank2/3的指针,指针变量为于bank0 中

bank2 unsigned char *ptr0;

//定义指向bank2/3的指针,指针变量为于bank1 中

bank2 unsigned char * bank1 ptr0;

从中可以看出规律:前面的 bank 修饰词指明了此指针的作用域;后面的 bank 修饰词定义了此指针变量自身的存放位置。只要掌握了这一法则,你就可以定义任何作用域的指针且可以将指针变量放于任何 bank中。


volatile、persistent 和 const 修饰词的位置含义 如果能理解上面介绍的 bank 修饰词的位置含义,实际上 volatile、persistent 和 const 这些关键词出现在前后不同位置上的含义规律是和 bank 一词相一致的。例如:

//定义指向bank0/1易变型字符变量的指针,指针变量位于bank0中且自身为非易变型

volatile unsigned char *ptr0;

//定义指向bank2/3非易变型字符变量的指针,指针变量位于bank1 中且自身为易变型

bank2 unsigned char * volatile bank1 ptr0;

//定义指向ROM 区的指针,指针变量本身也是存放于ROM区的常数

const unsigned char * const ptr0;

亦即出现在前面的修饰词其作用对象是指针所指处的变量;出现在后面的修饰词其作用对象就是指针变量自己。


既然定义的指针有明确的 bank 适用区域,在对指针变量赋值时就必须实现类型匹配,下面的指针赋值将产生一个致命错误:

unsigned char *ptr0; //定义指向bank0/1的指针

bank2 unsigned char buff[8]; //定义bank2中的一个缓冲区

程序语句:

ptr0 = buff; //错误!试图将bank2内的变量地址赋给指向bank0/1的指针

若出现此类错误的指针操作,PICC 在最后连接时会告知类似于下面的信息:

Fixup oveRFlow in expression (...)


同样的道理,若函数调用时用了指针作为传递参数,也必须注意 bank 作用域的匹配,而这点往往容易被忽视。假定有下面的函数实现发送一个字符串的功能:

void SendMessage(unsigned char *);

那么被发送的字符串必须位于 bank0 或bank1 中。如果你还要发送位于 bank2或 bank3内的

字符串,必须再另外单独写一个函数:

void SendMessage_2(bank2 unsigned char *);

这两个函数从内部代码的实现来看可以一模一样,但传递的参数类型不同。


按笔者的应用经验体会,如果你看到了“Fixup overflow”的错误指示,几乎可以肯定是指针类型不匹配的赋值所至。请重点检查程序中有关指针的操作

关键字:PICC  编译指针  指针寻址 编辑:什么鱼 引用地址:http://news.0830abc.com/mcu/ic488245.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:PICC ---- 函数
下一篇:PICC——基本知识(变量)

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

PICC环境写PIC单片机程序的探讨
简介:一般C语言产生的代码是比较繁琐的,所以要写出高质量、实用的C语言程序,就必须对单片机体系结构和硬件资源作详尽的了解.目前,Microchip公司生产的PIC系列单片机以其低成本、低功耗、高性能、开发速度快且一次性用户可编程等优点迅速占领了国内市场,成为国内销售量最大的单片机.但国内介绍其C语言开发工具的书籍和文章却比较少,在开发过程中给广大程序员带来了许多困难和不便.Microchip公司没有针对中低档系列PIC单片机的C语言编译器,但很多专业的第三方公司提供众多支持PIC单片机的C语言编译器,常见的有Hitech、CCS、IAR以及Bytecraft等公司.Hitech公司的PICC编译器稳定可靠,编译生成的代码效率高
发表于 2020-02-18
PICC ME16 C简要说明书
www.1720.com_【官方首页】-澳门美高梅第一部分为了对PIC单片机有更好的支持,PICC在标准C的基础上作了一些扩充:定义I/O函数,以便在你的硬件系统中使用中定义的函数。用C语言编写中断服务程序用C语言编写I/O操作程序C语言与汇编语言间的接口1-1 与标准C的不同PICC只在一处与标准C不同:函数的重入。因为PIC单片机的寄存器及堆栈有限,所以PICC不支持可重入函数。1-2 支持的PIC芯片PICC 支持很多PIC单片机,支持PIC单片机的类型在LIB目录下的picinfo.ini 文件中有定义。1-3 PICC 包含一些标准库1-4 PICC 编译器可以输出一些格式的目标文件,缺省设置为输出Bytecraft的'COD' 格式和 Intel
发表于 2020-02-14
PICC——嵌入汇编
的方法在 C 原程序中直接嵌入汇编指令是最直接最容易的方法。如果只需要嵌入少量几条的汇编指令,PICC 提供了一个类似于函数的语句:asm("clrwdt")双引号中可以编写任何一条 PIC 的标准汇编指令。例如:for (;;) {asm("clrwdt"); //清看门狗Task();ClockRun();asm("sleep"); //休眠asm("nop"); //空操作延时}如果需要编写一段连续的汇编指令,PICC 支持另外一种语法描述:用“#asm”开始汇编指令段,用“#endasm”结束。例如下面的一段嵌入汇编指令实现了将 0x20~0x7F 间的
发表于 2020-02-14
PICC——基本知识(变量)
www.1720.com_【官方首页】-澳门美高梅利用这一技术后所有的动态局部变量都可以按已知的固定地址地进行直接寻址,用 PIC 汇编指令实现的效率最高,但这时不能出现函数递归调用。PICC 在编译时会严格检查递归调用的问题并认为这是一个严重错误而立即终止编译过程。为了使编译器产生最高效的机器码,PICC 把单片机中数据寄存器的 bank问题交由编程员自己管理,因此在定义用户变量时你必须自己决定这些变量具体放在哪一个 bank 中。如果没有特别指明,所定义的变量将被定位在 bank0,除了 bank0 内的变量声明时不需特殊处理外,定义在其它 bank 内的变量前面必须加上相应的 bank序号中档系列 PIC 单片机数据寄存器的一个 bank 大小为 128 字节,刨去前面若干
发表于 2020-02-14
PICC ---- 函数
简介:一个良好的程序设计应该有一个清晰的组织结构,把不同的功能用不同的函数实现是最好的方法,因此一个函数 2K字长的限制一般不会对程序代码的编写产生太多影响。函数的代码长度限制PICC决定了C原程序中的一个函数经编译后生成的机器码一定会放在同一个程序页面内。中档系列的 PIC 单片机其一个程序页面的长度是 2K字,换句话说,用 C 语言编写的任何一个函数最后生成的代码不能超过 2K字。一个良好的程序设计应该有一个清晰的组织结构,把不同的功能用不同的函数实现是最好的方法,因此一个函数 2K字长的限制一般不会对程序代码的编写产生太多影响。如果为实现特定的功能确实要连续编写很长的程序,这时就必须把这些连续的代码拆分成若干函数,以保证每个
发表于 2020-02-13
C51编译器-语言扩展(3)-指针
可以访问所有的内存区域 注意:使用通用指针产生的代码比用特定存储器类型指针生成的代码执效率要低得多。这是因为在运行前变量的内存区域是不知道的。编译器不能优化存储器的访问,而是要生成适合所有存域的代码。如果要获得高的运行速度,最好使用特定存储器类型指针。 为运行速度考虑,也可以设定指针的存储区,在声明指针时前面加上储存区类型标识就可以把指针放在特定的存储器区域。 char * xdata strptr; /* generic ptr stored in xdata */ int * data numptr; /* generic ptr stored in data */ long * idata varptr
发表于 2016-11-14
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 0830abc.com, Inc. All rights reserved

页面底部区域 foot.htm