单片机的C语言程序设计.ppt

上传人:仙人指路1688 文档编号:2408818 上传时间:2023-02-18 格式:PPT 页数:88 大小:903KB
返回 下载 相关 举报
单片机的C语言程序设计.ppt_第1页
第1页 / 共88页
单片机的C语言程序设计.ppt_第2页
第2页 / 共88页
单片机的C语言程序设计.ppt_第3页
第3页 / 共88页
单片机的C语言程序设计.ppt_第4页
第4页 / 共88页
单片机的C语言程序设计.ppt_第5页
第5页 / 共88页
点击查看更多>>
资源描述

《单片机的C语言程序设计.ppt》由会员分享,可在线阅读,更多相关《单片机的C语言程序设计.ppt(88页珍藏版)》请在三一办公上搜索。

1、1/88,第五章 单片机的C语言程序设计 及仿真调试本章学习目标掌握单片机C语言程序中的常用功能掌握Keil C的程序设计掌握STC15F2K60S2单片机C语言程序调试过程,2/88,汇编语言和C语言的选择问题设计规模较小的嵌入式应用系统时,可以使用汇编语言。因为代码一般不长,且较简单。当程序比较复杂,且没有很好的注释时,使用汇编编程的可读性和可维护性会很差,代码的可重性也比较低。使用C语言编程,编写简单、直观易读、便于维护、通用性好。在控制任务比较复杂或者具有大量运算的系统中,C语言优势明显。由于模块化,用C语言编写的程序具有很好的可移植性。,3/88,5.1 单片机C语言程序中的常用功能

2、,一、逻辑运算和位运算1、逻辑运算符按逻辑运算符用于逻辑运算,包括与(&)、或(|)、非(!)三种。对于使用逻辑运算符的表达式,返回0表示“假”,返回1表示“真”。,4/88,与运算符(,5/88,或运算符(|)功能:检查两个条件中是否有一个为真的运算符,只要有一个条件为真,运算结果就为真。上例改为:如果任一语句为真,程序需执行某些操作,则条件代码如下:(a10)|(b=7);,6/88,逻辑非运算符(!)功能:表示对表达式的真值取反。例如,如果变量s小于10,程序需执行某些操作,则条件代码如下:(s=10)/s不大于等于10,7/88,2、位运算符很多系统程序常要求进行位(bit)运算或处理

3、。语言提供了六种位运算符:按位与(&)、按位或(|)、按位异或()、取反()、左移()。,8/88,(1)按位“与”运算按位与运算符“&”是双目运算符。功能是参与运算的两数各对应的二进制位相与。只有对应的两个位均为1时,结果位才为1,否则为0。例如,9&5 00001001&0000010100000001按位与运算通常用来对某些位清0或保留某些位。例如把a 的高八位清0,保留低八位 可用 a&255(255的二进制数为0000000011111111)。,9/88,(2)按位“或”运算按位或运算符“|”是双目运算符。功能是参与运算的两数各对应的二进制位相或。只要对应的两个位有一个为1时,结果

4、位就为1。例如,9|5 00001001|00000101=00001101(十进制为13)或运算通常用来对某些位置1。,10/88,(3)按位“异或”运算按位异或运算符“”是双目运算符。功能是参与运算的两数各对应的二进制位相异或。当两个对应的位相异时,结果为1。例如,95 0000100100000101 00001100(十进制为12)异或运算通常用来对某些位取反。,11/88,(4)求反运算求反运算符“”为单目运算符,具有右结合性。功能是对参与运算的数的各二进制位按位求反。例如,9(0000000000001001)结果为:1111111111110110,12/88,(5)左移运算左移

5、运算符“”是双目运算符。功能是把“”左边的运算数的各二进制位全部左移若干位,由“”右边的数指定移动的位数,高位丢弃,低位补0。例如:a4 指把a的各二进位向左移动4位。如a=00000011(十进制3),左移4位后为00110000(十进制48)。,13/88,(6)右移运算右移运算符“”是双目运算符。功能是把“”左边的运算数的各二进制位全部右移若干位,“”右边的数指定移动的位数。例如,设 a=15,a2 000001111右移为00000011(十进制3)。对于有符号数,在右移时,符号位将随同移动。当为正数时,最高位补0,而为负数时,符号位为 1,最高位是补0或是补1 取决于编译系统的规定。

6、,14/88,二、预处理 以“#”号开头的命令是预处理命令。语言提供了多种预处理功能,如宏定义#define、文件包含#include、条件编译等。合理地使用预处理功能,可以使得编写的程序便于阅读、修改、移植和调试,也利于模块化程序设计。下面介绍常用的预处理功能。,15/88,1、宏定义(define)在语言源程序中允许用一个标识符来表示一个字符串,称为宏。被定义为宏的标识符称为宏名。在编译预处理时,对程序中所有出现的宏名,都用宏定义中的字符串去代换,这称为宏代换或宏展开。宏代换是由预处理程序自动完成的。在语言中,宏分为有参数和无参数两种。,16/88,(1)无参宏定义无参宏的宏名后不带参数。

7、其定义的一般形式为:#define 标识符 字符串其中,标识符为所定义的宏名。字符串可以是常数、表达式、格式串等。符号常量的定义就是一种无参宏定义。此外,常对程序中反复使用的表达式进行宏定义。如要终止宏定义,可使用#undef命令。,17/88,(2)带参宏定义在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。带参宏定义的一般形式为:#define 宏名(形参表)字符串,18/88,在字符串中含有各个形参。带参宏调用的一般形式为:宏名(实参表);例如:#define MAX(a,b)(ab)?a:b/取a和b的最大数,19

8、/88,2、文件包含(include)文件包含的一般形式为:#include 文件名功能是把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。,20/88,说明以下几点:包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。例如:#include stdio.h#include 二者的区别:使用尖括号表示在包含文件目录中去查找(包含目录由用户在开发环境中设置),而不在源文件目录去查找;使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。,21/88,3、条件编译条件编译就是按不同的条件去编译不同的程序部分,从而产生不同的目标

9、代码文件。条件编译对于程序的移植和调试(可以分段调试)非常有用。特别是在操作系统的裁减中,经常使用条件编译。,22/88,(1)第一种形式:#ifdef 标识符 程序段1#else 程序段2#endif功能是:如果标识符已被#define命令定义过,则对程序段1进行编译;否则对程序段2进行编译。如果没有程序段2(它为空),本格式中的#else可以没有。,23/88,(2)第二种形式:#ifndef 标识符 程序段1#else 程序段2#endif功能是:如果标识符未被#define命令定义过则对程序段1进行编译,否则对程序段2进行编译。这与第一种形式的功能正相反。,24/88,(3)第三种形式

10、:#if 常量表达式 程序段1#else 程序段2#endif功能是,如果常量表达式的值为真(非0),则对程序段1进行编译,否则对程序段2进行编译。因此可以使程序在不同条件下,完成不同的功能。,25/88,5.2 Keil C 和 ANSI C,一、Keil C51扩展关键字C51有以下扩展关键字(共19个):_at_、sbit、sfr、bit、sfr16、idata、bdata、xdata、pdata、data、code、alien、small、compact、large、using、reentrant、interrupt、_task_,26/88,1、内存区域(Memory Areas):

11、(1)程序存储器:code:程序存储区。可以使用code定义表格常数。(2)内部RAM:用以下关键字说明:data:直接寻址区,内部RAM的低128字节,地址范围为00H7FH。idata:间接寻址区,包括整个内部RAM区,256字节,地址范围为00H0FFH。bdata:可位寻址区,地址范围为20H2FH。,27/88,(3)外部数据存储器:外部RAM视使用情况可由以下关键字标识:xdata:可指定多达64KB的外部直接寻址区,地址范围0000H0FFFFH。pdata:能访问1页(256Bytes)的外部RAM(很少用)。,28/88,存储类型的指定:变量或参数的存储类型可由存储模式指定缺

12、省类型,也可由关键字code、data、idata、xdata、pdata直接声明指定。例如:unsigned char data buffer;char code array=“hello!”;unsigned char xdata arr1044;,29/88,(4)特殊功能寄存器(SFR)STC15F2K60S2单片机的特殊功能寄存器(SFR)寻址区,用来控制定时器、计数器、串口、I/O及其他部件。为了支持SFR及其可寻址位的声明,引入了sfr、sbit等关键词。,30/88,sfr:字节寻址。语法如下:sfr sfr_name=int_constant;如 sfr P0=0 x80;0

13、 x80为P0口的地址,“=”后为常数,并且这个常数必须在特殊功能寄存器的地址范围内,位于0 x80到0 xFF之间。,31/88,sfr16:字寻址如sfr16 DPTR=0 x82;指定DPTR的地址DPL=0 x82,DPH=0 x83。sbit:位寻址 用于声明可位寻址的特殊功能寄存器的位变量。,32/88,sbit可以有下面声明方法:方法1:sbit bitname=sfr_namebit_number;其中,sfr_name必须是已定义的SFR的名字,bit_number是位号(07)。如:sbit CY=PSW7;/定义CY为PSW的第7位。方法2:sbit bitname=sf

14、r_addressbit_number;其中,sfr_address是SFR所在的地址(0 x800 xff),bit_number是位号(07)。如:sbit OV=0 xD02;/定义PSW中的OV位方法3:sbit bitname=bit_address;其中,bit_address是位地址。如:sbit EA=0 xAF;/第0 xAF位为EA,33/88,对于大多数8051内核单片机,Keil提供了一个包含所有特殊功能寄存器和它们的位的定义的头文件reg51.h。通过包含头文件可以很容易的进行新的扩展。附录C提供了STC15F2K60S2单片机的头文件stc15.h的内容,其中包含了

15、标准8051单片机寄存器的定义,编程时只需包含这一个文件即可。该文件可以从中下载。,34/88,2、_at_关键字 若要实现变量的绝对定位(称为绝对变量),可以直接在数据定义后加上“_at_ 常数地址”即可。注意:(1)绝对变量不能被初始化;(2)bit型函数及变量不能用_at_指定。,35/88,例如:unsigned char idata ADCdata _at_ 0 x40;/指定ADCdata变量在40H处 unsigned char xdata buffer20 _at_ 0 x0010;/指定buffer数组从XRAM的0010H单元开始,36/88,3、存储模式存储模式决定了没有

16、明确指定存储类型的变量时,函数参数等的缺省存储区域,有Small、Compact和Large三种模式。,指定存储模式,图5-1 指定存储模式,37/88,(1)Small模式在该模式中所有变量都默认位于单片机内部数据存储器,这和使用data指定存储器类型的方式一样。此模式访问变量的效率很高,但所有的数据对象和堆栈必须适合内部RAM堆栈的大小。如果将变量都配置在内部数据存储器内,Small模式是最佳选择。该模式的优点是访问速度快,缺点是空间有限,只适用于小程序。,38/88,(2)Compact模式所有缺省变量均位于外部RAM区的一页内(256字节),这和使用pdata指定存储器类型一样,在ST

17、ARTUP.A51文件中说明,也可用pdata指定。该模式空间比Small宽裕,速度比Small慢,比Large快,是一种中间状态。,39/88,(3)Large模式所有缺省变量可放在多达64KB的外部RAM区,这和使用xdata指定存储器类型一样,使用数据指针DPTR进行寻址。通过数据指针访问外部数据存储器的效率较低,特别是当变量为2个字节或更多字节时。该模式的数据访问比Small和Compact产生更多的代码。优点是空间大,可存变量多,缺点是速度较慢。,40/88,4、变量或数据类型,表5-1 C51数据类型,41/88,C51提供以下几种扩展数据类型:bit:位变量值为0或1。sbit:

18、从字节中定义的位变量(0或1)。sfr:sfr字节地址(0 x800 xff)。sfr16:sfr字地址(0 x800 xff,其实是占用 两个连续的地址)。其余数据类型如:char、enum、short、int、long、float等与ANSI C相同。下面着重介绍位变量及其声明。,42/88,(1)bit型变量bit型变量可用于变量类型和函数声明、函数返回值等,存储于内部RAM的20H2FH单元中。注意:1)使用禁止中断(#pragma disable)或包含明确的寄存器组切换(using n)的函数不能返回位值,否则,编译器会识别出来并产生一个错误信息。2)位不能声明为一个指针。如bit

19、*bit_poiter;是错误的。3)不能有bit数组如:bit arr5;是错误的。,43/88,(2)可位寻址区说明使用sbit声明可独立访问可位寻址对象的位。sbit声明要求基址对象的存贮器类型为“bdata”,否则只有绝对的位声明方法是合法的。位的位置(操作符号后的数字)的最大值依赖于指定的基类型对于char/uchar而言是07,对于int/uint/short/ushort而言是015,对于long/ulong而言是031。,44/88,下面举例说明位寻址的声明方法。例如,int bdata bittest _at_ 0 x20;/也可以省略“_at_ 0 x20”sbit bit

20、0bittest 0;/0 x20单元的第0位 sbit bit15=bittest 15;/0 x21单元的第7位注意:可位寻址对象的位的声明只能放到main函数的外部,作为全局变量使用,否则,编译会出错。,45/88,二、扩展I/O口的使用 STC15F2K60S2单片机除了芯片上的I/O口外,还可在片外扩展I/O端口。由于使用C语言访问外部I/O时用到指针的功能,因此,首先介绍Keil C51的指针。,46/88,1、Keil C51指针Keil C51支持一般指针(Generic Pointer)和存储器指针(Memory Specific Pointer)。一般指针的声明和使用均与标

21、准C相同,同时还可以说明指针的存储类型。,47/88,例如,下面的语句都声明pt为指向保存在外部RAM中unsigned char数据的指针,但pt本身的保存位置却不同:unsigned char xdata*pt;/pt本身依存储模式存放 unsigned char xdata*data pt;/pt被保存在内部RAM中 unsigned char xdata*xdata pt;/pt被保存在外部RAM中,48/88,一般指针本身用3个字节存放,分别为存储器类型,高位偏移量和低位偏移量。基于存储器的指针,说明时即指定了存储类型,例如:char data*str;/str指向data区中cha

22、r型数据 int xdata*pow;/pow指向外部RAM的int型整数这种指针存放时,只需一个字节或2个字节就够了,因为只需存放偏移量。,49/88,关于堆栈指针SP 的设定一般情况下,用户不需要在C语言程序中修改堆栈指针SP,但要关心一下SP的位置。C51为变量分配好内部RAM后,将SP放在第一个空闲的内部RAM处,可以在编译后生成的.m51文件中观察到栈顶的位置,一般程序编译连接成功后要习惯性地看一下.m51文件,看一下是不是有足够的栈空间可用。另外,C51是在startup.A51中设置SP指针的,用CODE选项生成的汇编代码中是找不到这段代码的。startup.A51是C51的初始

23、化代码,单片机复位后先执行这段代码,完成初始化后由它调用main()函数。特殊需要时,可以修改这段代码,然后连接到用户的程序中去。,50/88,2、外部扩展I/O口的访问在C51中有两种方法访问外部I/O端口。方法1:使用自定义指针。由于片外I/O端口与片外存储器统一编址,所以可以定义xdata类型的指针访问外部I/O端口。,51/88,例如,某单片机应用系统中,使用8255扩展I/O端口,采用线选法对8255进行地址译码,单片机的P 2.7(A15)接8255的片选引脚,8255的命令字地址为7FF3H,PA口地址为7FF0H,PB口地址为7FF1H,PC口地址为7FF2H,访问8255的C

24、程序如下:,52/88,写端口程序:char xdata*com8255;/定义指向外部存储区的指针 com8255=0 x7ff3;/使指针指向8255的控制口地址7FF3H*com8255=0 x81;/输出81H到控制端口 以上C程序相当于下面的汇编语言程序:MOV DPTR,#7FF3H MOV A,#81H MOVX DPTR,A,53/88,读端口程序:char xdata*com8255;/定义指针 com8255=0 x7ff0;/使指针指向8255的PA口地址7FF0H char i;i=*com8255;/读PA端口到变量i,54/88,方法2:使用C51预定义指针。为了方

25、便地访问外部存储器及I/O端口,在C51中的absacc.h头文件做了如下定义,利用这些定义可以方便地访问外部I/O端口。#define CBYTE(unsigned char volatile code*)0)#define DBYTE(unsigned char volatile data*)0)#define PBYTE(unsigned char volatile pdata*)0)#define XBYTE(unsigned char volatile xdata*)0),55/88,例如:#include#define PORTA XBYTE 0 x7ff0/其中,PORTA为程序

26、定义的I/O端口名称,内的内容/7ff0H为PORTA的地址void main(void)char a;PORTA=0 x81;/*输出81H到端口7ff0H a=PORTA;/读端口7ff0H到变量a,56/88,三、Keil C51函数 C51的函数声明对ANSI C作了扩展,具体包括:1、中断函数声明中断函数通过使用interrupt关键字和中断号(031)来声明。中断号告诉编译器中断服务程序的入口地址。,57/88,STC15F2K60S2单片机的中断号及中断服务程序入口地址如表所示。,表5-2中断号及中断服务程序入口地址,58/88,例如,串行口1的中断函数可以声明如下:void U

27、ART1_ISR(void)interrupt 4 using 1/*中断服务程序的代码*/上述代码声明了串行口1中断服务函数。其中,interrupt 4说明是串行口1的中断,using 1指明采用工作寄存器区1区,using 1在中括号中,说明该段可以省略。其他中断函数的定义与此类似。中断函数具体是哪个中断的函数,与中断号有关,而与函数名无关。,59/88,2、指定工作寄存器区当需要指定函数中使用的工作寄存器区时,使用关键字using后跟一个0到3的数,对应着工作寄存器0到3区。例如,在下面的函数中使用了工作寄存器1区(相当于PSW.4=0,PSW.3=1):unsigned char G

28、etKey(void)using 1/*用户程序代码*/,60/88,3、指定存储模式用户可以使用small,compact 及large说明存储模式。例如:void fun1(void)small 提示:small说明的函数内部变量全部使用内部RAM。关键的、经常性的、耗时的地方可以这样声明,以提高运行速度。,61/88,4、函数的参数传递规则最多只能有3个参数通过寄存器传递,规律如表5-3所示。,表5-3 函数的参数传递规则,62/88,5、函数返回值的规定函数返回值一律放于寄存器中,规则如表5-4所示。,表5-4 函数返回值的规定,63/88,6、函数的重入可以在函数前声明函数的可重入性

29、,只对一个函数有效。如果声明为不可重入的,说明该函数调用过程中将不可被中断。递归或可重入函数指定在主程序和中断中都可调用的函数,容易产生问题。因为单片机和PC不同,PC使用堆栈传递参数,且静态变量以外的内部变量都在堆栈中;而单片机一般使用寄存器传递参数,内部变量一般在RAM中,函数重入时会破坏上次调用的数据。,64/88,可以用以下两种方法解决函数的重入问题:第一种方法:在相应的函数前使用“#pragma disable”声明,即只允许主程序或中断之一调用该函数。第二种方法:将该函数说明为可重入的。如下:void func(param.)reentrant;,65/88,Keil C51编译后

30、将生成一个可重入变量堆栈,然后就可以模拟通过堆栈传递变量的方法。因为单片机内部堆栈空间的限制,C51没有像大系统那样使用调用堆栈。一般在C语言中调用过程时,会把过程的参数和过程中使用的局部变量入栈。,66/88,为了提高效率,C51没有提供这种堆栈,而是提供一种压缩栈。每个过程被给定一个空间,用于存放局部变量。过程中的每个变量都存放在这个空间的固定位置。当递归调用这个过程时,会导致变量被覆盖。在某些实时应用中,非重入函数是不可取的。因为,函数调用时可能会被中断程序中断,而在中断程序中可能再次调用这个函数,所以C51允许将函数定义成重入函数。重入函数可被递归调用和多重调用,而不用担心变量被覆盖,

31、因为每次函数调用时的局部变量都会被单独保存。因为这些堆栈是模拟的,重入函数一般都比较大,运行起来也比较慢。,67/88,由于一般可重入函数由主程序和中断调用,所以通常中断程序使用与主程序不同的工作寄存器组。另外,对可重入函数,在相应的函数前面加上开关#pragma noaregs,以禁止编译器使用绝对寄存器寻址,可生成不依赖于寄存器组的代码。,68/88,四、STC15F2K60S2单片机C51程序框架#include“stc15.h”/*stc15.h为单片机寄存器定义头文件,具体内容参见附录C*/void delay(long delaytime);/声明子函数,子函数可以有返回值void

32、 main(void)/此处可存放应用系统的初始化代码 while(1)/主程序循环/根据需要填入适当的内容 delay(100);/可以调用用户自定义的子函数,69/88,/-各个子函数的声明-void delay(long delaytime)while(delaytime0)delaytime-;/子函数的实现代码/-各个中断函数的实现-void INT0_ISR(void)interrupt 0/外部中断0服务子函数/根据需要填入程序代码void T0_ISR(void)interrupt 1/定时器0中断服务子函数/根据需要填入程序代码void INT1_ISR(void)inter

33、rupt 2/外部中断1服务子函数/根据需要填入程序代码void T1_ISR(void)interrupt 3/定时器1中断服务子函数/根据需要填入程序代码,70/88,void UART1_ISR(void)interrupt 4/串口1中断服务子函数/根据需要填入程序代码,注意中断请求标志的清零void ADC_ISR(void)interrupt 5/ADC中断服务子函数/根据需要填入程序代码,注意中断请求标志的清零void LVD_ISR(void)interrupt 6/低电压检测中断子函数/根据需要填入程序代码,注意中断请求标志的清零void PCA_ISR(void)inter

34、rupt 7/PCA中断子函数/根据需要填入程序代码,注意中断请求标志的清零void UART2_ISR(void)interrupt 8/串口2中断子函数/根据需要填入程序代码,注意中断请求标志的清零void SPI_ISR(void)interrupt 9/SPI中断子函数/根据需要填入程序代码,注意中断请求标志的清零,71/88,void INT2_ISR(void)interrupt 10/外部中断2服务子函数/根据需要填入程序代码void INT3_ISR(void)interrupt 11/外部中断3服务子函数/根据需要填入程序代码void T2_ISR(void)interrup

35、t 12/定时器2中断服务子函数/根据需要填入程序代码void INT4_ISR(void)interrupt 16/外部中断4服务子函数/根据需要填入程序代码,72/88,【例5-1】编程实现通过延时函数,P1.0输出方波信号,并通过示波器观察程序输出波形的周期。#include“stc15.h”/STC15F2K60S2单片机寄存器定义头文件 sbit P10=P10;/定义P1.0引脚 void delay(unsigned long cnt);/延时函数声明 void main(void)P10=1;while(1)/主程序循环 delay(60000);P10=P10;void de

36、lay(unsigned long cnt)/延时函数 while(cnt0)cnt-;,73/88,可以使用集成开发环境(IDE)对单片机程序进行软件模拟调试。由于此时无需任何硬件与开发,可以降低程序开发的成本,并且程序开发可以在系统硬件完成之前开始。,5.3 单片机C语言程序调试,74/88,模拟仿真调试的方法和过程与汇编语言模拟仿真调试的过程相同。但是,软件模拟调试无法仿真精确的硬件信号,难以仿真过程控制中的通信网络时序及实时转换,因此当软件开发过程进入必须有最终硬件参与共同完成的阶段时,就需要进行在系统调试。传统的仿真方法是使用仿真器进行仿真和调试。下面介绍如何使用仿真器进行程序的仿真

37、和调试。,75/88,一、使用仿真器进行程序的仿真调试 使用宏晶单片机仿真器适用于STC单片机应用技术的学习和实验程序的调试,使用过程如下:1、硬件设置 目前的仿真方式为双CPU仿真:监控CPU和仿真CPU。仿真CPU目标芯片必须是宏晶的IAP系列(目前只支持IAP15F2K60S2,仿真完成后,可以直接将程序下载STC15F2K60S2 单片机中)。,76/88,计算机、仿真器和学习板连接示意图如图所示:,图5-2 计算机、仿真器和学习板连接示意图,77/88,2、软件设置用户程序中需要在0 x73的地址处保留6个字节。C语言程序,需在代码中添加如下语句:char code reserved

38、6 _at_ 0 x73;/在程序中进行声明汇编语言程序,需在代码中添加如下语句:CSEG AT 73H;在代码段33H定址 RESERVED:DS 6;保留6字节 或者 ORG 73H;在代码段33H定址 RESERVED:DB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH;保留6字节,78/88,对于汇编语言程序,复位入口的程序必须为跳转指令(建议使用长跳转),如:ORG 0;复位入口地址 LJMP RESET;使用LJMP指令;其它中断向量 ORG 73H;保留字节地址 RESERVED:DB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH;保留6字节 ORG

39、0100H;用户代码地址 RESET:;复位入口;用户代码,79/88,按照上述要求,将例5-1中的程序进行改写,改写后的程序如下:#include“stc15.h”/STC15F2K60S2单片机寄存器定义头文件 char code reserved6 _at_ 0 x73;/在程序中进行声明 sbit P10=P10;/定义P1.0引脚 void delay(unsigned long cnt);/延时函数声明 void main(void)P10=1;while(1)/主程序循环 delay(60000);P10=P10;void delay(unsigned long cnt)/延时函

40、数 while(cnt0)cnt-;,80/88,3、仿真代码占用的资源程序空间:5K字节(0 xDC000 xF3FF)RAM:0字节 XRAM:0字节 I/O:P3.0/P3.1,81/88,4、Keil环境中的设置设置晶振频率 使用ProjectOptions for Target Target命令打开选项设置窗口,如图所示。,在此编辑框中输入晶振频率,图5-3 设置晶振频率,82/88,设置Output选项 在“Output”选项中作如图所示的设置。选中“Create HEX File”复选框,Keil每进行一次Build,都生成可以下载到单片机的HEX文件。,选中“Create HE

41、X File”复选框,图5-4 设置“Output”属性,83/88,选择硬件仿真 在“Debug”选项卡中,选中右半部分中的“Use”,从下拉列表框中选择“Keil Monitor-51 Driver”,并选中“Run to main”选项。如图所示。,选择Keil Monitor-51 Driver,选中“Run to main”,图5-5 选择硬件仿真,84/88,设置串口 在图5-5中,单击“Settings”按钮,弹出串口设置对话框,如图所示。,Setting,选择串口号,图5-6 设置串口对话框,图5-5 选择硬件仿真,85/88,其中,RTS和DTR是PC机在和单片机通信时给单片

42、机的握手信号主要的任务是设置串口号,其他可以不改变。串口号是仿真时,仿真器所使用的串口号。如果采用了USB转RS232芯片,需要特别注意串口号的选择。选中“Serial Interrupt”选项可以在全速运行程序时暂停用户程序的执行。设置完成后,就可以进行程序的调试了。,86/88,使用仿真器进行程序的仿真时,需要注意如下问题:仿真器与计算机USB连接须等待10秒以上,等仿真器上电稳定后再进行程序的调试。每次调试程序之前,需要重新上电。对IAP_TRIG寄存器写0 x5A和0 xA5的语句不可单步调试 即不要仿真EEPROM功能。不能写PCON寄存器的第5位。程序中不能对P3.0和P3.1进行写操作。不要关中断。目前的版本不能全速运行程序。一旦全速运行,只能通过复位单片机来停止调试过程。EEPROM第一个扇区不能用。,87/88,图5-7无法调试时的弹出窗口,调试时,有时可能出现如图5-7所示的情形。,88/88,调试时若出现前图所示情况,可能的原因有以下几点keil的选项设置不正确,按照步骤4)重新设置。串口设置不正确,重新设置串口。程序正在全速运行或调试前单片机未复位,给学习板重新上电复位后再进行程序调试。把仿真器与电脑重新连接,等待10秒以上稳定后再调试程序。设置完成后,就可以采用与第四章中介绍的类似的方法进行程序的调试了。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/施工/环境 > 项目建议


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号