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

PIC单片机C语言编程教程(1)

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

放在哪一个 bank 中。如

果没有特别指明,所定义的变量将被定位在 bank0,例如下面所定义的这些变量:

unsigned char buffer[32];

bit flag1,flag2;

float val[8];

除了 bank0 内的变量声明时不需特殊处理外,定义在其它 bank 内的变量前面必须加上

相应的 bank 序号,例如:

bank1 unsigned char buffer[32]; //变量定位在 bank1 中


bank2 bit flag1,flag2;

bank3 float val[8];


//变量定位在 bank2 中

//变量定位在 bank3 中


中档系列 PIC 单片机数据寄存器的一个 bank 大小为 128 字节,刨去前面若干字节的特

殊功能寄存器区域,在 C 语言中某一 bank 内定义的变量字节总数不能超过可用 RAM 字节

数。如果超过 bank 容量,在最后连接时会报错,大致信息如下:

Error[000] : Cant find 0x12C words for psect rbss_1 in segment BANK1

连接器告诉你总共有 0x12C(300)个字节准备放到 bank1 中但 bank1 容量不够。显然,只

有把一部分原本定位在 bank1 中的变量改放到其它 bank 中才能解决此问题。

虽然变量所在的 bank 定位必须由编程员自己决定,但在编写原程序时进行变量存取操

作前无需再特意编写设定 bank 的指令。C 编译器会根据所操作的对象自动生成对应 bank 设

定的汇编指令。为避免频繁的 bank 切换以提高代码效率,尽量把实现同一任务的变量定位

在同一个 bank 内;对不同 bank 内的变量进行读写操作时也尽量把位于相同 bank 内的变量

归并在一起进行连续操作。

11.5.4 PICC 中的局部变量

PICC 把所有函数内部定义的 auto 型局部变量放在 bank0。为节约宝贵的存储空间,它

采用了一种被叫做“静态覆盖”的技术来实现局部变量的地址分配。其大致的原理是在编译

器编译原代码时扫描整个程序中函数调用的嵌套关系和层次,算出每个函数中的局部变量字

节数,然后为每个局部变量分配一个固定的地址,且按调用嵌套的层次关系各变量的地址可

以相互重叠。利用这一技术后所有的动态局部变量都可以按已知的固定地址地进行直接寻

址,用 PIC 汇编指令实现的效率最高,但这时不能出现函数递归调用。PICC 在编译时会严

格检查递归调用的问题并认为这是一个严重错误而立即终止编译过程。

既然所有的局部变量将占用 bank0 的存储空间,因此用户自己定位在 bank0 内的变量字

节数将受到一定的限制,在实际使用时需注意。

11.5.5 PICC 中的位变量

bit 型位变量只能是全局的或静态的。PICC 将把定位在同一 bank 内的 8 个位变量合并

成一个字节存放于一个固定地址。因此所有针对位变量的操作将直接使用 PIC 单片机的位

操作汇编指令高效实现。基于此,位变量不能是局部自动型变量,也无法将其组合成复合型

高级变量。

PICC 对整个数据存储空间实行位编址,0x000 单元的第 0 位是位地址 0x0000,以此后

推,每个字节有 8 个位地址。编制位地址的意义纯粹是为了编译器最后产生汇编级位操作指

令而用,对编程人员来说基本可以不管。但若能了解位变量的位地址编址方式就可以在最后

程序调试时方便地查找自己所定义的位变量,如果一个位变量 flag1 被编址为 0x123,那么

实际的存储空间位于:

字节地址=0x123/8 = 0x24

位偏移 =0x123%8 = 3

即 flag1 位变量位于地址为 0x24 字节的第 3 位。在程序调试时如果要观察 flag1 的变化,必

须观察地址为 0x24 的字节而不是 0x123。

PIC 单片机的位操作指令是非常高效的。因此,PICC 在编译原代码时只要有可能,对

普通变量的操作也将以最简单的位操作指令来实现。假设一个字节变量 tmp 最后被定位在

地址 0x20,那么


tmp |= 0x80

tmp &= 0xf7


=> bsf

=> bcf


0x20,7

0x20,3


if (tmp&0xfe)


=> btfsc 0x20,0


即所有只对变量中某一位操作的 C 语句代码将被直接编译成汇编的位操作指令。虽然编程

时可以不用太关心,但如果能了解编译器是如何工作的,那将有助于引导我们写出高效简介

的 C 语言原程序。

在有些应用中需要将一组位变量放在同一个字节中以便需要时一次性地进行读写,这一

功能可以通过定义一个位域结构和一个字节变量的联合来实现,例如:

union {

struct {

unsigned b0: 1;

unsigned b1: 1;

unsigned b2: 1;

unsigned b3: 1;

unsigned b4: 1;

unsigned b5: 1;

unsigned : 2; //最高两位保留

} oneBit;

unsigned char allBits;

} myFlag;

例 11-3 定义位变量于同一字节

需要存取其中某一位时可以

myFlag.oneBit.b3=1; //b3 位置 1

一次性将全部位清零时可以

myFlag.allBits=0; //全部位变量清 0

当程序中把非位变量进行强制类型转换成位变量时,要注意编译器只对普通变量的最低

位做判别:

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

网站地图

Top