单片机实验报告史昊卿杨.docx
《单片机实验报告史昊卿杨.docx》由会员分享,可在线阅读,更多相关《单片机实验报告史昊卿杨.docx(35页珍藏版)》请在冰豆网上搜索。
单片机实验报告史昊卿杨
单片机实验报告
学院:
交通运输工程学院
班级:
交设1403
姓名:
史昊卿杨
学号:
1
指导老师:
傅勤毅
2017年5月20日
第一章单片机简介
单片机(Microcontrollers)是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。
从上世纪80年代,由当时的4位、8位单片机,发展到现在的300M的高速单片机。
单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。
相当于一个微型的计算机,和计算机相比,单片机只缺少了I/O设备。
概括的讲:
一块芯片就成了一台计算机。
它的体积小、质量轻、价格便宜、为学习、应用和开发提供了便利条件。
同时,学习使用单片机是了解计算机原理与结构的最佳选择。
单片机的使用领域已十分广泛,如智能仪表、实时工控、通讯设备、导航系统、家用电器等。
各种产品一旦用上了单片机,就能起到使产品升级换代的功效,常在产品名称前冠以形容词——“智能型”,如智能型洗衣机等。
单片机(Microcontrollers)诞生于1971年,经历了SCM、MCU、SoC三大阶段,早期的SCM单片机都是8位或4位的。
其中最成功的是INTEL的8051,此后在8051上发展出了MCS51系列MCU系统。
基于这一系统的单片机系统直到现在还在广泛使用。
随着工业控制领域要求的提高,开始出现了16位单片机,但因为性价比不理想并未得到很广泛的应用。
90年代后随着消费电子产品大发展,单片机技术得到了巨大提高。
随着INTELi960系列特别是后来的ARM系列的广泛应用,32位单片机迅速取代16位单片机的高端地位,并且进入主流市场。
而传统的8位单片机的性能也得到了飞速提高,处理能力比起80年代提高了数百倍。
高端的32位Soc单片机主频已经超过300MHz,性能直追90年代中期的专用处理器,而普通的型号出厂价格跌落至1美元,最高端的型号也只有10美元。
当代单片机系统已经不再只在裸机环境下开发和使用,大量专用的嵌入式操作系统被广泛应用在全系列的单片机上。
而在作为掌上电脑和手机核心处理的高端单片机甚至可以直接使用专用的Windows和Linux操作系统。
第二章 实验要求
1.学习Keil C51集成开发工具的操作及调试程序的方法,包括:
仿真调试与脱机运行间的切换方法
2.熟悉TD-51单片机系统板及实验系统的结构及使用
3.进行MCS51单片机指令系统软件编程设计与硬件接口功能设
4.学习并掌握Keil C51软件联机进行单片机接口电路的设计与编程调试
5.完成指定MCS51单片机综合设计题
第三章实验设备
1.HC600S-51单片机开发板
2.Keil C51
3.普中自动下载软件
第四章实验安排
1.LED灯实验
2.步进马达试验
3.独立按键控制LED实验
4.矩阵键盘实验
5.静态数码管实验
6.动态数码管实验
7.NE555脉冲发生器实验(定时/计数器)
8.RS232串口通信实验(接收与发送)
第五章实验内容
实验一:
LED流水灯实验
一、实验目的:
1.掌握Keil软件的使用方法。
2.掌握普中下载软件的使用方法。
3.加深理解单片机I/O引脚以及内存结构。
4.重新熟悉C语言编程法则。
二、实验要求
编写一段程序,使8个发光二极管D1、D2、D3、D4、D5、D6、D7、D8顺序(正序)点亮:
先点亮D1,再点亮D2、D3……D8、D1……,循环点亮。
每点亮一个LED,采用软件延时一段时间。
三、实验内容
1、实验程序设计
如图1-1为发光二极管的内部连接图,本次设计使用P1口进行连接。
发光二极管内部连接图
用KEIL软件设计程序如下:
#include
#include
#defineunitunsignedint
#defineucharunsignedchar
uchartemp;
sbitbeep=P2^3;//定义蜂鸣
voiddelay(unitz);//参数类型一定要写,参数名可以不写
voidmain()
{
beep=0;
temp=0xfe;
while
(1)//死循环
{
P1=temp;
temp=_crol_(temp,1);//循环左移一位
delay(200);
P1=temp;
}
}
voiddelay(unitz)
{
unitx,y;//局部变量
for(x=200;x>0;x--)
{
for(y=200;y>0;y--){};
};//延时程序
}
编译程序后生成.hex文件。
2、实验连线
如图,将P1口与锁存器74C53相连。
再利用普中科技软件将编译好.hex文件下载到单片机中。
可观察到流水灯连续闪烁的现象。
流水灯实验
实验二步进电机
一、实验目的
1.熟悉步进机的工作原理。
2.通过编写指令控制步进机工作,进一步熟悉单片机I/O引脚功能。
3.熟悉实验板及相关软件操作。
二、实验要求
P1口作为输出口控制步进电动机的四相绕组,编写程序,控制步进电动机每1s正向转动一步。
晶振频率12MHz。
解:
步距角:
θb=360/mZ(°)电机转速:
n=60f/mZ(r/min)
上式中:
f为脉冲频率,单位:
Hz或步/s。
m为拍数,本例中m=4。
Z为转子齿数,本例中Z=5。
则步距角θb=18°。
题目要求步进电动机每1s正向转动一步,即T=1s,
f=1Hz,电机转速n=3r/min。
三、实验内容
1、步进电机工作原理
步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件。
在非超载情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响,即给电机加一个脉冲信号,电机则转过一个步距角。
2、程序设计
根据步进电机的工作原理,设计步进电动机的控制状态与P1口的控制码的对应关系如下表2-1所示。
表2-1
控制状态
P1口
控制码
P1.7
P1.6
P1.5
P1.4
P1.3
P1.2
P1.1
P1.0
D相
C相
B相
A相
A相、B相绕组通电
03H
0
0
0
0
0
0
1
1
B相、C相绕组通电
06H
0
0
0
0
0
1
1
0
C相、D相绕组通电
0CH
0
0
0
0
1
1
0
0
D相、A相绕组通电
09H
0
0
0
0
1
0
0
1
3、程序:
#include
#defineuintunsignedint
voidDelayms(uintx);
main()
{
while
(1)//死循环
{P1=0x03;Delayms(1000);//A相、B相绕组通电
P1=0x06;Delayms(1000);//B相、C相绕组通电
P1=0x0c;Delayms(1000);//C相、D相绕组通电
P1=0x09;Delayms(1000);//D相、A相绕组通电
}
}
voidDelayms(uintx)//延时函数
{uintn;
for(;x>0;x--)
{for(n=0;n<123;n++)
{;}
}
}
4、实验连线
将程序下载到单片机中,可以看到步进电机转动。
实现现象如图2-1所示:
步进电机实验
实验三独立按键
一、实验目的
1.熟悉C51包含的头文件。
2.掌握独立按键的工作原理。
3.学习按键去抖动问题。
二、实验要求
通过开发板上的8个独立按键控制8个LED灯,实现按下按键对应的LED灯亮,其他灯灭的效果。
三、实验内容
3.1独立式按键问题
1、独立式按键:
其特点是每个按键单独占用一根I/O口线。
每个按键工作不会
影响其他I/O口线的状态,多用于所需按键不多的场合。
2、按键去抖问题:
按键的抖动时间约为5~10ms,抖动会引起CPU对一次键操作进行多次处理,从而错误的键响应。
软件去抖动:
检测到按键按下/释放后,延时10ms后再确认该键是否确实按下/释放,消除抖动影响。
3、实验程序设计
#include//此文件中定义了51的一些特殊功能寄存器
#include
//--定义要使用的IO口--//
#defineGPIO_KEYP1//独立键盘用P1口
#defineGPIO_LEDP0//led使用P0口
//--声明全局函数--//
voidDelay10ms(unsignedintc);//延时10ms
unsignedcharKey_Scan();
voidmain(void)
{
unsignedcharledValue,keyNum;
ledValue=0x01;
while
(1)
{
keyNum=Key_Scan();//扫描键盘
switch(keyNum)
{
case(0xFE):
//返回按键K1的数据
ledValue=0x01;
break;
case(0xFD):
//返回按键K2的数据
ledValue=0x02;
break;
case(0xFB):
//返回按键K3的数据
ledValue=0x04;
break;
case(0xF7):
//返回按键K4的数据
ledValue=0x08;
break;
case(0xEF):
//返回按键K5的数据
ledValue=0x10;
break;
case(0xDF):
//返回按键K6的数据
ledValue=0x20;
break;
case(0xBF):
//返回按键K7的数据
ledValue=0x40;
break;
case(0x7F):
//返回按键K8的数据
ledValue=0x80;
break;
default:
break;
}
GPIO_LED=ledValue;//点亮LED灯
}
}
unsignedcharKey_Scan()
{
unsignedcharkeyValue=0,i;//保存键值
//--检测按键1--//
if(GPIO_KEY!
=0xFF)//检测按键K1是否按下
{
Delay10ms
(1);//消除抖动
if(GPIO_KEY!
=0xFF)//再次检测按键是否按下
{
keyValue=GPIO_KEY;
i=0;
while((i<50)&&(GPIO_KEY!
=0xFF))//检测按键是否松开
{
Delay10ms
(1);
i++;
}
}
}
returnkeyValue;//将读取到键值的值返回
}
voidDelay10ms(unsignedintc)//误差0us
{
unsignedchara,b;
//--c已经在传递过来的时候已经赋值了,所以在for语句第一句就不用赋值了--//
for(;c>0;c--)
{
for(b=38;b>0;b--)
{
for(a=130;a>0;a--);
}
}
}
3.3实验现连线
将程序下载到单片机中,可以看到不同按键下相应的led灯点亮。
实现现象如图所示:
独立按键实验
实验四矩阵键盘
一、实验目的
1.充分理解4x4矩阵键盘内部接线图,并根据其结构进行程序设计。
2.试比较独立按键与矩阵键盘的区别。
3.进一步掌握单片机程序设计办法。
二、实验要求
按下矩阵键盘按键,1602显示其键值。
三、实验内容
1、矩阵键盘
矩阵键盘是进行逐行扫描的。
每一个按键的两端,都分别接在某一个列线和行线上,即:
“行线和列线是通过某个按键的按下和抬起实现联通和断开的”,和“导线两端上的信号是经过“与”的关系再体现到导线上的。
”
图4-1矩阵键盘
2、程序设计
根据表4-1K0~K15键码表以及独立按键的程序用KEIL软件设计如下程序:
表4-1K0~K15键码表
K0:
0xee11101110
K1:
0xde11011110
K2:
0xbe10111110
K3:
0x7e01111110
K4:
0xed11101101
K5:
0xdd11011101
K6:
0xbd10111101
K7:
0x7d01111101
K8:
0xeb11101011
K9:
0xdb11011011
K10:
0xbb10111011
K11:
0x7b01111011
K12:
0xe711100111
K13:
0xd711010111
K14:
0xb710110111
K15:
0x7701110111
#include
#include"lcd.h"
//--定义使用的IO口--//
#defineGPIO_KEYP1
//--定义全局变量--//
unsignedcharPuZh[17]="Thekeyvalueis:
";
unsignedcharKeyValue;
//用来存放读取到的键值
voidKeyScan(void);//--声明全局函数--//
voidDelay10ms(unsignedintc);//误差0us
voidmain(void)
{
unsignedchari;
LcdInit();
for(i=0;i<17;i++)
{
if(i==14)
{
LcdWriteCom(0x80+0x40);
}
LcdWriteData(PuZh[i]);
}
while
(1)
{
KeyScan();
LcdWriteCom(0x80+0x44);
if(KeyValue<10)
{
LcdWriteData('0'+KeyValue);
}
else
{
LcdWriteData('7'+KeyValue);//A的ASCII码的前10位是7,所以用7做基数
}
}
}
voidKeyScan(void)
{
chara=0;
GPIO_KEY=0x0f;
if(GPIO_KEY!
=0x0f)//读取按键是否按下
{
Delay10ms
(1);//延时10ms进行消抖
if(GPIO_KEY!
=0x0f)//再次检测键盘是否按下
{
//测试列
GPIO_KEY=0X0F;
switch(GPIO_KEY)
{
case(0X07):
KeyValue=0;break;
case(0X0b):
KeyValue=4;break;
case(0X0d):
KeyValue=8;break;
case(0X0e):
KeyValue=12;break;
}
//测试行
GPIO_KEY=0XF0;
switch(GPIO_KEY)
{
case(0X70):
KeyValue=KeyValue+3;break;
case(0Xb0):
KeyValue=KeyValue+2;break;
case(0Xd0):
KeyValue=KeyValue+1;break;
case(0Xe0):
KeyValue=KeyValue;break;
}
while((a<50)&&(GPIO_KEY!
=0xf0))//检测按键松手检测
{
Delay10ms
(1);
a++;
}
}
}
}
voidDelay10ms(unsignedintc)//误差0us
{
unsignedchara,b;
//--c已经在传递过来的时候已经赋值了,所以在for语句第一句就不用赋值了--//
for(;c>0;c--)
{
for(b=38;b>0;b--)
{
for(a=130;a>0;a--);
}
}
}
附1:
lcd.c(包含main函数中lcdinit函数)
#include"lcd.h"
voidLcd1602_Delay1ms(uintc)//误差0us
{
uchara,b;
for(;c>0;c--)
{
for(b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
#ifndefLCD1602_4PINS//当没有定义这个LCD1602_4PINS时
voidLcdWriteCom(ucharcom)//写入命令
{
LCD1602_E=0;//使能
LCD1602_RS=0;//选择发送命令
LCD1602_RW=0;//选择写入
LCD1602_DATAPINS=com;//放入命令
Lcd1602_Delay1ms
(1);//等待数据稳定
LCD1602_E=1;//写入时序
Lcd1602_Delay1ms(5);//保持时间
LCD1602_E=0;
}
#else
voidLcdWriteCom(ucharcom)//写入命令
{
LCD1602_E=0;//使能清零
LCD1602_RS=0;//选择写入命令
LCD1602_RW=0;//选择写入
LCD1602_DATAPINS=com;
//由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms
(1);
LCD1602_E=1;//写入时序
Lcd1602_Delay1ms(5);
LCD1602_E=0;
Lcd1602_Delay1ms
(1);
LCD1602_DATAPINS=com<<4;//发送低四位
Lcd1602_Delay1ms
(1);
LCD1602_E=1;//写入时序
Lcd1602_Delay1ms(5);
LCD1602_E=0;
}
#endif
#ifndefLCD1602_4PINS
voidLcdWriteData(uchardat)//写入数据
{
LCD1602_E=0;//使能清零
LCD1602_RS=1;//选择输入数据
LCD1602_RW=0;//选择写入
LCD1602_DATAPINS=dat;//写入数据
Lcd1602_Delay1ms
(1);
LCD1602_E=1;//写入时序
Lcd1602_Delay1ms(5);//保持时间
LCD1602_E=0;
}
#else
voidLcdWriteData(uchardat)//写入数据
{
LCD1602_E=0;//使能清零
LCD1602_RS=1;//选择写入数据
LCD1602_RW=0;//选择写入
LCD1602_DATAPINS=dat;//因4位的接线是接到P0口的高四位,传送高四位不用改
Lcd1602_Delay1ms
(1);
LCD1602_E=1;//写入时序
Lcd1602_Delay1ms(5);
LCD1602_E=0;
LCD1602_DATAPINS=dat<<4;//写入低四位
Lcd1602_Delay1ms
(1);
LCD1602_E=1;//写入时序
Lcd1602_Delay1ms(5);
LCD1602_E=0;
}
#endif
#ifndefLCD1602_4PINS
voidLcdInit()//LCD初始化子程序
{
LcdWriteCom(0x38);//开显示
LcdWriteCom(0x0c);//开显示不显示光标
LcdWriteCom(0x06);//写一个指针加1
LcdWriteCom(0x01);//清屏
LcdWriteCom(0x80);//设置数据指针起点
}
#else
voidLcdInit()//LCD初始化子程序
{
LcdWriteCom(0x32);//将8位总线转为4位总线
LcdWriteCom(0x28);//在四位线下的初始化
LcdWriteCom(0x0c);//开显示不显示光标
LcdWriteCom(0x06);//写一个指针加1
LcdWriteCom(0x01);//清屏
LcdWriteCom(0x80);//设置数据指针起点
}
#endif
附2:
lcd.h(上述两个程序引用的头文件)
#ifndef__LCD_H_
#define__LCD_H_
/**当使用的是4位数据传输的时候定义,使用8位取消这个定义**/
#defineLCD1602_4PINS
/**包含头文件**/
#include
//---重定义关键词---//
#ifndefuchar
#defineucharunsignedchar
#endif
#ifndefuint
#defineuintunsignedint
#endif
#defineLCD1602_DATAPINSP0
sbitLCD1602_E=P2^7;
sbitLCD1602_RW=P2^5;
sbitLCD1602_RS=P2^6;
voidLcd1602_Delay1ms(uintc);//误差0us
/*LCD1602写入8位命令子函数*/
voidLcdWriteCom(u