片机的C51语言简介.ppt
单片机原理与应用,第4章 MCS-51单片机 的C语言简介,TOPICS,C51的程序结构,1,C51的数据结构,2,3,4,5,6,C51的绝对地址访问,C51的输入输出,C51中断服务函数的定义方法,汇编语言与C51的混合编程,4.1 C51的程序结构,汇编语言与C51语言的区别:,汇编语言能直接操作单片机的硬件资源,即编程者必须具体地组织、分配存储器资源和处理端口数据。指令执行速度快,但其程序可读性差,且编写、移植困难。,C51语言特点:,结构化语言,代码紧凑效率可与汇编语言媲美 接近真实语言,程序可读性强易于调试、移植 库函数丰富,编程工作量小产品开发周期短,4.1 C51的程序结构,C51语言编程者不用像用汇编语言那样具体地组织、分配存储器资源和处理端口数据。但对数据类型和变量的定义,必须要与单片机存储结构相关联,否则编译器不能正确地映射定位。,C51与标准C的比较:,相同点:语法规则、程序结构、编程方法,4.1 C51的程序结构,不同点:,用C51语言编写程序需根据单片机存储结构及内部资源定义相应的数据类型和变量。库函数、存储模式;中断处理;输入/输出处理。,C51与标准C程序结构完全相同。,程序由函数组成(一个主函数,或一个主函数和若干自定义函数);利用预处理命令对变量或函数进行集中定义或说明;函数和变量都需遵循先定义后使用的基本原则;主函数中的所有语句执行完毕,则程序结束。,4.1 C51的程序结构,举例:LED灯的闪烁控制功能,4.1 C51的程序结构,预处理命令-,函数说明-,全局变量定义-,主函数-,调用函数-,局部变量定义-,程序体,程序体-,4.1 C51的程序结构,1.C51的变量,在程序执行过程中,数值可以发生改变的量称为变量。,例如,变量名与存储单元地址相对应;变量值与存储单元的内容相对应。,4.2 C51的数据结构,【存储种类】数据类型【存储类型】变量名,(标准C),(标准C),*括号项可以缺省(但需有缺省值),C51变量定义的四要素:,(C51),(标C+C51),4.2 C51的数据结构,【存储种类】数据类型【存储类型】变量名,auto(自动型)extern(外部型)static(静态型)register(寄存器型),4.2 C51的数据结构 存储种类,存储种类是指变量在程序执行过程中的作用范围。,【存储种类】数据类型【存储类型】变量名,标准C语言的数据类型,*有符号数类型可以忽略signed标识符,4.2 C51的数据结构-数据类型,C51扩充数据类型:bit、sfr或sfr16、sbit,bit 型,bit用于定义一个位变量,语法规则如下:,bit bit_name=常数01;,例如:bit door=0;/定义一个叫door的变量且初值为0,4.2 C51的数据结构-数据类型,sfr或sfr16型,sfr或sfr16用于定义特殊功能寄存器变量,语法规则如下:sfr 或 sfr16 sfr_name=字节地址常数;,4.2 C51的数据结构-数据类型,用关键字“sfr16”来定义“=”后面的地址必须用16位SFR的低字节地址,即16位SFR的低地址作为“sfr16”的定义地址,其高位地址在定义中没有体现。sfr16 T2=0 xCC;/T2的低8位为0CCH,高8位为0CDH sfr16 T0=0 x8A;/错误,不能这样定义定时器/计数器0,4.2 C51的数据结构-数据类型,例如:sfr P0=0 x80;/定义P0口地址80H sfr PCON=0 x87;/定义PCON地址87H sfr16 DPTR=0 x82;/定义DPTR,低端地址DPL=82H,高端地址DPH=83H,4.2 C51的数据结构-数据类型,sbit型,绝对位地址,相对位地址,字节地址,使用“sbit”来定义SFR的位寻址单元。,4.2 C51的数据结构-数据类型,sbit有三种定义方法:,1)将SFR的绝对位地址定义为位变量名sbit bit_name=位地址常数;例如,sbit CY=0 xD7;,2)将SFR的相对位地址定义为位变量名sbit bit_name=sfr字节地址 位位置;例如,sbit CY=0 xD07;,3)将SFR的07位直接定义为位变量名 sbit bit_name=sfr_name 位位置;例如,sbit CY=PSW7;,4.2 C51的数据结构-数据类型,C51编译器在头文件“reg51.h”中定义了全部sfr/sfr16和sbit变量。,用#include 包含头文件到C51程序中,无需重定义即可直接使用它们的名称。,4.2 C51的数据结构-数据类型,应用举例:,4.2 C51的数据结构-数据类型,C51使用#define或typedef语句定义数据类型的别名。,#define 别名 C51固有的数据类型 typedef C51固有的数据类型 别名;,4.2 C51的数据结构-数据类型,具体格式为:,eg:#define uchar unsigned char#define uint unsigned int typedef unsigned int WORD;这样,在其后的程序就可以用uchar代替unsigned char,用uint或WORD代替unsigned int来定义变量,从而节省书写时间、减少错误和增强可读性。如:uchar x;/定义变量x为无符号字符型变量 uint y;/定义变量y为无符号整型变量 WORD z;/定义变量z为无符号整型变量,4.2 C51的数据结构-数据类型,【存储种类】数据类型【存储类型】变量名,4.2 C51的数据结构 存储类型,C51存储类型与存储空间的对应关系,共有6种存储类型,4.2 C51的数据结构 存储类型,4.2 C51的数据结构 存储类型,三种编译模式分别对应于三种缺省(默认)存储类型。,【存储种类】数据类型【存储类型】变量名,4.2 C51的数据结构 存储类型,变量名由字母、数字和下划线三种字符组成;第一个字符必须为字母或下划线;变量名长度随编译系统而定。变量名区分字母大小写。,【存储种类】数据类型【存储类型】变量名,4.2 C51的数据结构 变量名,强调:头文件中定义的变量都是大写的,若程序采取小写变量则需要重新定义。,变量名不得使用标准C语言和C51语言的关键字。,谭浩强C程序设计第三版 清华大学出版社,附录B中C语言中的关键字 37个,4.2 C51的数据结构 变量名,unsigned char data system_status=0;,/定义system_status为无符号字符型自动变量,该变量位于data区中且初值为0。,数据结构定义举例,变量名为system_status,位于片内RAM区,无符号字符型,自动型,初值为零,4.2 C51的数据结构 变量名,unsigned char bdata status_byte;,unsigned int code unit_id2=0 x1234,0 x89ab;,/定义status_byte为无符号字符型自动变量,该变量位于bdata区,/定义unit_id2为无符号整型自动变量,该变量位于code区中,是长度为2的数组,且初值为0 x1234和0 x89ab。,4.2 C51的数据结构 变量名,2.C51的指针,数据类型【指向存储类型】【自身存储类型】变量名,用来存放变量地址的变量指针变量 C51指针变量也要先定义后使用。,可见,C51指针变量突出了两个问题:1)指针变量自身位于哪个存储区域;2)该指针的值指向的是哪个存储区域里的地址。,4.2 C51的数据结构 指针,定义的一般形式:,例1 若ptr是指向idata存储区的指针变量,该存储区将以无符号字符形式存放数据。要求ptr本身位于xdata存储区,值是位于idata存储区里的unsigned char型自动变量a(初值为A)的地址。试据此完成相应变量的定义及初始化。,解:假想具体值量化如下:,4.2 C51的数据结构 指针,例如,用来存放变量地址的变量指针变量,在程序执行过程中,数值可以发生改变的量称为变量。,解:若编译器默认的存储类型为data,则指针pi自身被存放在data区内,它是指向 xdata 存储区的无符号字符型变量。,解:指针port自身被存放在idata区内,它是指向 code 存储区的无符号字符型变量。,例2unsigned char xdata*pi;,例3unsigned char code*idata port;,4.2 C51的数据结构 指针,4.3 C51的绝对地址访问,一、使用C51运行库中预定义宏,C51通过头文件absace.h 宏定义有:#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)#define CWORD unsigned int volatile code*)0)#define DWORD unsigned int volatile data*)0)#define PWORD unsigned int volatile pdata*)0)#define XWORD unsigned int volatile xdata*)0)具体访问绝对地址的格式为:宏名地址;注意:absace.h一定要有。,#include/必须要,不能少#define uchar unsigned char#define uint unsigned intvoid main(void)uchar varl;uint var2;var1=XBYTE0 x0008;/访问片外RAM的0008H字节单元var2=XWORD0 x1002;/访问片外RAM的1002H字单元.while(1);,4.3 C51的绝对地址访问,二、通过指针访问,#define uchar unsigned char#define uint unsigned intvoid main(void)uchar data varl;uchar pdata*dp1;/定义指向一个pdata区的指针dp1uint xdata*dp2;/定义指向一个xdata区的指针dp2uchar data*dp3;/定义指向一个data区的指针dp3dp1=0 x20;/赋地址值,指向pdata区的20Hdp2=0 x1000;/赋地址值,指向xdata区的1000H*dp1=0 x80;/片外RAM的20H单元赋值80H*dp2=0 x2012;/片外RAM的1000H单元赋值2012Hdp3=,4.3 C51的绝对地址访问,三、使用C51扩展关键字_at_访问,C51用_at_对存储器绝对地址访问的一般格式为:存储器类型 数据类型 变量名 _at_ 地址常数;,#define uchar unsigned char#define uint unsigned intdata uchar var1 _at_ 0 x40;/data区字节变量var1的地址为40Hxdata uint var2 _at_ 0 x2000;/xdata区字变量var2的地址为2000H void main(void)var1=0 x90;/片内RAM地址40H赋值90Hvar2=0 x2012;/片外RAM地址2000H赋值2012H.while(1);,4.3 C51的绝对地址访问,4.4 C51的输入输出,C51本身不提供输入和输出语句,其输入输出操作是通过MCS51的串行口来实现的。,一、格式输出函数printf(),格式输出函数的作用是通过串行口输出符合格式控制要求的特定类型的数据。格式为:printf(格式控制,输出参数表);,4.4 C51的输入输出,printf(格式控制,输出参数表);,格式控制为用双引号括起来的字符串,也称转换控制字符串,它包括三种信息:格式说明符、普通字符和转义字符。,格式说明符:由“%”和格式字符组成,其作用是指明输出数据的类型和格式。,普通字符,按原样输出,用来输出某些提示信息。,4.4 C51的输入输出,转义字符:用来输出特定的不可显示的控制信息和字符。在其前面加反斜杠“”组成转义字符。,4.4 C51的输入输出,二、输入函数scanf(),作用:通过串行口实现数据输入。格式:scanf(格式控制,地址列表);,格式控制为用双引号括起来的字符串,包括三种信息:空白字符、普通字符和格式说明。,4.4 C51的输入输出,#include#include/一般I/O函数库,必须有void main(void)int x,y;SCON=0 x52;/串行口工作于方式1TMOD=0 x20;/定时器/计数器1选择模式2TH1=0 xF3;/设定波特率TL1=0 xF3;TR1=1;printf(“Input x,y:n”);/输出提示Input x,y:,换行scanf(“%d%d”,4.4 C51的输入输出,4.5 C51中断服务函数的定义方法,中断服务函数的一般形式为:,n1是中断号,取值范围为 031。编译器从 8*n13处产生中断向量,基本中断源和中断向量如表所示。,函数类型 函数名(形式参数表)interrupt n1using n2,C51编译器扩展了一个关键字using,专门用来选择MCS51系列单片机中不同的工作寄存器组。using后面的n2是一个03的整型常数,分别选中4个不同的工作寄存器组。,4.5 C51中断服务函数的定义方法,编写MCS51系列单片机中断程序时应遵循的规则:中断函数不能进行参数传递,否则将导致编译出错。中断函数没有返回值,如果企图定义一个返回值将得到不正确的结果。任何情况下都不能直接调用中断函数,否则会编译出错。,4.5 C51中断服务函数的定义方法,例:在两个数据中选出较大的数据,并赋值给变量c。其中,要求选数任务采用汇编子程序完成。,/以下代码在main.c文件中实现void max(char a,char b);/由汇编语言实现main()char a=30,b=40,c;c=max(a,b);,一、在C51中调用汇编程序,4.6 汇编语言与C51的混合编程,1)程序的寻址。main.c中调用的max函数,如何与汇编文件中的相应代码对应起来。,2)参数传递。main.c中传递给max()函数的参数a和b,存放在何处可使汇编程序能够获取到它们的值。,3)返回值传递。汇编语言计算得到的结果,存放在何处可使C语言程序能够获取到。,C51程序中调用汇编语言,需要解决三个问题:,4.6 汇编语言与C51的混合编程,1)程序的寻址问题,通过在汇编文件中定义同名的“函数”来实现。,PUBLIC _MAXDE SEGMENT CODERESG DE_MAX:,/以下代码在main.c文件中实现void max(char a,char b);/由汇编语言实现main()char a=30,b=40,c;c=max(a,b);,4.6 汇编语言与C51的混合编程,2)参数传递问题,_MAX:MOV A,R7;取第1个参数MOV 30H,R5;取第2个参数CJNE A,30H,TAGTAG:JNC EXIT;返回第1个参数MOV A,R5MOV R7,A;返回第2个参数EXIT:RETEND,/以下代码在main.c文件中实现void max(char a,char b);/由汇编语言实现main()char a=30,b=40,c;c=max(a,b);,4.6 汇编语言与C51的混合编程,3)返回值传递问题,_MAX:MOV A,R7;取第1个参数MOV 30H,R5;取第2个参数CJNE A,30H,TAGTAG:JNC EXIT;返回第1个参数MOV A,R5MOV R7,A;返回第2个参数EXIT:RETEND,/以下代码在main.c文件中实现void max(char a,char b);/由汇编语言实现main()char a=30,b=40,c;c=max(a,b);,4.6 汇编语言与C51的混合编程,二、C51中嵌入汇编代码,在C51函数内嵌入汇编代码,可以有三种不同方法。,方法一 直接在函数体内的每个汇编语句前加“asm”。例如:,void reset_data(void)asm MOV R0,#0AHasm LOOP:INC A asm DJNZ R0,LOOPReturn;,4.6 汇编语言与C51的混合编程,方法二 把asm 作为关键字,后续汇编用大括号括起来即可。,void reset_data(void)asm MOV R0,#0AH LOOP:INC A DJNZ R0,LOOPReturn;,4.6 汇编语言与C51的混合编程,例如:,方法三在C 模块内通过语句“#pragma”嵌入汇编代码。例如:,void reset_data(void)#pragma asm MOV R0,#0AH LOOP:INC A DJNZ R0,LOOP#pragma endasmReturn;,4.6 汇编语言与C51的混合编程,作 业,教材P97 第1、3、8、11题,Thank You!,Back,