TDxxxV1.0
dw 0000h dw 0ae1fh dw 0ae2fh dw 0ae3fh dw 0ae4fh dw 0ae5fh dw 0ae6fh
;A-1 ; ; ; ; ;
dw 0ae7fh ;
我们可以看到,汇编的表是用DW关键字定义一个word,它是存放在.code段里面的,通过表头地址来得到每一个相对应的值。
那么在SN8 C 里面又如何来处理这些表呢?
在讲到表的处理之前,必须先提一提变量定义关键字的问题。SN8 C定义一个变量时,可以指明它所放置的地方(RAM或ROM),分别用关键字__RAM和__ROM来指定存放的地点,如:
Unsigned int __RAM ramVeriable; __RAM unsigned int ramVeriable2; Unsigned int __ROM romVeriable; __ROM unsigned int romVeriable2;
我们可以知道,当一个量放到了ROM当中就没法改变它的值了,其实就是我们说的常量。 在C当中,可以通过一个头名称来访问的变量类型比较多,其中数组是比较方便的一种,我们可以通过定义一个数组来存储这些表的数值,然后通过对数组的访问来查询对应的值。
如:
unsigned long __ROM disp_automenu[]= {
0x0000,0x0ae1f,0x0ae2f,0x0ae3f,0x0ae4f, 0x0ae5f,0x0ae6f,0x0ae7f
//显示菜单用第二数字表格
//将变量存放在RAM中 //将变量存放在ROM中
};
这是一个与上面的汇编表完全相同的表,我们将它存放在__ROM中,通过调用数组来查表,这在后面将详细介绍。
而在程序中还有另外一类的量是会在程序中不断被改变的,比如程序中的计数器,状态寄存器等等都会随着程序的运行而改变。我们将这一类量称之为变量。 我们先来看看汇编的定义变量的方法:
.DATA
org temp1 temp2 temp3 temp4 led_dp step
0h
ds 1 ds 1 ds 1 ds 1 ds 1 ds 1
;当前状态
16
TDxxxV1.0
上面的代码定义了temp1、temp2、temp3、temp4、led_dp、step6个变量,它们分别占用一个Byte的RAM空间,那么程序当中就可以通过变量名对该变量的空间进行读写。当然在汇编中你也可以用一个变量名来访问两个或多个RAM空间,这类似于查表的操作,其定义如下:
Job_mode
Power_mode
ds 2 ds 4
对上面的job_mode 变量可以通过job_mode 和job_mode+1来读写定义的两个存储单元,以此类推power_mode 或其他多个RAM空间定义的变量可以通过相同的方法来定义。可见,SN8ASM定义变量的方法主要是通过DS关键字来申请需要的变量空间,空间一旦被申请,就在整个程序流程里面被占用,也就是说定义一个变量就少一个空间,这对于RAM本身就很少的单片机而言,不能不说是一种浪费。
那么SN8C又是如何来定义变量的呢?
要说到C的变量,就不能不提一提变量的有效作用域。
我们知道,汇编当中定义的变量都是在整个程序中有效的,在程序中任何地方都可以改变变量的值,这样程序员就会经常遇到这样的情况:在调试程序时发现变量的值有误,却无法判断变量到底在什么地方被错误赋值或被赋予了错误的值,从而不得不在整个程序中到处设置断点,运行多次才找出问题的所在。这就是汇编当中变量定义造成不方便的地方!
而C的变量的定义区分了作用域,分为全局变量和局部变量,而区分定义这两种变量的方法很简单,只是在不同的位置定义就行了,这与标准C所规定的方法是一样的,后面再详细讨论。
下面是SN8 C定义的几个变量:
unsigned int temp1; unsigned int temp2; unsigned int temp3; unsigned int temp4; unsigned int led_dp; unsigned int step;
//当前状态
unsigned long job_mode; unsigned long power_mode1; float powerValue; int temp1_1; long temp2_2;
//有符号的
从上面的定义可以看到C的变量不仅区分了作用域,还有不同长度的变量类型,这样就方便了程序员的使用。
与面向数学运算的计算机相比,单片机的编程对变量类型或数据类型的选择更具有关键性意义。SN8 系列单片机是8-bit处理器的单片机,只有Byte型的数据是处理器直接支持的。对于C这样的高级语言,不管使用何种数据类型,虽然某一行程序从字面上看,其操作十分简单,然而,实际上系统的C编译器需要用一系列机器指令对其复杂的变量类型、数据类型的进行处理。相同的一行语句,变量选择的类型不同,处理时就会产生很大的差别,产生的代码更是差别很多。特别是当使用浮点变量时,将明显地赠加运算时间和程序的长度。当程序必须保证运算精度时,C编译器将调用相应的子程序库,把它们加到程序中。然而许多不熟练的程序员,
17
TDxxxV1.0
在编写C程序时往往会使用大量的、不必要的变量类型。这就导致C编译器相应地增加所调用的库函数以处理大量增加的变量类型,并最终导致程序变得过于庞大,运行速度减慢,甚至因此会在Link时,出现因程序过大而装不进ROM的情况。所以必须特别慎重的选择变量和数据类型。
而对于有符号与无符号的变量类型。在编写程序时,如果使用signed和unsigned两种数据类型,那么就得使用两种格式类型的库函数。这将使得占用的存储空间成倍增长。因此在编程时,如果只强调程序的运算速度而又不进行负数运算时,最好采用无符号(unsigned)格式。
Note: 1、选择数据类型的时候,在能够顺利完成功能的情况下,请尽量选择占空间少的数据类型,这样不管是在RAM空间使用上还是在产生代码效率上都是有益的! 2、能使用无符号数的都使用无符号数,以免处理出错,因为芯片内部是以无符号数处理的。 3、 切记!C语言对大小写敏感,在开始定义变量的时候就要注意要有相应的规范可循,用驼峰式是一个好的选择,这对于习惯于汇编的程序员来说,可能不大习惯!
当然,在标准C编程当中,经常会有为书写方便,对数据类型进行缩写定义,这在SN8 C也是允许的。如:
#define uchar unsigned char
#define uint unsigned int
这样,在以后的编程中,就可以用uchar代替unsigned char,用uint 代替 unsigned int 来定义变量。
3.3 数据的存储类型与存储结构
在前面分析查表类型数据定义的时候已经提到了数据在单片机里的存储,会分为ROM和RAM两部分,我们分别称之为程序存储器(ROM)和数据存储器(RAM)。它们在我们编写汇编的时候,会分别用关键字.code和.data来预先声明。
通常SN8系列单片机不用扩展存储器,它提供种类丰富的机型,你完全可以根据你的需求来选择合适的机型。因此,数据只存储在片内,寻址也不存在片内片外的区分。
SN8P单片机的数据存储器(RAM)的结构如下:
18
TDxxxV1.0
Bank0
0000H 007FH 0080H 00FFH Bank1
00100 01FFh 通用存储区
图3-2、RAM区结构
SN8P系列单片机的通用RAM区的大小依不同的芯片而不同,但都是按BANK来划分,每一个BANK内的地址为00H~FFH。而所有芯片的Bank0 的80H~ FFH的空间都是留给系统专用的系统寄存器区。
其实我们上面定义的变量都是放在RAM区的数据结构,在定义一个变量时,我们前面已经提到可以用__RAM和__ROM关键字来指定存储的地方,而变量定义一般都放在RAM当中,因而__RAM关键字是缺省项。看下面的例子:
unsigned int temp1; unsigned int __RAM temp2; __RAM unsigned int temp3;
unsigned long job_mode;
unsigned long __RAM job_mode2; __RAM unsigned long job_mode3; float powerValue; float __RAM powerValue; __RAM float powerValue; int temp1_1; int __RAM temp1-2;
__RAM temp1-3; long temp2_2;
其实上面的定义都是相同的效果,就是定义变量,并将其放置在数据存储区(RAM)内。也就是说,我们在定义一个变量,按我们C常用的方法定义就自动地放到RAM里了,缺省项给我们带来了很大的方便。
上面已经说明了,在RAM存储区内,80H~FFH是系统寄存器区。
那么我们又是如何来定义系统寄存器区呢? 我们先来看看系统寄存器都有哪些内容:
19
128Byte 用户存储区
通用存储区 80H~FFH为系统寄存器区域
更多的用户存储区
系统寄存器区 //有符号的
TDxxxV1.0
8 L 0 H 1 R - - ADB P2M P2 2 Z - - ADR - - 3 Y - - - P4M P4 4 X - - - P5M P5 5 6 7 8 - - - - 9 - - - - A - - - - B - - - - C - - - - D - - E - - F PFLAG RBANK - - - - - - - - - - - @YZ - - - 9 AMPM - A - - P4CON - - PEDGE PCH B DAM ADM C - D P0 - - INTRQ INTEN OSCM - T0M - - - WDTR TC0R PCL TC0M TC0C TC1M TC1C TC1R STKP - - - - - - E P0UR - P2UR - P4UR P5UR - F STK7L STK7H STK6L STK6H STK5L STK5H STK4L STK4H STK3L STK3H STK2L STK2H STK1L STK1H STK0L STK0H
表3-2、SN8P系列单片机系统寄存器列表
根据不同的芯片的资源,寄存器的内容会随之改变,但是他们定义的区域都不变。这些寄存器都分别对应了芯片内部的资源,SN8 C针对这部分的系统资源,对这些寄存器进行了定义,其定义的形式如下:
#define L #define H #define R #define Z #define Y
(*((__RAM unsigned int*)0x80)) (*((__RAM unsigned int*)0x81)) (*((__RAM unsigned int*)0x82)) (*((__RAM unsigned int*)0x83)) (*((__RAM unsigned int*)0x84))
#define X (*((__RAM unsigned int*)0x85))
#define PFLAG (*((__RAM unsigned int*)0x86))
这些定义都被包含在相应芯片的头文档里(.h),因此并不需要用户自己去定义寄存器的相应名称,只需要在程序的开头包含相应的头文档就行了。如下所示:
#include
Note: 这些系统寄存器都是以大写字母进行定义的,在编写程序时要注意这一点。
20
搜索“diyifanwen.net”或“第一范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,第一范文网,提供最新初中教育松翰C语言编程指导C+Program+Guide (4)全文阅读和word下载服务。
相关推荐: