bank1c语言啥作用,PIC 单片机 C 语言编程简介(2)

量不要使用函数指针。

&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 编译器生成了错误的代码,

最后究其原因就是因为没有事先声明函数类型所致。

建议大家在编写一个函数的原代码时,立即将此函数的类型声明复制到原文件的起始

处,见例 11-1;或是复制到专门的包含头文件中,再在每个原程序模块中引用。

11.6.4 中断函数的实现

PICC 可以实现 C 语言的中断服务程序。中断服务程序有一个特殊的定义方法:

void interrupt ISR(void);

其中的函数名“ISR”可以改成任意合法的字母或数字组合,但其入口参数和返回参数类型

必须是“void”型,亦即没有入口参数和返回参数,且中间必须有一个关键词“interrupt”。

中断函数可以被放置在原程序的任意位置。因为已有关键词“interrupt”声明,PICC 在

最后进行代码连接时会自动将其定位到 0x0004 中断入口处,实现中断服务响应。编译器也

会实现中断函数的返回指令“retfie”。一个简单的中断服务示范函数如下:

void interrupt ISR(void) //中断服务程序

{

if (T0IE

&& T0IF)

{

T0IF = 0;

//在此加入 TMR0 中断服务

}

//判 TMR0 中断

//清除 TMR0 中断标志

if (TMR1IE && TMR1IF)

//判 TMR1 中断

{

TMR1IF0;

//在此加入 TMR1 中断服务

}

}

//清除 TMR1 中断标志

//中断结束并返回

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值