版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、 单片机资源的C51编程实例 C51数据的存储类型和存储模式 C51的数据类型与运算 单片机C语言概述 C51程序基本结构与相关语句 51单片机系统开发常用工具软件keil C51 C51的函数第10章 单片机C语言程序设计 单片机C语言概述 C51的数据类型与运算 C51数据的存储类型和存储模式 C51程序基本结构与相关语句 C51的函数 单片机资源的C51编程实例 51单片机系统开发常用工具软件keil C51本章知识点 随着单片机硬件性能的不断提高和应用技术的不断发展,开发者越来越注重目标系统的开发成效,而开发成效在很大程度上取决于程序本身的编写效率。为了适应这种要求,出现了单片机高级语
2、言C语言。 10.1 单片机C语言概述10.1.1 C语言的特点及程序结构 单片机的C语言编译器:德国的KEIL C51开发平台、加拿大DAVEDUNFIELD的MICRO-C51、美国Franklin软件公司的Franklin C51等。目前最流行的是Keil C51编译器。一C语言的特点1语言简洁、紧凑,使用方便、灵活。2运算符丰富。3数据结构丰富。具有现代化语言的各种数据结构。4可进行结构化程序设计。5可以直接对计算机硬件进行操作。6生成的目标代码质量高,程序执行效率高。7可移植性好。 C语言程序采用函数结构,每个C语言程序由一个或多个函数组成,在这些函数中至少应包含一个主函数main(
3、),也可以包含一个main()函数和若干个其它的功能函数。不管main()函数放于何处,程序总是从main()函数开始执行,执行到main()函数结束则结束。 二C语言的程序结构 用C51语言和汇编语言主要不同之处在于: 用汇编语言编写51单片机程序必须要考虑其存储器结构,尤其必须考虑其片内数据存储器与特殊功能寄存器的使用以及按实际地址处理端口数据。而用C51语言编写的51单片机应用程序,则不用具体组织、分配存储器资源和处理端口数据。但在C51语言编程中,对数据类型与变量的定义,必须要与单片机的存储结构相关联,否则编译器不能正确地映射定位。10.1.2 C语言与MCS-51单片机C51语言与标
4、准C语言程序区别: (1)C51中定义的库函数和标准C语言定义的库函数不同。后者是按通用微型计算机来定义的,而C51中的库函数是按MCS-51单片机相应情况来定义的; (2)数据类型有一定的区别。在C51中增加了几种针对MCS-51单片机特有的数据类型; (3)C51中变量的存储模式与MCS-51单片机的存储器紧密相关; (4)C51中的输入输出是通过MCS-51串行口来完成的,输入输出指令执行前必须要对串行口进行初始化; (5)C51中有专门的中断函数。10.2 C51的数据类型与运算 10.2.1 C51的数据类型 分为基本数据类型和扩展(组合)数据类型。基本数据类型除了标准C中的字符型(
5、char)、整型(int)、长整型(long)、单精浮点型(float)、双精浮点型(double)外,还有特殊功能寄存器型(sfr和sfr16两种)和位类型(bit和sbit两种)。扩展数据类型包括数组、指针型(*)以及结构(struct)和联合(union)等。表10-1 KEIL C51编译器支持的基本数据类型一字符型char signed char:用于定义带符号字节数据,其字节的最高位为符号位,“0”表示正数,“1”表示负数,补码表示,所能表示的数值范围是-128+127; unsigned char:用于定义无符号字节数据或字符,可以存放一个字节的无符号数,也可以存放西文字符,取值
6、范围为0255。 二int整型 分singed int和unsigned int。默认为signed int。它们的长度均为两个字节,用于存放一个双字节数据。对于signed int,用于存放两字节带符号数,补码表示,数的范畴为-32768+32767。对于unsigned int,用于存放两字节无符号数,数的范围为065535。三long长整型 分singed long和unsigned long。默认为signed long。它们的长度均为四个字节,用于存放一个四字节数据。对于signed long,用于存放四字节带符号数,补码表示,数的范畴为-2147483648+2147483647。
7、对于unsigned long,用于存放四字节无符号数,数的范围为04294967295。四float浮点型 长度为四个字节,包含指数和尾数两部分。最高位为符号位,“1”表示负数,“0”表示正数。单片机中使用浮点应注意以下三点: 由于单片机中没有专门的浮点运算硬件,因此在运算时会比较慢。 由于51单片机本身是8位的,因此在计算中不可能达到太高的精度。 与单精浮点相比,双精浮点型(double)具有更高的计算精度,但计算时间会更长,速度更慢,C51不支持双精浮点型。 五特殊功能寄存器型 分sfr和sfr16两种类型。 sfr:字节型特殊功能寄存器类型,占一个内存单元。利用它可以访问MCS-51内
8、部的所有特殊功能寄存器; sfr16:双字节型特殊功能寄存器类型,占用两个字节单元。利用它可以访问MCS-51内部的所有两个字节的特殊功能寄存器,如DPTR。 头文件reg51.h:包含了所有特殊功能寄存器和对其相应位的定义,通过在程序开头用#include reg51.h语句包含头文件可以很容易地进行新的扩展。【例10-1】特殊功能寄存器型数据定义。sfr SCON=0X98; /定义 SCONsbit SM0=0X9F; /定义 SCON 的各位sbit SM1=0X9E;sbit SM2=0X9D;sbit REN=0 x9C;sbit TB8=0X9B;sbit RB8=0X9A;sb
9、it TI=0X99;sbit RI=0X98;六位类型 功能:用于访问MCS-51单片机中的可寻址的位单元。 bit型:定义的位变量在C51编译器编译时,在不同的时候位地址是可以变化的。 sbit型:定义的位变量必须与MCS-51单片机的一个可以寻址位单元或可位寻址的字节单元中的某一位联系在一起。在C51编译器编译时,其对应的位地址是不可变化的。隐式转换:出现在运算中数据类型不一致时,按下列转换的优先级顺序: bitcharintlongfloat signedunsigned 例:当char型与int型进行运算时,先自动对char型扩展为int型,然后与int型进行运算,运算结果为int型
10、。 强制类型转换符“()”:对数据类型进行人为的强制转换。 10.2.2 关于指针型数据 指针(*)是一种特殊的数据类型,指向变量的地址,实质上指针就是存储单元的地址。 在C51中它的长度一般为13个字节。根据所指的变量类型不同,可以是字符型指针(char *)、整型指针(int *)、长整型指针(long *)、浮点型指针(float *)及结构指针(struct *)与联合指针(union *)。 1. 一般指针 一般指针的声明和使用均与标准C相同,不过同时还能说明指针的存储类型,例如: long * state; /为一个指向long型整数的指针,而state本身则依存储模式存放。 ch
11、ar * xdata ptr; /ptr为一个指向char数据的指针,而ptr本身放于外部RAM区。 一般指针本身用3个字节存放,分别为存储器类型、高位偏移量、低位偏移量。 2. 存储器指针 基于存储器的指针说明时即指定了存储类型,例如: char data * str; /str指向data区中char型数据。 int xdata * pow; /pow指向外部RAM的int型整数。 存放时,只需一个字节或2个字节就够了,因为只需存放偏移量。10.2.3 C51的运算符 运算符:完成某种特定运算的符号。C51常见的运算符有算术运算符、赋值运算符、关系运算符、逻辑运算符、按位运算符和联合(复合
12、赋值)运算符。除此之外,还有一些用于完成特殊任务的运算符,如逗号运算符、条件运算符、指针与地址运算符。1. 常见的运算符1). 算术运算符 在实际编程中,为了程序的简练,经常使用i+与+i这样的语句。i+是先进行运算,再执行i=i+1的操作;而+i则是先执行i=i+1的操作,再进行运算。 例:int x=0,y=0; y=x+; /执行后y的值仍为0 而 int x=0,y=0; y=+x; /执行后y的值则为12). 赋值运算符“=”功能:将一个数据的值赋给一个变量,如x=10。 赋值表达式:利用赋值运算符将一个变量与一个表达式连接起来的式子称为赋值表达式。 赋值语句:在赋值表达式的后面加一
13、个分号“;”就构成了赋值语句。一个赋值语句的格式如下: 变量=表达式; 执行时先计算出右边表达式的值,然后赋给左边的变量。例如:x=8+9; /将8+9的值赋绐变量x x=y=5; /将常数5同时赋给变量x和y 在C51中,允许在一个语句中同时给多个变量赋值,赋值顺序自右向左。 3). 关系运算符 C51中有6种关系运算符: 关系表达式通常用来作为判别条件构造分支或循环程序。关系表达式的一般形式如下: 表达式1 关系运算符 表达式2 关系运算的结果为逻辑量,成立为真(1),不成立为假(0)。其结果可以作为一个逻辑量参与逻辑运算。例如:53,结果为真(1),而10=100,结果为假(0)。注意:
14、关系运算符等于“=”是由两个“=”组成。4). 逻辑运算符C51有3种逻辑运算符:| 逻辑或& 逻辑与! 逻辑非 关系运算符用于反映两个表达式之间的大小关系,逻辑运算符则用于求条件式的逻辑值,用逻辑运算符将关系表达式或逻辑量连接起来的式子就是逻辑表达式。 逻辑与,格式: 条件式1 & 条件式2 当条件式1与条件式2都为真时结果为真(非0值),否则为假(0值)。逻辑或,格式: 条件式1 | 条件式2 当条件式1与条件式2都为假时结果为假(0值),否则为真(非0值)。逻辑非,格式: !条件式 当条件式原来为真(非0值),逻辑非后结果为假(0值)。当条件式原来为假(0值),逻辑非后结果为真(非0值)
15、。例如:若a=8,b=3,c=0,则!a为假,a & b为真,b & c为假。5). 位运算符 位运算是按位对变量进行运算,但并不改变参与运算的变量的值。如果要求按位改变变量的值,则要利用相应的赋值运算。C51中位运算符只能对整数进行操作,不能对浮点数进行操作。C51中的位运算符有:【例10-1】设a=0 x78=01111000B,b=0 x0f=00001111B,则a&b、a|b、ab、a、a2分别为多少?a&b=00001000b=0 x08;a|b=01111111B=0 x7f;ab=01110111B=0 x77;a=10000111B=0 x87;a2=00000011B=0
16、x03; 6). 联合(复合赋值)运算符 C51语言中支持在赋值运算符“=”的前面加上其它运算符,组成联合(复合赋值)。 联合运算的一般格式如下: 变量 联合运算符 表达式 处理过程:先把变量与后面的表达式进行某种运算,然后将运算的结果赋给前面的变量。例如:a+=b 相当于 a=a+b;a*=b 相当于 a=a*b;a&=b 相当于 a=a&b。7). 逗号运算符 “,”运算符将两个或两个以上的表达式连接起来,称为逗号表达式。逗号表达式的一般格式为: 表达式1,表达式2,表达式n处理过程:按从左至右的顺序依次计算出各个表达式的值,而整个逗号表达式的值是最右边的表达式(表达式n)的值。 例如:x
17、=(a=3,6*3)结果x的值为18。 8). 条件运算符 条件运算符“?:”是C51语言中唯一的一个三目运算符,条件表达式的一般格式为: 逻辑表达式?表达式1:表达式2其功能是先计算逻辑表达式的值,当逻辑表达式的值为真(非0值)时,将计算的表达式1的值作为整个条件表达式的值;当逻辑表达式的值为假(0值)时,将计算的表达式2的值作为整个条件表达式的值。 例如:条件表达式max=(ab) ? a:b的执行结果是将a和b中较大的数赋值给变量max。 9). 指针与地址运算符 变量的指针就是该变量的地址,还可以定义一个专门指向某个变量的地址的指针变量。 C51中提供了两个专门的运算符: * 指针运算
18、符 & 取地址运算符2. C51的运算量1). 常量 常量是指在程序执行过程中其值不能改变的量。C51支持整型常量、浮点型常量、字符型常量和字符串型常量。 整型常量 整型常量也就是整型常数,根据其值范围在计算机中分配不同的字节数来存放。十进制整数。如234、-56、0等。十六进制整数。以0 x开头表示,如0 x12表示十六进制数12H。长整数。在存储器中占四个字节,另外,如一个整数后面加一个字母L,这个数在存储器中也按长整型存放。如123L在存储器中占四个字节。 浮点型常量 浮点型常量也就是实型常数。有十进制表示形式和指数表示形式。 十进制表示形式又称定点表示形式,由数字和小数点组成。如 0.
19、123、38.645等都是十进制数表示形式的浮点型常量。 指数表示形式为: 数字 .数字 e 数字例如:123.456e-3、-3.123e2等都是指数形式的浮点型常量。 字符型常量字符型常量是用单引号引起的字符,如a、1、F等。可以是可显示的ASCII字符,也可以是不可显示的控制字符。对不可显示的控制字符须在前面加上反斜杠“”组成转义字符。利用它可以完成一些特殊功能和输出时的格式控制。常用的转义字符如表10-2所示。 字符串型常量 字符串型常量由双引号“”括起的字符组成。如“D”、“1234”、“ABCD”等。一个字符串常量在内存中存放时不仅双引号内的字符一个占一个字节,而且系统会自动的在后
20、面加一个转义字符“o”作为字符串结束符。不要将字符常量和字符串常量混淆,如字符常量A和字符串常量“A”是不一样的。2). 变量 变量定义的格式如下: 存储种类 数据类型说明符 存储器类型 变量名1=初值,变量名2初值; 变量名由字母、数字和下划线三种字符组成,且第一个字母必须为字母或下划线。 变量名有两种:普通变量名和指针变量名。它们的区别是指针变量名前面要带“*”号。 另外,在C51中,为了增加程序的可读性,允许用户为系统固有的数据类型说明符用typedef起别名,格式如下: typedef c51固有的数据类型说明符 别名; 定义别名后,就可以用别名代替数据类型说明符对变量进行定义。别名可
21、以用大写,也可以用小写,为了区别一般用大写字母表示。【例10-2】 typedef的使用。typedef unsigned int WORD;typedef unsigned char BYTE;BYTE a1=0 x12;WORD a2=0 x1234; 变量的存储种类是指变量在程序执行过程中的作用范围。C51变量的存储种类有四种,分别是自动(auto)、外部(extern)、静态(static)和寄存器(register)。 auto 使用auto定义的变量称为自动变量,其作用范围在定义它的函数体或复合语句内部,自动变量一般分配在内存的堆栈空间中。定义变量时,如果省略存储种类,则该变量默认
22、为自动(auto)变量。 extern使用extern定义的变量称为外部变量。在一个函数体内,要使用一个已在该函数体外或别的程序中定义过的外部变量时,该变量在该函数体内要用extern说明。外部变量被定义后分配固定的内存空间,在程序整个执行时间内都有效,直到程序结束才释放。 static使用static定义的变量称为静态变量。它又分为内部静态变量和外部静态变量。在函数体内部定义的静态变量为内部静态变量,它在对应的函数体内有效;外部静态变量是在函数外部定义的静态变量。 register使用register定义的变量称为寄存器变量。它定义的变量存放在CPU内部的寄存器中,处理速度快,但数目少。C5
23、1编译器编译时能自动识别程序中使用频率最高的变量,并自动将其作为寄存器变量,用户可以无需专门声明。3). 位变量在C51中,允许用户通过位类型符定义位变量。位类型符有两个:bit和sbit。可以定义两种位变量。bit位类型符用于定义一般的可位处理位变量。它的格式如下: bit 位变量名; sbit位类型符用于定义在可位寻址字节或特殊功能寄存器中的位,定义时须指明其位地址,可以是位直接地址,也可以是可位寻址变量带位号,还可以是特殊功能寄存器名带位号。格式如下: 格式一: sbit位变量名=特殊功能寄存器名带位号; 例如:sbit OV=PSW2 ; / 定义OV位为PSW.2,地址为D2H sb
24、it CY=PSW7 ; / 定义CY位为PSW.7,地址为D7H 格式二:sbit位变量名= 寄存器的字节地址带位号;例如: sbit OV=0XD02 ;/ 定义OV位地址是D0H字节中的第2位 sbit CY=0XD07 ;/ 定义CY位地址是D0H字节中的第7位格式三:sbit 位变量名= 寻址位的绝对位地址;例如: sbit OV=0XD2 ;/ 定义OV位地址为D2H sbit CY=0XD7 ;/ 定义CY位地址为D7H 特殊功能位代表了一个独立的定义类,不能与其它位定义和位域互换。 4). 特殊功能寄存器变量 C51定义特殊功能寄存器变量的一般语法格式如下:sfr/sfr16
25、sfr-name = int constant; 或写为: sfr(或sfr16) 特殊功能寄存器名=地址(整型常数); sfr16用于对双字节特殊功能寄存器进行定义,特殊功能寄存器名一般用大写字母表示。地址一般用直接地址形式,以整型常数表示,范围必须在SFR地址范围内,位于0 x800 xFF,不允许带有运算符的表达式。【例10-3】特殊功能寄存器的定义举例。 sfr SCON=0 x98; / 串口控制寄存器地址98H sfr TMOD=0 x89; / 定时器/计数器方式控制寄存器地址89H sfr P1=0 x90; /P1口的地址90H sfr16 DPTR=0 x82; /数据指针
26、DPTR的地址82H10.3.1 数据的存储类型 定义变量类型时,还必须定义它的存储类型,变量的存储类型是用于指明变量所处的单片机的存储器区域情况。C51编译器能识别的存储类型有以下几种,如表10-3所示。 10.3 数据的存储类型和存储模式表10-3 C51的变量的存储类型及其数据长度和值域 带存储类型的变量的定义的一般格式为: 数据类型 存储类型 变量名 访问内部数据存储器(idata)比访问外部数据存储器(xdata)相对要快一些。因此,可将经常使用的变量置于内部数据存储器中,而将较大及很少使用的数据变量置于外部数据存储器中。例如定义变量x语句:data char x (等价于char
27、data x)。【例10-4】变量定义过程中存储种类和存储器类型举例。 char data varl; /在片内RAM低128B定义用直接寻址方式访问的字符型变量var1 int idata var2; /在片内RAM256B定义用间接寻址方式访问的整型变量var2 unsigned int pdata sion; /在片外RAM的低256B定义无符号整型变量sion 【例10-5】 带存储类型的bit型变量的定义。bit data a1; /正确bit bdata a2; /正确bit pdata a3; /错误bit xdata a4; /错误 10.3.2 存储模式 1. SMALL模式
28、: SMALL模式称为小编译模式。在SMALL模式下,编译时参数及局部变量放入可直接寻址片内RAM的用户区中(最大128字节)。一般来说,如果系统所需要的内存数小于内部RAM 数时都应以小存储模式进行编译。优点:存取速度很快缺点:供用户使用的存储空间小。 2. COMPACT模式: COMPACT模式称为紧凑编译模式。在COMPACT模式下,编译时函数参数及局部变量被放在片外RAM的低256字节空间,通过R0或R1间接访问,存储器类型为pdata。 3. LARGE模式: LARGE模式称为大编译模式。在LARGE模式下,编译时函数参数和局部变量被默认在片外RAM的64K字节空间,使用数据指针
29、DPTR来进行寻址,存储器类型为xdata。用此数据指针进行访问效率较低,尤其对两个或多个字节的变量,这种数据类型的访问机制直接影响代码的长度。【例10-6】变量的存储模式。#pragma small /变量的存储模式为SMALLchar k1;int xdata m1;#pragma compact /变量的存储模式为SMALLchar k2;int xdata m2;int func1(int x1, int y1) large /函数的存储模式为LARGEreturn(x1+y1);int func2(int x2, int y2) /函数的存储模式隐含为SMALL return(x2-
30、y2); C51程序与标准的C程序在以下几个方面不同: 1C51中定义的库函数和标准C语言定义的库函数不同。标准的C语言定义的库函数是按通用微型计算机来定义的,而C51中的库函数是按MCS-51单片机相应情况来定义的; 2 C51中的数据类型与标准C的数据类型也有一定的区别。在C51中还增加了几种针对MCS-51单片机特有的数据类型; 10.4 C51程序基本结构与相关语句 3变量的存储模式不一样。C51中变量的存储模式是与MCS-51单片机的存储器紧密相关; 4 输入输出处理不一样。C51中的输入输出是通过MCS-51串行口来完成的,输入输出指令执行前必须要对串行口进行初始化; 5 C51与
31、标准C在函数使用方面也有一定的区别,C51中有专门的中断函数。10.4.1 C51程序基本结构 C语言程序的一般组成结构如下所示: 全局变量说明 /可被各函数引用 main( ) /主函数 局部变量说明 /只在本函数引用执行语句(包括函数调用语句) fun1(形式参数表) /函数1 形式参数说明局部变量说明 执行语句(包括调用其他函数语句)funn(形式参数表) /函数n形式参数说明 局部变量说明 执行语句 1顺序结构 顺序结构程序是仅包含一个main( )函数的简单程序,程序只由低地址向高地址顺序执行指令代码,适当运用表达式语句就能设计出具有某特定功能的顺序结构C51程序。虽然该程序设计方法
32、简单,但在具体运用中的算法仍然采用自顶向下逐步求精的方法进行设计。2选择结构 也称为分支结构。当条件成立,即条件语句为“真”时,执行一个分支,当条件不成立时,即条件语句为“假”时,执行另一个分支。在C51中,实现选择结构的语句为if-else,if-else-if语句。另外在C51中还支持多分支结构,多分支结构既可以通过if和else if语句嵌套实 3. 循环结构 循环结构的特点是:在给定条件成立时,反复执行某程序段,直到条件不成立时为止。循环结构有两种形式:当型循环和直到型循环,这和其它高级语言相同,不再赘述。在C51中,可以构成循环结构的语句主要有:while、do while、for、
33、goto等。10.4.1 C51相关语句 1. if 语句 if 语句一共有3种语句形式,分别简述如下: 1). if 语句,格式如下: if(表达式)语句; 处理机理是:如果表达式为真,则执行语句,否则不执行该语句。当花括号中的语句不只一条,花括号不能省。 如 if (a=b) a+; /当a等于b时,a就加1 再如if (x!=y) printf(“x=%d, y=%dn”, x, y); /如果x不等于y,则输出x的值和y的值 2). if-else语句,格式如下: if (表达式)语句1; else语句2; 处理机理是:当条件表达式成立时,就执行语句1,否则就执行语句2 如: if (
34、a=b) a+; else a-; 当a等于b时,a加1,否则a-1。 3). if-else多重嵌套语句,格式如下: if (条件表达式1) 语句1 else if (条件表达式2) 语句2 else if (条件表达式3) 语句3 else if (条件表达式m) 语句n else 语句m 实现多方向条件分支,使用应注意if 和else的配对使用,记住else 总是与最临近的if 相配对。 如果分支数量较多时最好选用下面将要介绍的switch开关语句。 2. switch语句 又称开关语句,它可以从多种情况中选择满足条件的一种情况,是多分支选择结构语句。 它的格式如下:switch (表达
35、式)case 常量表达式1:语句1;break; case 常量表达式2:语句2;break; case 常量表达式n:语句n;break; default:语句n+1;【例10-7】 根据flag的值设置上(up)下(down)左(left)右(right)标志位void main( ) unsigned int flag=0, up=0, down=0, left=0, right=0;switch(flag) case 1:up=1;break; /置标志case 2:down=1;break;case 3:left=1;break;case 4:right=1;break;defaul
36、t:error=1;break; 本例中输入一个无符号整数,经switch判断后,将相应标志置1,若整数不在14的范围内时就输出“error”。 3. for语句 for循环控制语句的语法结构如下: f or(表达式1; 表达式2; 表达式3) 处理程序; 处理机理是:首先计算“表达式1”的值;再计算“表达式2”的值,若值为“真”则执行循环体一次,否则跳出循环;然后再计算“表达式3”的值,转回第2步重复执行。在整个for循环过程中,“表达式1”只计算一次,作为for的入口语句条件,“表达式2”和“表达式3”则可能计算多次。循环体也可能多次执行,也可能一次都不执行。例如:void main( )
37、int n, sum=0;for(n=0; n=50; n+)sum+=n;在使用for语句中有几点要特别注意:. 循环体内的处理程序可以为空操作;. for语句的各表达式都可以省略,而分号不能省略。在省略各表达式时要特别小心分析,防止造成无限死循环。 4. while语句 实现当型循环结构,它的格式如下: while(表达式) 语句; /循环体 当表达式为非0(真)时,就重复执行循环体内的语句;当表达式为0(假)时,则中止while循环,程序将执行循环结构之外的下一条语句。它的特点是: 先判断条件,后执行循环体。如条件第一次就不成立,则循环体一次也不执行。 【例10-8】 下面程序是通过wh
38、ile语句实现计算并输出1100的累加和。#include /包含特殊功能寄存器库#include /包含I/O函数库void main(void) /主函数 int i, s=0; /定义整型变量x和y i=1; SCON=0 x52; /串口初始化 TMOD=0 x20; TH1=0 xf3; TR1=1; while (i=100) /累加1100之和在s中 s=s+i; i+; printf(“1+2+3+100=%dn”, s); while(1); 5. do while语句 do while语句在C51中用于实现直到型循环结构,它的格式如下: do 语句; /循环体 while(
39、表达式); 它的特点是:先执行循环体中的语句,后判断表达式。如表达式成立(真),则再执行循环体,然后又判断,直到有表达式不成立(假)时,退出循环,执行do while结构的下一条语句。【例10-9】 通过do while语句实现计算并输出1100的累加和。#include /包含特殊功能寄存器库#include /包含I/O函数库void main(void) /主函数 int i, s=0; /定义整型变量x和y i=1; SCON=0 x52; /串口初始化 TMOD=0 x20; TH1=0XF3; TR1=1; do /累加1100之和在s中 s=s+i; i+; while (i=1
40、00); printf(“1+2+3+100=n”, s); while(1); 6. break和continue语句 1)break语句 用break语句可以跳出switch结构,使程序继续执行switch结构后面的一个语句。使用break语句还可以从循环体中跳出循环,提前结束循环而接着执行循环结构下面的语句。它不能用在除了循环语句和switch语句之外的任何其它语句中。 【例10-10】用C51编程计算圆的面积,当计算到面积大于100时,由break语句跳出循环。for (r=1; r100) break; printf(“%fn”, area); 2).continue语句 conti
41、nue语句用于结束本次循环,跳过循环体中continue下面尚未执行的语句,直接进行下一次是否执行循环的判定。 continue语句和break语句的区别在于:continue语句只是结束本次循环而不是终止整个循环;break语句则是结束循环,不再进行条件判断。 【例10-11】输出100200间不能被3整除的数。for (i=100; i=200; i+) if (i%3=0) continue; printf(“%d ” ; i ); 在程序中,当i能被3整除时,执行continue语句,结束本次循环,跳过printf()函数,只有能被3整除时才执行printf()函数。7.return语
42、句 return语句放在函数的最后位置,用于终止函数的执行,并控制程序返回调用该函数时所处的位置。返回时还可以通过return语句带回返回值。格式有两种: 1).return; 2).return (表达式); 如果后面带有表达式,则要计算表达式的值,并将表达式的值作为函数的返回值。若不带表达式,则函数返回时将返回一个不确定的值。 8.goto语句 goto是一个无条件的转向语句,只要执行到这个语句,程序指针就会跳转到goto后的标号所在的程序段。语法如下: goto 语句标号;其中的语句标号为一个带冒号的标识符。 【例10-12】void main(void) unsigned char a
43、; start: a+; if (a=10) goto end; goto start; end:; 该程序是一个死循环,只是说明一下goto的用法。这段程序的意思是在程序开始处用标识符start:标识,表示程序这是程序的开始,end:标识程序的结束,程序执行a+,a的值加1,当a等于10时程序会跳到end标识处结束程序,否则跳回到start标识处继续a+,直到a等于10。 函数是C51程序的基本单位,一个C51程序就是一堆函数的集合,有且只有一个名为main的函数(主函数)。 C51中函数分为两大类,一类是库函数,一类是用户定义函数库函数:用户在编程时只要用include预处理指令将头文件包
44、含在用户文件中,直接调用即可。用户函数是用户自己定义和调用的一类函数。 一个函数在程序中可以有三种形态:函数定义、函数调用和函数说明。10.5 C51的函数 1. 函数的定义 C51函数定义的一般格式如下: 函数类型 函数名(形式参数表) reentrantinterrupt musing n 形式参数说明局部变量定义函数体 有关修饰符interrupt m和using n的介绍见10.6.3节。 2函数的调用 函数调用的一般形式如下: 函数名(实参列表); 函数调用方式有以下三种: 1). 函数语句。把被调用函数作为主调用函数的一个语句。 2). 函数表达式。函数被放在一个表达式中,以一个运
45、算对象的方式出现。 3). 函数参数。被调用函数作为另一个函数的参数。 3. 自定义函数的声明 在C51中,函数原型一般形式如下: extern 函数类型 函数名(形式参数表); 函数的声明是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便调用函数时系统进行对照检查。函数的声明后面要加分号。 如果声明的函数不在文件内部,声明时须带extern【例10-13】外部函数的使用 程序serial_initial.c#include /包含特殊功能寄存器库#include /包含I/O函数库void serial_initial(void) /主函数 SCON=0 x52; /串口初
46、始化 TMOD=0 x20; TH1=0XF3; TR1=1; 程序x.c#include /包含特殊功能寄存器库#include /包含I/O函数库extern serial_initial();void main(void) int a, b; serial_initial(); scanf(“please input a, b:%d, %d”, &a, &b); printf(“n”); printf(“max is:%dn”, a=b?a:b); while(1); 上述程序x.c中,由于函数serial_initial( )不在文件内部,而在另一个文件中,因此在声明时带了extern
47、。10.6.1 C51程序的反汇编程序 【例10-14】用C51语言编程完成外部RAM的000EH单元和000FH单元的内容交换。 #include /该头文件的主要功能是通过定义的宏来访问绝对地址 main( ) char c; for( ; ; ) c=XBYTE0 x000E; XBYTE0 x000E=XBYTE0 x000F; XBYTE0 x000F=c; 10.6 单片机资源的C51编程实例 程序中为方便反复观察,使用了死循环语句for( ; ; )只要用Ctrl+C即可退出死循环。上面程序通过编译,生成的机器代码和反汇编程序如下:0000 020014 LJMP 0014H 0
48、003 90000E MOV DPTR,#000EH0006 E0 MOVX A,DPTR0007 FF MOV R7,A0008 A3 INC DPTR 0009 E0 MOVX A,DPTR000A 90000E MOV DPTR,#000EH 000D F0 MOVX DPTR,A 000E A3 INC DPTR 000F EF MOV A,R70010 F0 MOVX DPTR,A 0011 80F0 SJMP 0003H 0013 22 RET 0014 787F MOV R0,#7FH 0016 E4 CLR A 0017 F6 MOV R0,A 0018 D8FD DJNZ R
49、0,0017H 001A 758107 MOV SP,#07H 001D 020003 LJMP 0003H 从本例可以看出: 1.一进入C语言程序,首先执行初始化,将内部RAM的07FH 128个单元清零,然后置SP为07H(视变量多少不同,SP置不同值,依程序而定) 2. C语言程序设定的变量,C51自行安排寄存器或存储器作参数传递区,通常在R0R7(一组或两组,视参数多少定) 3. 如果不特别指定变量的存储类型,通常被安排在内部RAM中。 10.6.2 并行口及键盘、显示器接口的C51编程【例10-15】设P1口做输出口,接八只发光二极管,编写程序,使发光二极管循环点亮。 说明:由准双向
50、口结构可知当P1口用为输入口时,必须先对它置“1”。 P1口循环点灯的C51程序如下:#include void delay( ) /定义延时函数 unsigned int i; for (i=0; i20000; i+) void main() unsigned char index; unsigned char LED; while (1) LED = 1; for (index=0; index 8; index+) P1 = LED; LED = 1; /右移一位 delay( ); 【例10-16】 将AT89C51单片机的P0.0p0.7分别和一位共阴数码管的ah的笔段相连接,数码
51、管的公共端接地,用C51编程让数码管循环显示09十个数字的功能,时间间隔0.2秒。对应的C51程序如下:#include unsigned char code table=0 x3f,0 x06,0 x5b,0 x4f,0 x66, 0 x6d,0 x7d,0 x07,0 x7f,0 x6f; /共阴极数码管字型码表unsigned char dispcount; void delay02s(void) /定义延时函数 unsigned char i,j,k; for(i=20;i0;i-) for(j=20;j0;j-) for(k=248;k0;k-); void main(void) w
52、hile(1) for(dispcount=0;dispcount10;dispcount+) P0=tabledispcount; delay02s( ); 【例10-17】如图10-1所示,行列式键盘接口中以P1.0P1.3作输出线,以P1.4P1.7作输入线,编写相应的键盘扫描处理程序。 图10-1 44矩阵键盘 C51程序清单如下:#include#define uchar unsigned char#define uint unsigned intvoid dlms (void);uchar kbscan(void); / 函数说明void main (void); uchar ke
53、y; while (1) key=kbscan( ); / 键盘扫描函数,返回键码送key保存 dlms( ); void dlms (void) / 延时 uchar i; for (i=200;i0;i- -) uchar kbscan(void) / 键盘扫描函数 uchar sccode,recode; P1=0 xf0; /P1.0P1.3发全0,P1.4P1.7输入 if ( (P1 & 0 xf0)! =0 xf0) /如P1口高四位不全为1有键按下 dlms( ); / 延时去抖动 if ( (P1 & 0 xf0) ! =0 xf0) / 在读输入值 sccode =0 xf
54、e / 最低位置0 while ( ( sccode & 0 x10)! =0) / 不到最后一行循环 P1 =sccode; /P1口输出扫描码 If ( (P1 & 0 xf0)! =0 xf0) / 如P1.4P1.7不全为1,该行有键按下 recode = (P1 & 0 xf0; ); / 保留P1口高四位,低四位变“1”,作为列值 return( (sccode) + (recode) ); /行码+列值=键编码返回主程序 else sccode =(sccode1) | 0 x01; / 如该行无键按下,查下一行,行扫描值左移一位 return(0); / 无键按下,返回值为0
55、10.6.3 C51中断程序的编制 中断服务程序定义为函数,函数的完整定义如下。 返回值 函数名(参数)模式再入interrupt musing n 必选项 interrupt m表示将函数声明为中断服务函数,系统编译时把对应函数转化为中断函数,自动加上程序头段和尾段,并按MCS-51系统中断的处理方式自动把它安排在程序存储器中的相应位置。m可以是031间的整数,对应的中断情况如下:0外部中断01定时/计数器T02外部中断13定时/计数器T14串行口中断5定时/计数器T2 其它值预留。 C51编译器对中断函数编译时会自动在程序开始处对ACC、B、DPH、DPL和PSW入栈,结束时出栈。可选修饰
56、符using n用于指定本函数内部使用的工作寄存器组,其中n的取值为03,表示寄存器组号。【例10-18】编写一个用于统计外中断0的中断次数的中断服务程序extern int x;void int0( ) interrupt 0 using 1 x+; 本例中加入using 1后,C51在编译时自动的在函数的开始处和结束处加入以下指令: PUSH PSW; / 标志寄存器入栈 MOV PSW,#; / 修改PSW中的工作寄存器组选择位 POP PSW; / 标志寄存器出栈10.6.4 定时/计数器的C51编程【例10-19】 设单片机的晶体振荡频率fosc=6MHz,要求在P1.7脚上输出周期
57、为4ms的方波,编写相应的控制程序。分析:周期为4ms的方波要求定时时间隔2ms,每次时间到P1.7取反。 机器周期=12/fosc=2s 需计数次数=2000/(12/fosc)=2000/2=600 由于计数器是加1计数,为得到600个计数之后的定时器溢出,必须给定时器置初值为-600(即600的补数)。方法一:采用查询式控制方式,选用定时器0,工作于方式1,编程如下: # include sbit P1_7=P17 ; void main(void) TMOD=0 x01; / 设置定时器1为非门控制方式1 TR0=1 ; / 启动定时器/计数器T0 for( ; ; ) TH0= -(
58、600/256) ; / 装载计数器初值 TL0= -(600%256) ; do while (!TF0) ; / 查询等待TF0置位 P1_7=!P1_7; / 定时时间到P1.7反相 TF0=0; / 软件清 TF0 方法二:采用中断控制方式,仍选用用定时器0,工作于方式1。程序如下: # include sbit P1_7=P17 ; void time (void) interrupt 1 using 1 / 定时器/计数器T0中断服务程序入口 P1_7=!P1_7 ; / P1.7取反 TH0= -(600/256); / 重新装载计数初值 void main(void) TMOD=0 x01 ; / T0工作在定时器非门控制方式1 P1_7=0; TH0= -(600/256 ); / 预置计数初值 TL0= -(600%256) ; EA=1 ; / CPU中断开放 ET0= 1 ; / 定时器/计数器T0中断开放 TR0=1 ; / 启动T0开始定时 do while(1) ; / 等待中断 10.6.5 串行通信的C
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- NB/T 11821-2025煤层气资源勘查设计规范
- 2026届辽宁省盘锦市双台子区一中学初三(数学试题理)4月第一次综合练习试卷含解析
- 护理课件制作软件的数据分析优化
- 2026年大学大一(机械电子工程)液压与气压传动阶段测试题及答案
- 遂宁职业规划教学方案
- 英语专业就业方向解析
- 2025年前台防疫接待礼仪练习题
- 护理学导论急救护理技能
- 放飞想象 赏析习作-六上“变形记”习作教学
- 物资出入库、盘点管理制度
- 城市轨道交通行车值班员理论考试题库及答案
- 结核病的知识讲座
- 烟草公司物流中心装卸业务服务方案
- 园林植物主要食叶害虫及防治
- 景观绿化工程安全生产操作规程
- 《Linux网络操作系统管理》教学教案
- GB/T 18910.201-2021液晶显示器件第20-1部分:目检单色液晶显示屏
- 服饰配件设计1课件
- 市政工程监理交底书
- 2022年徐州生物工程职业技术学院单招职业技能考试笔试试题及答案解析
- ××团支部换届选举选票
评论
0/150
提交评论