《单片机(微控制器)原理及应用》第9章C51语言程序设计_第1页
《单片机(微控制器)原理及应用》第9章C51语言程序设计_第2页
《单片机(微控制器)原理及应用》第9章C51语言程序设计_第3页
《单片机(微控制器)原理及应用》第9章C51语言程序设计_第4页
《单片机(微控制器)原理及应用》第9章C51语言程序设计_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

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

文档简介

第9章C51语言程序设计

教学目的:了解C51语言与通用C语言的不同处(扩展特点)和应用于单片机编程时的主要特点及使用注意事项教学重点:1.C51支持的数据类型

2.C51数据的存储类型

教学难点:C51语言对单片机硬件的访问

9.1单片机的C51语言概述

9.1.1C51语言的主要优点1.不要求对单片机的指令系统十分熟悉2.易于表达,使用方便3.C51语言程序容易移植4.具有丰富的库函数5.源代码可读性较强,容易理解和编程

9.1.2C51语言的运算符及表达式运算符或表达式是构成C51程序的各种语句,因而这是C51的基础知识。9.1.3C51语言的程序结构

9.1.4C51语言的流程控制语句1.选择结构在C51中实现选择的语句主要是:if,switch/case。2.循环结构在C51中可实现循环的语句为:while,do−while,for9.2C51语言对通用C语言的扩展

9.2.1数据的存储类型C51编译器支持80C51的存储器结构,能够访问80C51的所有存储器空间。针对80C51存储空间的多样性,制定了修饰存储空间的修饰符,用以指明所定义的变量应分配在什么样的存储空间。1.程序存储区程序(CODE)存储区是只读的,不能写入。硬件决定最多只能有64KB的程序存储区。定义举例:charcodetext[]="ENTER";/*在代码段定义了一个字符型数组*/2.内部数据存储区内部数据存储区是可读、可写的。80C51系列最多可有256字节的内部数据存储区。内部数据区可以分成三个不同的存储类型data、idata

和bdata。

定义举例:chardatavr

;/*定义字符变量vr在data存储区*/floatidatax,y;/*定义浮点变量x,y在idata存储区*/bitbdataflags;/*定义位变量flags在bdata存储区*/。3.外部数据存储区外部数据存储区是可读、可写的。可通过一个数据指针加载一个地址间接访问外部数据区。因此,访问外部数据存储区的速度比访问内部数据存储区慢。定义举例:unsignedlongxdataarray[100];/*定义无符号长整型数组array[100]在片外数据存储区*/unsignedint

pdatadimension;/*定义无符号整型数dimension在一页范围内的片外数据存储区*/unsignedcharxdatavector[10][4][4];/*定义无符号字符型三维数组变量vector[10][4][4]在片外数据存储区*/charbdataflags;/*定义字符型变量flags位于片内位寻址区*/4.存储模式在C51编译器中,可以用控制命令SMALL,COMPACT和LARGE定义存储模式,用以指明所定义变量的默认存储器类型。在定义变量时,如果已经指定存储器类型,就不必加上述存储模式命令。9.2.2数据类型在C51程序中用到的变量一定要先定义数据类型,定义之后C51编译器才能在内存中按数据类型长度给该变量分配空间,C51支持的各种规格的数据类型列于表9−2。除了这些数据类型以外,变量可以组合成结构、联合及数组。在用C51语言编写单片机程序时,需要根据单片机的存储器结构和内部资源定义相应的数据类型和变量。1.bit

类型bit数据类型可以定义一个位变量,可能在变量声明参数列表和函数返回值中有用。例如bitbdataag1; /*定义ag1为位变量*/2.sbit、sfr和sfr16数据类型

80C51系列单片机用特殊功能寄存器SFR来控制计时器、计数器、串口、并口和外围设备。它们可以用位、字节和字访问。与此对应,编译器提供sbit、sfrs和sfr16数据类型访问SFR。1)sfr

类型sfr和C的其他变量一样声明。例如:

sfrP0=0x80; /*定义80C51的P0口,地址为80h*/2)sfr16类型编译器提供sfr16数据类型,将两个8位的SFR作为一个16位的SFR来访问。访问该16位的SFR只能是低字节跟着高字节,即将低字节的地址用作sfr16声明的地址。例如:sfr16DPTR=0x82;/*定义数据指针DPL的地址为082H,DPH的地址为083H*/3)sbit

类型编译器用sbit数据类型访问可位寻址的SFR中的位。例如:

sbitEA=0xAF;/*定义EA位的地址为0AFH*/9.2.3指针指针用于间接访问变量,正确使用指针,可以有效地表示复杂的数据结构,直接处理内存地址,并可以有效方便地使用数组。1.指针的概念变量的指针−−−−−在C语言中变量的指针是该变量的地址。指针变量−−−−−−用于存放“变量的指针”的变量称为指针变量。

2.指针变量的定义C语言规定所有的变量在使用前必须定义,以确定其类型。指针定义的一般形式为:类型识别符[存储器类型]*指针变量名(*表示该变量为指针变量)char*s; /*定义一个指向字符串变量的指针变量s*/

3.存储器指针 基于存储器的指针在定义时要包含一个存储器类型说明,在编译时才被确定。例如:chardata*str;/*在data区域中定义一个指向字符串变量的指针变量str,指针为1字节长*/

4.指针变量的引用 在对变量、指针变量定义之后,就可以用指针进行间接访问了。下面举例说明。

intx;/*定义整型变量x*/

inta;/*定义整型变量a*/a=10;/*给整型变量a赋值为10*/int*sp;/*定义指针变量sp*/sp=&a;/*通过取地址运算符&使sp指向变量a的地址*/x=*sp;/*整型变量a的值10通过间接寻址的方法赋给x*/在对变量、指针变量定义之后,C编译器会自动给它们在内存中安排相应的内存单元。在此,特别要注意“*”在不同的场合所代表的含义是不同的,例如:int*sp; 此时的*为指针变量说明符。x=*sp;此时的*为指针变量sp的运算符,即把sp所指向的变量值赋给x。

9.2.4函数

C语言程序是由函数构成的,函数是C语言程序中的基本模块,C51函数分为2类,一类是库函数,一类是用户定义函数。C51中函数的定义、参数和函数值及函数调用等内容与标准C语言基本相同,下面仅说明几个不同点。1.寄存器组的切换(using修饰符的应用)void函数标识符(形参表) usingn2.中断服务程序(interrupt修饰符的应用)void函数标识符(void) interruptm[usingn]9.2.5C51语言对单片机硬件的访问

1.访问特殊功能寄存器

在C51中定义了一个头文件:reg51.h(对于52系列,如AT89S52是reg52.h),它定义了80C51的所有功能寄存器和中断,在C51语言的源程序中采用#include<reg51.h>就可包含这个文件,在包含了这个文件后,程序就可以识别这些寄存器以及可位寻址的寄存器位的符号。例如:

#include<reg51.h>/*包含寄存器头文件*/2.访问存储器 在C51中可以通过变量的形式访问存储器,也可以通过绝对地址访问存储器。对绝对地址的访问主要有3种形式。1)采用C51中的预定义宏#defineCBYTE((unsignedcharvolatilecode*)0)#defineDBYTE((unsignedcharvolatiledata*)0)…………#defineXWORD((unsignedintvolatilexdata*)0)例如ucharvar1;

uintvar2;

var1=DBYTE[0x30];/*把data区中30h地址单元中的数赋给var1*/ var2=XBYTE[0x1000];/*把xdata区中1000h地址单元中的数赋给var2*/ …….2)通过指针访问采用指针可以不关心具体地址指针,但也可以实现对任意指定存储单元的访问。例如:uchardatavar1;uchardata*dp1;/*定义一个data区中指针dp1*/uint

xdata*dp2;/*定义一个xdata区中指针dp2*/uchar

pdata*dp3;/*定义一个pdata区中指针dp3*/dp1=&var1;/*取data区中变量var1的指针*/*dp1=0xa0; /*给变量var1赋值a0h*/dp2=0x2000;/*dp2指针赋值,指向xdata区的2000h*/*dp2=0x16;/*将数据16h送到片外RAM区的2000h单元*/ dp3=0x20; /*dp3指针赋值,指向pdata区的20h*/ *dp3=0x80; /*将数据80h送到pdata区的20h单元*/3)采用扩展关键字_at_采用扩展关键字_at_访问存储器绝对地址的一般格式如下:

[存储器类型]数据类型说明符变量名_at_地址常数 例如:

dataucharx1_at_0x20;/*在data区中定义字符变量的地址为20h*/

xdata

uintx2_at_0x2000;/*在xdata区中定义整数变量的地址为2000h*/ 3.访问外围接口器件地址 采用扩展外设的方法,扩展的I/O口采取与数据存储器相同的寻址方法,与片外数据存储器统一编址,可以采取上述寻址方法的任何一种。例如假设一块8255A芯片的命令口地址确定为ffadh,A口地址确定为ffaah,那么在程序中可以如下编制:

#definePD8255XBYTE[0xffad]/*定义命令口地址在片外RAM的ffadh*/#definePA8255XBYTE[0xffaa]/*定义A口地址在片外RAM的ffaah*/ PD8255=0X80;/*给命令口赋值*/PA8255=0XFF; /*给A口赋值*/

9.3C51语言编程举例

例1采用7.4.2的例1,该题用C51语言编程如下:#include<REG51.H>/*包含SFR的头文件*/#include<stdio.h>/*包含标准I/O功能的头文件*/sbitOUT=P1^0;/*定义OUT为P1.0位*/voidmain(void){TMOD=0x01;

TL0=0xf0;

TH0=0xD8;//置10mS定时初值

IE=0x82;//CPU,T0开中断

TR0=1; //启动定时器T0while(1){};//循环等待定时到

}//中断服务程序void timer0int() interrupt1{TL0+=0xf0;

TH0=0xD8;//置10mS定时初值

OUT=~OUT;//P1.0位取反

}例2.采用7.4.2的例2,该题用C51语言编程如下:#include<REG51.H>/*包含SFR的头文件*/#include<stdio.h>/*包含标准I/O功能的头文件*/unsignedchardatacount_at_0x50;sbitOUT1=P1^2;/*定义OUT1为P1.2位*/sbitOUT2=P1^4;/*定义OUT2为P1.4位*/voidmain(void){TL0=0x9C;//置T0计数100的初值

TH0=0xFF;TL1=0xf0;//置T110ms初值

TH1=0xD8;

TMOD=0x15;//设置T1为方式1定时,T0为方式1计数

TCON=0x50;//启动定时器T0,定时器T1 count=0;//计数单元清0 OUT1=1;//P1.2置为高

IE=0x82;//CPU,T0开中断

while(1){};}//T0中断服务程序void timer0int() interrupt1 { TL0+=0x9C;

TH0=0xFF;//置10mS定时初值

count++;

if(count>=100) { OUT1=0;//计数到,P1.2脚输出低电平

IE=0x88;//关T0中断,开T1中断

TR0=0;

} }//T1中断服务程序void timer1int() interrupt3/*定义函数名为timer1的定时器1中断3服务函数*/{TL1+=0xf0;

TH1=0xD8;//置10mS定时初值

OUT2=~OUT2;//P1.4取反

}源程序如下:

ORG 0000HLJMP MAIN …..ORG 000BH;T0中断入口

LJMP SUB1;转T0中断服务程序入口

例3.采用7.4.2的例3,该题用C51语言编程如下:/*------甲机发送程序--------*/#include<REG51.H>#include<stdio.h>#definesize16unsignedchardatasenddata[size]_at_0x50;/*发送数据首地址为50H*/unsignedcharcount;voidmain(void){TMOD=0x20;//定时器1设置为方式2 TL1=0xf4;//置T1初值

TH1=0xf4;EA=1;

ES=0;//串行口关中断TR1=1; //启动定时器T0 TI=0;

SCON=0x40;//串行口置工作方式1count=0;

ES=1;//串行口开中断

SBUF=size;//发送第一个字节

while(1);//等待发送

}/****串行口数据中断处理程序****/void UARTint()interrupt4using1/*定义函数名为UART的串行中断4服务函数,使用第1组寄存器*/ { if(TI) {SBUF=senddata[count];//启动发送

count++;

if(count>=16)ES=0;//发送完16个数据后,关串行口中断

TI=0;

}elseRI=0;

}/*------乙机接收程序--------*/#include<REG51.H>#include<stdio.h>#definesize16unsignedchardatarececivedata[size]_at_0x60;/*接收数据首地址为60H*/

unsignedcharcount,i;voidmain(void){TMOD=0x20;//定时器1设置为方式2 TL1=0xf4;

TH1=0xf4;//置T1初值

EA=1;

ES=0;

TR1=1; //启动定时器T1 TI=0;//清发送中断标志

SCON=0x40;

i=0; //接收计数器清0 F0=0;ES=1;

while(1);}

/******串行口数据中断处理程序*****/void UARTint()interrupt4using1 { if(RI) {if(F0==0){ count=SBUF;/*数据长度送计数单元*/ F0=1;

}else { rececivedata[i]=SBUF;/*接收数据*/ i++;

if(i>=count)ES=0;/*没有接收完数据则继续,接收完则关串口中断*/ } RI=0;/*RI清0*/}elseTI=0;/*清发送中断标志*/ }9.4C51语言与汇编语言的混合编程9.4.1函数名的转换规则

9.4.2函数调用1.参数传递规则C51编译器利用CPU

温馨提示

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

评论

0/150

提交评论