单片机的c语言

51单片机
C语言入门教程

 

51单片机
C语言学习杂记

学习单片机实在不是件易事,一来要购买高价格的编程器,仿真器,二来要学习编程语
言,还有众多种类的单片机选择真是件让人头痛的事。在众多单片机中
51架构的芯片风行
很久,学习资料也相对很多,是初学的较好的选择之一。
51的编程语言常用的有二种,一
种是汇编语言,一种是
C语言。汇编语言的机器代码生成效率很高但可读性却并不强,复
杂一点的程序就更是难读懂,而
C语言在大多数情况下其机器代码生成效率和汇编语言相
当,但可读性和可移植性却远远超过汇编语言,而且
C语言还可以嵌入汇编来解决高时效
性的代码编写问题。对于开发周期来说,中大型的软件编写用
C语言的开发周期通常要小
于汇编语言很多。综合以上
C语言的优点,我在学习时选择了
C语言。以后的教程也只是
我在学习过程中的一些学习笔记和随笔,在这里加以整理和修改,希望和大家一起分享,一
起交流,一起学习,一起进步。

 *注:可以肯定的说这个教程只是为初学或入门者准备的,笔者本人也只是菜鸟一只,
有望各位大侠高手指点错误提出建议。
明浩
2003-3-30 pnzwzw@163.com

第一课建立您的第一个
C项目

使用
C语言肯定要使用到
C编译器,以便把写好的
C程序编译为机器码,这样单片机
才能执行编写好的程序。
KEIL uVISION2是众多单片机应用开发软件中优秀的软件之一,
它支持众多不同公司的
MCS51架构的芯片,它集编辑,编译,仿真等于一体,同时还支持,
PLM,汇编和
C语言的程序设计,它的界面和常用的微软
VC++的界面相似,界面友好,易
学易用,在调试程序,软件仿真方面也有很强大的功能。因此很多开发
51应用的工程师或
普通的单片机爱好者,都对它十分喜欢。

以上简单介绍了
KEIL51软件,要使用
KEIL51软件,必需先要安装它。
KEIL51是一个
商业的软件,对于我们这些普通爱好者可以到
KEIL中国代理周立功公司的网站上下载一份
能编译
2K的
DEMO版软件,基本可以满足一般的个人学习和小型应用的开发。(安装的方
法和普通软件相当这里就不做介绍了)

安装好后,您是不是迫不及待的想建立自己的第一个
C程序项目呢?下面就让我们一
起来建立一个小程序项目吧。或许您手中还没有一块实验板,甚至没有一块单片机,不过没
有关系我们可以通过
KEIL软件仿真看到程序运行的结果。

首先当然是运行
KEIL51软件。怎么打开?噢,天!那您要从头学电脑了。呵呵,开个
玩笑,这个问题我想读者们也不会提的了:P。运行几秒后,出现如图
1-1的屏幕。



1-1启动时的屏幕

- 1 -


51单片机
C语言入门教程

 

接着按下面的步骤建立您的第一个项目:

(1)点击
Project菜单,选择弹出的下拉式菜单中的
New Project,如图
1-2。接着弹
出一个标准
Windows文件对话窗口,如图
1-3,这个东东想必大家是见了
N次的了,用法
技巧也不是这里要说的,以后的章节中出现类似情况将不再说明。在“文件名”中输入您的
第一个
C程序项目名称,这里我们用“
test”,这是笔者惯用的名称,大家不必照搬就是了,
只要符合
Windows文件规则的文件名都行。“保存”后的文件扩展名为
uv2,这是
KEIL
uVision2项目文件扩展名,以后我们可以直接点击此文件以打开先前做的项目。

1-2 New Project菜单



1-3文件窗口

(2)选择所要的单片机,这里我们选择常用的
Ateml公司的
AT89C51。此时屏幕如图
1-4所示。
AT89C51有什么功能、特点呢?不用急,看图中右边有简单的介绍,稍后的章
节会作较详细的介绍。完成上面步骤后,我们就可以进行程序的编写了。
(3)首先我们要在项目中创建新的程序文件或加入旧程序文件。如果您没有现成的程
序,那么就要新建一个程序文件。在
KEIL中有一些程序的
Demo,在这里我们还是以一个
C程序为例介绍如何新建一个
C程序和如何加到您的第一个项目中吧。点击图
1-5中
1的
新建文件的快捷按钮,在
2中出现一个新的文字编辑窗口,这个操作也可以通过菜单
File-New或快捷键
Ctrl+N来实现。好了,现在可以编写程序了,光标已出现在文本编辑窗口
中,等待我们的输入了。第一程序嘛,写个简单明了的吧。下面是经典的一段程序,呵,如
- 2 -


51单片机
C语言入门教程

 

果您看过别的程序书也许也有类似的程序:


#include <AT89X51.H>
#include <stdio.h>

void main(void)

{
SCON = 0x50; //串口方式
1,允许接收
TMOD = 0x20; //定时器
1定时方式
2
TCON = 0x40; //设定时器
1开始计数
TH1 = 0xE8; //11.0592MHz 1200波特率
TL1 = 0xE8;
TI = 1;
TR1 = 1; //启动定时器

 while(1)
{
printf ("Hello World!/n"); //显示
Hello World
}
}



1-4选取芯片

- 3 -


51单片机
C语言入门教程

 


1-5新建程序文件

这段程序的功能是不断从串口输出“
Hello World!”字符,我们先不管程序的语法和意思吧,
先看看如何把它加入到项目中和如何编译试运行。

(4)点击图
1-5中的
3保存新建的程序,也可以用菜单
File-Save或快捷键
Ctrl+S
进行保存。因是新文件所以保存时会弹出类似图
1-3的文件操作窗口,我们把第一个程序
命名为
test1.c,保存在项目所在的目录中,这时您会发现程序单词有了不同的颜色,说明
KEIL的
C语法检查生效了。如图
1-6鼠标在屏幕左边的
Source Group1文件夹图标上右击
弹出菜单,在这里可以做在项目中增加减少文件等操作。我们选“
Add File to Group ‘Source
Group 1’”弹出文件窗口,选择刚刚保存的文件,按
ADD按钮,关闭文件窗,程序文件已
加到项目中了。这时在
Source Group1文件夹图标左边出现了一个小
+号说明,文件组中有
了文件,点击它可以展开查看。

1-6把文件加入到项目文件组中

- 4 -


51单片机
C语言入门教程

 

(5)C程序文件已被我们加到了项目中了,下面就剩下编译运行了。这个项目我们只
是用做学习新建程序项目和编译运行仿真的基本方法,所以使用软件默认的编译设置,它不
会生成用于芯片烧写的
HEX文件,如何设置生成
HEX文件就请看下面的第三课。我们先
来看图
1-7吧,图中
1、2、3都是编译按钮,不同是
1是用于编译单个文件。
2是编译当
前项目,如果先前编译过一次之后文件没有做动编辑改动,这时再点击是不会再次重新编译
的。3是重新编译,每点击一次均会再次编译链接一次,不管程序是否有改动。在
3右边的
是停止编译按钮,只有点击了前三个中的任一个,停止按钮才会生效。
5是菜单中的它们,
我个人就不习惯用它了。嘿嘿,这个项目只有一个文件,您按
123中的一个都可以编译。按
了?好快哦,呵呵。在
4中可以看到编译的错误信息和使用的系统资源情况等,以后我们要
查错就靠它了。
6是有一个小放大镜的按钮,这就是开启
/关闭调试模式的按钮,它也存在于
菜单
Debug-Start/Stop Debug Session,快捷键为
Ctrl+F5。

1-7编译程序


(6)进入调试模式,软件窗口样式大致如图
1-8所示。图中
1为运行,当程序处于停止
状态时才有效,
2为停止,程序处于运行状态时才有效。
3是复位,模拟芯片的复位,程序
回到最开头处执行。按
4我们可以打开
5中的串行调试窗口,这个窗口我们可以看到从
51
芯片的串行口输入输出的字符,这里的第一个项目也正是在这里看运行结果。这些在菜单中
也有,这里不再一一介绍大家不妨找找看,其它的功能也会在后面的课程中慢慢介绍。首先

4打开串行调试窗口,再按运行键,这时就可以看到串行调试窗口中不断的打印“
Hello
World!”。呵呵,是不是不难呀?这样就完成了您的第一个
C项目。最后我们要停止程序运
行回到文件编辑模式中,就要先按停止按钮再按开启
/关闭调试模式按钮。然后我们就可以
进行关闭
KEIL等相关操作了。
到此为止,第一课已经完结了,初步学习了一些
KEIL uVision2的项目文件创建、编译、
运行和软件仿真的基本操作方法。其中一直有提到一些功能的快捷键的使用,的确在实际的
开发应用中快捷键的运用可以大大提高工作的效率,建议大家多多使用,还有就是对这里所
讲的操作方法举一反三用于类似的操作中。

- 5 -


51单片机
C语言入门教程

 


1-8调试运行程序

第二课初步认识
51芯片

上一课我们的第一个项目完成了,可能有懂
C语言的朋友会说,“这和
PC机上的
C语言
没有多大的区别呀”。的确没有太大的区别,
C语言只是一种程序语言的统称,针对不同的
处理器相关的
C语言都会有一些细节的改变。编写
PC机的
C程序时,如要对硬件编程您就
必须对硬件要有一定的认识,
51单片机编程就更是如此,因它的开发应用是不可与硬件脱
节的,所以我们先要来初步认识一下
51苾片的结构和引脚功能。
MSC51架构的芯片种类很
多,具体特点和功能不尽相同(在以后编写的附录中会加入常用的一些
51芯片的资料列表),
在此后的教程中就以
Atmel公司的
AT89C51和
AT89C2051为中心对象来进行学习,两者是
AT89系列的典型代表,在爱好者中使用相当的多,应用资料很多,价格便宜,是初学
51的
首选芯片。嘿嘿,口水多多有点卖广告之嫌了。:P



2-1 AT89C51和
AT89C2051引脚功能图

- 6 -


51单片机
C语言入门教程

 

AT89C51 AT89C2051
4KB可编程
Flash存储器(可擦写
1000次)
2KB可编程
Flash存储器(可擦写
1000次)
三级程序存储器保密两级程序存储器保密
静态工作频率:0Hz-24MHz 静态工作频率:0Hz-24MHz
128字节内部
RAM 128字节内部
RAM
2个
16位定时/计数器 2个
16位定时/计数器
一个串行通讯口一个串行通讯口
6个中断源 6个中断源
32条
I/O引线 15条
I/O引线
片内时种振荡器 1个片内模拟比较器


2-1 AT89C51和
AT89C2051主要性能表


2-1中是
AT89C51和
AT89C2051的引脚功能图。而表
2-1中则是它们的主要性能表。
以上可以看出它们是大体相同的,由于
AT89C2051的
IO线很少,导致它无法外加
RAM和程

ROM,片内
Flash存储器也少,但它的体积比
AT89C51小很多,以后大家可根据实际需要
来选用。它们各有其特点但其核心是一样的,下面就来看看
AT89C51的引脚具体功能。


1.电源引脚
Vcc 40 电源端
GND 20 接地端
*工作电压为
5V,另有
AT89LV51工作电压则是
2.7-6V, 引脚功能一样。
2.外接晶体引脚

2-2 外接晶体引脚

 XTAL1 19
XTAL2 18


 XTAL1是片内振荡器的反相放大器输入端,
XTAL2则是输出端,使用外部振荡器
时,外部振荡信号应直接加到
XTAL1,而
XTAL2悬空。内部方式时,时钟发生器对振
荡脉冲二分频,如晶振为
12MHz,时钟频率就为
6MHz。晶振的频率可以在
1MHz-24MHz
内选择。电容取
30PF左右。

- 7 -


51单片机
C语言入门教程

 

*型号同样为
AT89C51的芯片,在其后面还有频率编号,有
12,16,20,24MHz可选。
大家在购买和选用时要注意了。如
AT89C51 24PC就是最高振荡频率为
24MHz,40P6封
装的普通商用芯片。
3.复位 RST 9
在振荡器运行时,有两个机器周期(
24个振荡周期)以上的高电平出现在此引腿
时,将使单片机复位,只要这个脚保持高电平,
51芯片便循环复位。复位后
P0-P3口
均置
1引脚表现为高电平,程序计数器和特殊功能寄存器
SFR全部清零。当复位脚由
高电平变为低电平时,芯片为
ROM的
00H处开始运行程序。常用的复位电路如图
23
所示。

*复位操作不会对内部
RAM有所影响。

2-3 常用复位电路


4.输入输出引脚
(1)P0端口[P0.0-P0.7] P0是一个
8位漏极开路型双向
I/O端口,端口置
1(对端
口写
1)时作高阻抗输入端。作为输出口时能驱动
8个
TTL。
对内部
Flash程序存储器编程时,接收指令字节
;校验程序时输出指令字节,要
求外接上拉电阻。
在访问外部程序和外部数据存储器时,
P0口是分时转换的地址
(低
8位)/数据
总线,访问期间内部的上拉电阻起作用。


(2) P1端口[P1.0-P1.7] P1是一个带有内部上拉电阻的
8位双向
I/0端口。输出时
可驱动
4个
TTL。端口置
1时,内部上拉电阻将端口拉到高电平,作输入用。
对内部
Flash程序存储器编程时,接收低
8位地址信息。
(3) P2端口[P2.0-P2.7] P2是一个带有内部上拉电阻的
8位双向
I/0端口。输出时
可驱动
4个
TTL。端口置
1时,内部上拉电阻将端口拉到高电平,作输入用。
对内部
Flash程序存储器编程时,接收高
8位地址和控制信息。
在访问外部程序和
16位外部数据存储器时,
P2口送出高
8位地址。而在访问
8
位地址的外部数据存储器时其引脚上的内容在此期间不会改变。

- 8 -


51单片机
C语言入门教程

 

(4) P3端口[P3.0-P3.7] P2是一个带有内部上拉电阻的
8位双向
I/0端口。输出时
可驱动
4个
TTL。端口置
1时,内部上拉电阻将端口拉到高电平,作输入用。
对内部
Flash程序存储器编程时,接控制信息。除此之外
P3端口还用于一些
专门功能,具体请看表
2-2.。

*P1-3端口在做输入使用时,因内部有上接电阻,被外部拉低的引脚会输出
一定的电流。
P3引脚兼用功能
P3.0 串行通讯输入(RXD)
P3.1 串行通讯输出(TXD)
P3.2 外部中断
0( INT0)
P3.3 外部中断
1(INT1)
P3.4 定时器
0输入(T0)
P3.5 定时器
1输入(T1)
P3.6 外部数据存储器写选通
WR
P3.7 外部数据存储器写选通
RD


2-2 P3端口引脚兼用功能表

呼!一口气说了那么多,停一下吧。嗯,什么?什么叫上拉电阻?上拉电阻简单来说就
是把电平拉高,通常用
4.7-10K的电阻接到
Vcc电源,下拉电阻则是把电平拉低,电阻接

GND地线上。具体说明也不是这里要讨论的,接下来还是接着看其它的引脚功能吧。


5.其它的控制或复用引脚
(1)ALE/PROG 30访问外部存储器时,
ALE(地址锁存允许)的输出用于锁存地址
的低位字节。即使不访问外部存储器,
ALE端仍以不变的频率输出脉冲信号
(此
频率是振荡器频率的
1/6)。在访问外部数据存储器时,出现一个
ALE脉冲。对
Flash存储器编程时,这个引脚用于输入编程脉冲
PROG
(2)PSEN 29该引是外部程序存储器的选通信号输出端。当
AT89C51由外部程序存
储器取指令或常数时,每个机器周期输出
2个脉冲即两次有效。但访问外部数
据存储器时,将不会有脉冲输出。
(3)EA/Vpp 31 外部访问允许端。当该引脚访问外部程序存储器时,应输入低电平。
要使
AT89C51只访问外部程序存储器(地址为
0000H-FFFFH),这时该引脚必须
保持低电平。对
Flash存储器编程时,用于施加
Vpp编程电压。
Vpp电压有两
种,类似芯片最大频率值要根据附加的编号或芯片内的特征字决定。具体如表
2-3所列。
Vpp = 12V Vpp = 5V
印刷在芯片面上的型号
AT89C51
xxxx
YYWW
AT89LV51
xxxx
YYWW
AT89C51
xxxx-5
YYWW
AT89LV51
xxxx-5
YYWW
030H=1EH 030H=1EH 030H=1EH 030H=1EH
片内特征字
031H=51H 031H=61H 031H=51H 031H=61H
032H=FFH 032H=FFH 032H=05H 032H=05H


2-3 Vpp与芯片型号和片内特征字的关系

- 9 -


51单片机
C语言入门教程

 

看到这您对
AT89C51引脚的功能应该有了一定的了解了,引脚在编程和校验时的时序我
们在这里就不做详细的探讨,通常情况下我们也没有必要去撑握它,除非您想自己开发编程
器。下来的课程我们要开始以一些简单的实例来讲述
C程序的语法和编写方法技巧,中间穿
插相关的硬件知识如串口,中断的用法等等。

第三课生成
HEX文件和最小化系统

在开始C语言的主要内容时,我们先来看看如何用KEIL uVISION2来编译生成用于烧写
芯片的HEX文件。HEX文件格式是Intel公司提出的按地址排列的数据信息,数据宽度为字
节,所有数据使用16进制数字表示,常用来保存单片机或其他处理器的目标程序代码。它保
存物理程序存储区中的目标代码映象。一般的编程器都支持这种格式。我们先来打开第一课
做的第一项目,打开它的所在目录,找到test.Uv2的文件就可以打开先前的项目了。然后右
击图3-1中的1项目文件夹,弹出项目功能菜单,选
Options for Target’Target1’,弹出项目选项
设置窗口,同样先选中项目文件夹图标,这时在
Project菜单中也有一样的菜单可选。打开项
目选项窗口,转到
Output选项页图
3-2所示,图中
1是选择编译输出的路径,
2是设置编译输
出生成的文件名,
3则是决定是否要创建
HEX文件,选中它就可以输出
HEX文件到指定的路
径中。选好了?好,我们再将它重新编译一次,很快在编译信息窗口中就显示
HEX文件创建
到指定的路径中了,如图
3-3。这样我们就可用自己的编程器所附带的软件去读取并烧到芯
片了,再用实验板看结果,至于编程器或仿真器品种繁多具体方法就看它的说明书了,这里
也不做讨论。
(技巧:一、在图3-1中的1里的项目文件树形目录中,先选中对象,再单击它就可对它进
行重命名操作,双击文件图标便可打开文件。二、在
Project下拉菜单的最下方有最近编辑过
的项目路径保存,这里可以快速打开最近在编辑的项目。)


图3-1项目功能菜单

- 10 -


51单片机
C语言入门教程

 

图3-2项目选项窗口



3-3 编译信息窗口

或许您已把编译好的文件烧到了芯片上,如果您购买或自制了带串口输出元件的学习实
验板,那您就可以把串口和
PC机串口相联用串口调试软件或
Windows的超级终端
,将其波特
率设为
1200,就可以看到不停输出的“
Hello World!”字样。也许您还没有实验板,那这
里先说说
AT89C51的最小化系统,再以一实例程序验证最小化系统是否在运行,这个最小化
系统也易于自制用于实验。图
3-4便是
AT89C51的最小化系统
,不过为了让我们可以看出它
是在运行的,我加了一个电阻和一个
LED,用以显示它的状态,晶振可以根据自己的情况使
用,一般实验板上是用
11.0592MHz或
12MHz,使用前者的好外是可以产生标准的串口波特率,
后者则一个机器周期为
1微秒,便于做精确定时。在自己做实验里,注意的是
VCC是+5V的,
不能高于此值,否则将损坏单片机,太低则不能正常工作。在
31脚要接高电平,这样我们
才能执行片内的程序,如接低电平则使用片外的程序存储器。下面,我们建一个新的项目名

OneLED来验证最小化系统是否可以工作(所有的例程都可在我的主页下面下载到,网址:
http://cdle.yeah.net
http://cdle.126.com)。程序如下:

- 11 -


51单片机
C语言入门教程

 

#include <AT89X51.h> //预处理命令


void main(void) //主函数名
{
//这是第一种注释方式

 unsigned int a; //定义变量
a为
int类型
/*

这是第二种注释方式


*/

do{ //do while组成循环
for (a=0; a<50000; a++); //这是一个循环
P1_0 = 0; //设
P1.0口为低电平,点亮
LED
for (a=0; a<50000; a++); //这是一个循环
P1_0 = 1; //设
P1.0口为高电平,熄灭
LED
}
while(1);

}



3-4 AT89C51最小化系统

这里先讲讲
KEIL C编译器所支持的注释语句。一种是以“
//”符号开始的语句,符号
之后的语句都被视为注释,直到有回车换行。另一种是在
“/*”和“*/”符号之内的为注释。
注释不会被
C编译器所编译。一个
C应用程序中应有一个
main主函数,
main函数可以调用

- 12 -


51单片机
C语言入门教程

 

别的功能函数,但其它功能函数不允许调用
main函数。不论
main函数放在程序中的那个位
置,总是先被执行。用上面学到的知识编译写好的
OneLED程序,并把它烧到刚做好的最小
化系统中。上电,刚开始时
LED是不亮的(因为上电复位后所有的
IO口都置
1引脚为高电
平),然后延时一段时间(
for (a=0; a<50000; a++)这句在运行),LED亮,再延时,
LED
熄灭,然后交替亮、灭。第一个真正的小应用就做完,呵呵,先不要管它是否实用哦。如果
没有这样的效果那么您就要认真检查一下电路或编译烧写的步骤了。

第四课数据类型

先来简单说说
C语言的标识符和关键字。标识符是用来标识源程序中某个对象的名字
的,这些对象可以是语句、数据类型、函数、变量、数组等等。
C语言是大小字敏感的一种
高级语言,如果我们要定义一个定时器
1,可以写做“
Timer1”,如果程序中有“
TIMER1”,
那么这两个是完全不同定义的标识符。标识符由字符串,数字和下划线等组成,注意的是第
一个字符必须是字母或下划线,如“
1Timer”是错误的,编译时便会有错误提示。有些编译
系统专用的标识符是以下划线开头,所以一般不要以下划线开头命名标识符。标识符在命名
时应当简单,含义清晰,这样有助于阅读理解程序。在
C51编译器中,只支持标识符的前
32位为有效标识,一般情况下也足够用了,除非你要写天书:P。

关键字则是编程语言保留的特殊标识符,它们具有固定名称和含义,在程序编写中不允
许标识符与关键字相同。在
KEIL uVision2中的关键字除了有
ANSI C标准的
32个关键字外
还根据
51单片机的特点扩展了相关的关键字。其实在
KEIL uVision2的文本编辑器中编写
C程序,系统可以把保留字以不同颜色显示,缺省颜色为天蓝色。(标准和扩展关键字请看
附录一中的附表
1-1和附表
1-2)

先看表
4-1,表中列出了
KEIL uVision2 C51编译器所支持的数据类型。在标准
C语
言中基本的数据类型为
char,int,short,long,float和
double,而在
C51编译器中
int和
short相同,float和
double相同,这里就不列出说明了。下面来看看它们的具体定义:

数据类型长度值域
unsigned char 单字节 0~255
signed char 单字节 -128~+127
unsigned int 双字节 0~65535
signed int 双字节 -32768~+32767
unsigned long 四字节 0~4294967295
signed long 四字节 -2147483648~+2147483647
float 四字节
±1.175494E-38~±3.402823E+38
* 1~3字节对象的地址
bit 位 0或
1
sfr 单字节 0~255
sfr16 双字节 0~65535
sbit 位 0或
1


4-1 KEIL uVision2 C51编译器所支持的数据类型


1.
char字符类型
char类型的长度是一个字节,通常用于定义处理字符数据的变量或常量。分无符号字
符类型
unsigned char和有符号字符类型
signed char,默认值为
signed char类型。
- 13 -


51单片机
C语言入门教程

 

unsigned char类型用字节中所有的位来表示数值,所可以表达的数值范围是
0~255。
signed char类型用字节中最高位字节表示数据的符号,
“0”表示正数,
“1”表示负数,
负数用补码表示。所能表示的数值范围是
-128~+127。unsigned char常用于处理
ASCII
字符或用于处理小于或等于
255的整型数。

*正数的补码与原码相同,负二进制数的补码等于它的绝对值按位取反后加
1。
2.
int整型
int整型长度为两个字节,用于存放一个双字节数据。分有符号
int整型数
signed int
和无符号整型数
unsigned int,默认值为
signed int类型。
signed int表示的数值范
围是-32768~+32767,字节中最高位表示数据的符号,
“0”表示正数,
“1”表示负数。
unsigned int表示的数值范围是
0~65535。
好了,先停一下吧,我们来写个小程序看看
unsigned char和
unsigned int用于延时
的不同效果,说明它们的长度是不同的,呵,尽管它并没有实际的应用意义,这里我们学习
它们的用法就行。依旧用我们上一课的最小化系统做实验,不过要加多一个电阻和
LED,如

4-1。实验中用
D1的点亮表明正在用
unsigned int数值延时,用
D2点亮表明正在用
unsigned char数值延时。



4-1 第
4课实验用电路

我们把这个项目称为
TwoLED,实验程序如下:
#include <AT89X51.h> //预处理命令

- 14 -


51单片机
C语言入门教程

 

void main(void) //主函数名


{

unsigned int a; //定义变量
a为
unsigned int类型


unsigned char b; //定义变量
b为
unsigned char类型

 do
{ //do while组成循环
for (a=0; a<65535; a++)
P1_0 = 0; //65535次设
P1.0口为低电平,点亮
LED
P1_0 = 1; //设
P1.0口为高电平,熄灭
LED


for (a=0; a<30000; a++); //空循环

 for (b=0; b<255; b++)

 P1_1 = 0; //255次设
P1.1口为低电平,点亮
LED

 P1_1 = 1; //设
P1.1口为高电平,熄灭
LED

for (a=0; a<30000; a++); //空循环
}
while(1);
}

同样编译烧写,上电运行您就可以看到结果了。很明显
D1点亮的时间长于
D2点亮的时间。
程序中的循环延时时间并不是很好确定,并不太适合要求精确延时的场合,关于这方面我们
以后也会做讨论。这里必须要讲的是,当定义一个变量为特定的数据类型时,在程序使用该
变量不应使它的值超过数据类型的值域。如本例中的变量
b不能赋超出
0~255的值,如
for
(b=0; b<255; b++)改为
for (b=0; b<256; b++),编译是可以通过的,但运行时就会有问题
出现,就是说
b的值永远都是小于
256的,所以无法跳出循环执行下一句
P1_1 = 1,从而
造成死循环。同理
a的值不应超出
0~65535。大家可以烧片看看实验的运行结果,同样软
件仿真也是可以看到结果的。


3.
long长整型
long长整型长度为四个字节,用于存放一个四字节数据。分有符号
long长整型
signed
long和无符号长整型
unsigned long,默认值为
signed long类型。
signed int表示
的数值范围是
-2147483648~+2147483647,字节中最高位表示数据的符号,
“0”表示正
数,“1”表示负数。unsigned long表示的数值范围是
0~4294967295。
4.
float浮点型
float浮点型在十进制中具有
7位有效数字,是符合
IEEE-754标准的单精度浮点型数
据,占用四个字节。因浮点数的结构较复杂在以后的章节中再做详细的讨论。
5.* 指针型
指针型本身就是一个变量,在这个变量中存放的指向另一个数据的地址。这个指针变量
- 15 -


51单片机
C语言入门教程

 

要占据一定的内存单元,对不同的处理器长度也不尽相同,在
C51中它的长度一般为
1~
3个字节。指针变量也具有类型,在以后的课程中有专门一课做探讨,这里就不多说了。


6.
bit位标量
bit位标量是
C51编译器的一种扩充数据类型,利用它可定义一个位标量,但不能定义
位指针,也不能定义位数组。它的值是一个二进制位,不是
0就是
1,类似一些高级语
言中的
Boolean类型中的
True和
False。
7.
sfr特殊功能寄存器
sfr也是一种扩充数据类型,点用一个内存单元,值域为
0~255。利用它可以访问
51
单片机内部的所有特殊功能寄存器。如用
sfr P1 = 0x90这一句定
P1为
P1端口在片内
的寄存器,在后面的语句中我们用以用
P1 = 255(对
P1端口的所有引脚置高电平)之
类的语句来操作特殊功能寄存器。
*AT89C51的特殊功能寄存器表请看附录二
8.sfr16 16位特殊功能寄存器
sfr16占用两个内存单元,值域为
0~65535。sfr16和
sfr一样用于操作特殊功能寄存
器,所不同的是它用于操作占两个字节的寄存器,好定时器
T0和
T1。
9.
sbit可录址位
sbit同位是
C51中的一种扩充数据类型,利用它可以访问芯片内部的
RAM中的可寻址
位或特殊功能寄存器中的可寻址位。如先前我们定义了
sfr P1 = 0x90; //因
P1端口的寄存器是可位寻址的,所以我们可以定义
sbit P1_1 = P1^1; //P1_1为
P1中的
P1.1引脚
//同样我们可以用
P1.1的地址去写,如
sbit P1_1 = 0x91;
这样我们在以后的程序语句中就可以用
P1_1来对
P1.1引脚进行读写操作了。通常这些
可以直接使用系统提供的预处理文件,里面已定义好各特殊功能寄存器的简单名字,直
接引用可以省去一点时间,我自己是一直用的。当然您也可以自己写自己的定义文件,
用您认为好记的名字。
关于数据类型转换等相关操作在后面的课程或程序实例中将有所提及。大家可以用所讲
到的数据类型改写一下这课的实例程序,加深对各类型的认识。

第五课常量

上一节我们学习了
KEIL C51编译器所支持的数据类型。而这些数据类型又是怎么用在
常量和变量的定义中的呢?又有什么要注意的吗?下面就来看看吧。晕!你还区分不清楚什
么是常量,什么是变量。常量是在程序运行过程中不能改变值的量,而变量是可以在程序运
行过程中不断变化的量。变量的定义可以使用所有
C51编译器支持的数据类型,而常量的数
据类型只有整型、浮点型、字符型、字符串型和位标量。这一节我们学习常量定义和用法,
而下一节则学习变量。

常量的数据类型说明是这样的


1.整型常量可以表示为十进制如
123,0,-89等。十六进制则以
0x开头如
0x34,-0x3B
等。长整型就在数字后面加字母
L,如
104L,034L,0xF340等。
2.浮点型常量可分为十进制和指数表示形式。十进制由数字和小数点组成,如
- 16 -


51单片机
C语言入门教程

 

0.888,3345.345,0.0等,整数或小数部分为
0,可以省略但必须有小数点。指数表
示形式为
[±]数字[.数字]e[±]数字,
[]中的内容为可选项,其中内容根据具体情
况可有可无,但其余部分必须有,如
125e3,7e9,-3.0e-3。
3.字符型常量是单引号内的字符,如‘
a’,‘d’等,不可以显示的控制字符,可以
在该字符前面加一个反斜杠
“/”组成专用转义字符。常用转义字符表请看表
5-1。
4.字符串型常量由双引号内的字符组成,如“
test”,“OK”等。当引号内的没有字
符时,为空字符串。在使用特殊字符时同样要使用转义字符如双引号。在
C中字符
串常量是做为字符类型数组来处理的,在存储字符串时系统会在字符串尾部加上/
o
转义字符以作为该字符串的结束符。字符串常量“
A”和字符常量‘
A’是不同的,
前者在存储时多占用一个字节的字间。
5.位标量,它的值是一个二进制。
转义字符含义 ASCII码(16/10进制)
/o 空字符(NULL) 00H/0
/n 换行符(LF) 0AH/10
/r 回车符(CR) 0DH/13
/t 水平制表符(HT) 09H/9
/b 退格符(BS) 08H/8
/f 换页符(FF) 0CH/12
/' 单引号 27H/39
/" 双引号 22H/34
//反斜杠 5CH/92


5-1 常用转义字符表

常量可用在不必改变值的场合,如固定的数据表,字库等。常量的定义方式有几种
,下

面来加以说明。
#difine False 0x0; //用预定义语句可以定义常量
#difine True 0x1; //这里定义
False为
0,True为
1

//在程序中用到
False编译时自动用
0替换,同理
True替换为
1
unsigned int code a=100; //这一句用
code把
a定义在程序存储器中并赋值
const unsigned int c=100; //用
const定义
c为无符号
int常量并赋值
以上两句它们的值都保存在程序存储器中,而程序存储器在运行中是不允许被修改的,

所以如果在这两句后面用了类似
a=110,a++这样的赋值语句,编译时将会出错。

说了一通还不如写个程序来实验一下吧。写什么程序呢?跑马灯!对,就写这个简单易
懂的吧,这个也好说明典型的常量用法。先来看看电路图吧。它是在我们上一课的实验电路
的基础上增加
6个
LED组成的,也就是用
P1口的全部引脚分别驱动一个
LED,电路如图
5-1所示。

新建一个
RunLED的项目,主程序如下:
#include <AT89X51.H> //预处理文件里面定义了特殊寄存器的名称如
P1口定义为
P1
void main(void)
{

//定义花样数据
cons tunsigned char design[32]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,

- 17 -


51单片机
C语言入门教程


 
0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFF,
0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,
0xE7,0xDB,0xBD,0x7E,0xFF};

unsigned int a; //定义循环用的变量
unsigned char b; //在
C51编程中因内存有限尽可能注意变量类型的使用
//尽可能使用少字节的类型,在大型的程序中很
受用

 do{

 for (b=0; b<32; b++)

{

 for(a=0; a<30000; a++); //延时一段时间

 P1 = design[b]; //读已定义的花样数据并写花样数据到
P1口

 }
}while(1);
}

程序中的花样数据可以自以去定义
,因这里我们的
LED要
AT89C51的
P1引脚为低电平才
会点亮,所以我们要向
P1口的各引脚写数据
O对应连接的
LED才会被点亮,
P1口的八个引
脚刚好对应
P1口特殊寄存器的八个二进位,如向
P1口定数据
0xFE,转成二进制就是
11111110,最低位
D0为
0这里
P1.0引脚输出低电平,
LED1被点亮。如此类推,大家不难算
出自己想要做的效果了。大家编译烧写看看,效果就出来,显示的速度您可以根据需要调整
延时
a的值,不要超过变量类型的值域就很行了。哦,您还没有实验板?那如何可以知道程
序运行的结果呢?呵,不用急,这就来说说用
KEIL uVision2的软件仿真来调试
IO口输出
输入程序。



5-1 八路跑马灯电路

- 18 -


51单片机
C语言入门教程

 

编译运行上面的程序,然后按外部设备菜单
Peripherals-I/O Ports-Port1就打开
Port1的调试窗口了,如图
5-3中的
2。这时程序运行了,但我们并不能在
Port1调试窗口
上看到有会什么效果,这时我们可以用鼠标左击图
5-3中
1旁边绿色的方条,点一下就有
一个小红方格在点一下又没有了,哪一句语句前有小方格程序运行到那一句时就停止了,就
是设置调试断点,同样图
5-2中的
1也是同样功能,分别是增加
/移除断点、移除所有断点、
允许/禁止断点、禁止所有断点,菜单也有一样的功能,另外菜单中还有
Breakpoints可打
开断点设置窗口它的功能更强大,不过我们这里先不用它。我们在“
P1 = design[b];”这
一句设置一个断点这时程序运行到这里就停住了,再留意一下
Port1调试窗口,再按图
5-2
中的
2的运行键,程序又运行到设置断点的地方停住了,这时
Port1调试窗口的状态又不同
了。也就是说
Port1调试窗口模拟了
P1口的电平状态,打勾为高电平,不打勾则为低电平,
窗口中
P1为
P1寄存器的状态,
Pins为引脚的状态,注意的是如果是读引脚值必须把引脚
对应的寄存器置
1才能正确读取。图
5-2中
2旁边的{}样的按钮分别为单步入,步越,
步出和执行到当前行。图中
3为显示下一句将要执行的语句。图
5-3中的
3是
Watches窗
口可查看各变量的当前值,数组和字串是显示其头一个地址,如本例中的
design数组是保
存在
code存储区的首地址为
D:0x08,可以在图中
4 Memory存储器查看窗口中的
Address地
址中打入
D:0x08就可以查看到
design各数据和存放地址了。如果你的
uVision2没有显示
这些窗口,可以在
View菜单中打开在图
5-2中
3后面一栏的查看窗口快捷栏中打开。



5-2 调试用快捷菜单栏



5-3 各调试窗口

- 19 -


 

参与评论 您还未登录,请先 登录 后发表或查看评论
《新概念51单片机C语言教程:入门、提高、开发、拓展全攻略》从实际应用入手,以实验过程和实验现象为主导,循序渐进地讲述51单片机C语言编程方法以及51单片机硬件结构和功能应用。全书共分5篇,分别为入门篇、内外部资源操作篇、提高篇、实战篇和拓展篇。《新概念51单片机C语言教程:入门、提高、开发、拓展全攻略》内容丰富,实用性强,书中大部分内容均来自科研工作及教学实践,许多C语言代码可以直接应用到工程项目中。《新概念51单片机C语言教程:入门、提高、开发、拓展全攻略》可作为大学本、专科单片机课程教材,适合于51单片机初学者和使用51单片机从事项目开发技术人员,也可供从事自动控制、智能仪器仪表、电力电子、机电一体化等专业技术人员参考。 但是不完全满意!优点是理论联系实际结合实验板立即验证理论,实用;缺点是因为突出实用而被迫放弃了理论系统性。而且作者对汇编嗤之以鼻一点都不讲,对不了解单片机内部原理初学者是不妥当。其实就学习任何课程来说,总有很多知识点并不一定能在实践中立即用到,却是理解掌握那些所谓“最实用”知识基础,地基不牢何以应用 内容很丰富 不过要配合视频看才行 光书里面知识点有点简略 拓展方面很丰富,感觉是有别与其他教参,都是以亲身经历来写,所讲到得内容很实用。 第1篇 入门篇 1.1 单片机概述 1.1.1 什么是单片机 1.1.2 单片机标号信息及封装类型 1.1.3 单片机能做什么 1.1.4 如何开始学习单片机 1.2 51单片机外部引脚介绍 1.3 电平特性 1.4 二进制与十六进制 1.4.1 二进制 1.4.2 十六进制 1.5 二进制逻辑运算 1.5.1 与 1.5.2 或 1.5.3 非 1.5.4 同或 1.5.5 异或 1.6 单片机C51基础知识介绍 1.6.1 利用C语言开发单片机优点 1.6.2 C51中基本数据类型 1.6.3 C51数据类型扩充定义 1.6.4 C51中常用头文件 1.6.5 C51中运算符 1.6.6 C51中基础语句 1.6.7 学习单片机应该掌握主要内容 2.1 Keil工程建立及常用按钮介绍 2.1.1 Keil工程建立 2.1.2 常用按钮介绍 2.2 点亮第一个发光二极管 2.3 while语句 2.4 for语句及简单延时语句 2.5 Keil仿真及延时语句精确计算 2.6 不带参数函数写法及调用 2.7 带参数函数写法及调用 2.8 利用C51库函数实现流水灯 第2篇 内外部资源操作篇 3.1 数码管显示原理 3.2 数码管静态显示 3.3 数码管动态显示 3.4 中断概念 3.5 单片机定时器中断 4.1 独立键盘检测 4.2 矩阵键盘检测 5.1 模拟量与数字量概述 5.2 A/D转换原理及参数指标 5.3 ADC0804工作原理及其实现方法 5.4 D/A转换原理及其参数指标 5.5 DAC0832工作原理及实现方法 5.6 DAC0832输出电流转换成电压方法 第6章 串行口通信原理及操作流程 6.1 并行与串行基本通信方式 6.2 RS-232电平与TTL电平转换 6.3 波特率与定时器初值关系 6.4 51单片机串行口结构描述 6.5 串行口方式1编程与实现 6.6 串行口打印在调试程序中应用 第7章 通用型1602,12232,12864液晶操作方法 7.1 液晶概述 7.2 常用1602液晶操作实例 7.3 常用12232液晶操作实例 7.4 常用12864液晶操作实例 第8章 I2C总线AT24C02芯片应用 8.1 I2C总线概述 8.2 单片机模拟I2C总线通信 8.3 E2PROM AT24C02与单片机通信实例 第9章 基础运放电路专题 9.1 运放概述及参数介绍 9.2 反相放大器 9.3 同相放大器 9.4 电压跟随器 9.5 加法器 9.6 差分放大器 9.7 微分器 9.8 积分器 第3篇 提高篇 第10章 定时器/计数器应用提高 10.1 方式0应用 10.2 方式2应用 10.3 方式3 应用 10.4 52单片机定时器2介绍 10.5 计数器应用 第11章 串行口应用提高 11.1 方式0应用 11.2 方式2和方式3应用 11.3 单片机双机通信 11.4 单片机多机通信 第12章 指针 12.1 指针与指针变量 12.1.1 内存单元、地址和指针 12.1.2 指针变量定义、赋值与引用 12.2 指针变量运算 12.3 指针与数组 12.3.1 指针与一维数组 12.3.2 指针与多维数组 12.4 指针与函数 12.4.1 指针作为函数参数 12.4.2 指向函数指针 12.4.3 指针型函数 12.5 指针与字符串 12.5.1 字符串表达形式 12.5.2 字符指针作为函数参数 12.5.3 使用字符指针与字符数组区别 12.6 指针数组与命令行参数 12.6.1 指针数组定义和使用 12.6.2 指向指针指针 12.6.3 指针数组作为main()函数命令行参数 12.7 指针小结 12.7.1 指针概念综述 12.7.2 指针运算小结 12.7.3 等价表达式 12.8 C51中指针使用 12.8.1 指针变量定义 12.8.2 指针应用 第13章 STC系列51单片机功能介绍 13.1 单片机空闲与掉电模式应用 13.2 “看门狗”概念及其应用 13.3 用软件实现系统复位 13.4 内部扩展RAM应用 13.5 扩展P4口应用 13.6 内部E2PROM应用 13.7 STC89系列单片机内部A/D应用 13.8 STC12系列单片机内部A/D应用 13.9 STC12系列单片机PCA/PWM介绍 13.10 STC12系列单片机SPI接口介绍 13.11 STC12系列单片机“576MHz”超速运行 第4篇 实战篇 第14章 利用51单片机定时器设计一个时钟 14.1 如何从矩阵键盘中分解出独立按键 14.2 原理图分析 14.3 实例讲解 第15章 使用DS12C887时钟芯片设计高精度时钟 15.1 时钟芯片概述 15.2 DS12C887时钟芯片介绍 15.3 如何用TX-1C实验板扩展本实验 15.4 原理图分析 15.5 实例讲解 第16章 使用DS18B20温度传感器设计温控系统 16.1 温度传感器概述 16.2 DS18B20温度传感器介绍 16.3 实例讲解 第17章 太阳能充/放电控制器 17.1 控制器原理图分析 17.2 控制器板上元件介绍 17.3 实例讲解 第18章 VC、VB(MSCOMM控件)与单片机通信实现温度显示 18.1 VC MSCOMM控件与单片机通信实现温度显示 18.2 VB MSCOMM控件与单片机通信实现温度显示 第5篇 拓展篇 第19章 使用Protell 99绘制电路图全过程 19.1 绘制电路板概述 19.2 建立工程 19.3 制作元件库 19.4 添加封装及制作PCB封装库 19.5 错误检查及生成PCB 19.6 布线电气特性设置 19.7 自动布线和手动布线 第20章 ISD400x系列语音芯片应用 20.1 ISD400x系列语音芯片介绍 20.2 ISD400x系列语音芯片操作规则 20.3 ISD400x系列语音芯片应用实现 第21章 电机专题 21.1 直流电机原理及应用 21.2 步进电机原理及应用 21.3 舵机原理及其应用 第22章 常用元器件介绍 22.1 二极管 22.2 电容 22.3 场效应管 22.4 光耦 22.5 蜂鸣器 22.6 继电器 22.7 自恢复保险 22.8 瞬态电压抑制器 22.9 晶闸管(可控硅) 22.10 电荷泵 第23章 直流稳压电源专题 23.1 整流电路 23.2 滤波电路 23.3 稳压电路 23.4 集成稳压模块使用 23.5 串联开关型稳压电源 第24章 运放扩展专题 24.1 简单低通滤波器 24.2 “电流-电压”转换电路 24.3 光电放大器 24.4 精密电流源 24.5 可调参考电压源 24.6 复位稳定放大器 24.7 模拟乘法器 24.8 全波整流器和平均值滤波器 24.9 正弦波振荡器 24.10 三角波发生器 24.11 自动跟踪对称电源 24.12 可调实验电源 24.13 运放相关术语表 附录A 天祥电子开发实验板简介 A.1 TX-1C 51单片机开发板(配套详细视频教程) A.2 AVR单片机开发板(配套详细视频教程) A.3 PIC单片机开发板(配套详细视频教程) A.4 J-Link全功能ARM仿真器 A.5 三星S3C44B0 ARM7入门级开发板 A.6 三星S3C44B0 ARM7提高级开发板 A.7 TX-51STAR 51单片机开发板(配套详细视频教程)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

jakenh36

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值