学习一门编程语言,最重要的是建立一个练习环境,这样才能在练习的同时学好。Keil软件是开发80C51系列单片机最流行的软件。Keil提供了完整的开发方案,包括C编译器、宏汇编、连接器、库管理和强大的模拟调试器。通过集成开发环境(?Vision)将这些部分放在一起。
请在学习前安装KEILC51软件。学会使用汇编语言后,学习C编程就相对容易了。我们将通过一系列的例子来介绍C编程的方法。图1-1所示的电路图采用89c51单片机作为主芯片。这个单片机属于80C51系列,内部有8K的FLASH ROM,可以反复擦除,非常适合做实验。89c51的P1引脚连接8个发光二极管,P3.2~P3.4引脚连接4个按钮开关。我们的任务是使与P1引脚相连的发光二极管按要求发光。
一个简单的C程序介绍
例1-1:让连接到P1.0引脚的LED发光。
/************************************************
单灯闪烁程序
*************************************************/
#include “reg51.h”//这句话是将51个常用端口和内部寄存器的定义文件包含到这个程序中。
it p1_0=p1^0;
void main()
{ P1 _ 1 = 0;
}
该程序的功能是使连接到P1.0引脚的LED亮起。我们来分析一下这个C语言程序包含了哪些信息。
1)”文件包含”处理。
程序的第一行是一个“文件包含”进程。
所谓“文件包含”,就是一个文件包含了另一个文件的所有内容,所以这里的程序只有四行,但是C编译器在处理的时候却要处理几十行或者上百行。这里程序中包含REG51.h文件的目的是使用符号P1,也就是告知C编译器,程序中写的P1指的是80C51单片机的P1端口,而不是其他变量。这是怎么做到的?
打开reg51.h,可以看到这样的内容:
/* – REG51。H
通用80C51和80C31微控制器的头文件。
版权所有(c) 1988-2001 Keil Elektronik GmbH和Keil Software,Inc。
保留所有权利。
– */
/*字节寄存器*/
sfr P0 = 0x80
sfr P1 = 0x 90;
sfr P2 = 0xa 0;
sfr P3 = 0xb 0;
sfr PSW = 0xD0
sfr ACC = 0xE0
sfr B = 0xF0
sfr SP = 0x81
sfr DPL = 0x 82;
sfr DPH = 0x 83;
sfr PCON = 0x 87;
sfr TCON = 0x 88;
sfr TMOD = 0x 89;
sfr TL0 = 0x8A
sfr TL1 = 0x8B
sfr TH0 = 0x8C
sfr TH1 = 0x8D
sfr IE = 0xA8
sfr IP = 0xB8
sfr SCON = 0x 98;
sfr UF = 0x99
/*位寄存器*/
/* PSW */
it CY = 0xD7
it AC = 0xD6
it F0 = 0xD5
it RS1 = 0xD4
it RS0 = 0xD3
it OV = 0x D2;
it P = 0xD0
/* TCON */
it TF1 = 0x8F
it TR1 = 0x8E
it TF0 = 0x8D
it TR0 = 0x8C
it IE1 = 0x8B
it IT1 = 0x8A
it IE0 = 0x89
it IT0 = 0x88
/* IE */
it EA = 0xAF
it ES = 0xAC
it ET1 = 0xAB
it EX1 = 0xAA
it ET0 = 0xA9
it EX0 = 0xA8
/* IP */
it PS = 0xBC
it PT1 = 0xBB
it PX1 = 0xBA
it PT0 = 0xB9
it PX0 = 0xB8
/* P3 */
it RD = 0xB7
it WR = 0xb 6;
it T1 = 0xB5
it T0 = 0xB4
it INT1 = 0xB3
it INT0 = 0xB2
it TXD = 0x B1;
it RXD = 0xb 0;
/* SCON */
it 0 = 0x9F
it 1 = 0x9E;
it 2 = 0x9D;
it REN = 0x9C
it TB8 = 0x9B
it RB8 = 0x9A
it TI = 0x99
it RI = 0x98
熟悉80C51内部结构的读者不难看出,这里有一些符号的定义,即规定了符号名称与地址的对应关系。请注意,这里有
sfr P1 = 0x 90;
这样一行(上面用粗体显示)表示P1对应地址0x90,P1端口地址是0x90(0x90是C语言十六进制数的写法,相当于汇编语言写90H)。
还可以看到一个经常出现的词:sfr。
Sfr和C语言的标准关键字,但Keil在80C51中提供了直接访问SFR的新关键字,其用法是:
Sfrt变量名=地址值。
2) P1_0用于表示P1.0引脚。
在C语言中,如果直接写P1.0,C编译器无法识别,而P1.0又不是合法的C语言变量名,所以你得给它另起一个名字。这里的名字是P1_0,但是P1_0是P1.0吗?你这么认为,但是C编译器不这么认为,所以有必要和他们建立联系。这里用Keil C的关键字it来定义。it有三种用途:
第一种方法:it位变量名=地址值。
第二种方法:it位变量名= =SFR名变量位地址值
第三种方法:it位变量名= =SFR地址值变量位地址值。
如果在PSW中定义OV,可以使用以下三种方法:
it OV=0xd2 (1)描述:0xd2是OV的位地址值。
itov = PSW 2 (2)说明:PSW必须首先由sfr定义。
itov = 0xD0 2 (3)描述:0xD0是PSW的地址值。
因此,此处使用sfr P1 _ 0 = P1 0;也就是说,P1.0引脚是由符号P1_0定义的,如果你愿意,你可以把它命名为P10,只要下面的程序相应地改变。
3)main称为“主函数”。
每个C语言程序都有且只有一个main函数,所以必须有一个main函数,不要求放在程序的最后(推荐),函数后面必须有一对大括号“{}”,其他程序都写在里面。
从上面的分析,我们知道了C语言的一些特点。让我们看一个稍微复杂一点的例子。
示例1-2让连接到P1.0引脚的LED闪烁。
/*************************************************
单灯闪烁程序
*************************************************/
#包含“reg51.h”
#定义uchar无符号字符
#定义uint无符号整数
it p10=p1^0;
/*延迟程序
延迟时间由延迟参数决定
*/
void mDelay(无符号整数延迟)
{无符号整数I;
for(;延迟& gt0;延迟-)
{ for(I = 0;我& lt124;i++)
{;}
}
}
void main()
{ for(;;)
{ P10=!P10//反转P1.0引脚
姆德雷(1000);
}
}
程序分析:暂时忽略主程序中的第一行,第二行是“P1_0=!P1 _ 0;”,有一个符号“!”在P1之前。,符号“!”它是C语言的一种运算符,就像数学中的“+”、“-”一样,是一种运算符号,意思是“反转”,即符号后面的变量值反转。
注意:求逆运算只针对变量的值,不会自动改变变量本身。你可以认为C编译器处理的是“!P1_0”,将P1_0的值赋给一个临时变量,然后对这个临时变量进行否定,而不是直接否定P1_0。因此,在求反之后,使用赋值符号(“=”)将被求反的值赋给P1_0。这样,如果原来的P1.0为低(LED亮),那么取反后,P1.0为高。
这条指令重复执行的关键在于main中程序的第一行:for(;;),这里就不详细介绍这个了。读者暂时只需要知道这一行程序,加上一对大括号“{}”,构成了一个无限循环语句,大括号中的语句会被重复执行。
程序的第三行是:“mDelay(1000);”该程序的目的是将指令延迟1秒。因为单片机执行指令的速度很快,如果没有延时,打开后灯马上就灭了,关闭后灯马上就亮了。速度太快,人眼分辨不清。
这里的mDelay(1000)不是Keil C提供的库函数,也就是说你在任何情况下都无法编写这样一行程序来实现延迟。如果你写其他程序的时候写这样一行,你会发现编译不会通过。那么为什么这是对的呢?注意观察,可以发现这个程序里有一行类似void mDelay(…)的。可以看出,mDelay这个词是我们自己的名字,为此还写了一些程序行。如果你的程序里没有这一行,就不能用mDelay(1000)。脑子快的人可能马上会想,我能不能把这个程序复制到我的其他程序里,然后我就可以用mDelay(1000)了?答案当然是肯定的。还有一点需要注意的是,mDelay这个名字是程序员自己起的,可以自己更改,但是一旦更改了名字,main()函数中的名字也要相应更改。
mDelay后面有一个括号,括号里有数据(1000)。这个1000叫做“参数”,可以用来在一定范围内调整延迟时间的长短。这里,1000用于要求延迟时间为1000毫秒。要做到这一点,必须由我们自己编写的mDelay的程序来决定。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。