KeilC及其程序设计(二).ppt_第1页
KeilC及其程序设计(二).ppt_第2页
KeilC及其程序设计(二).ppt_第3页
KeilC及其程序设计(二).ppt_第4页
KeilC及其程序设计(二).ppt_第5页
已阅读5页,还剩61页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

(3)片外程序存储器 code:外部程序存储器的64KB空间。 程序存储区用来存放程序代码、数据及表格(数据及表格 中的数据是不变的)。 程序的代码(CODE)存储区是只读的,不能写入。硬件 决定最多可能有64KB的程序存储区。【因为是16位】 用code标识符来访问片内、片外统一编址的程序存储区, 寻址范围为065535。 对单片机编程,正确地定义数据类型以及存储类型, 是所有编程者在编程前都需要首先考虑的问题。在资源有 限的条件下,如何节省存储单元并保证运行效率,是对开 发者的一个考验。只有对C51中的各种数据类型以及存储 类型非常熟练的掌握,才能运用自如。 1 1 定义变量类型应考虑如下问题:程序运行时该变量可 能的取值范围,是否有负值,绝对值有多大,以及相应需 要的存储空间大小。在够用的情况下,尽量选择8位即一 个字节的char型,特别是unsiged char。对于51系列这样 的定点机而言,浮点类型变量将明显增加运算时间和程序 长度,如果可以的话,尽量使用灵活巧妙的算法来避免浮 点变量的引入。 定义数据的存储类型通常遵循如下原则:只要条件满 足,尽量选择内部直接寻址的存储类型data,然后选择 idata即内部间接寻址。对于那些经常使用的变量要使用内 2 2 部寻址。在内部数据存储器数量有限或不能满足要求的情 况下才使用外部数据存储器。选择外部数据存储器可先选 择pdata类型,最后选用xdata类型。 扩展片外存储器,原理上虽很简单,但在实际开发中 ,很多时候,会带来不必要的麻烦,如可能降低系统稳定 性、增加成本、拉长开发和调试周期等,推荐充分利用片 内存储空间。 通常的单片机应用都是面对小型的控制,代码比较短 ,对于程序存储区的大小要求很低,常常是片内RAM很紧 张而片内Flash ROM很富裕,因此如果实时性 3 3 要求不高,可考虑使用宏,以及将一些子函数的常量数据 做成数据表,放置在程序存储区,当程序运行时,进入子 函数动态调用下载至RAM即可,退出子函数后立即释放该 内存空间。 4 4 3.2.3 一个简单的C51程序 一个C51源程序是由一个个模块化的函数所构成,函 数是指程序中的一个模块,main()函数为程序的主函 数,其他若干个函数可以理解为一些子程序。 一个C51源程序无论包含了多少函数,它总是从main ()函数开始执行,不论main()函数位于程序的什么 位置。程序设计者就是编写一系列的函数模块,并在需要 的时候调用这个函数,实现程序所要求的功能。 5 5 1. C51程序与函数 下面通过一个简单C51程序,认识C51程序与函数。 【例3-1】 在STC89C51的P1.0脚接有一只发光二极管, 二极管的阴极接P1.0脚,阳极通过限流电阻接+5V,现在 让发光二极管每隔800ms闪灭,占空比为50%。已知单片 机时钟晶振为12MHz,即每个机器周期1s,采用软件延 时的方法,参考程序如下: 6 6 #include / 包含reg51.h 头文件 sbit P10=P10; / 定义位变量P1.0 ,也可使用 sbit P10=0x90 void delay(unsigned int count) / 延时函数delay( ),count是 形式参数 / 两个花括号之间为函数delay( )的函数体 unsigned int i,j; / 定义变量i,j for(i=0; i (2)用户自定义函数 用户根据自己需要所编写的函数。如例3-1中的delay 函数。编写时,需要注意以下几点。 1313 函数的首部(函数的第1行),包括函数名、函数类 型、函数属性、函数参数(形式参数)名、参数类型。 例如:void Delay(unsigned int i) 函数体,即函数首部下面的花括号“ ”内的部分。如 果一个函数体内有多个花括号,则最外层的一对“ ”为函 数体的范围。 C51区分大小写,例如Delay与delay,编译时是不同 的两个名称。 每个语句最后必须有一个分号,分号是C语句的必要 组成部分。 1414 从函数的定义的形式上划分可以有三种形式:无参数 函数、有参数函数和空函数。 (1)无参数函数 此种函数在被调用时,既无参数输入,也不返回结果 给调用函数,只是为完成某种操作而编写的。 (2)有参数函数 调用此种函数时,必须提供实际的输入函数,必须说 明与实际参数一一对应的形式参数,并在函数结束时返回 结果,供调用它的函数使用。 1515 (3)空函数 函数体内无语句,是空白的。调用空函数时,什么工 作也不做,不起任何作用。定义空函数的目的,是为以后 程序功能的扩充。程序最初设计时,往往只涉及最基本的 功能模块的函数,其他模块的功能函数可以在以后补上。 因此先将非基本模块的功能函数定义成空函数,用一个空 语句“;”占好位置,并写好注释,以后再用一个编好的函 数代替它。 1616 3. 函数调用 程序设计者的任务就是编写一系列的用户自定义函数 模块,并在需要的时候调用这些函数以及库函数,实现程 序所要求的功能。调用分为以下几种。 (1)简单调用 调用格式为:函数名(实际参数1,实际参数2,) 例如,例3-1中主函数main ( )里的子函数调用语句 “delay(800);”,其中800为实际参数。 1717 (2)嵌套调用 是在被调用的函数中又调用其他函数的语句。 (3)递归调用 函数的递归调用就是一个函数在其函数体内有调用自身 。 再入函数是一种可以在函数体内直接或间接调用自身的一种 函数,在Keil C51中递归函数必须是可重入的,可重入的函数 需要加上reentrant。 1818 3.2.4 C51的运算符 在程序中实现运算,要熟悉常用的运算符。本节对C51中 用到的标准C运算符进行简单回顾,为C51的程序设计打下基 础。 1. 算术运算符 如表3-3所示。 1919 表3-3 算术运算符及其说明 20 符号说明 +加法运算 -减法运算 *乘法运算 /除法运算(取商) % 取模运算(取余数 ) +自增1 -自减1 20 对于“/”和“%”往往会有疑问。这两个符号都涉及除法 运算,但“/”运算是取商,而“%” 运算为取余数。例如“5/3” 的结果(商)为1,而“5%3”的结果为2(余数)。 表3-3中的自增和自减运算符是使变量自动加1或减1 ,自增和自减运算符放在变量前和变量之后是不同的。 +i,-i:在使用i之前,先使i值加(减)1。 i+,i-:在使用i之后,再使i值加(减)1。 2121 例如:若i=4,则执行x=+i时,先使i加1,再引用结 果,即x=5,运算结果为i=5,x=5。 再如:若i=4,则执行x=i+时,先引用i值,即x=4, 再使i加1,运算结果为i=5,x=4。 2. 逻辑运算符 逻辑运算符及其说明如表3-4所示。 2222 表3-4 逻辑运算符及其说明 3. 关系运算符 判断两个数之间的关系。关系运算符及其说明如表3-5 。 23 符号说明 uint var2; var1=XBYTE0x0005; /XBYTE0x0005访问片外RAM的0005字 节单元 var2=XWORD0x0002; /XWORD0x0002访问片外RAM的0002 字单元 40 xval=XBYTE0x0002; /把外部存储区地址0x0002的数据存 入变量xval中 XWORD0x0002=0x2000; /把0x2000送到外部存储区地址 为0x0002的单元 #define DAC0832 XBYTE0x7fff /定义DAC0832的端口 地址 DAC0832=0x80; /启动一次D/A转换 while(1); 在上面程序中,其中XBYTE0x0005就是以绝对地址方式访 问的片外RAM 0005字节单元;XWORD0x0002就是以绝 对地址方式访问的片外RAM 0002字单元。 41 3.2.7 使用C51扩展关键字_at_ 使用_at_对指定的存储器空间的绝对地址进行访问,一般格 式如下: 存储器类型 数据类型说明符 变量名 _at_ 地址常数; 其中,存储器类型为data、bdata、idata、pdata等C51能 识别的数据类型,如省略则按存储模式规定的默认存储器类型 确定变量的存储器区域;数据类型为C51支持的数据类型。地 址常数用于指定变量的绝对地址,必须位于有效的存储器空间 之内;使用_at_定义的变量必须为全局变量。 42 【例】通过_at_实现绝对地址的访问。 #define uchar unsigned char/定义符号uchar为数据类 型符unsigned char #define uint unsigned int /定义符号uint为数据类型符 unsigned int void main(void) data uchar x1 _at_ 0x40; /在data区中定义字节变 量x1,它的地址为40H xdata uint x2 _at_ 0x2000; /在xdata区中定义字变量x2, 它的地址为2000H x1=0xff; x2=0x1234; while(1); 43 3.2.7 C51中断服务函数的定义 由于标准C没有处理单片机中断的定义,为直接编写 中断服务程序,C51编译器对函数的定义进行了扩展,增 加了一个扩展关键字interrupt,使用该关键字可以将一个 函数定义成中断服务程序。由于C51编译器在编译时对声 明为中断服务程序的函数自动添加了相应的现场保护、阻 断其他中断、返回时恢复现场等处理的程序段,因而在编 写中断服务函数时可不必考虑这些问题,减轻了用汇编语 言编写中断服务程序的繁琐程度,而把精力放在如何处理 引发中断请求的事件上。 44 中断服务函数的一般形式为: void 函数名(void)interrupt n using n 在函数声明时,用“interrupt n”语句,可以把所声 明的函数定义为一个中断服务程序。从定义中可 以看出,中断函数必须是无参数、无返回值的函 数。 关键字interrupt后面的 n是中断号,对于 AT89S51,取值为04,编译器从8n+3处产生中 断向量。AT89S51中断源对应的中断号和中断向 量见表3-3。 45 表3-3 中断号n和中断向量 中断号n中断源中断向量 (8n+3 ) 0外部中断 0 0003H 1定时器0 中断 000BH 2外部中断 1 0013H 3定时器1 中断 001BH 4串行口中 断 0023H 其他值( 531 ) 预留(8n+3) 46 AT89S51在内部RAM中有4个工作寄存器区,每个寄存器区 包含8个工作寄存器(R0-R7)。C51扩展了一个关键字 using,专门用来选择AT89S51的4个不同的工作寄存器区。 在定义一个函数时,using是一个选项,如果不选用该项, 则由编译器选择一个寄存器区作为绝对寄存器区访问。 例如: unsigned int interruptcnt; unsigned char second; void timer0(void) interrupt 1 using 2 /定时0中断服务程 序 if (+interruptcnt =4000) second+; Interruptcnt=0; 47 关键字using对函数目标代码的影响: 在中断函数的入口处将当前工作寄存器区内容保护 到堆栈中,函数返回前将被保护的寄存器区的内容从堆栈 中恢复。 使用关键字using在函数中确定一个工作寄存器区 时必须小心,要保证工作寄存器区切换都只在指定的控制 区域中发生,否则将产生不正确的函数结果。还要注意, 带using属性的函数原则上不能返回bit类型的值,且关键 字using和 48 关键字interrupt都不允许用于外部函数,另外也都 不允许有一个带运算符的表达式。 例如,外中断1( /int1 )的中断服务函数书写如下 : void int1( void) interrupt 2 using 0 /中断号n=2, 选择0区工作寄存器区 49 编写AT89S51中断程序时,应遵循以下规则: (1)中断函数没有返回值,如果定义了一个返回值 ,将会得到不正确的结果。因此建议在定义中断函 数时,将其定义为void类型,以明确说明没有返回 值。 (2)中断函数不能进行参数传递,如果中断函数中 包含任何参数声明都将导致编译出错。 (3)在任何情况下都不能直接调用中断函数,否则 会产生编译错误。 (4)如果在中断函数中再调用其他函数,则被调用 的函数所使用的寄存器区必须与中断函数使用的寄 存器区不同。 50 (5)C51编译器对中断函数编译时会自动在程序开始和结 束处加上相应的内容,具体如下:在程序开始处对ACC、B 、DPH、DPL和PSW入栈,结束时出栈。中断函数未加 using n修饰符的,开始时还要将R0R1入栈,结束时出栈 。如中断函数加using n修饰符,则在开始将PSW入栈后还 要修改PSW中的工作寄存器组选择位。 (6)C51编译器从绝对地址8m+3处产生一个中断向量,其 中m为中断号,也即interrupt后面的数字。该向量包含一个 到中断函数入口地址的绝对跳转。 (7)中断函数最好写在文件的尾部,并且禁止使用extern存 储类型说明。防止其它程序调用。 51 3.3 C51的集成开发环境Keil Vision3介绍 C51程序开发是在Keil Vision3 开发环境下进行,首 先介绍该开发环境。 3.3.1 集成开发环境Keil Vision3简介 Keil Software公司推出的Keil Vision3 是一款基于 Windows的软件平台,它是一种用于51单片机的集成开发 环境(IDEIntergrated Development Eviroment)。 Vision3提供了对基于8051内核的各种型号单片机的支 持,完全兼容先前的Keil Vision2版本。目前当前较新的 版本为Keil C51 V8.08a。 5252 开发者可购买Keil Vision3软件,也可到Keil software公司的主页免费下载Eval(评估)版本。该版本 同正式版本一样,但有一定的限制,最终生成的代码不能 超过2KB,但用于学习已经足够。开发者还可以到Keil公 司网站申请免费的软件试用光盘。 Keil Vision3内包含了功能强大的编辑器和调试器。 编辑器可以像一般的文本编辑器一样对源代码进行编辑, 并允许用户在编辑时设置程序断点(可在源代码未经编译 和汇编之前)。用户启动Vision3的调试器之后,断点即 被激活。 5353 断点可被设为条件表达式、变量或存储器访问,断点 被触发后,调试器的命令或调试功能即可执行,因此用户 可以在编辑器内调试程序,使用户快速地检查和修改程序 。 用户还可以在编辑器中选中变量和存储器来观察其值 。并可在双层窗口中显示,还可对其进行适当的调整。此 外,Vision3调试器具有符号调试特性以及历史跟踪,代 码覆盖,复杂断点等功能。 Keil C51编译器在遵循ANSI C标准的同时,为51单片 机进行了特别的设计和扩展,能让用户使用在应用中需要 的所有资源。 5454 Keil C51的库函数含有100多种功能,其中大多数是 可再入的。函数库支持所有的ANSI C的程序。库函数中 的程序还为硬件提供特殊指令,例如nop、testbit、rol、 ror等,方便了应用程序的开发。 Keil Vision的串口调试器软件comdebug.exe,用于 在电脑端能够看到单片机发出的数据,该软件无需安装, 可直接在当前位置运行这个软件。若读者需最新版,可到 有关搜索网站输入关键词“串口调试器”,找到一个合适的 下载网站,可即下载最新版本。当然,使用Windows自带 的“超级终端”也是不错的选择。 5555 3.3.2 Keil Vision3软件的安装、启动和运行 1. 软件安装 Keil Vision3的安装,同大多数软件安装一样,根据提 示进行。安装完毕后,可在桌面上看到Keil Vision3软件 的快捷图标。 2. 软件启动 点击桌面上的Keil Vision3软件的快捷图标,即可启动 该软件,几秒后,出现编辑界面。 3. 软件的运行 5656 (1)建立一个新工程 Keil Vision3把用户每一个应用程序设计都当作一个项目 ,用项目管理的方法把一个应用程序设计中所需要用到的、互 相关联的程序链接在同一项目中。这样,打开一个项目时,所 需的关联程序也都跟着进入了调试窗口,方便用户对项目中各 个程序的编写、调试和存储。 用户也可能开发多个项目,每个项目用到了相同或不同的 程序文件和库文件,采用项目管理,很容易区分不同项目中所 用到的程序文件和库文件。因此,在编写一个新的应用程序前 ,先建立项目的良好习惯。下面首先介绍如何建立一个新项 5757 目。 在编辑界面下,首先要建立一个点击“Project”菜单, 选择下拉式菜单中的“New Project”,弹出文件对话窗口, 选择要保存的路径,在“文件名”中输入一个程序项目名称 ,保存后的文件扩展名为“.uv2”,这是Keil Vision3项目 文件的扩展名,以后可直接点击此文件就可打开先前做的 项目。 点击“保存”后,这是会弹出一个对话框,要求选择单 片机的型号,用户可根据所使用的单片机来选择。Keil Vision3支持几乎所有的51内核的单片机。 5858 开始编写第一个程序。点击“File”菜单,再在下拉菜单 中单击“New”选项。此时光标在编辑窗口里闪烁,这时, 用户可以输入代码了。 输入完毕,单击菜单上的“File”,在下拉菜单中单击 “Save As”,在“文件名”栏的编辑框中,键入文件名,同时 ,必须键入正确的扩展名。 注意,如果用C语言编写程序,则扩展名为“.c”;如果 用汇编语言编写程序,则扩展名必须为“.asm”。然后,单 击“保存”按钮。 上述工作完成后,还有有关项目的设置,程序的编译 5959 和链接,程序的调试。这些内容,读者可按Keil Vision3 开发环境的帮助功能,进行反复练习和操作,从而熟练地 掌握该软件的使用。 3.3.3 C51程序的开发流程 C51程序开发与在Windows中运行的项目工程的开发 有所不同,在Windows中,一般程序的编译结果是后缀名 为“.exe”的可执行文件,该文件在Windows系统中能直接 运行,而单片机C51程序的开发属于嵌入式开发,遵循主 流的交叉编译模式,即在宿主机(运行Keil Vision3的PC 机)上开发编译,在目标机(51系列单片机)上运行。在 6060 宿主机上的编译结果为COFF文件或是满足Intel规范的 文件,文件包含了可执行的机器码,要经过编程器烧写到 单片机的程序区(Flash ROM)才能执行。 一个单片机C51应用程序的开发流程如下: 在Keil Vision3中新建项目工程建立并编辑源文件 编译调试项目工程生成目标文件下载到程序存储器 中程序运行。有关Keil Vision3的具体使用,请见Keil Vision3的使用操作说明。 3.4 C51与汇编语言的混合编程 目前多数开发人员都在用C51开发单片机程序,但 6161 在一些速度和时序敏感的场合下,C51略显不足,而有些 特殊的要求必须通过汇编语言程序来实现,但是用汇编语 言编写的程序远不如用C51语言编写的可读性好和效率高 。因此采用C51与汇编语言混合编程是解决这类问题的最 好方案。 C51编译器在头文件“reg51.h”中定义了全部sfr/sfr16和 sbit变量。用一条预处理命令#include 把这个 头文件包含到C51程序中,无需重定义即可直接使用它们 的名称。 6262 n#ifndef _REG51_H_ /先测试是否被宏定义过 n#define _REG51_H_ n/* BYTE Register */ 字节寄存器 nsfr P0 = 0x80; nsfr P1 = 0x90; nsfr P2 = 0xA0; nsfr P3 = 0xB0; nsfr PSW = 0xD0; nsfr ACC = 0xE0; nsfr B = 0xF0; nsfr SP = 0x81; nsfr DPL = 0x82; nsfr DPH = 0x83; nsfr PCON = 0x87; nsfr TCON = 0x88; nsfr TMOD = 0x89; nsfr TL0 = 0x8A; nsfr TL1 = 0x8B; nsfr T

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论