第十章 单片机C语言程序设计

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

第十章单片机C语言程序设计10.1C语言与MCS-51单片机10.1.1C语言的特点及程序结构一.C语言的特点1.语言简洁、紧凑,使用方便、灵活。2.运算符丰富。3.数据结构丰富。具有现代化语言的各种数据结构。4.可进行结构化程序设计。5.可以直接对计算机硬件进行操作。6.生成的目标代码质量高,程序执行效率高。7.可移植性好。二.C语言的程序结构C语言程序采用函数结构,每个C语言程序由一个或多个函数组成,在这些函数中至少应包含一个主函数main(),也可以包含一个main()函数和若干个其它的功能函数。不管main()函数放于何处,程序总是从main()函数开始执行,执行到main()函数结束则结束。在main()函数中调用其它函数,其它函数也可以相互调用,但main()函数只能调用其它的功能函数,而不能被其它的函数所调用。功能函数可以是C语言编译器提供的库函数,也可以是由用户定义的自定义函数。在编制C程序时,程序的开始部分一般是预处理命令、函数说明和变量定义等。10.1.2C语言与MCS-51单片机用C语言编写MCS-51单片机程序与用汇编语言编写MCS–51单片机程序不一样。用汇编语言编写MCS–51单片机程序必须要考虑其存储器结构,尤其必须考虑其片内数据存储器与特殊功能寄存器的使用以及按实际地址处理端口数据。用C语言编写的MCS–51单片机应用程序,则不用像汇编语言那样须具体组织、分配存储器资源和处理端口数据,但在C语言编程中,对数据类型与变量的定义,必须要与单片机的存储结构相关联,否则编译器不能正确地映射定位。C语言编写单片机应用程序时,需根据单片机存储结构及内部资源定义相应的数据类型和变量,而标准的C语言程序不需要考虑这些问题;C51包含的数据类型、变量存储模式、输入输出处理、函数等方面与标准的C语言有一定的区别。其它的语法规则、程序结构及程序设计方法等与标准的C语言程序设计相同。用C语言编写单片机应用程序与标准的C语言程序也有相应的区别:现在支持MCS-51系列单片机的C语言编译器有很多种,如AmericanAutomation、Avocet、BSO/TASKING、DUNFIELDSHAREWARE、KEIL/Franklin等。各种编译器的基本情况相同,但具体处理时有一定的区别,其中KEIL/Franklin以它的代码紧凑和使用方便等特点优于其它编译器,现在使用特别广泛。本章主要以KEIL编译器介绍MCS-51单片机C语言程序设计。10.1.3C51程序结构C51的语法规定、程序结构及程序设计方法都与标准的C语言程序设计相同,但C51程序与标准的C程序在以下几个方面不一样:(1)C51中定义的库函数和标准C语言定义的库函数不同。标准的C语言定义的库函数是按通用微型计算机来定义的,而C51中的库函数是按MCS-51单片机相应情况来定义的;(2)C51中的数据类型与标准C的数据类型也有一定的区别,在C51中还增加了几种针对MCS-51单片机特有的数据类型;(3)C51变量的存储模式与标准C中变量的存储模式不一样,C51中变量的存储模式是与MCS-51单片机的存储器紧密相关;(4)C51与标准C的输入输出处理不一样,C51中的输入输出是通过MCS-51串行口来完成的,输入输出指令执行前必须要对串行口进行初始化;(5)C51与标准C在函数使用方面也有一定的区别,C51中有专门的中断函数。10.2C51的数据类型C51的数据类型分为基本数据类型和组合数据类型,情况与标准C中的数据类型基本相同,但其中char型与short型相同,float型与double型相同,另外,C51中还有专门针对于MCS-51单片机的特殊功能寄存器型和位类型。基本数据类型长度取值范围unsignedchar1字节0~255signedchar1字节-128~+127unsignedint2字节0~65535signedint2字节-32768~+32767unsignedlong4字节0~4294967295signedlong4字节-2147483648~+2147483647float4字节1.175494E-38~3.402823E+38bit1位0或1sbit1位0或1sfr1字节0~255sfr162字节0~65535KEILC51编译器能够识别的基本数据类型:四.存储器类型存储器类型是用于指明变量所处的单片机的存储器区域情况。存储器类型与存储种类完全不同。C51编译器能识别的存储器类型有以下几种,见表所示。存储器类型描述data直接寻址的片内RAM低128B,访问速度快bdata片内RAM的可位寻址区(20H~2FH),允许字节和位混合访问idata间接寻址访问的片内RAM,允许访问全部片内RAMpdata用Ri间接访问的片外RAM的低256Bxdata用DPTR间接访问的片外RAM,允许访问全部64k片外RAMcode程序存储器ROM64k空间定义变量时也可以省“存储器类型”,省时C51编译器将按编译模式默认存储器类型,具体编译模式的情况在后面介绍。【例】变量定义存储种类和存储器类型相关情况。chardatavarl;/*在片内RAM低128B定义用直接寻址方式访问的字符型变量var1*/intidatavar2;/*在片内RAM256B定义用间接寻址方式访问的整型变量var2*/autounsignedlongdatavar3;/*在片内RAM128B定义用直接寻址方式访问的自动无符号长整型变量var3*/externfloatxdatavar4;/*在片外RAM64KB空间定义用间接寻址方式访问的外部实型变量var4*/intcodevar5;/*在ROM空间定义整型变量var5*/unsigncharbdatavar6;/*在片内RAM位寻址区20H~2FH单元定义可字节处理和位处理的无符号字符型变量var6*/五.特殊功能寄存器变量MCS-51系列单片机片内有许多特殊功能寄存器,通过这些特殊功能寄存器可以控制MCS-51系列单片机的定时器、计数器、串口、I/O及其它功能部件,每一个特殊功能寄存器在片内RAM中都对应于一个字节单元或两个字节单元。在C51中,允许用户对这些特殊功能寄存器进行访问,访问时须通过sfr或sfr16类型说明符进行定义,定义时须指明它们所对应的片内RAM单元的地址。格式如下:sfr或sfr16特殊功能寄存器名=地址;sfr用于对MCS-51单片机中单字节的特殊功能寄存器进行定义,sfr16用于对双字节特殊功能寄存器进行定义。特殊功能寄存器名一般用大写字母表示。地址一般用直接地址形式,具体特殊功能寄存器地址见前面内容。【例4-3】特殊功能寄存器的定义。sfrPSW=0xd0;sfrSCON=0x98;sfrTMOD=0x89;sfrP1=0x90;sfr16DPTR=0x82;sfr16T1=0X8A;六.位变量在C51中,允许用户通过位类型符定义位变量。位类型符有两个:bit和sbit。可以定义两种位变量。bit位类型符用于定义一般的可位处理位变量。它的格式如下:bit位变量名;在格式中可以加上各种修饰,但注意存储器类型只能是bdata、data、idata。只能是片内RAM的可位寻址区,严格来说只能是bdata。【例】bit型变量的定义。bitdataa1;/*正确*/bitbdataa2;/*正确*/bitpdataa3;/*错误*/bitxdataa4;/*错误*/sbit位类型符用于定义在可位寻址字节或特殊功能寄存器中的位,定义时须指明其位地址,可以是位直接地址,可以是可位寻址变量带位号,也可以是特殊功能寄存器名带位号。格式如下:sbit位变量名=位地址;如位地址为位直接地址,其取值范围为0x00~0xff;如位地址是可位寻址变量带位号或特殊功能寄存器名带位号,则在它前面须对可位寻址变量或特殊功能寄存器进行定义。字节地址与位号之间、特殊功能寄存器与位号之间一般用“^”作间隔。【例】sbit型变量的定义:sbitOV=0xd2;sbitCY=oxd7;unsignedcharbdataflag;sbitflag0=flag^0;sfrP1=0x90;sbitP1_0=P1^0;sbitP1_1=P1^1;sbitP1_2=P1^2;sbitP1_3=P1^3;sbitP1_4=P1^4;sbitP1_5=P1^5;sbitP1_6=P1^6;sbitP1_7=P1^7;在C51中,为了用户处理方便,C51编译器把MCS-51单片机的常用的特殊功能寄存器和特殊位进行了定义,放在一个“reg51.h”或“reg52.h”的头文件中,当用户要使用时,只须要在使用之前用一条预处理命令#includereg52.h把这个头文件包含到程序中,然后就可使用殊功能寄存器名和特殊位名称。5.interruptm修饰符interruptm是C51函数中非常重要的一个修饰符,这是因为中断函数必须通过它进行修饰。在C51程序设计中,当函数定义时用了interruptm修饰符,系统编译时把对应函数转化为中断函数,自动加上程序头段和尾段,并按MCS-51系统中断的处理方式自动把它安排在程序存储器中的相应位置。在该修饰符中,m的取值为0~31,对应的中断情况如下:0——外部中断01——定时/计数器T02——外部中断13——定时/计数器T14——串行口中断5——定时/计数器T2其它值预留。【例22】编写一个用于统计外中断0的中断次数的中断服务程序externintx;voidint0()interrupt0using1{x++;}6.usingn修饰符修饰符usingn用于指定本函数内部使用的工作寄存器组,其中n的取值为0~3,表示寄存器组号。对于usingn修饰符的使用,注意以下几点:(1)加入usingn后,C51在编译时自动的在函数的开始处和结束处加入以下指令。{PUSHPSW;标志寄存器入栈MOVPSW,#与寄存器组号相关的常量……POPPSW;标志寄存器出栈}(2)usingn修饰符不能用于有返回值的函数,因为C51函数的返回值是放在寄存器中的。如寄存器组改变了,返回值就会出错。一、基本示例分析:例1、LED的控制使用805l的Port1连接8个LED,以产生跑马灯的效果。连接好电路并且完成程序之后,您将可以看到8个LED依次轮流闪烁。在这次练习中,您将学会如何使用I/OPort输出数据,以及如何使用循环实现时间延迟。电路图#includeREGX51.Hvoiddelay(void)/*delay函数*/{unsignedchari,j;/*这个函数执行时间的延迟*/for(i=0;i255;i++)for(j=0;j255;j++);}voidmain(void){unsignedcharj=0XFE;/*声明变量j*/while(1)/*无穷循环*/{/*依次让LED0,1,2,3,4,5,6,7闪烁*/j=(j1)|0x01;if(j==0XFF)j=0XFE;P1=j;/*将数值输出到Port1,控制LED亮或灭*/delay();/*调用delay函数*/}}例2、指拨开关的输入目的是使用8051的Portl连接到8个LED,Port2则连接到1个指拨开关,当用户拨动指拨开关时,相对应的LED就会亮或灭。在这次练习中,您将学会如何使用8051输入数据。例如,您要从Port2输入数据给变量temp时,可以执行temp=P2;电路图#includeREGX51.Hvoiddelay(void)/*delay函数*/{unsignedchari,j;/*这个函数执行时间的延迟*/for(i=0;i255;i++)for(j=0;j255;j++);}voidmain(void){unsignedchartemp;/*声明变量temp*/while(1)/*无穷循环*/{temp=P2;/*将P2输入的数据直接放入变量temp当中*/P1=temp;/*将变量temp中

1 / 35
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功