单片机实验指导书自编.docx

上传人:b****6 文档编号:5621009 上传时间:2022-12-29 格式:DOCX 页数:93 大小:3.67MB
下载 相关 举报
单片机实验指导书自编.docx_第1页
第1页 / 共93页
单片机实验指导书自编.docx_第2页
第2页 / 共93页
单片机实验指导书自编.docx_第3页
第3页 / 共93页
单片机实验指导书自编.docx_第4页
第4页 / 共93页
单片机实验指导书自编.docx_第5页
第5页 / 共93页
点击查看更多>>
下载资源
资源描述

单片机实验指导书自编.docx

《单片机实验指导书自编.docx》由会员分享,可在线阅读,更多相关《单片机实验指导书自编.docx(93页珍藏版)》请在冰豆网上搜索。

单片机实验指导书自编.docx

单片机实验指导书自编

实验一:

单片机开发系统的使用

学时分配:

2课时

实验属性:

验证必开

一、教学目的和要求

1.让学生了解单片机开发系统的构成;

2.学会keil软件的使用;

3.掌握基本的源程序编辑,编译及下载调试的方法;

4.编程实现P1口闪灯。

二、教学过程

1.介绍单片机开发系统的构成。

Step1:

实验箱功能模块介绍。

Step2:

仿真器介绍。

0

Step3:

计算机在单片机开发系统中的作用介绍。

2.开发软件keil的使用和仿真器连接设置

Keil是一个应用很好的单片机应用系统开发软件,借助keil可以进行源程序的编辑、编译、下载、调试及仿真,也可以连接具体仿真器进行硬件仿真。

首先打开安装好的Keil软件,然后点击Project选择下拉菜单中的NewProject(新建项目),在弹出的窗口中选择新建项目的保存路径,任意输入一个文件名然后点击保存,然后在弹出的窗口选择Atmel(点击Atmel前面的小+即可),选择单片机型号为AT89S52(单击AT89S52即可),然后点击确定,在弹出的窗口点击否,然后单击左边窗口中Target1前面的小+号,再用鼠标右击SourceGroup1,在弹出的窗口中点击AddFilestoGroup“SourceGroup1”,在弹出的窗口中选择文件类型为Allfiles,再选择已经保存好的源程序文件(如没有源程序文件,可以点击新建按钮,编辑一个源程序文件,保存),然后单击需要添加的程序再点击Add程序就添加成功了,再点击Close关闭即可,再单击SourceGroup1前面的小+号,程序就在新建项目中了双击程序打开即可,然后点击Project选择下拉菜单中的OptionsforTarget“Target1”,在弹出的窗口中进行设置,Xtal(晶振)设置为24,在output选项卡选中生成hex文件选项,再点击Debug,再点击右边的Use前面的小圆圈,再点击Settings,在弹出的窗口中选择Port(通讯口)为COM3,Baudrate(波特率)为115200,再点击OK点击确定即设置完成,最后编译运行程序,如果没有出错提示,则生成相应hex文件,点击debugsession即可进行调试运行程序。

3.源程序编辑,编译及下载调试的过程

具体过程参考附录一

4.实验具体要求:

编程实现P1.5口闪灯

三、参考电路:

四、参考程序:

/********************************************************************

工程名称:

led_shan

功能描述:

使用单片机的P1.5口做输出口,使该位发光二极管闪烁。

硬件连接:

用8位排线将J8与J13连接

维护记录:

2011-8-22

***************************************************************************************************/

#include"reg51.h"//包含头文件

sbitled=P1^5;//表示用led等效于P1^5,P1^0就是指头文件里定义的P1寄存器的第5BIT

#defineucharunsignedchar

#defineuintunsignedint

//**************************************************************************************************

//延时函数

//**************************************************************************************************

delay(uinttime)//int型数据为16位,所以最大值为65535

{

uinti,j;//定义变量i,j,用于循环语句

for(i=0;i

for(j=0;j<50;j++);//for循环,循环50次

}

//**************************************************************************************************

//主函数

//**************************************************************************************************

voidmain()//主函数

{

while

(1)//进入while死循环

{

led=~led;//led电平取反来控制LED亮灭

delay(5000);//延时,修改延时即可修改闪烁频率

}

}

五、思考?

1.P1.5输出为方波,如果改变延迟时间,接P1.5到蜂鸣器或者继电器,有何现象?

2.结合以上代码,写出能输出不同频率方波的函数。

参考代码如下:

/*************延时x毫秒*****************/

voiddelay(unsignedcharx)//设晶体振荡器的频率11.0592MHz

{unsignedchark;

while(x--)//延时大约x毫秒

for(k=0;k<125;k++){}

}

voidspeaker(unsignedchark,unsignedcharm)

{

unsignedcharcnt;

for(cnt=0;cnt<=k;cnt++)//k控制时间

{

led=~led;//产生方波

delay(m);//改变m延时值可产生不同频率的声音

}

}

voidspeaker1(void)

{

unsignedcharcnt;

for(cnt=0;cnt<=150;cnt++)

{

led=~led;//产生方波

delay(4);//改变延时值可产生不同频率的声音

}

}

实验二查表、延时程序设计

学时分配:

2课时

实验属性:

验证必开

一、教学目的和要求

1.进一步学习keil的使用;

2.了解模块化程序设计思想学会keil软件的使用,掌握函数的定义和调用方法;

3.学习用keilc进行查表的方法;

4.通过查表实现花样流水灯。

二、教学过程

1.模块化程序设计设计介绍,函数的调用和定义。

上一实验的例子中有用到函数,其实一直出现在例子中的main()也算是一个函数,只不过它比较特殊,编译时以它做为程序的开始段。

有了函数C语言就有了模块化的优点,一般功能较多的程序,会在编写程序时把每项单独的功能分成数个子程序模块,每个子程序就能用函数来实现。

函数还能被反复的调用,因此一些常用的函数能做成函数库以供在编写程序时直接调用,从而更好的实现模块化的设计,大大提高编程工作的效率。

函数定义:

通常C语言的编译器会自带标准的函数库,这些都是一些常用的函数,Keiluv中也不例外。

标准函数已由编译器软件商编写定义,使用者直接调用就能了,而无需定义。

但是标准的函数不足以满足使用者的特殊要求,因此C语言允许使用者根据需要编写特定功能的函数,要调用它必须要先对其进行定义。

定义的模式如下:

函数类型函数名称(形式参数表)

函数体

函数类型是说明所定义函数返回值的类型。

返回值其实就是一个变量,只要按变量类型来定义函数类型就行了。

如函数不需要返回值函数类型能写作“void”表示该函数没有返回值。

注意的是函数体返回值的类型一定要和函数类型一致,不然会造成错误。

函数名称的定义在遵循C语言变量命名规则的同时,不能在同一程序中定义同名的函数这将会造成编译错误(同一程序中是允许有同名变量的,因为变量有全局和局部变量之分)。

形式参数是指调用函数时要传入到函数体内参与运算的变量,它能有一个、几个或没有,当不需要形式参数也就是无参函数,括号内能为空或写入“void”表示,但括号不能少。

函数体中能包含有局部变量的定义和程序语句,如函数要返回运算值则要使用return语句进行返回。

在函数的{}号中也能什么也不写,这就成了空函数,在一个程序项目中能写一些空函数,在以后的修改和升级中能方便的在这些空函数中进行功能扩充。

函数的调用:

函数定义好以后,要被其它函数调用了才能被执行。

C语言的函数是能相互调用的,但在调用函数前,必须对函数的类型进行说明,就算是标准库函数也不例外。

标准库函数的说明会被按功能分别写在不一样的头文件中,使用时只要在文件最前面用#include预处理语句引入相应的头文件。

如前面一直有使用的printf函数说明就是放在文件名为stdio.h的头文件中。

调用就是指一个函数体中引用另一个已定义的函数来实现所需要的功能,这个时候函数体称为主调用函数,函数体中所引用的函数称为被调用函数。

一个函数体中能调用数个其它的函数,这些被调用的函数同样也能调用其它函数,也能嵌套调用。

笔者本人认为主函数只是相对于被调用函数而言。

在c51语言中有一个函数是不能被其它函数所调用的,它就是main主函数。

调用函数的一般形式如下:

函数名(实际参数表)“函数名”就是指被调用的函数。

实际参数表能为零或多个参数,多个参数时要用逗

号隔开,每个参数的类型、位置应与函数定义时所的形式参数一一对应,它的作用就是把参数传到被调用函数中的形式参数,如果类型不对应就会产生一些错误。

调用的函数是无参函数时不写参数,但不能省后面的括号。

在以前的一些例子我们也能看不一样的调用方式:

1.函数语句

如printf("HelloWorld!

\n");这是在我们的第一个程序中出现的,它以"Hello

World!

\n"为参数调用printf这个库函数。

在这里函数调用被看作了一条语句。

2.函数参数“函数参数”这种方式是指被调用函数的返回值当作另一个被调用函数的实际参

数,如temp=StrToInt(CharB(16));CharB的返回值作为StrToInt函数的实际参数传递。

3.函数表达式

而在上一篇的例子中有temp=Count();这样一句,这个时候函数的调用作为一个运算对象出现在表达式中,能称为函数表达式。

例子中Count()返回一个int类型的返回值直接赋值给temp。

注意的是这种调用方式要求被调用的函数能返回一个同类型的值,不然会出现不可预料的错误。

前面说到调用函数前要对被调用的函数进行说明。

标准库函数只要用#include引入已写好说明的头文件,在程序就能直接调用函数了。

如调用的是自定义的函数则要用如下形式编写函数类型说明

类型标识符函数的名称(形式参数表);这样的说明方式是用在被调函数定义和主调函数是在同一文件中。

你也能把这些写到

文件名.h的文件中用#include"文件名.h"引入。

如果被调函数的定义和主调函数不是在同一文件中的,则要用如下的方式进行说明,说明被调函数的定义在同一项目的不一样文件之上,其实库函数的头文件也是如此说明库函数的,如果说明的函数也能称为外部函数。

extern类型标识符函数的名称(形式参数表);函数的定义和说明是完全不一样的,在编译的角度上看函数的定义是把函数编译存放在ROM的某一段地址上,而函数说明是告诉编译器要在程序中使用那些函数并确定函数的地址。

如果在同一文件中被调函数的定义在主调函数之前,这个时候能不用说明函数类型。

也就是说在main函数之前定义的函数,在程序中就能不用写函数类型说明了。

能在一个函数体调用另一个函数(嵌套调用),但不允许在一个函数定义中定义另一个函数。

还要注意的是函数定义和说明中的“类型、形参表、名称”等都要相一致。

 

2.表的概念以及表中数据的存取

在汇编语言中我们往往把连续存放在存储器中的一段同类型的数据称为表,在c51中我们则称之为数组。

数组不过就是同一类型变量的有序集合。

形象的能这样去理解,就像一个学校在操场上排队,每一个级代表一个数据类型,每一个班级为一个数组,每一个学生就是数组中的一个数据。

数据中的每个数据都能用唯一的下标来确定其位置,下标能是一维或多维的。

就如在学校的方队中要找一个学生,这个学生在I年级H班X组Y号的,那么能把这个学生看做在I类型的H数组中(X,Y)下标位置中。

数组和普通变量一样,要

求先定义了才能使用,下面是定义一维或多维数组的方式:

数据类型

数组名

[常量表达式];

数据类型

数组名

[常量表达式1]......[常量表达式N];

“数据类型”是指数组中的各数据单元的类型,每个数组中的数据单元只能是同一数据

类型。

“数组名”是整个数组的标识,命名方法和变量命名方法是一样的。

在编译时系统会根据数组大小和类型为变量分配空间,数组名能说就是所分配空间的首地址的标识。

“常量表达式”是表示数组的长度和维数,它必须用“[]”括起,括号里的数不能是变量只能是常量。

unsignedintxcount[10];//定义无符号整形数组,有10个数据单元

charinputstring[5];//定义字符形数组,有5个数据单元

floatoutnum[10],[10];//定义浮点型数组,有100个数据单元

在C语言中数组的下标是从0开始的而不是从1开始,如一个具有10个数据单元的数

组count,它的下标就是从count[0]到count[9],引用单个元素就是数组名加下标,如count[1]就是引用count数组中的第2个元素,如果错用了count[10]就会有错误出现了。

还有一点要注意的就是在程序中只能逐个引用数组中的元素,不能一次引用整个数组,但是字符型的数组就能一次引用整个数组。

数组也是能赋初值的。

在上面介绍的定义方式只适用于定义在内存DATA存储器使用的内存,有的时候我们需要把一些数据表存放在数组中,通常这些数据是不用在程序中改变数值的,这个时候就要把这些数据在程序编写时就赋给数组变量。

因为51芯片的片内RAM很有限,通常会把RAM分给参与运算的变量或数组,而那些程序中不变数据则应存放在片内的CODE存储区,以节省宝贵的RAM。

赋初值的方式如下:

数据类型[存储器类型]数组名[常量表达式]={常量表达式};

数据类型[存储器类型]数组名[常量表达式1]......[常量表达式N]={{常量表达式}...{常量表达式N}};

在定义并为数组赋初值时,开始学习的朋友一般会搞错初值个数和数组长度的关系,而致使编译出错。

初值个数必须小于或等于数组长度,不指定数组长度则会在编译时由实际的初值个数自动设置。

unsignedcharLEDNUM[2]={12,35};//一维数组赋初值

intKey[2][3]={{1,2,4},{2,2,1}};//二维数组赋初值

unsignedcharIOStr[]={3,5,2,5,3};//没有指定数组长度,编译器自动设置

unsignedcharcodeskydata[]={0x02,0x34,0x22,0x32,0x21,0x12};//数据保存在code区

数组同样能作为函数的参数进行传递。

数组做参数时是用数组名进行传递的,一个数组的数组名表示该数组的首地址,在用数组名作为函数的调用参数时,它的传递方式是采用了地址传递,就是将实际参数数组的首地址传递给函数中的形式参数数组,这个时候实际参数数组和形式参数数组实际上是使用了同一段内存单元,当形式参数数组在函数体中改变了元素的值,同时也会影响到实际参数数组,因为它们是存放在同一个地址的。

上面的例子同时还使用到字符数组。

字符数组中每一个数据都是一个字符,这样一个一维的字符数组就组成了一个字符串,在C语言中字符串是以字符数组来表达处理的。

为了能测定字符串的长度,C语言中规定以‘\o’来做为字符串的结束标识,编译时会自动在字符串的最后加入一个‘\o’,那么要注意的是如果用一个数组要保存一个长度为10字节的字符串则要求这个数组至少能保存11个元素。

‘\o’是转义字符,它的含义是空字符,它的ASCII码为00H,也就是说当每一个字符串都是以数据00H结束的,在程序中操作字符数据组时要注意这一点。

字符数组除了能对数组中单个元素进行访问,还能访问整个数组,其实整个访问字符数组就是把数组名传到函数中,数组名是一个指向数据存放空间的地址指针,函数根据这个指针和‘/o’就能完整的操作这个字符数组。

符数组元素来进行运算,但不能用整个数组来做运算,因为数组名是指针而不是数据。

3.延时程序设计

就是通过各种循环,实现延时。

可以带参数控制延时时间,也可以无参。

三、实验电路

四、实验程序

通过查表方式实现P1口各种闪灯效果,同时蜂鸣器相应发出声音。

P1接L0-L7,P3.0接蜂鸣器in。

#include

voiddelay(unsignedchar);

voidspeaker(unsignedcharm);

sbitspk=P3^0;

unsignedchartab[]={0x18,0x24,0x42,0x81};

unsignedchartab1[]={2,3,4,5};

voidmain(void)

{

while

(1)

{unsignedchari;

for(i=0;i<4;i++)

P1=tab[i];

speaker(tab1[i]);

}

}

/*************延时x毫秒*****************/

voiddelay(unsignedcharx)//设晶体振荡器的频率11.0592MHz

{unsignedchark;

while(x--)//延时大约x毫秒

for(k=0;k<50;k++){}

}

voidspeaker(unsignedcharm)

{

unsignedcharcnt;

for(cnt=0;cnt<=100;cnt++)

{

spk=~spk;//产生方波

delay(m);//改变延时值可产生不同频率的声音

}

}

 

实验三多分支程序设计(电子琴)

学时分配:

2课时

实验属性:

验证必开

一、教学目的和要求

1.掌握多分支程序设计的方法;

2.蜂鸣器发生的原理及发生控制;

3.按键查询的程序设计方法以及消抖方法。

二、教学过程

1.多分支程序的设计方法

在c51中可以通过if语句,switch语句实现程序的多分支。

2.蜂鸣器的发生原理及控制

通过给蜂鸣器送入不同频率的脉冲信号,可以使得蜂鸣器发出不同频率的声音。

通过改变延迟时间和所送脉冲的个数就达到控制声音时长和频率的目的。

3.按键查询程序设计及消抖

不管是矩阵键盘还是独立按键,对单片机而已都要通过扫描的方法来获得响应的键号,具体扫描方式见教材。

若要消除抖动,可以采用延时法进行软件消抖。

三、实验电路

四、参考程序

Key0-key7接P1口,P3.0接蜂鸣器IN输入。

#include

sbitspk=P3^0;

sbitkey0=P1^0;

sbitkey1=P1^1;

sbitkey2=P1^2;

sbitkey3=P1^3;

sbitkey4=P1^4;

sbitkey5=P1^5;

sbitkey6=P1^6;

sbitkey7=P1^7;

voiddelay(unsignedchar);

voidspeaker(unsignedcharm);

voidmain(void)

{

while

(1)

{

if(key0==0)speaker(8);

if(key1==0)speaker(7);

if(key2==0)speaker(6);

if(key3==0)speaker(5);

if(key4==0)speaker(4);

if(key5==0)speaker(3);

if(key6==0)speaker

(2);

if(key7==0)speaker

(1);

}

}

/*************延时x毫秒*****************/

voiddelay(unsignedcharx)//设晶体振荡器的频率11.0592MHz

{unsignedchark;

while(x--)//延时大约x毫秒

for(k=0;k<55;k++){}

}

voidspeaker(unsignedcharm)

{

unsignedcharcnt;

while(P1!

=0xff)

{

spk=~spk;//产生方波

delay(m);//改变延时值可产生不同频率的声音

}

}

实验四中断实验

学时分配:

2课时

实验属性:

验证必开

一、教学目的和要求

1.了解中断系统的构成及相关中断控制寄存器;

2.掌握中断服务程序的编写;

3.利用外部中断和定时中断led闪灯。

二、教学过程

1.简要介绍中断系统构成和相关中断控制寄存器。

 

2.介绍中断服务程序的编写方法。

中断服务函数是编写单片机应用程序不可缺少的。

中断服务函数只有在中断源请求响应中断时才会被执行,这在处理突发事件和实时控制是十分有效的。

例如:

电路中一个按钮,要求按钮后LED点亮,这个按钮何时会被按下是不可预知的,为了要捕获这个按钮的事件,通常会有三种方法,一是用循环语句不断的对按钮进行查询,二是用定时中断在间隔时间内扫描按钮,三是用外部中断服务函数对按钮进行捕获。

在这个应用中只有单一的按钮功能,那么第一种方式就能胜任了,程序也很简单,但是它会不停的在对按钮进行查询浪费了CPU的时间。

实际应用中一般都会还有其它的功能要求同时实现,这个时候能根据需要选用第二或第三种方式,第三种方式占用的CPU时间最少,只有在有按钮事件发生时,中断服务函数才会被执行,其余的时间则是执行其它的任务。

如果你学习过汇编语言的话,刚开始写汇编的中断应用程序时,你一定会为出入堆栈的问题而困扰过。

单片机c语言语言扩展了函数的定义使它能直接编写中断服务函数,你能不必考虑出入堆栈的问题,从而提高了工作的效率。

扩展的关键字是interrupt,它是函数定义时的一个选项,只要在一个函数定义后面加上这个选项,那么这个函数就变成了中断服务函数。

在后面还能加上一个选项using,这个选项是指定选用51芯片内部4组工作寄存器中的那个组。

开始学习者能不必去做工作寄存器设定,而由编译器自动选择,避免产生不必要的错误。

定义中断服务函数时能用如下的形式。

函数类型函数名(形式参数)interruptn[usingn]

in

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 工学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1