单片机实习报告
学 院:
专 业:
姓 名:
学 号:
起讫时间:
指导教师:
二〇##年九月九日
一、实习目的
1、熟悉单片机的原理、功能与应用
2、熟悉单片机开发的相关软硬件
3、培养单片机应用开发的兴趣
4、提高单片机应用系统的开发能力
二、实习要求
1、熟悉MCS-51单片机的原理;
2、熟悉单片机KEIL C51编程语言;
3、熟悉uVision2单片机C语言开发环境;
三、实习内容
1、熟悉单片机实习板的电路原理,焊接数字钟电路板,连接实习板上的电路,构成数字钟电路。
2、熟悉C51编程语言和开发环境,设计数字钟的软件程序,调试软硬件实习数字时钟功能。
数字钟的具体设计要求
一、设计要求
1、以MCS-51系列单片机为核心器件,组成一个电子时钟系统。
2、系统显示器由8位LED数码管组成,分别显示时间值的小时、分和秒,以24h(小时)计时方式。
3、 能够使用按键开关随时对当前时间进行调整。(推荐:键1为功能切换键,键2为移位键,键3为增加键,键4为减少键。也可自行定义。)
4、 有精力的学生可以实现秒表功能、闹钟定时功能、温度显示功能和通讯功能。
二、实习工具
计算机、万用表、稳压电源、编程器、电烙铁、单片机实习套件
三、方案论证
1、总体设计
为了实现LED显示器的数字显示,采用静态显示法和动态显示法。由于静态显示法需要数据锁存器等硬件,接口复杂一些。考虑时钟显示有8位,且系统没有其他复杂的处理任务,所以决定采用动态扫描法实现LED的显示。单片机采用Atmel的AT89S52芯片,这样单片机可具有足够的空余硬件资源实现其它的扩充功能。
2、系统硬件电路的设计
秒表/时钟计时器的硬件电路采用AT89S52单片机,最小化应用设计;采用共阴七段LED显示器,P0口输出段码数据,P2.0~P2.5口作列扫描输出,P1.0,P1.1,P1.2,p1.3口接四个按钮开关,用以调时功能设置。P3.2口接温度传感器,P3.3口接闹铃,P3.4口接闹铃旁的LED。采用12MHz晶振,有利于精确定时。
3、系统程序的设计
(1)程序实现功能说明
刚开始复位,数码管显示学号,随后从1秒开始计时。短按按键1,可以实现调时功能,长按1可实现闹钟设置功能,当可以设置闹钟时LED灯亮,当设置时间与计时时间吻合时,闹铃响1分钟。短按按键2,实现移位功能,长按按键2,实现确定锁定功能。按键3实现“+”功能,按键4实现“-”功能。18B20为温度传感器,所以数码管后两位可以实现温度显示功能。
(2)主程序
本设计中,计时采用定时器T0中断完成,其余状态循环调用显示子程序,当端口开关按下时,转入相应功能程序。
(3)LED显示子程序
数码管显示的数据存放在内存单元dis [0]-dis[5]中。其中dis[0]-dis[1]存放秒数据,dis[2]-dis[3]存放分数据,dis[4]-dis[5]存放时数据,每一地址单元内均为十进制BCD码。由于采用软件动态扫描实现数据显示功能,显示用十进制BCD码数据的对应码段存放在ROM表(LEDMAP[]中)。显示时,先取出dis[0]-dis[5]中的某一数据,然后查得对应的显示用码段,并从P0口输出,P2口将对应的数码管选中供电,就能显示该地址单元的数据值。
(4)定时器T0中断服务程序
定时器T0用于时间计时。中断进入后,时钟计时累计中断达1秒时,对秒计数单元进行加1操作。在计数单元中采用十进制BCD码计数,满60进位,T0中断服务程序执行流程见图2.4。
(5)具体程序如下
#include <reg52.h>
#include <math.h>
#define LEDLen 8
#define jump_ROM 0xcc
#define start 0x44
#define read_EEROM 0xbe
unsigned char k=0;
unsigned char status; //按键处理的状态
bit seconds_flag=0; //秒标志位,表明时间已到一秒
bit flag_key_delay; //键盘连续处理间隔时间周期信号
bit key_first=1; //第一次扫描到按键按下
#define KEY_PORT P1 //按键连接的端口
bit key_operated=1; //按键已处理过标记
unsigned char elaps; //按键长按的时间
unsigned char timer_s; //按键随时时间
unsigned char temperature; //温度显示
unsigned char hours, minutes, seconds; //时间显示的时、分、秒
unsigned char timer_hours,timer_minutes; //闹钟定时的小时、分钟
unsigned char hours_flag,minutes_flag,naozhong_flag;//小时,分钟,闹钟可设置标志位
sbit P10 = P1^0;
sbit P11 = P1^1;
sbit P12 = P1^2;
sbit P13 = P1^3;
sbit DQ = P3^2;
sbit P33 = P3^3;
sbit P34 = P3^4;
unsigned char dis[LEDLen]; //发光二极管位选数组
code unsigned char LEDMAP[] = { //发光二极管0~F的段码
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71
};
————————————————延时程序———————————————————
void delay_ms(unsigned char N) //N*100us 软件延时
{
unsigned char i,j;
i=N;
j=50;
do
{
do
{
}while(--j);
}while(--i);
}
————————————————-键盘相关程序————————————————
unsigned char scankey() //按键的监测
{
unsigned char temp1,temp2;
unsigned char start_time;
temp1=~KEY_PORT; //按键未按下为1,按下为0
temp1&=0x0f; //取低四位
if(temp1==0) //若没有键按下,temp1为0
{
key_first=1;
elaps=0;
}
else //否则有键按下
{
delay_ms(10); //延时去抖动,通过比较temp1 和
temp2=~KEY_PORT; temp2是否相等,确切判断是否有键
temp2&=0x0f; 按下
if(temp1==temp2)
{
if(key_first)
{
start_time=timer_s;
key_first=0;
key_operated=0;
}
elaps= (timer_s+60-start_time)%60; //计算按键时间长短
return temp1; //返回键值
}
}
return 0; //没键按下时返回0
}
void keydeal() //按键的处理
{
unsigned char keyval; //键值
keyval=scankey();
if(keyval==1) //长按及短按key1(调时、定时闹钟)
{
if(elaps<=6)
{
hours_flag=1; //小时标志位,等于1时表示可设置小时
}
if(elaps>6)
{
hours_flag=1;
naozhong_flag=1; //闹钟标志位,等于1时表示可以设置闹钟
P34=0; //可设置闹钟时间时LED灯亮
}
}
if(keyval==2) //短按及长按key2(移位、锁定)
{
if(elaps<=6) minutes_flag=1; //分钟标志位,等于1时表示可设置分
if(elaps>6) //长按为锁定功能
{
if((hours_flag==1)&&(minutes_flag==0)&&(naozhong_flag==0)) hours_flag=0;
if((hours_flag==1)&&(minutes_flag==1)&&(naozhong_flag==0))
{
hours_flag=0;
minutes_flag=0;
}
if((hours_flag==1)&&(minutes_flag==1)&&(naozhong_flag==1))
{
P34=1;
hours_flag=0;
minutes_flag=0;
naozhong_flag=0;
}
if((hours_flag==1)&&(minutes_flag==0)&&(naozhong_flag==1))
{
P34=1;
hours_flag=0;
minutes_flag=0;
naozhong_flag=0;
}
}
}
if((keyval==4)&&(!key_operated)) //短按key3(慢+)
{
key_operated=1;
if(hours_flag==1&&(minutes_flag==0)&&(naozhong_flag==0))
{
hours++;
hours=hours%24;
}
if((hours_flag==1)&&(minutes_flag==1)&&(naozhong_flag==0))
{
minutes++;
minutes=minutes%60;
}
if((hours_flag==1)&&(minutes_flag==0)&&(naozhong_flag==1))
{
timer_hours++;
timer_hours=timer_hours%24;
}
if((hours_flag==1)&&(minutes_flag==1)&&(naozhong_flag==1))
{
timer_minutes++;
timer_minutes=timer_minutes%60;
}
}
if((keyval==8)&&(!key_operated)) //短按key4键(慢-)
{
key_operated=1;
if(hours_flag==1&&(minutes_flag==0)&&(naozhong_flag==0))
{
hours+=24;
hours--;
hours=hours%24;
}
if((hours_flag==1)&&(minutes_flag==1)&&(naozhong_flag==0))
{
minutes+=60;
minutes--;
minutes=minutes%60;
}
if((hours_flag==1)&&(minutes_flag==0)&&(naozhong_flag==1))
{
timer_hours+=24;
timer_hours--;
timer_hours=timer_hours%24;
}
if((hours_flag==1)&&(minutes_flag==1)&&(naozhong_flag==1))
{
timer_minutes+=60;
timer_minutes--;
timer_minutes=timer_minutes%60;
}
}
}
————————————————温度相关函数—————————————————
void delay(unsigned char N) //N*4us 软件延时
{
unsigned char i;
i=N;
do
{
}while(--i);
}
unsigned char reset(void) //18B20复位
{
unsigned char ready;
DQ=1;
delay(1);
DQ=0;
delay(120); //>480us ,120
DQ=1;
delay(8); //大于60us小于75 ,注意值不能太大或太小(7)
ready=DQ;
delay(80); //响应周期>300us ,75,不能太小
return(ready);
}
void write_byte(unsigned char dat)//18B20写字节
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ=0;
DQ=dat&0x01; //至少隔1us再输出
delay(15); //数据至少保持60us ,注意值不能太大或太小(10)
DQ=1;
dat>>=1; //至少隔1us再输出下一位
}
}
unsigned char read_byte(void) //18B20读字节
{
unsigned char i=0;
unsigned char dat=0;
for(i=0;i<8;i++)
{
DQ=0;
dat>>=1; //1us
DQ=1;
if(DQ==1)
dat|=0x80;
delay(15); //大于60us ,15
}
return(dat);
}
void convert_temp(void)
{
while(reset());
write_byte(jump_ROM);
write_byte(start);
}
void read_temp(void) //温度测量子程序
{
unsigned char TMPH,TMPL,temp=0;
while(reset());
write_byte(jump_ROM);
write_byte(read_EEROM);
TMPL=read_byte();
TMPH=read_byte();
TMPH=TMPH<<4;
TMPL=TMPL>>4;
temp=(TMPH+TMPL);
if(temp<85)
{
dis [6]=LEDMAP[temp/10];
dis [7]=LEDMAP[temp%10];
temperature=temp;
}
else
{
temperature=256-temperature;
dis [6]=17;
dis [7]=temperature%10;
}
}
————————————————-定时中断——————————————————
#define Tick 500 // 500 x 2 ms = 1s
unsigned int C100us;
void T0Int() interrupt 1
{
static unsigned char Pos=0x01;
unsigned char LED;
TH0 = 0xfc;
TL0 = 0x18;
P2 = 0;
LED = dis[k];
k++;
if(k>7) k=0;
P0 = LED;
P2= Pos;
Pos <<= 1;
if(Pos==0x00) Pos=0x01;
C100us--;
if (C100us == 0) {
C100us = Tick;
seconds_flag=1; //秒标志位,表明时间已到一秒
seconds++;
timer_s=seconds;
if (seconds >= 60) {
seconds = 0;
minutes++;
if (minutes >= 60) {
minutes = 0;
hours++;
if (hours >= 24) hours = 0;
}
}
}
}
——————————————————主程序————————————————-
void main()
{
static bit wendu_flag=1;
unsigned int x=60000;
TMOD = 0x01; //定时工作方式,采用工作方式1
TH0 = 0xfc;
TL0 = 0x18;
IE = 0x82; // EA=1(中断总允许), ET0 = 1(允许定时器中断)
hours = 0;
minutes = 0;
timer_hours=0;
timer_minutes=0;
seconds = 0;
hours_flag = 0;
minutes_flag = 0;
naozhong_flag=0;
C100us = Tick;
TR0 = 1; //启动定时器
do{
disp_buf[0]=0x3F;
disp_buf[1]=0x07;
disp_buf[2]=0x3F;
disp_buf[3]=0x06;
disp_buf[4]=0x3F;
disp_buf[5]=0xCF;
if(seconds_flag)
{
seconds_flag=0;
if(wendu_flag)
{
read_temp();
wendu_flag=0;
}
else
{
convert_temp();
wendu_flag=1;
}
}
}while(x--);
while (1)
{
if(naozhong_flag==1)
{
dis[0]=LEDMAP[timer_hours/10];
dis[1]=LEDMAP[timer_hours%10]|0x80;
}
else
{
dis[0] = LEDMAP[hours/10];
dis[1] = LEDMAP[hours%10] | 0x80;
}
if(naozhong_flag==1)
{
dis[2]=LEDMAP[timer_minutes/10];
dis[3]=LEDMAP[timer_minutes%10]|0x80;
}
else
{
dis[2] = LEDMAP[minutes/10];
dis[3] = LEDMAP[minutes%10] | 0x80;
}
dis[4] = LEDMAP[seconds/10];
dis[5] = LEDMAP[seconds%10]| 0x80;
scankey();
keydeal();
if((timer_hours==hours)&&(timer_minutes==minutes)&&(timer_hours!=0)&&(timer_minutes!=0)&&(naozhong_flag==0)) P33=0; //定时时间到闹铃响
if((P33==0)&&(abs(timer_minutes-minutes)>=1)) P33=1;
if(seconds_flag)
{
seconds_flag=0;
if(wendu_flag)
{
read_temp();
wendu_flag=0;
}
else
{
convert_temp();
wendu_flag=1;
}
}
}
}
四、实习小结
这是我第一次用单片机做成功的小制作硬件。在制作过程中,我对52单片机的了解进一步的加深,对KEIL软件的使用更加灵活。程序是整个系统的核心,没有程序,硬件就无法运行,所以程序的编写就是我们学习的重点。学好了每一个软件的使用方法,自己就可以在软件里做自己想实现的工能。回顾起此次单片机实习,从理论到实践,在接近两个星期的日子里,可以说是苦多于甜,但是可以学到很多很多的的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,这毕竟第一次做的,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,比如说对单片机汇编语言掌握得不好……通过这次实习之后,我对单片机的了解更深了。总之这次单片机的实习让我把理论设计和工程实践相结合、巩固基础知识与培养创新意识相结合、个人作用和集体协作相结合等方面全面的培养学生的全面素质。这些在我今后的学习和工作当中都会有很大的帮助。