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

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

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

因此,除非特殊算法的需要,建议大家尽

量不要使用函数指针。

&O1540; 指针的类型修饰

前面介绍的指针定义都是最基本的形式。和普通变量一样,指针定义也可以在前面加上

特殊类型的修饰关键词,例如“persistent”、“volatile”等。考虑指针本身还要限定其作用域,

因此 PICC 中的指针定义初看起来显得有点复杂,但只要了解各部分的具体含义,理解一个

指针的实际用图就变得很直接。

㈠ 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;

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

就是指针变量自己。

11.6


PICC 中的子程序和函数

中档系列的 PIC 单片机程序空间有分页的概念,但用 C 语言编程时基本不用太多关心

代码的分页问题。因为所有函数或子程序调用时的页面设定(如果代码超过一个页面)都由

编译器自动生成的指令实现。

11.6.1 函数的代码长度限制

PICC 决定了 C 原程序中的一个函数经编译后生成的机器码一定会放在同一个程序页面

内。中档系列的 PIC 单片机其一个程序页面的长度是 2K 字,换句话说,用 C 语言编写的任

何一个函数最后生成的代码不能超过 2K 字。一个良好的程序设计应该有一个清晰的组织结

构,把不同的功能用不同的函数实现是最好的方法,因此一个函数 2K 字长的限制一般不会

对程序代码的编写产生太多影响。如果为实现特定的功能确实要连续编写很长的程序,这时

就必须把这些连续的代码拆分成若干函数,以保证每个函数最后编译出的代码不超过一个页

面空间。

11.6.2 调用层次的控制

中档系列 PIC 单片机的硬件堆栈深度为 8 级,考虑中断响应需占用一级堆栈,所

有函数调用嵌套的最大深度不要超过 7 级。编程员必须自己控制子程序调用时的嵌套深

度以符合这一限制要求。

PICC 在最后编译连接成功后可以生成一个连接定位映射文件(*.map),在此文件

中有详细的函数调用嵌套指示图“call graph”,建议大家要留意一下。其信息大致如下

(取自于一示范程序的编译结果):

Call graph:

*_main size 0,0 offset 0

_RightShift_C

* _Task size 0,1 offset 0

lwtoft

ftmul size 0,0 offset 0

ftunpack1

ftunpack2

ftadd size 0,0 offset 0

ftunpack1

ftunpack2

ftdenorm

例 11-4 C 函数调用层次图

上面所举的信息表明整个程序在正常调用子程序时嵌套最多为两级(没有考虑中断)。因为

main 函数不可能返回,故其不用计算在嵌套级数中。其中有些函数调用是编译代码时自动

加入的库函数,这些函数调用从 C 原程序中无法直接看出,但在此嵌套指示图上则一目了

然。

11.6.3 函数类型声明

PICC 在编译时将严格进行函数调用时的类型检查。一个良好的习惯是在编写程序代码

前先声明所有用到的函数类型。例如:

void Task(void);

unsigned char Temperature(void);

void BIN2BCD(unsigned char);

void TimeDisplay(unsigned char, unsigned char);

这些类型声明确定了函数的入口参数和返回值类型,这样编译器在编译代码时就能保证生成

正确的机器码。笔者在实际工作中有时碰到一些用户声称发现 C 编译器生成了错误的代码,

最后

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

网站地图

Top