微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > PIC 单片机 C 语言编程简介(2)

PIC 单片机 C 语言编程简介(2)

时间:11-22 来源:互联网 点击:

多的实际意义,相信大家在实际编

程时不会大量用到。

&O1540; persistent 非初始化变量声明

按照标准 C 语言的做法,程序在开始运行前首先要把所有定义的但没有预置初值的变

量全部清零。PICC 会在最后生成的机器码中加入一小段初始化代码来实现这一变量清零操

作,且这一操作将在 main 函数被调用之前执行。问题是作为一个单片机的控制系统有很多

变量是不允许在程序复位后被清零的。为了达到这一目的,PICC 提供了“persistent”修饰

词以声明此类变量无需在复位时自动清零,编程员应该自己决定程序中的那些变量是必须声

明成“persisten”类型,而且须自己判断什么时候需要对其进行初始化赋值。例如:

persistent unsigned char hour,minute,second; //定义时分秒变量

经常用到的是如果程序经上电复位后开始运行,那么需要将 persistent 型的变量初始化,

如果是其它形式的复位,例如看门狗引发的复位,则无需对 persistent 型变量作任何修改。

PIC 单片机内提供了各种复位的判别标志,用户程序可依具体设计灵活处理不同的复位情

形。

11.5.9 PICC 中的指针

PICC 中指针的基本概念和标准 C 语法没有太多的差别。但是在 PIC 单片机这一特定的

架构上,指针的定义方式还是有几点需要特别注意。

&O1540; 指向 RAM 的指针

如果是汇编语言编程,实现指针寻址的方法肯定就是用 FSR 寄存器,PICC 也不例外。

为了生成高效的代码,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 中存放指针变量。

既然定义的指针有明确的 bank 适用区域,在对指针变量赋值时就必须实现类型匹配,

下面的指针赋值将产生一个致命错误:


unsigned char *ptr0;

bank2 unsigned char buff[8];

程序语句:


//定义指向 bank0/1 的指针

//定义 bank2 中的一个缓冲区


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

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

Fixup overflow in expression_r(...)

同样的道理,若函数调用时用了指针作为传递参数,也必须注意 bank 作用域的匹配,

而这点往往容易被忽视。假定有下面的函数实现发送一个字符串的功能:

void SendMessage(unsigned char *);

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

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

void SendMessage_2(bank2 unsigned char *);

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

按笔者的应用经验体会,如果你看到了“Fixup overflow”的错误指示,几乎可以肯定

是指针类型不匹配的赋值所至。请重点检查程序中有关指针的操作。

&O1540; 指向 ROM 常数的指针

如果一组变量是已经被定义在 ROM 区的常数,那么指向它的指针可以这样定义:


const unsigned char company[]=”Microchip”;

const unsigned char *romPtr;

程序中可以对上面的指针变量赋值和实现取数操作:

romPtr = company; //指针赋初值

data = *romPtr++; //取指针指向的一个数,然后指针加 1


//定义 ROM 中的常数

//定义指向 ROM 的指针


反过来,下面的操作将是一个错误,因为该指针指向的是常数型变量,不能赋值。

*romPtr = data; //往指针指向的地址写一个数

&O1540; 指向函数的指针

单片机编程时函数指针的应用相对较少,但作为标准 C 语法的一部分,PICC 同样支持

函数指针调用。如果你对编译原理有一定的了解,就应该明白在 PIC 单片机这一特定的架

构上实现函数指针调用的效率是不高的:PICC 将在 RAM 中建立一个调用返回表,真正的

调用和返回过程是靠直接修改 PC 指针来实现的。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top