1、武汉理工大学单片机实训报告 第一章 绪论 2 1.1概述 2 1.2课程设计任务 2 第二章硬件系统设计 3 2.1单片机最小系统 3 2.1.1 STC89C52的介绍 3 2.1.2 stc89c52系列单片机最小系统的介绍 4 2.2矩阵键盘模块 5 2.3数码管显示单元 5 2.4 LCD1602液晶显示电路 6 2.5蜂鸣器单元 8 第三章 软件设计 9 3.1数码管实验 9 3.1.1循环数码管显示0—F程序设计结构图: 9 3.1.2 59秒倒计数流程图 10 3.2 矩阵键盘流程图 11 3.3 LCD1602滚动显示年月日时分秒 12 3
2、4 AD转换, 13 3.5家电遥控器 14 第四章调试结果分析 15 4.1数码管调试及分析 15 4.1.1循环数码管显示0—F 15 4.1.2数码管59秒倒计数 15 4.2矩阵键盘 16 4.3 LCD1602滚动显示年月日时分秒 17 4.4 AD转换 17 4.5家电遥控器 18 第五章小结 19 参考文献: 19 第一章 绪论 1.1概述 随着我国工业技术和电子技术的发展和进步,自动控制技术也已经得到了极大的普及和应用,而这些自动控制技术的核心技术就是单片微型计算机,简称单片机。它以其高可靠性、高性价比、低电压、低功耗等一系
3、列优点,被广泛应用于控制系统、数据采集等领域。而51单片机系列以其超高的性价比深受广大电子爱好者和开发者以及大学生群体的欢迎。故而本次课程设计采用STC89C52单片机。 1.2课程设计任务 必做项目(这是每个学生必做的任务): 1. 基本系统:在51单片机开发系统PCB电路板上完成电子元器件的焊接、调试、程序下载,并实现数码管显示、矩阵键盘扫描、中断程序、定时器程序、串口通讯等基本功能; 2. 显示功能:焊接电路并实现对1602液晶屏的显示功能,要求能滚动显示字符; 3. 输出控制:焊接电路并实现对继电器的控制功能; 4. 数据采集:焊接电路并实现对AD0832的数据采集功能;
4、 选做项目(以下任选一): 1. 家电遥控器:实现对红外接收管和发射管的控制功能,要求能够学习遥控器的红外码,并能发射相应的编码,实现红外遥控器的功能。 2. 增强显示:实现光魔方的功能,要求搭建不少于8*8*4单元的光魔方,能够动态显示字符。 3. 空气质量监测:实现对室外空气PM2.5浓度测量,要求能够实时读取PM2.5模块数据计算浓度,并将结果显示在屏幕中,或者通过无线方式发送到PC机中显示,或者超过设定值启动电机模拟开关窗。 4. 入侵在线报警:要求通过采集远红外传感器数据,自动触发相机模块抓拍,照片发至PC或网络中。 5. 穿戴式设备控制:对陀螺仪传感器的数据采集和处理,要
5、求能根据采集到的数据计算出传感器加速度值,识别基本动作触发继电器开合,模拟启动外部设备。 6. 智能台灯:根据环境光强度自动调节LED亮度,通过光敏元器件采集环境亮度,通过PWM方式控制LED灯亮度。定时自动开灯,设定开灯时间,到时间由暗逐渐变亮。通过门控检测夜晚有人回家时自动开启LED灯等功能。 7. 火灾在线探测:采集烟感/异味传感器数据,并进行判断有无火情,继而控制继电器动作同时通过无线发送信息到PC或网络中。 8. 智能门磁:设计门磁开关,一端安装门上,另一端安装在门框。读取霍尔传感器输出,确定门开合状态,并在门状态变化时发送提示信息到PC或者网络中。 9. 智能窗帘:根据光强
6、变化、夜晚休息、人离开等多种条件自动开闭窗帘。可以设计导轨及电机控制机构。 10. 智能信息提示:每天早上自动搜集门户网站头条新闻、当天天气情况等,滚动显示在屏幕中。也可以将用户设定的提醒信息从PC机推送至单片机系统显示;也可以若置于门背,开门时显示重要提示信息。 上述无线方式包括WIFI,蓝牙,Zigbee,433M等多种 第二章硬件系统设计 2.1单片机最小系统 2.1.1 STC89C52的介绍 STC89C52是一种带8K字节闪烁可编程可擦除只读存储器的低电压,高性能COMOS8的微处理器,俗称单片机。该器件采用ATMEL高密度非易失存
7、储器制作技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。其引脚图如下图所示。 图2.1 STC89C52单片机 STC89C52RC引脚功能说明: VCC(40引脚):电源电压 VSS(20引脚):接地 P0端口(P0.0~P0.7,39~32引脚):P0口是一个漏极开路的8位双向I/O口。 P1端口(P1.0~P1.7,1~8引脚):P1口是一个带内部上拉电阻的8位双向I/O口。 P2端口(P2.0~P2.7,21~28引脚):P2口的基本功能和P1端口相同。 P3端口(P3.0~P3.7,10~17引脚):P3口的基本功能和P1端口相同。
8、ALE/(30引脚):地址锁存控制信号(ALE)是访问外部程序存储器时,锁存低8位地址的输出脉冲。 2.1.2 stc89c52系列单片机最小系统的介绍 单片机最小系统是单片机工作的最简单电路,它由单片机、电源、晶体振荡器、复位电路等构成。它是本系统的处理单元也是控制单元,负责处理信号、外设的接口与控制,同时它也是所有软件的载体。对52单片机来说,最小系统一般应该包括:单片机、时钟电路、复位电路、输入/ 输出设备等。52单片机最小系统见下图。 图2.1.2 STC89C52单片
9、机最小系统 (1)时钟电路: XTAL1(19 脚) :芯片内部振荡电路输入端。 XTAL2(18 脚) :芯片内部振荡电路输出端。 XTAL1 和XTAL2 是独立的输入和输出反相放大器,它们可以被配置为使用石英晶振的片内振荡器,或者是器件直接由外部时钟驱动。图2-2 中采用的是内时钟模式,即采用利用芯片内部的振荡电路,在XTAL1、XTAL2 的引脚上外接定时元件(一个石英晶体和两个电容),内部振荡器便能产生自激振荡。 (2) 复位电路: 在单片机系统中,复位电路是非常关键的,当程序跑飞(运行不正常)或死机(停止运行)时,就需要进行复位。 5l 系列单片机的
10、复位引脚RST( 第9 管脚) 出现2个机器周期以上的高电平时,单片机就执行复位操作。如果RST 持续为高电平,单片机就处于循环复位状态。 2.2矩阵键盘模块 矩阵键盘的工作原理是:从0行开始,顺序行扫描,即该行输出为0。每扫描一行,读入列线数据,从0开始,列检查,找该行输出为0的列,若无,则顺序扫描下一行,并检查其各列;若找到某列线为0,则该列与检查行交叉的按键为被按下的键。从0行0列开始,顺序将按键编号,就可以按扫描的值得到按键的值。此外还要消除按键在闭合或断开时的抖动。消除抖动的方法可采用消抖电路(RS触发器闩锁电路硬件消除抖动),也克采用延时方式软件消除抖动(延时后再重读
11、以跳过抖动期)。在矩阵键盘中,通常采用软件消除抖动。 本设计中主要使用了独立键盘,故电路图中简要的画出了4*4的矩阵键盘,其电路原理图如图2.2所示 图2.2矩阵键盘 2.3数码管显示单元 本次设计的显示单元是由4个共阴的7段LED数码管组成的显示电路。原理电路图见图2.3所示: 图2.3数码管显示单元 如上图所示,4个数码管的段选和位选分别由单片机的不同IO口控制,此图用了一个锁存器74HC573来实现数码管的段选,而其位选则由单片机的其他IO
12、口控制。 2.4 LCD1602液晶显示电路 本次课程设计采用的液晶显示屏是LCD1602,其具有体积小、功耗小、显示操作简单LCD1602主要技术参数: 显示容量:16×2个字符 芯片工作电压:4.5—5.5V 工作电流:2.0mA(5.0V) 模块最佳工作电压:5.0V 字符尺寸:2.95×4.35(W×H)mm LCD1602采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如表所示: 引脚功能说明: 第1脚:VSS为地电源。 第2脚:VDD接5V正电源。 第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度
13、最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。 第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。 第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。 第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。 第7~14脚:D0~D7为8位双向数据线。 第15脚:背光源正极。 第16脚:背光源负极。 其原理图如图2.4所示:
14、 图2.4LCD1602接口电路 2.5蜂鸣器单元 本次课程设计采用的蜂鸣器为电磁式蜂鸣,其采用直流供电,其可分为两种类型:有源式和无源式。本次课程设计采用的为无源蜂鸣。其原理图如图2.5所示: 图2.5蜂鸣器 第三章 软件设计 3.1数码管实验 3.1.1循环数码管显示0—F程序设计结构图: 实验要求:能循环数码管显示0—F
15、 图3.1.1循环数码管显示0—F 3.1.2 59秒倒计数流程图 实验要求:能用定时器循环显示59秒倒计时。 图3.1.2 数码管59秒倒计数 3.2 矩阵键盘流程图 实验要求:实现按键检测能用按键控制数码管加减,控制定时器的启动和停止
16、 图3.2矩阵键盘 3.3 LCD1602滚动显示年月日时分秒 实验要求:要求用1602滚动显示年月日时分秒,并可发送到上位机,上位机可修改1602上显示的时间 3.4 AD转换, 实验要求:实现AD采集电阻的电压,并把采集到的数据通过串口传送给上位机。
17、 3.5家电遥控器 实验要求:实现对红外接收管和发射管的控制功能,要求能够学习遥控器的红外码,并能发射相应的编码,实现红外遥控器的功能。 图3.5家电遥控器接收红外数据 27 第四章调试结果分析 4.1数码管调试及分析 4.1.1循环数码管显示0—F 数码管位选接单片机的P2口,段选接+5V电压。当用KEIL软件把程序编号以后点击编译按钮,程序便
18、编译好了,然后通过数据线把生成的HEX文下载进单片机,其实验现象如图4.1.1所示为数码管循环显示的部分图片。 图4.1.1数码管循环显示 由其现象可知其程序调试成功。 4.1.2数码管59秒倒计数 数码管的段选端接单片机的P2口,四个位选端接单片机P0端口,当编译好后,并把线路连接好后,数码管变开始从60开始每隔一秒倒计数,当记到0时,数码管的值便又变成60,如此开始循环。其部分实验现象图如图4.1.2所示: 图4.2.1数码管59秒倒计数 4.2矩阵键盘 矩
19、阵键盘的接口接单片机的P1口, 数码管的段选端接单片机的P2口,四个位选端接单片机P0端口。当开始运行程序时矩阵键盘从0行开始,顺序行扫描,即该行输出为0。每扫描一行,读入列线数据,从0开始,列检查,找该行输出为0的列,若无,则顺序扫描下一行,并检查其各列;若找到某列线为0,则该列与检查行交叉的按键为被按下的键。通过赋予相应按键++或——或停止数码管中断的功能并对相应按键进行编程即可实现数码管++、——、让定时器停止的功能。其实验现像如下: 图4.2矩阵键盘控制数码管加数字加减及定时器开启及停止 4.3 LCD1602滚动显示年月日时分秒 本次设计的程序的L
20、CD数据端接单片机的P0口,E,RW,RS分别接P3.7,P3.6,P3.5。矩阵键盘接单片机的P1口。当程序正确运行时应该可以在LCD1602上看到年月日,和时分秒的时间,且此时正在计时。其实验现象如下图所示: 图4.3LCD1602滚动显示年月日时分秒 由实验现象可知程序调试成功。 4.4 AD转换 本次实验采用的AD是ADC0832,它是一款8位AD。其各控制引脚接线如下Cs= P1^0; Clk= P1^1; Di=P1^7;Do= P1^7;其通道1接可调电阻,通道应为不用顾不接。当程序正确运行时可
21、以在LCD1602上看到通道1所测试的电压值。并可以通过串口调试助手看到单片机发送到串口调试助手的电压值。其实验现象如图4.4所示: 图4.4 AD转换 由以上实验现象可知和预测的功能相同顾本次实验调试成功。 4.5家电遥控器 本次遥控器实验采用的是NEC编码方式对遥控器的键值进行编码,以及对遥控器发送的红外线进行解码。其编码图如图4.5所示 图4.5 红外编码时序图 由次时序图可见,本次红外编码
22、成功。 第五章小结 经过这次为期一周的单片机实训,让我受益匪浅。通过这次实训,使我不仅对单片机的各个模块更加的了解了,而且加深了我对于单片机这门课程知识的理解。这次实训不仅提高了我的编程能力,同时也提高了我的动手能力。在刚开始拿到单片机最小系统板的硬件时,面对这那些细如针眼芯片引脚和及其微小的贴片电阻,我感到了十分的无助,然而通过学长的演示和询问其他同学焊接方法,渐渐的我逐渐掌握了方法。焊接贴片电阻和芯片的速度也逐渐变快,然而当焊完芯片和贴片电阻后却发现下载不来程序,经过我用万用表对每个部件的电位进行检查后发现,原来焊接的下载芯片的引脚有些
23、部位是虚焊,因而下不进程序,当我对虚焊部位重新焊了一遍后,单片机才可以下载程序。然而在后来的编程过程中我也遇到了许多小问题,让我调了很久的程序,比如把变量的的类型定义错误,该定义为全局变量的变量我定义成了局部变量等等,总之这一次实训让我受益匪浅,使我认识到了自身知识的匮乏,督促我去提升自己。 参考文献: [1] 李群芳,张士军等.《单片微型计算机与接口技术》(第三版).电子工业出版社.出版年份:2008年。 [2] 杨路明.《C语言程序设计教程》.北京邮电大学出版社.出版年份:2005年。 [4] 赵
24、亮,侯国锐.《单片机C语言编程与实例》.人民邮电出版社.出版年份:2007年 。 [5] 彭虎, 周佩玲, 傅忠谦.《单片机原理与接口技术》(第二版).电子工业出版社.出版年份:2008年。 [5] 郭天祥,《新概念51单片机C语言教程》,电子工业出版社,出版年份:2010年. 实验5家电遥控器程序: 红外编码程序: #include "reg52.h" #define uchar unsigned char #define uint unsigned int uchar key,key1,key2,key3,key4;
25、sbit IR_OUT=P1^0 ;
void delay_ms(uint ms)
{
uint i,j;
for(i=0;i<120;i++)
{
for(j=0;j 26、0592/38.0/12)/2+0.5; //(0.5为误差)
//特殊
TL1=256-(1000*11.0592/38.0/12)/2+0.5;
ET1=1; //开定时器中断1
EA=1;//开总中断
}
//发送引导码(9ms) 发送方:4.5ms高电平+4.5ms低电平.
void Send_Start_Bit(void) //TR1的值=发送的电平
{
//4.5ms 1
TH0=(65536-8295)/256;
TL0=(65536-8295)%256;
TR0=1; 27、// 启动定时器0;
TR1=1;
while(!TF0);
TR1=0;
TF0=0;//定时器0溢出标志位。
TR0=0; //关闭定时器0.
IR_OUT=0;
//4.5ms 0
TH0=(65536-4146)/256;
TL0=(65536-4146)%256;
TR0=1;
TR1=0;
while(!TF0);//等待定时器0产生中断。
TR1=0;
TF0=0;
TR0=0;
IR_OUT=0;
}
28、//发送二进制0(0.565us载波+0.565us空闲)
void Send_Bit_0(void)
{
//0.565us 1 载波
TH0=(65536-521)/256;
TL0=(65536-521)%256;
TR0=1;
TR1=1;
while(!TF0);
TR1=0;
TF0=0;
TR0=0;
IR_OUT=0;
//0.565us 0 空闲
TH0=(65536-521)/256;
TL0=(65536-521)%256;
TR0=1;
TR1=0;
while(!TF0) 29、
TR1=0;
TF0=0;
TR0=0;
IR_OUT=0;
}
//发送二进制 1 (0.565us载波+1.685ms空闲)
void Send_Bit_1(void)
{
//0.565us 1 载波
TH0=(65536-521)/256;
TL0=(65536-521)%256;
TR0=1;
TR1=1;
while(!TF0);
TR1=0;
TF0=0;
TR0=0;
IR_OUT=0;
//1.685ms 0 空闲
TH0=(65536-1563)/256;
30、 TL0=(65536-1563)%256;
TR0=1;
TR1=0;
while(!TF0);
TR1=0;
TF0=0;
TR0=0;
IR_OUT=0; /*****************************************/
}
void Send_over(void) //发送一个结束码,因为最后一个位只有遇到下降沿才能读取(发射端的上升沿)
{
//0.565us 1 //小于0.5us 接收端很难识别到
TH0=(65536-521)/256;
TL0=(65536-521)%256;
31、
TR0=1;
TR1=1;
while(!TF0);
TR1=0;
TF0=0;
TR0=0;
IR_OUT=0;
//0.565us 0
TH0=(65536-521)/256;
TL0=(65536-521)%256;
TR0=1;
TR1=0;
while(!TF0);
TR1=0;
TF0=0;
TR0=0;
IR_OUT=0;
}
//发送一字节 8位
void Send_Char()
{
unsigned char i,j1,j2,Key3,Key33,Key4, 32、Key44;
j1=0xBE;//用户码
j2=0x41;//用户反码
Key3=0xDE;//key1 键值码
Key33=0x20;//key1 键值反码
Key4=0x30;//key2 键值码
Key44=0xc0;//key2 键值反码
Send_Start_Bit();//发送引导码
Send_Bit_0();//
for(i=0;i<8;i++)
{
if(j1&0x80)
Send_Bit_0();
else
Send_Bit_1();
j1=j1<<1;
33、 //先发射低位
}
j2=0;
for(i=0;i<8;i++)
{
if(j2&0x80)
Send_Bit_0();
else
Send_Bit_1();
j2=j2<<1;
//先发射低位
}
for(i=0;i<8;i++)
{
if(key3&0x80)
Send_Bit_0();
else
Send_Bit_1();
key3=key3<<1;
}
for(i=0;i<8;i+ 34、)
{
if(Key33&0x80)
Send_Bit_0();
else
Send_Bit_1();
Key33=Key33<<1;
//先发射低位
}
//}
for(i=0;i<8;i++)
{
if(Key4&0x80)
Send_Bit_0();
else
Send_Bit_1();
Key4=Key4<<1;
}
for(i=0;i<8;i++)
{
35、 if(Key44&0x80)
Send_Bit_0();
else
Send_Bit_1();
Key44=Key44<<1;
//先发射低位
}
//}
Send_over();//结束符
}
void T1_ISR(void) interrupt 3
{
IR_OUT=!IR_OUT;
}
void main(void)
{
Init_Timer();
while(1)
{
Send_Char(); 36、//发送8位数据
delay_ms(1000);
}
}
红外解码程序:
#include"reg52.h"
#define LCD P0
#define uchar unsigned char
#define uint unsigned int
sbit IR_INPUT = P3^2;//红外接收引脚
sbit E=P2^7;
sbit RW=P2^5;
sbit RS=P2^6;
sbit int0=P3^2;
uchar code tab1[11]={"key value:"};
uchar code tab2[1 37、3]={" -H"};
uchar hongwaivalue[6];
uchar Time;
void IrInit();
void delay(uint x) //10us
{
unsigned char i;
while(x--)
{
for (i = 0; i<10; i++)
{}
}
}
void write_com(uchar cmd)//写指令函数
{
RS=0;
RW=0;
LCD=cmd;
delay(1);
E=1;
delay(5);
E=0;
}
v 38、oid write_data(uchar dat)//写数据
{
RS=1;
RW=0;
LCD=dat;
delay(1);
E=1;
delay(10);
E=0;
}
void lcd_init()
{
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
}
void hongwai_init()//7. /* 初始化红外接收功能 */
{
IT0=1;//下降沿触发
EX0 39、1;//打开中断0允许
EA=1; //打开总中
int0=1;//初始化端口
}
void lcd_display()
{
hongwaivalue[4]=hongwaivalue[2]>>4; //高位
hongwaivalue[5]=hongwaivalue[2]&0x0f; //低位
if(hongwaivalue[4]>9)
{
write_com(0xc0+0x09); //设置显示位置
write_data(0x37+hongwaivalue[4]); //将数值转换为该显示的ASCII码
}
40、 else
{
write_com(0xc0+0x09);
write_data(hongwaivalue[4]+0x30); //将数值转换为该显示的ASCII码
}
if(hongwaivalue[5]>9)
{
write_com(0xc0+0x0a);
write_data(hongwaivalue[5]+0x37); //将数值转换为该显示的ASCII码
}
else
{
write_com(0xc0+0x0a);
write_data(hongwaivalue[5]+0x30); //将 41、数值转换为该显示的ASCII码
}
}
void main()
{
uchar i;
hongwai_init();
lcd_init();
write_com(0x80);
for(i=0;i<10;i++)
{
write_data(tab1[i]);
}
write_com(0x80+0x40);
for(i=0;i<12;i++)
{
write_data(tab2[i]);
}
while(1)
{
lc 42、d_display();
}
}
void Read() interrupt 0
{
uchar j,k;
uint n;
Time=0;
delay(70);
if(int0==0) //确认是否真的接收到正确的信号
{
n=1000; //1000*10us=10ms,超过说明接收到错误的信号
//当两个条件都为真则循环,如果有一个条件为假的时候跳出循环,免得
//程序出错的时侯,程序死在这里
while((int0==0)&&(n>0)) //等待前面9ms的载波低电平过去 43、
{
delay(1);//10us
n--;
}
if(int0==1) //如果正确等到9ms低电平
{
n=500;
while((int0==1)&&(n>0))//等待4.5ms的空闲起始高电平过去
{
delay(1);//10us
n--;
}
for(k=0;k<4;k++) //共有4组数据(用户码、用户反码、键码、键码反码)
{
for(j=0;j<8;j++) //接收一组数据
{
n=60;
44、 while((int0==0)&&(n>0))//等待信号前面的560us低电平过去
{
delay(1);//10us
n--;
}
n=500;
while((int0==1)&&(n>0)) //计算高电平的时间长度。
{
delay(1);
Time++;
n--;
if(Time>30)
{
EX0=1;
return;
}
}
hongwaivalue[k]>>=1; //k表示第几组数据
if(Time>=8) //如果高电平出现大于565us,那么是1
{
hongwaivalue[k]|=0x80;
}
Time=0; //用完时间要重新赋值
}
}
}
if(hongwaivalue[2]!=~hongwaivalue[3])
{
return;
}
}
}
©2010-2025 宁波自信网络信息技术有限公司 版权所有
客服电话:4009-655-100 投诉/维权电话:18658249818