单片机原理及应用:第4章 单片机的C语言编程_第1页
单片机原理及应用:第4章 单片机的C语言编程_第2页
单片机原理及应用:第4章 单片机的C语言编程_第3页
单片机原理及应用:第4章 单片机的C语言编程_第4页
单片机原理及应用:第4章 单片机的C语言编程_第5页
已阅读5页,还剩106页未读 继续免费阅读

下载本文档

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

文档简介

1、第4章 单片机的C语言编程4.1 C51的程序结构4.2 C51的数据类型及运算符4.3 C51的函数4.4 C51程序设计本章要点 介绍C语言的基础知识。 掌握C语言程序的基本结构,学会编制一些简单的单片机应用序,并能在Windows环境下使用C51编译器进行编译操作。 由于8051单片机的应用程序用的是C51编译器,应注意在存储类型、对片内硬件资源的定义等方面与标准C语言的区别。概述 单片机C51语言是由C语言继承而来的。 和C语言不同的是,C51语言运行于单片机平台,而C语言则运行于普通的桌面平台。 C51语言具有C语言结构清晰的优点,便于学习,同时具有汇编语言的硬件操作能力。 对于具有

2、C语言编程基础的读者,能够轻松地掌握单片机C51语言的程序设计。 4.1 C51的程序结构 C51程序结构同ANSI C一样,必须有一个主函数main( ),从主函数main( )开始执行程序,默认情况下主函数是一个“死循环”结构,不停地循环执行。 例:C51程序基本结构在此处定义全局变量; /所有函数都可以使用void main( ) /* 定义主函数*/ 在此处定义局部变量; /只能在本函数范围内使用 bgn: goto bgn;C语言程序的组成结构如下所示:注释说明;头文件包含命令;宏定义;全局变量定义 /*可被各函数引用*/用户自定义函数声明; main() /*主函数*/ 局部变量定

3、义 /*只在本函数引用*/执行语句 /*包括函数调用语句*/ 用户自定义函数;中断服务程序定义;用“/”符号开头来注释一行,如“/变量声明”。用“/*”符号开头,并以“*/”符号结束。采用这种方法,可以对C51源程序中的任何部分进行注释,如“/*声明整型变量count */”。 一、注释说明返回 库函数是编译系统系统的标准函数。在使用时,只需在源程序的开始处使用预处理命令#include将有关的头文件包含进来即可。 下面便介绍C51常用库函数。本证库函数 直接访问存储区宏定义 字符串操作库函数 字符转换和字符分类库函数 数学库函数 输入输出库函数 二、头文件包含命令格式: #include (

4、一)、本征库函数 头文件intrins.h_crol_,_cror_:将char型变量循环向左(右)移动指定位数后返回。_iror_,_irol_:将int型变量循环向左(右)移动指定位数后返回。_lrol_,_lror_:将long型变量循环向左(右)移动指定位数后返回。_nop_:相当于插入汇编指令NOP。_testbit_:相当于JBC bitvar测试该位变量并跳转同时清除。_chkfloat_: 测试并返回源点数状态。例:#include “intrins.h”Void main() unsigned int a,b; bit test_falg,brlt; a=0 x1234; b

5、=_irol_(a,4) /a变量循环左移4位 test_flag=1; brlt=_testbit_(test_flag) /测试位变量test_flag,并将其请0, /brlt=1,test_flag=0;练习:利用上述库函数编写LED灯流水灯程序(二)、直接访问存储区的宏定义 C51编译器提供了一组宏定义来对51系列单片机的code、data、pdata和xdata空间进行绝对寻址。规定只能以无符号数方式访问,定义了8个宏定义: CBYTE以字节形式对code区寻址, DBYTE以字节形式对data区寻址 PBYTE以字节形式对pdata区寻址, XBYTE以字节形式对xdata区寻址

6、, CWORD以字形式对code区寻址, DWORD以字形式对data区寻址, PWORD以字形式对pdata区寻址, XWORD以字形式对xdata区寻址。 这些函数原型放在absacc.h文件中。使用时须用预处理命令把该头文件包含到文件中,形式为:#include 。 访问形式如下: 宏名地址 宏名为CBYTE、DBYTE、PBYTE、XBYTE、CWORD、DWORD、PWORD或XWORD。地址为存储单元的绝对地址,一般用十六进制形式表示。注意:CWORD、DWORD、PWORD和XWORD地址中的地址不是所访问存储单元的实际地址,所访问存储单元的地址=2*地址,WORD类型为两个字节

7、例、绝对地址对存储单元的访问#include /*将绝对地址头文件包含在文件中*/#include /*将寄存器头文件包含在文件中*/#define uchar unsigned char #define uint unsigned int void main(void)uchar var1;uint var2;var1=XBYTE0 x0005; /*XBYTE0 x0005访问片外RAM的0005字节单元*/var2=XWORD0 x0002; /*XWORD0 x0002访问片外RAM的0004字单元*/.while(1); 在上面程序中,其中XBYTE0 x0005就是以绝对地址方式访

8、问的片外RAM 0005字节单元;XWORD0 x0002就是以绝对地址方式访问的片外RAM 0004字单元。 (三)、字符串操作 头文件string.h,包括字符串比较、连接、复制、统计字符串长度、查找定位字符等功能函数等。#include “string.h”Void main() Char str=“today is”, wstr=sunny,weather20; strcopy ( weather, str); /执行后weather=“today is” strcat( weather, wstr); /执行后weather=“today is sunny”; (四)、字符转换和字符

9、分类 头文件stype.h,包括判断类别,如:isdigit,islower和isupper等功能函数等。#include “ctype.h”Void main()Char c, cupp;Bit i; c=h; /执行后c=0 x86 i= isdigit(c); /执行后i=0; cupp=_toupper(c); /执行后 cupp=0 x48,即H的ASCII码(五)、数学函数 头文件math.h,包括判断类别,如:sin,cos和abs等功能函数等。#include “math.h”Void main()int x,y;flaot z;Begin: x=-100; y=abs(x);

10、 /执行后y=100; z=log10(y); /执行后 z=2Goto begin;三、宏定义宏定义语句属于C51语言的预处理命令,使用宏定义可以使变量的书写简化,增加程序的可读性、可维护性和可移植性。简单的宏定义格式如下:#define 宏替换名 宏替换体例如:#define uchar unsigned char在编译时可由C51编译器把“unsigned char”用“uchar”来替代返回 变量在程序运行中其值可以改变的量。 一个变量由变量名和变量值构成,变量名即是存贮单元地址的符号表示,而变量的值就是该单元存放的内容。定义一个变量,编译系统就会自动为它安排一个存贮单元,具体的地址值

11、用户不必在意。 变量的定义的一般格式为 数据类型 存储类型 变量名 C51中定义变量除了定义数据类型外,还应定义存储类型 例:int data x , y ; 表示x , y 为16位整数并指定放在片内数据存储区四、全局变量与局部变量定义inti,j;/整型变量charch;/字符型变量short int shi;/短整型变量unsigned int ut;/无符号整型变量float fset,st;/浮点型变量1、 数据类型 C51编译器兼容ANSI C,支持ANSI C的基本数据类型,并对数据类型进行了扩展 (1)C51支持的ANSI C数据类型变量名称符号类型数据长度值域范围位型量bit

12、1位0,1字符型有符号signed char 8位-128+127无符号unsigned char8位0255整数型有符号signed int16位-32768+32767无符号unsigned int16位065535长整型有符号signed long32位-231231-1无符号unsigned long32位232-1浮点型float32位3.4E-383.4E+38 (2)C51扩展数据类型 Sfr,sfr16、sbit 用于访问特殊功能的寄存器SFR,这三种类型的变量只能声明为全局变量,并且在定义时必须指定变量访问的SFR地址。 sfr 变量可以访问指定地址的8位SFR 格式:sfr

13、 变量名=SFR地址例如: sfr P0=0X80; sfr P1=0X90; sfr P2=0XA0; sfr P3=0XB0; sfr16 变量可以访问指定地址的16位SFR 格式:sfr16 变量名=变量地址 变量地址为16位特殊功能寄存器的低8位地址。 例如: sfr16 T2=0XCC; sfr T2-L=0XCC; sfr T2-H=0XCD; 定义sfr16和sfr类型的变量用于访问单片机定时器2的16位计数寄存器 sbit 变量可以访问可位寻址的SFR中的某一位 格式: sbit变量名=位地址 sbit变量名=SFR地址位序号 sbit变量名=Sfr变量位序号 sbit变量名=

14、Sfr16变量位序号 例如:sfr P0=0X80; sbit P0-0=0X80; sbit P0-1=P012、存储类型 (1) 程序存储器 如某变量需要存放在程序存储器中,定义时用存储类型标识符code,程序运行中不可以改变用code定义的变量的值 (2)数据存储器 内部数据存储器 Data:片内数据存储区的低128字节中,直接寻址,访问速度快 bdata :可位寻址片内数据存储区,允许位与字节混合访问(16字节) ,必须定义为全部变量 idata :片内数据存储区整个(256字节) ,间接访问 外部数据存储器 间接访问,存取速度比较慢 pdata :分页寻址片外数据存储区(256字节)

15、 由MOVX R0,A指令访问 xdata :片外数据存储区(64K) 由MOVX DPTR,A指令访问 存储类型 与存储空间的对应关系 data 直接寻址片内数据存储区,访问速度快(128字节) bdata 可位寻址片内数据存储区,允许位与字节混合访问(16字节) idata 间接寻址片内数据存储区,可访问片内全部RAM地址空间(256字节) pdata 分页寻址片外数据存储区(256字节)由MOVX R0,A指令访问 xdata 片外数据存储区(64K),由MOVX DPTR,A指令访问 code 代码存储区(64K),由MOVC A,A+DPTR指令访问 表 C51存储类型存储模式 默认

16、的存储类型 SMALL 默认的存储类型为data,最大为128字节 COMPACT 默认的存储类型为pdata,每页256字节 LARGE 默认的存储类型为xdata,最大为64K 3、 存储模式 小模式,紧凑模式,大模式 变量若未定义存储类型,则C51编译器自动选择默认存储类型返回五、用户自定义函数声明当用户自定义的函数放在main函数的后面时,需要进行函数声明当用户自定义的函数放在main函数的前面时,不需要进行函数声明函数声明的方法:只需要将自定义函数的函数头复制到该位置即可;例如:用户定义了以下函数Void delay()Unsigned char i;For(i=0;i (大于);

17、= (大于或等于); var2); result =(var1=var2); result =( var1var2 ); result =( var1=var2 ); goto bgn; 4、逻辑运算符及其表达式& 逻辑与 (两个操作数都为真时,结果才为真,否则 为假) 逻辑或 (只要两个操作数中有一个为真,结果便为真,否则为假)! 逻辑非 (对操作数的值取反) &和 要求有两个操作对象,而!是单目运算符,只要求有一个运算对象。例、void main( ) unsigned int var1, var2 ,result; gbn: var1=0 x5555; var2=0 xAAAA; res

18、ult =var1&var2; result =var1|var2; result =var1var2; result =var1; var1=0 x1234; var2=0 x0002; result =var12; goto bgn; 5、位操作运算符及其表达式 &按位与; 按位或; 按位异或; 按位取反。 位右移6、特殊运算符C51中支持的位运算符有:(1)?运算:格式:?表达式2:表达式3;若表达式1的值为真,就返回表达式2的值,否则返回表达式3的值(2)&运算:返回操作数的地址(3)*运算:操作数为指针,所做的操作均是针对指针所指向的变量。例、void main( ) unsigne

19、d int var1, var2 ,result,*spt; gbn: var1=100; var2=200; result =var1var2? Var1:var2; var1=300; var2=200; spt =&result; *spt =var1+var2; var2=*spt; goto bgn; 例:若i=5 则j=i+; (执行后i=6,j=?) j=+i; (I=6,j=6)7、自增减运算符及其表达式 作用:使变量的值增1或减l, 如:+i (使用i之前,先使i值增1) -i (使用i之前,先使i值减1) i+ (在使用i之后,使i值增l) i- (在使用i之后,使i值减1

20、)(二)分支与循环程序结构1、分支控制语句 实现分支控制语句的有if语言和switch语言 (1)if 语句 形式1: if(表达式) 语句; 形式2: if(表达式) 语句1; else 语句2;形式3:if(表达式1)语句1;else if(表达式2)语句2;else if(表达式3)语句3;.else(语句n;)八、执行语句(2)switch 语句switch语句的格式如下:switch(表达式1)case 常量表达式1:语句1;break;case 常量表达式2:语句2;break;case 常量表达式3:语句3;break;.case 常量表达式n:语句n;break;default

21、:语句n+1;2、循环控制语句 实现循环控制语句的有while语句、do-while语句和for语句 (1)while语句 while(表达式) 循环体语句; (2)do-while语句 do 循环体语句; while表达式(3)for语句 for(表达式1;表达式2;表达式3) 循环体语句; 表达式1:循环变量初值设定 表达式2:循环条件表达式 表达式3:循环变量更新表达式返回练习:1、编写程序使LED闪烁/* 名称:闪烁的LED;说明:LED 按设定的时间间隔闪烁*/#includesbit LED=P10;/延时void DelayMS(uint x) unsigned char i;w

22、hile(x-)for(i=0;i120;i+);/主程序void main()while(1)LED=LED;DelayMS(150);2、编写程序使LED左右来回点亮/* 名称:8 只LED 左右来回点亮说明:程序利用循环移位函数_crol_和_cror_形成来回滚动的效果*/#include#includevoid DelayMS(uint x) /延时uchar i;while(x-)for(i=0;i120;i+);/主程序void main() unsigned char i; P2=0 x01; while(1)for(i=0;i7;i+)P2=_crol_(P2,1); /P2

23、 的值向左循环移动DelayMS(150);for(i=0;i7;i+)P2=_cror_(P2,1); /P2 的值向右循环移动DelayMS(150);(3)编写程序,用数码管显示按键的编号#include unsigned char code DSY_CODE=0 xc0,0 xf9,0 xa4,0 xb0,0 x99,0 x92,0 x82,0 xf8,0 x80,0 x90;void main() unsigned char a,b;while(1) a=P1;switch(a)case 0 xfe:b=1;break;case 0 xfd:b=2;break;case 0 xfb:

24、b=3;break;case 0 xf7:b=4;break;case 0 xef:b=5;break;case 0 xdf:b=6;break;case 0 xbf:b=7;break;case 0 x7f:b=8;break;default:break; P2=DSY_CODEb;3、交通灯:东西向绿灯亮若干秒,黄灯闪烁5 次后红灯亮, 红灯亮后,南北向由红灯变为绿灯,若干秒后南北向黄灯闪烁5 此后变红灯,东西向变绿灯,如此重复。/* 名称:LED 模拟交通灯说明:东西向绿灯亮若干秒,黄灯闪烁5 次后红灯亮, 红灯亮后,南北向由红灯变为绿灯,若干秒后南北向黄灯闪烁5 此后变红灯,东西向变绿

25、灯,如此重复。*/#include#define uchar unsigned char#define uint unsigned intsbit RED_A=P00; /东西向灯sbit YELLOW_A=P01;sbit GREEN_A=P02;sbit RED_B=P03; /南北向灯sbit YELLOW_B=P04;sbit GREEN_B=P05;uchar Flash_Count=0,Operation_Type=1; /闪烁次数,操作类型变量/延时void DelayMS(uint x)uchar i;while(x-) for(i=0;i120;i+);void Traffi

26、c_Light()switch(Operation_Type)case 1: RED_A=1;YELLOW_A=1;GREEN_A=0; RED_B=0;YELLOW_B=1;GREEN_B=1; DelayMS(2000);Operation_Type=2;break;case 2: DelayMS(300); YELLOW_A=YELLOW_A;GREEN_A=1; if(+Flash_Count!=10) return; /闪烁5 次 Flash_Count=0;Operation_Type=3;break;case 3: RED_A=0;YELLOW_A=1;GREEN_A=1; RE

27、D_B=1;YELLOW_B=1;GREEN_B=0; DelayMS(2000); Operation_Type=4;break;case 4: DelayMS(300); YELLOW_B=YELLOW_B;GREEN_B=1; if(+Flash_Count!=10) return; Flash_Count=0;Operation_Type=1;/主程序void main()while(1) Traffic_Light();4、数码管从左到右依次滚动显示07,程序通过每次仅循环选通一只数码管/*名称:8 只数码管滚动显示单个数字说明:数码管从左到右依次滚动显示07,程序通过每次仅循环选通

28、一只数码管*/#include#includeUnsigned char code DSY_CODE=0 xc0,0 xf9,0 xa4,0 xb0,0 x99,0 x92,0 x82,0 xf8,0 x80,0 x90;/延时void DelayMS(uint x)Unsigned char t;while(x-) for(t=0;t120;t+);/主程序void main()uchar i,wei=0 x80;while(1)for(i=0;i8;i+)wei=_crol_(wei,1);P0=DSY_CODEi; /发送数字段码P2=wei; /发送位码DelayMS(300);P2=

29、0 xff; /关闭显示八、用户自定义函数及中断服务程序C51可以自定义任意多个函数。C51程序从main主函数开始执行。C51的编译环境提供了多种库函数供用户使用。合理使用函数来设计程序,可以有利于代码的模块化,促进团队协作和资源共享。 函数定义的一般格式如下:函数类型 函数名(参数表)reentrantinterrupt musing n局部变量定义函数体前面部件称为函数的首部,后面称为函数的尾部,格式说明:1、函数类型函数类型说明了函数返回值的类型。2、函数名函数名是用户为自定义函数取的名字以便调用函数时使用。3、形式参数表形式参数表用于列录在主调函数与被调用函数之间进行数据传递的形式参

30、数。(一)、函数及中断服务程序定义4reentrant修饰符 这个修饰符用于把函数定义为可重入函数。所谓可重入函数就是允许被递归调用的函数。函数的递归调用是指当一个函数正被调用尚未返回时,又直接或间接调用函数本身。一般的函数不能做到这样,只有重入函数才允许递归调用。 5interrupt m修饰符 interrupt m是C51函数中非常重要的一个修饰符,这是因为中断函数必须通过它进行修饰。在C51程序设计中,当函数定义时用了interrupt m修饰符,系统编译时把对应函数转化为中断函数,自动加上程序头段和尾段,并按MCS-51系统中断的处理方式自动把它安排在程序存储器中的相应位置。 在该修

31、饰符中,m的取值为031,对应的中断情况如下:0外部中断01定时/计数器T02外部中断13定时/计数器T14串行口中断5定时/计数器T2 其它值预留。编写89C51中断函数注意如下:(1)中断函数不能进行参数传递,如果中断函数中包含任何参数声明都将导致编译出错。(2)中断函数没有返回值,如果企图定义一个返回值将得不到正确的结果,建议在定义中断函数时将其定义为void类型,以明确说明没有返回值。(3)在任何情况下都不能直接调用中断函数,否则会产生编译错误。因为中断函数的返回是由8051单片机的RETI指令完成的,RETI指令影响8051单片机的硬件中断系统。如果在没有实际中断情况下直接调用中断函

32、数,RETI指令的操作结果会产生一个致命的错误。【例】编写一个用于统计外中断0的中断次数的中断服务程序extern int x;void int0() interrupt 0 using 1 x+;6using n修饰符 修饰符using n用于指定本函数内部使用的工作寄存器组,其中n的取值为03,表示寄存器组号。 对于using n修饰符的使用,注意以下几点:(1)加入using n后,C51在编译时自动的在函数的开始处和结束处加入以下指令。 PUSH PSW ;标志寄存器入栈 MOV PSW,#与寄存器组号相关的常量 POP PSW ;标志寄存器出栈(2)using n修饰符不能用于有返回

33、值的函数,因为C51函数的返回值是放在寄存器中的。如寄存器组改变了,返回值就会出错。声明函数的注意事项 在声明函数时,应该注意如下几点:如果没有类型说明符出现,函数返回一个整型值。如果函数没有返回值,则可以采用void说明符。函数类型的说明必须处于对它的首次调用之前。当函数被调用时,形式参数列表中的变量用来接收调用参数的值。如果函数没有返回值,则可以省略return语句。函数与变量一样,在使用前必须先定义。 函数的参数包括两类:形参实参(二)、C51函数参数传递及返回值传递 函数参数用于主调函数与被调函数间进行的数据交换。 函数的形参和实参在使用时需要注意如下几点:形参变量只有在被调用时才分配

34、内存单元。实参可以是常量、变量、表达式等。在C51语言中,实参和形参都可以采用多种数据类型。实参的类型和个数应该与形参的定义类型和个数完全相同。形参和实参在顺序上应保持严格一致。在函数调用过程中,形参的值发生改变,而实参中的值不会变化。在函数调用时,数据传送是单向的从实参传送给形参。1、函数参数传递2、函数返回值的传递 函数的返回值是指函数被调用执行之后,最终返回给主调函数的计算结果。函数的返回值通过return语句返回给主调函数。C51编译器通过寄存器传递函数的返回值return语句的一般形式如下: return 表达式;return (表达式); 例:定义函数sum,实现两个参数求和功能。

35、unsigned int sum(unsigned int var1, var2);void main( )unsigned int rlt;bgn: rlt=sum(100,200); goto bgn;unsigned int sum(unsigned int var1, var2) return(var1+var2);在C51中,使用return语句应该注意如下几点:函数只能有一个返回值。函数返回值的类型和函数定义中的类型应保持一致。如函数返回值为整型,在函数定义时可省去类型说明。凡不要求返回值的函数都应定义为空类型。一旦函数被定义为空类型后,就不能使用return语句。return语句

36、的注意事项(三)、函数的调用 函数调用的方式就是我们在程序中如何使用函数的问题。在C51语言中,函数调用的一般形式如下: 函数名(实参列表) 初步总结一下,函数可以有以下几种调用方式:函数语句。示例如下:delay();函数表达式。示例如下:z=min(x,y);/函数min求x、y中的最小值函数参数。示例如下:z=min(x,min(y,z);/函数min求x、y、z中的最小值 程序中需要定义多个函数时,可以在另一个文件中集中定义函数,而将相关函数声明放在一个头文件中,主程序只要用#include语句包含头文件,便可调用文件中声明的函数文件myfunc.c#include /包含特殊功能寄存

37、器库bit func_cmp(long var1,long var2) if (var1var2) return 1; else return 0; 头文件myfunc.h#ifndef _myfunc_def_h#define _myfunc_def_hExtern bit func_cmp(long var1,long var2); /声明函数func_cmp#endif文件main.c#include /包含特殊功能寄存器库#include extern serial_initial();void main(void) long var1=100,var2=50; bit rtn; rt

38、n= func_cmp(var1, var2); while(1);返回*2、通过函数指针调用函数: 将函数的地址赋值给指针 char code *pfun pfun=(void*)fun 通过指针调用函数时,其指令格式为 (返回值类型(code*)(形参说明)函数指针)(实参说明) int fun_add(int var1,int var2); void main() char code *pfun; int rtn=0; pfun=(void *)fun_add; rtn=(int(code*)(int,int)pfun)(200,100);int fun_add(int var1,int

39、 var2) return(var1+var2);练习:利用下图所示的电路实现以下功能:按第一个键,实现两个变量相加按第二个键,实现两个变量相键按第三个键,实现两个变量相乘按第四个键,实现两个变量相除将运算结果通过数码管显示出来说明:变量相加、相减、相乘、相除、键盘扫描及显示编写成用户自定义函数,主程序只需调用上述函数即可#include unsigned char code leddata=0 xc0,0 xf9,0 xa4,0 xb0,0 x99,0 x92,0 x82,0 xf8,0 x80,0 x90;unsigned char code ledsel=0 x01,0 x02,0 x0

40、4,0 x08,0 x10,0 x20; void delay()unsigned char i;for(i=0;i200;i+);unsigned int sum(unsigned char a,b)return(a+b);unsigned int mul(unsigned char a,b)return(a*b);unsigned char sub(unsigned char a,b)return(a-b);unsigned int div(unsigned char a,b)return(a/b);void display(unsigned int d)unsigned char aa5

41、;unsigned char j; aa0=d/10000;aa1=d%10000/1000;aa2=d%1000/100;aa3=d%100/10;aa4=d%10;for(j=0;j5;j+)P0=leddataaaj;P2=ledselj;delay();P2=0 x00;unsigned char keyscan()unsigned char bb;unsigned char keyvalue;bb=P1;switch(bb)case 0 xfe:keyvalue=2;break;case 0 xfd:keyvalue=3;break;case 0 xfb:keyvalue=4;bre

42、ak;case 0 xf7:keyvalue=5;break;default:break;return keyvalue; void main()unsigned char key;unsigned int num;while(1)key=keyscan();switch(key)case 2:num=sum(200,100);break;case 3:num=sub(200,100);break;case 4:num=mul(200,100);break;case 5:num=div(200,100);break;default:break;display(num);4.2、C51的指针 变

43、量名对应于内存单元的地址,变量值则是放在内存单元中的数据。同时把存放变量x的地址称为指针,使用指针前也必须定义。 指针是一种特殊的数据类型,用指针声明的变量称为指针变量。 指针变量的值实际上是一个地址,是单片机内存单元的编号。 声明一个指针变量具有特殊的形式,如下所示: 数据类型 指向存储区*存储位置指针变量名1、通用指针 指向任何存储类型的变量 占3个字节,第一个字节说明存储类型,第二个字节为变量地址的高8为;第三个字节为变量地址的低8位。void main() unsigned char code HZ=0 x88; unsigned char data var_data=0 x12; u

44、nsigned char *ptr; /通用指针ptr,指针存放在默认存储区中 unsigned char *idata iptr; /通用指针iptr,指针存放在idata存储区中 char idata myvar=0 x0A; ptr=&HZ; iptr=&var_data; myvar=myvar+*ptr; myvar=myvar+*iptr;2、指向固定存储区变量的指针指向固定存储区的变量void main() int code HZ=0 x0101; int data var_data=0 x12; int code *ptr; /指向code存储区的指针ptr,指针存放在默认存储

45、区中 int idata *pdata iptr; /指向idata存储区的指针iptr,指针存放在pdata存储区中 int idata myvar=0 xFF; ptr=&HZ; iptr=&var_data; myvar=myvar+*ptr; myvar=myvar+*iptr; return;一、变量绝对地址定位 在定义变量时使用 _at_ 关键字加上地址就可.格式为:数据类型 存储类型 变量名 (空格)_at_ (空格)地址常数例如:unsigned char idata myvar _at_ 0 x40;把变量 myvar 定义在 idata 的 0 x40 处4.3、 C51对

46、扩展外设的访问使用_at_定义的变量必须为全局变量 MCS-51系列单片机并行I/O接口除了芯片上的4个I/O口(P0 P3)外,还可以在片外扩展I/O口。MCS-51单片机I/O口与数据存储器统一编址,即把一个I/O口当作数据存储器中的一个单元来看待。因此定义变量访问外部扩展I/O地址时,将变量的数据类型说明为xdata或pdata,并需要指定变量在存储区中的绝对地址。 P0、P1、P2和P3的定义在头文件REG51.h和REG52.h中,扩展的外部RAM单元和外部I/O需要用户自己定义。 二、C51对外设的访问例、#define uchar unsigned char /*定义符号ucha

47、r为数据类型符unsigned char*/#define uint unsigned int /*定义符号uint为数据类型符unsigned int*/uchar data x1 _at_ 0 x40; /*在data区中定义字节变量x1,它的地址为40H*/uint xdata x2 _at_ 0 x2000; /*在xdata区中定义字变量x2,它的地址为2000H*/void main(void)x1=0 xff;/*将数据ffH写入内部数据存储器地址为0 x40的存储单元*/x2=0 x34;/*将数据34H写入外部数据存储器地址为0 x2000的存储单元或I/O端口*/.whil

48、e(1);4.4 C51程序设计用户自定义头文件有利于合作开发用户自定义头文件的内容主要包括函数声明和宏定义导入方式:#include “头文件名称”C51程序设计实例例1:编程实现:1905+7453的加法运算,并将运算结果通过LED显示器显示(数码管的段选信号和位选信号分别通过P1和P2口控制)模块分析:1、算数运算模块(函数定义和声明分别放在math.c和math.h中)2、显示模块(函数定义和声明放在display.c和display.h中)1、文件 mymain.c#include “display.h”#inlcude “mymath.h”void main()unsigned i

49、nt rlt; rlt=sum(1905,7543);dspint(rlt);2、文件 mymath.cunsigned int sum(unsigned int x,y)return(x+y);头文件mymath.h#ifndf_mymath_def_h#define_mymath_def_hextern unsigned int sum(unsigned int x,y);#endif;3、文件 display.c#include unsigned char code ledsel=0 xfe, 0 xfd, 0 xfb,0 xf7, 0 xef, 0 xdf;unsigned char

50、code ledcode=0 x3F,0 x06,0 x5B,0 x4F,0 x66,0 x6D,0 x7D,0 x07,0 x7F,0 x6F,0 x77,0 x7C,0 x39,0 x5E,0 x79,0 x71;void delay(unsigned int t)unsigned int i;for(i=0;i0)stri-=x%10;x=x/10;for(i=0;i0;x-) for(y=110;y0;y-);uchar keyscan() /键盘扫描程序,返回uchar型参数uchar i; for(i=0;i4;i+) P1=_crol_(0 xfe,i); temp=P1; te

51、mp=temp&0 xf0; while(temp!=0 xf0) delay(5); /延时消抖 temp=P1; temp=temp&0 xf0; while(temp!=0 xf0) temp=P1; switch(temp) case 0 xee:num=1;break; case 0 xde:num=2;break; case 0 xbe:num=3;break; case 0 x7e:num=4;break; case 0 xed:num=5;break; case 0 xdd:num=6;break; case 0 xbd:num=7;break; case 0 x7d:num=

52、8; break; case 0 xeb:num=9;break; case 0 xdb:num=10;break; case 0 xbb:num=11;break; case 0 x7b:num=12;break; case 0 xe7:num=13;break; case 0 xd7:num=14;break; case 0 xb7:num=15;break; case 0 x77:num=16;break; while(temp!=0 xf0) /等待按键释放 temp=P1; temp=temp&0 xf0; return num;例2:P1端口接一支共阴数码管SLED,在P2、P3端

53、口接16个按键,分别编号为KEY_0、KEY_1到KEY_F,操作时只能按一个键,按键后SLED显示对应键编号。#include unsigned char code Seg7Code16=0 x3f,0 x06,0 x5b,0 x4f,0 x66,0 x6d,0 x7d,0 x07,0 x7f,0 x6f,0 x77,0 x7c,0 x39,0 x5e,0 x79,0 x71;void main()unsigned char a,b,i;while(1)a=P2;switch(a)case 0 xfe:i=0;break;case 0 xfd:i=1;break;case 0 xfb:i=2

54、;break;case 0 xf7:i=3;break;case 0 xef:i=4;break;case 0 xdf:i=5;break;case 0 xbf:i=6;break;case 0 x7f:i=7;break;default:break;b=P3;switch(b)case 0 xfe:i=8;break;case 0 xfd:i=9;break;case 0 xfb:i=10;break;case 0 xf7:i=11;break;case 0 xef:i=12;break;case 0 xdf:i=13;break;case 0 xbf:i=14;break;case 0 x

55、7f:i=15;break;default:break;P1=Seg7Codei;例3、LED模拟交通灯 说明:东西向绿灯亮若干秒,黄灯闪烁 5 次后红灯亮, 红灯亮后,南北向由红灯变为绿灯,若干秒后南北向黄灯闪烁 5 此后变红灯,东西向变绿灯,如此重复。 #include sbit dred=P00;sbit dyellow=P01;sbit dgreen=P02;sbit nred=P03;sbit nyellow=P04;sbit ngreen=P05;void delay(unsigned int i)unsigned char a;while(i-)for(a=0;a120;a+);

56、void main()unsigned char n;while(1)dred=1;dyellow=1;dgreen=0;nred=0;nyellow=1;ngreen=1;delay(4000);dred=1; dgreen=1;for(n=0;n=4;n+)dyellow=dyellow;delay(400);dred=0;dyellow=1;dgreen=1;nred=1;nyellow=1;ngreen=0;delay(4000);nred=1; ngreen=1;for(n=0;n=4;n+)nyellow=nyellow;delay(400);练习题: 1、请根据下图所示的电路,编

57、写一个程序,使八个LED灯左右来回点亮2、请根据下图所示的电路,编写一个程序,使八个数码管滚动显示0-7C51语言习题一、填空题1Data存储类型可以直接寻址( ),共( )字节,访问速度快。2、sfr16存储类型用于( )寻址,定义( ) ,且该16位必须低位在低字节,高位在紧跟的高字节才行。3、在keil uVision编译系统中,支持的8051单片机存储模式共有如下三种( )、 ( )和( )4、 ( )是指向特定的存储区的指针类型,其在声明时指定了存储类型5、片内低128字节RAM区的地址范围为 ( ) 6、在C51语言程序中,注释一般采用( )和( )来实现。7、字符char型变量的

58、取值范围为 ( ) 。8、“?”运算符是 ( ) 目运算符。9、在C51语言中,单目运算符为 ( ) 结核性,双目运算符为 ( ) 结合性,三目运算符为 ( ) 结合性。10 、 ( ) 单片机存储器中最小的存储单元,通常 ( ) 称为一个内存单元。单片机内存单元的编号也就是 ( )11、在定义指针变量时,指针名前的 ( ) 不能省略,同一个指针变量只能指向 ( )12、指针变量的专用运算符包括 ( ) 和 ( ) 。13、指针变量可以参与 ( ) 和 ( ) 运算。14、通过( )可以访问字符串常量中的内容,但( )对其进行修改15、在指针变量说明中,*是( ),表示其后是( )16、表达式

59、中出现“*”则是( ),用来表示指针变量所指向的地址中的数据。17、无返回值的函数使用( )来声明18、跳转语句goto,只能在( )使用,而不能( ) 19、在C51语言中,除了( )函数外,各个函数都是平行的20、函数调用方式包括( )、 ( ) 、 ( )和( )21、形参变量只有在( )才分配内存单元,在( )结束后,将立即释放内存单元。22、函数的返回值只能通过 ( ) 语句返回给主调函数。23、在C51语言的程序中,循环语句一般采用 ( ) 、 ( ) 和 ( ) 来实现。24、字符在c51语言的程序中,跳转语句一般采用 ( ) 、 ( ) 和 ( ) 来实现。25、Do whil

60、e语句在执行时,先执行 ( ) ,然后执行 ( )。26、返回语句由关键字 ( ) 来表示,用用于 ( )。27、C51的存储类型有 ( ) , ( ) , ( ) , ( ) , ( ) , ( ) ,存储模式有 ( ) ( ) , ( ) 。28、修饰符interrupt m中m的取值为0对应的中断情况是( ),1对应的中断情况是( ),2对应的中断情况是( ),3对应的中断情况是( ),4对应的中断情况是( ),5对应的中断情况是( ),修饰符using n的功能是( )。29、定义变量a、b、c,a为内部RAM的可位寻址区的字符变量;b为外部数据存储区浮点型变量;c为指向int型xda

温馨提示

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

评论

0/150

提交评论