ImageVerifierCode 换一换
格式:DOCX , 页数:17 ,大小:29.12KB ,
资源ID:4087538      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/4087538.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(第3章 KeilC语言及其程序设计21.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

第3章 KeilC语言及其程序设计21.docx

1、第3章 KeilC语言及其程序设计21(3)片外程序存储器code:外部程序存储器的64KB空间。程序存储区用来存放程序代码、数据及表格(数据及表格中的数据是不变的)。程序的代码(CODE)存储区是只读的,不能写入。硬件决定最多可能有64KB的程序存储区。【因为是16位】用code标识符来访问片内、片外统一编址的程序存储区,寻址范围为065535。对单片机编程,正确地定义数据类型以及存储类型,是所有编程者在编程前都需要首先考虑的问题。在资源有限的条件下,如何节省存储单元并保证运行效率,是对开发者的一个考验。只有对C51中的各种数据类型以及存储类型非常熟练的掌握,才能运用自如。定义变量类型应考虑

2、如下问题:程序运行时该变量可能的取值范围,是否有负值,绝对值有多大,以及相应需要的存储空间大小。在够用的情况下,尽量选择8位即一个字节的char型,特别是unsiged char。对于51系列这样的定点机而言,浮点类型变量将明显增加运算时间和程序长度,如果可以的话,尽量使用灵活巧妙的算法来避免浮点变量的引入。 定义数据的存储类型通常遵循如下原则:只要条件满足,尽量选择内部直接寻址的存储类型data,然后选择idata即内部间接寻址。对于那些经常使用的变量要使用内部寻址。在内部数据存储器数量有限或不能满足要求的情况下才使用外部数据存储器。选择外部数据存储器可先选择pdata类型,最后选用xdat

3、a类型。 需指出,扩展片外存储器,原理上虽很简单,但在实际开发中,很多时候,会带来不必要的麻烦,如可能降低系统稳定性、增加成本、拉长开发和调试周期等,推荐充分利用片内存储空间。 另外,通常的单片机应用都是面对小型的控制,代码比较短,对于程序存储区的大小要求很低,常常是片内RAM很紧张而片内Flash ROM很富裕,因此如果实时性要求不高,可考虑将一些子函数的常量数据做成数据表,放置在程序存储区,当程序运行时,进入子函数动态调用下载至RAM即可,退出子函数后立即释放该内存空间。3.2.3 一个简单的C51程序 一个C51源程序是由一个个模块化的函数所构成,函数是指程序中的一个模块,main()函

4、数为程序的主函数,其他若干个函数可以理解为一些子程序。 一个C51源程序无论包含了多少函数,它总是从main()函数开始执行,不论main()函数位于程序的什么位置。程序设计者就是编写一系列的函数模块,并在需要的时候调用这个函数,实现程序所要求的功能。1. C51程序与函数下面通过一个简单C51程序,认识C51程序与函数。【例3-1】 在AT89S51的P1.0脚接有一只发光二极管,二极管的阴极接P1.0脚,阳极通过限流电阻接+5V,现在让发光二极管每隔800ms闪灭,占空比为50%。已知单片机时钟晶振为12MHz,即每个机器周期1s,采用软件延时的方法,参考程序如下:#include / 包

5、含reg51.h 头文件sbit P10=P10; / 定义位变量P1.0 ,也可使用sbit P10=0x90void delay(unsigned int count) / 延时函数Delay( ),count是形式参数 / 两个花括号之间为函数Delay( )的函数体unsigned int i,j; / 定义变量i,j for(i=0; icount;i+) / 如果icount,则i加1 /在时钟频率为12MHz时,循环120次,大约为1ms for(j=0;j120;j+) / 如果j大于=大于或等于=小于或等于=等于!=不等于4. 位运算C51中的位运算符及其说明如表3-6所示。

6、表3-6 位运算其说明符号说 明&按位与按位或按位异或按位取反右移【例】设a=0x54=01010100B,b=0x3b=00111011B,则a&b、a|b、ab、a、a2分别为多少?a=0x54=01010100Bb=0x3b=00111011B a&b=00010000b=0x10 a|b=01111111B=0x7f ab=01101111B=0x6f a=10101011B=0xab a2=01010000B=0x50 【a2=00001110B=0x0e 【b=2】5 复合赋值运算符C51语言中支持在赋值运算符“=”的前面加上其它运算符,组成复合赋值运算符。下面是C51中支持的复合

7、赋值运算符: += 加法赋值 + 减法赋值 *= 乘法赋值 /= 除法赋值 %= 取模赋值 &= 逻辑与赋值 |= 逻辑或赋值 = 逻辑异或赋值 = 逻辑非赋值 = 右移位赋值 =2相当于x=x2。3.2.5 C51的分支与循环程序结构 程序结构上可把程序分为三类,即顺序、分支和循环结构。顺序结构是程序的基本结构,程序自上而下,从main()的函数开始一直到程序运行结束,程序只有一条路可走,没有其他的路径可以选择。顺序结构比较简单和便于理解,这里介绍分支结构和循环结构。1. 分支结构程序(1) 只有两条分支的时候用If (条件) 分支1else 分支2(2) 分支较多时 在分支较多时的情况下使

8、用switch语句。switch ( ) case( ):语句; break; case( ):语句;break;default:语句;break;注意:每个switch分支必须有一个break语句,否则程序并不能跳出switch,就会继续执行case后面的case语句。2. 循环结构程序 循环语句有以下三种。(1)for循环格式为:for(循环体初始化;循环体执行条件;循环体执行后操作) 循环体 花括号中为循环体内容。(2)while循环 格式为: while(循环体执行条件) 花括号中为循环体内容。 (3)do while循环 格式为: do 花括号 中为循环体内容 while(循环体执行

9、条件) 前两种循环是先判断循环条件是否满足,才决定循环体是否执行;而“do while循环”是在执行完循环体后再判断条件是否满足,再决定循环体是否继续执行。三种循环中,经常使用的是for语句和while语句。下面来说明for语句的应用。【例】求1到100之间整数的和 程序如下: #include #include main( ) unsigned int nVar1, nsum;/ unsigned char nsum;unsigned int nVar1; 能节省一个单元 for(nVar1=0,nSum=1;nSum=100;nSum+) nVar1+ = nSum; /*累加求和*/ w

10、hile(1); 关于循环,需说明的是,在无操作系统的控制器和处理器上运行的程序,主体通常采用轮询方式,即把所有的操作包含在一个while(1)中,如例3-1。这样的无限循环在面向通用计算机的软件设计中是不被允许的,然而嵌入式系统软件设计中,则由于其硬件构成和使用需求,常常采用这种无限循环。3.2.6 绝对地址访问使用C51运行库中预定义宏C51编译器提供了一组宏定义来对51系列单片机的code、data、pdata和xdata空间进行绝对寻址。规定只能以无符号数方式访问,定义了8个宏定义,其函数原型如下:#define CBYTE (unsigned char volatile code *

11、) 0)#define DBYTE (unsigned char volatile data *) 0)#define PBYTE (unsigned char volatile pdata *) 0)#define XBYTE (unsigned char volatile xdata *) 0)#define CWORD (unsigned int volatile code *) 0)#define DWORD (unsigned int volatile data *) 0)#define PWORD (unsigned int volatile pdata *) 0)#define

12、XWORD (unsigned int volatile xdata *) 0)这些函数原型放在absacc.h文件中。使用时须用预处理命令把该头文件包含到文件中,形式为:#include 。其中:CBYTE以字节形式对code区寻址,DBYTE以字节形式对data区寻址,PBYTE以字节形式对pdata区寻址,XBYTE以字节形式对xdata区寻址,CWORD以字形式对code区寻址,DWORD以字形式对data区寻址,PWORD以字形式对pdata区寻址,XWORD以字形式对xdata区寻址。访问形式如下: 宏名地址 宏名为CBYTE、DBYTE、PBYTE、XBYTE、CWORD、DWO

13、RD、PWORD或XWORD。地址为存储单元的绝对地址,一般用十六进制形式表示。【例4-7】绝对地址对存储单元的访问。#include /将绝对地址头文件包含在文件中#include /将寄存器头文件包含在文件中#define uchar unsigned char /定义符号uchar为数据类型符unsigned char#define uint unsigned int /定义符号uint为数据类型符unsigned intvoid main(void)uchar var1;uint var2;var1=XBYTE0x0005; /XBYTE0x0005访问片外RAM的0005字节单元va

14、r2=XWORD0x0002; /XWORD0x0002访问片外RAM的0002字单元xval=XBYTE0x0002; /把外部存储区地址0x0002的数据存入变量xval中XWORD0x0002=0x2000; /把0x2000送到外部存储区地址为0x0002的单元#define DAC0832 XBYTE0x7fff /定义DAC0832的端口地址DAC0832=0x80; /启动一次D/A转换.while(1);在上面程序中,其中XBYTE0x0005就是以绝对地址方式访问的片外RAM 0005字节单元;XWORD0x0002就是以绝对地址方式访问的片外RAM 0002字单元。3.2.

15、7 使用C51扩展关键字_at_ 使用_at_对指定的存储器空间的绝对地址进行访问,一般格式如下: 存储器类型 数据类型说明符 变量名 _at_ 地址常数; 其中,存储器类型为data、bdata、idata、pdata等C51能识别的数据类型,如省略则按存储模式规定的默认存储器类型确定变量的存储器区域;数据类型为C51支持的数据类型。地址常数用于指定变量的绝对地址,必须位于有效的存储器空间之内;使用_at_定义的变量必须为全局变量。【例】通过_at_实现绝对地址的访问。#define uchar unsigned char /定义符号uchar为数据类型符unsigned char#defi

16、ne uint unsigned int /定义符号uint为数据类型符unsigned intvoid main(void)data uchar x1 _at_ 0x40; /在data区中定义字节变量x1,它的地址为40Hxdata uint x2 _at_ 0x2000; /在xdata区中定义字变量x2,它的地址为2000Hx1=0xff;x2=0x1234;.while(1);3.2.7 C51中断服务函数的定义 由于标准C没有处理单片机中断的定义,为直接编写中断服务程序,C51编译器对函数的定义进行了扩展,增加了一个扩展关键字interrupt,使用该关键字可以将一个函数定义成中断

17、服务程序。由于C51编译器在编译时对声明为中断服务程序的函数自动添加了相应的现场保护、阻断其他中断、返回时恢复现场等处理的程序段,因而在编写中断服务函数时可不必考虑这些问题,减轻了用汇编语言编写中断服务程序的繁琐程度,而把精力放在如何处理引发中断请求的事件上。 中断服务函数的一般形式为: void 函数名(void)interrupt n using n在函数声明时,用“interrupt n”语句,可以把所声明的函数定义为一个中断服务程序。从定义中可以看出,中断函数必须是无参数、无返回值的函数。关键字interrupt后面的 n是中断号,对于AT89S51,取值为04,编译器从8n+3处产生

18、中断向量。AT89S51中断源对应的中断号和中断向量见表3-3。表3-3 中断号n和中断向量中断号n中断源中断向量(8n+3)0外部中断00003H1定时器0中断000BH2外部中断10013H3定时器1中断001BH4串行口中断0023H其他值(531)预留(8n+3)AT89S51在内部RAM中有4个工作寄存器区,每个寄存器区包含8个工作寄存器(R0-R7)。C51扩展了一个关键字using,专门用来选择AT89S51的4个不同的工作寄存器区。在定义一个函数时,using是一个选项,如果不选用该项,则由编译器选择一个寄存器区作为绝对寄存器区访问。例如:unsigned int interr

19、uptcnt;unsigned char second;void timer0(void) interrupt 1 using 2 /定时0中断服务程序 if (+interruptcnt =4000) second+; Interruptcnt=0; 关键字using对函数目标代码的影响: 在中断函数的入口处将当前工作寄存器区内容保护到堆栈中,函数返回前将被保护的寄存器区的内容从堆栈中恢复。 使用关键字using在函数中确定一个工作寄存器区时必须小心,要保证工作寄存器区切换都只在指定的控制区域中发生,否则将产生不正确的函数结果。还要注意,带using属性的函数原则上不能返回bit类型的值,且

20、关键字using和关键字interrupt都不允许用于外部函数,另外也都不允许有一个带运算符的表达式。例如,外中断1( /int1 )的中断服务函数书写如下:void int1( void) interrupt 2 using 0 /中断号n=2,选择0区工作寄存器区 编写AT89S51中断程序时,应遵循以下规则:(1)中断函数没有返回值,如果定义了一个返回值,将会得到不正确的结果。因此建议在定义中断函数时,将其定义为void类型,以明确说明没有返回值。(2)中断函数不能进行参数传递,如果中断函数中包含任何参数声明都将导致编译出错。(3)在任何情况下都不能直接调用中断函数,否则会产生编译错误。

21、(4)如果在中断函数中再调用其他函数,则被调用的函数所使用的寄存器区必须与中断函数使用的寄存器区不同。(5)C51编译器对中断函数编译时会自动在程序开始和结束处加上相应的内容,具体如下:在程序开始处对ACC、B、DPH、DPL和PSW入栈,结束时出栈。中断函数未加using n修饰符的,开始时还要将R0R1入栈,结束时出栈。如中断函数加using n修饰符,则在开始将PSW入栈后还要修改PSW中的工作寄存器组选择位。(6)C51编译器从绝对地址8m+3处产生一个中断向量,其中m为中断号,也即interrupt后面的数字。该向量包含一个到中断函数入口地址的绝对跳转。(7)中断函数最好写在文件的尾

22、部,并且禁止使用extern存储类型说明。防止其它程序调用。3.4 C51的集成开发环境Keil Vision3介绍C51程序开发是在Keil Vision3 开发环境下进行,首先介绍该开发环境。3.4.1 集成开发环境Keil Vision3简介Keil Software公司推出的Keil Vision3 是一款基于Windows的软件平台,它是一种用于51单片机的集成开发环境(IDEIntergrated Development Eviroment)。Vision3提供了对基于8051内核的各种型号单片机的支持,完全兼容先前的Keil Vision2版本。目前当前较新的版本为Keil C51 V8.08a。开发者可购买Keil Vision3软件,也可到Keil software公

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1