单片机专周实验
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
重庆科技学院
学生实习(实训)总结报告
院(系):_智能技术与工程学院_ 专业班级:___ __
学生姓名:_____ ________学号:___
实习(实训)地点:____I513__ _ ____________
报告题目:__ 单片机系统综合训练——可编程作息时间控制器设计报告日期: 2018 年 12 月 17 日
指导教师评语: _______________________________________ _________________________________________________________
成绩(五级记分制):______ _______
指导教师(签字):_____________________
目录
1.功能描述(课程设计内容及要求) (3)
2 方案设计 (3)
2.1 系统分析 (3)
2.2 器件选择 (4)
2.2.1 微处理器 (4)
2.2.2 显示器 (4)
2.2.3 按键 (4)
2.2.4 闹铃 (4)
3、硬件电路设计 (5)
3.1 最小系统设计 (5)
3.2 显示电路设计 (5)
3.3 按键电路设计 (6)
3.4 声音报警电路设计 (6)
3.5 电源电路设计 (7)
4、软件设计 (7)
4.1 操作功能设计 (7)
4.2程序编制思想 (8)
4.3 主程序 (8)
5 程序调试 (10)
6 技术小结 (10)
7多功能电脑时钟的使用说明 (11)
8心得体会 (11)
9参考文献(最近3年) (12)
附录1:电路原理图 (13)
附录2:程序参考清单 (14)
设计报告
1.功能描述
设计一个多功能数字电子钟设计
1)实时显示当前时间即北京时间(时、分)。
2)可修改北京时间(时、分)。
3)可设定闹铃时间(时、分)。
4)按设定闹铃时间定时报时,报时时长为1分钟。
5)具有秒表功能,能启动、暂停、停止秒表,启到后实时显示秒、百分秒。
按设定时间用蜂鸣器报时。
6)可设定初值的倒计时功能(扩展)
2 方案设计
2.1 系统分析
根据系统功能要求,可将系统组成结构分成四大部分:单片机控制中心、键盘接口、时钟显示和声音报时,如下图为系统的组成结构图。
其中,单片机控制中心是核心。
MCU 根据按键输入,可切换不同的显示模式或设置不同的参数。
时钟显示完成北京时间或秒表时钟的信息。
声音报时可完成闹铃的提示。
系统组成结构图
2.2 器件选择
2.2.1 微处理器
市场上微处理器种类很多。
这里,选取微处理器从多方面考:成本低、性能高、能够满足功能要求等等。
这里,选取STC89C51芯片。
因为其功能与普通51芯片相同,其价格非常低廉、程序空间大、资源较丰富、在线下载非常方便。
同时,使用该芯片,编程上亦可采用所熟悉的KEIL软件,使课程设计非常简单。
2.2.2 显示器
常见的显示器件LED数码管和LCD液晶器件。
LED数码管能够显示数字和部分字符,价格便宜,硬件电路、软件编程均非常简单,而且使用动态扫描技术可节省大量硬件成本。
LCD液晶显示器件,显示字迹清晰、能够显示数字、字符和汉字,但价格比LED非常高,编程复杂,软硬件调试都比较花时间。
系统显示主要还是数字,根据这两种显示器件的特性,选取LED数码管器件。
由于系统要求显示小时和分钟,采用四位数码管显示即可。
2.2.3 按键
按键是用来设置北京时间或闹钟时间或启动秒表等功能的。
这里采用普通按键即可,选用原则:以最少的按键,实现尽可能多的功能。
所以这里,设置三个按键:模式键、UP 键、DOWN键。
2.2.4 闹铃
选用最常见,亦最常用的声音提示方式——蜂鸣器。
3、硬件电路设计
3.1 最小系统设计
单片机功能系统图。
单片机最小系统由STC89C51单片机、复位电路、晶振电路组成。
如图3.1所示
图3.1
3.2 显示电路设计
常用的7段显示器的结构如图所示,阴极连在一起的成为共阴显示器。
1位显示器由8个发光二极管组成,其中7个发光二极管a~g控制7 个笔画的亮或暗,另一个控制一个小数点的亮和暗,这种笔画的七段显示器能显示的字符较少,字符的形状有些失真,但失控简单,使用方便。
图3.2
3.3 按键电路设计
如图3.2所示,时间设定模块设计的设计要点是按键的去抖动处理与“一键多态”的处理。
即只涉及两个键完成4位时间参数的设定。
软件法去抖动的实质是软件延时,即检测到某一键状态变化后延时一段时间,再检测该按键的状态是否保持着,如是则作为按键处理,否则,视为抖动,不予理睬。
3.4 声音报警电路设计
BEEP端无法直接驱动BUZZER,通过PNP放大电流来驱动蜂鸣器。
电路图如图3.4
3.5 电源电路设计
MCU工作电压为5V。
为了使用方便,用USB接口供电是最方便的,因此,系统采用USB接口供电的方式,直接从USB接口获取5V电源。
原理如下图。
4、软件设计
4.1 操作功能设计
根据系统功能描述,可以将功能大致分成三类:北京时间功能、闹铃功能、秒表功能。
系统设有四个数码管,三个按键。
采用菜单式人机对话,便于操作。
所以可分成多种菜单,功能键切换菜单,UP或DOWN键设置时间。
菜单设计如下:
默认:北京显示:显示格式为:小时.分钟(如:09.50,为9点50分)
菜单1:修改北京时间的小时:显示格式为:00.小时(如00.14,为北京时间的小时设为14点)
菜单2:修改北京时间的分钟:显示格式为:00.分钟(如00.34,为北京时间的分钟设为34分)
菜单3:修改闹铃时间的小时:显示格式为:00.小时(如00.14,为闹铃时间的小时设为14点)
菜单4:修改闹铃时间的分钟:显示格式为:00.分钟(如00.34,为闹铃时间分钟设为
34分)
菜单5:秒表功能:显示格式为:秒百分秒(如1290为当前秒表计时到12秒900毫秒),在此种菜单下,UP键设为用来启动/停止秒表、DOWN键设为用来暂停秒表。
4.2程序编制思想
数码管采用动态扫描原理。
所以系统需使用单片机定时器资源。
定时时间可设为5ms,即4位数码管,每5ms扫描一位数码管,20ms循环一次。
另一方面,按键接普通IO口,所以按键管理程序所涉及到的识键、译键均需采用软件扫描的方法。
这里选用定时扫描控制方式。
所以,程序编制思想为:使用定时器0(或1)完成数码管动态扫描,并对按键进行扫描。
扫描到相应的按键时,如功能键,则执行相应的操作,如,切换菜单。
切换菜单的方法,主要是通过程序定义一个变量,变量不同的值表示不同的菜单。
在进行切换菜单后,在按键处理子程序中,需对菜单变量重新赋值,并更新数码管显示内容。
另外,系统有北京时间和表秒功能,所以,可以利用该5ms的定时器,完成北京时间的计时任务。
秒表则采用另一个1ms的定时器,因为1ms刚好是秒表的最后一位,每当走过100次时,代表经过了1s。
每次当即将在等于100次的时候将其清为零,进行下一次计时。
来完成秒表的任务。
4.3 主程序
主程序
5 程序调试
数字闹钟是多功能的数字型,可以看当前时间。
数字闹钟功能很多,所以对于它的程序也较为复杂,所以在编写程序和调试时出现了相对较多的问题。
最后经过多次的模块子程序的修改,一步一步的完成,最终解决了软件。
在软件的调试过程中主要遇到的问题如下:1.下载程序后,LED数码管显示闪动,而且亮度不均匀。
解决:首先对调用的延时进行逐渐修改,可以解决显示闪动问题。
其次,由于本作品使作动态扫描方式显示的数字,动态扫描很快,人的肉眼是无法看出,但是调用的显示程序时,如果不在反回时屏蔽掉最后的附值,则会出现很亮的现象,所以在显示的后面加了屏蔽子令,最后解决了此问题。
2.按键难以控制按下的次数。
解决:第一步加上一条语句while(!key);在这起到是等待按键按开的作用,防止一直不按开按键判断错误。
第二步消抖,设置一个延时函数,检测在按键被按下的一段时间后,是不是还是被按下了,如果确实还是有按下,那么说明是真的按下了按键,所以要执行相应的操作。
也就是t_mode要加1
6 技术小结
(1).在测试中遇到发光二极管、LED数码管为不显示时,首先使用试测仪对电路进行测试,观察是否存在漏焊,虚焊,或者元件损坏.
(2).LED 数码管显示不正常,还有亮度不够,首先使用试测仪对电路进行测试,观察电路是否存在短路现象。
查看烧写的程序是否正确无误,对程序进行认真修改。
(3).DS1302 与微处理器进行数据交换时,首先由微处理器向电路发送命令字节,命令字节最高位MSB(D7)必须为逻辑1,如果D7=0,则禁止写DS1302,即写保护;D6=0,指定时钟数据,D6=1,指定RAM 数据;D5~D1 指定输入或输出的特定寄存器;最低位LSB(D0)为逻辑0,指定写操作(输入),D0=1,指定读操作(输出)。
在DS1302 的时钟日历或RAM 进行数据传送时,DS1302 必须首先发送命令字节。
若进行单字节传送,8 位命令字节传送结束之后,在下2 个SCLK 周期的上升沿输入数据字节,或在下8 个SCLK 周期的下降沿输出数据字节。
DS1302 与RAM 相关的寄存器分为两类:一类是单个RAM 单元,共31 个,每个单
元组态为一个8 位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;再一类为突发方式下的RAM 寄存器,在此方式下可一次性读、写所有的RAM 的31 个字节。
要特别说明的是备用电源B1,可以用电池或者超级电容器(0.1F 以上)。
虽然DS1302 在主电源掉电后的耗电很小,但是,如果要长时间保证时钟正常,最好选用小型充电电池。
可以用老式电脑主板上的3.6V 充电电池。
如果断电时间较短(几小时或几天)时,就可以用漏电较小的普通电解电容器代替。
100 μF 就可以保证1 小时的正常走时。
DS1302 在第一次加电后,必须进行初始化操作。
初始化后就可以按正常方法调整时间。
7多功能电脑时钟的使用说明
设置三个按键:模式键、UP键、DOWN键。
当没有按下Mode按键时,显示的是当前的时间,当第一次按下Mode键时,用户可以修改当前的时间的小时,当第二次按下Mode 键时,用户可以修改当前时间的分钟。
当第三次按下Mode键时,用户设置闹钟的时间的小时,当第四次按下Mode键时,用户设置闹钟的时间的分钟,当第五次按下Mode键时,用户开启了秒表功能,显示格式为:秒百分秒(如1290为当前秒表计时到12秒900毫秒),在此种菜单下,UP键设为用来启动/停止秒表、DOWN键设为用来暂停秒表。
当再次按下Mode键时,回到原来的样子,显示当前的时间。
而且用户不需要记住当前到底按了多少次,数码管下面的LED灯,会提示用户当前在第几的模式下。
LED灯一二进制的方式提示用户。
8心得体会
一周的单片机课程设计结束了,在这一周的时间里,我从最初的兴致勃勃,经历了写程序的艰苦奋战,也体验了调程序找不出为题所在时的苦恼,当然最终还是得到了成功时的喜悦。
从这学期开始接触单片机,简单运用单片机,我初步认识了单片机。
再经过这一周的单片机的专门学习,我对单片机有了进一步的学习和认识,加深了我对单片机理论知识的理解,提升了我个人理论结合实际的实践能力。
从简单的单片机设计开始,一步一步的增加难度。
刚开始设计时,老师给我们的任务很简单,可以轻松完成任务完成。
单片机可编程的作息时间设计,是在时钟的基础上慢慢的添加一个又一个的功能,然后一个一个的调试。
在调试的过程中我们遇到了很多的问题,不过我通过不断的学习,在网上查阅资料,都慢慢的将一个一个的问题解决了。
最后形成了一个完整的程序。
符合设计的要求。
通过本次单片机系统课程设计,我对单片机的基础知识及基本的应用技术有了深刻的了解,提升了个人理论到实践的运用能力。
或许对我以后从事单片机工作打下了坚实的基础。
9参考文献(最近3年)
[1]吴险峰. 51单片机项目教程(C语言版)[M]. 人民邮电出版社. 2016.
[2]郭天祥. 新概念51单片机C语言教程――入门、提高、开发、拓展全攻略(第2版)[M]. 电子工业出版社. 2018.
[3]林凌,李刚. 单片机与嵌入式系统600问[M]. 电子工业出版社. 2017.
[4]蔡杏山. 零基础学51单片机(C语言版)[M]. 人民邮电出版社. 2018.
单片机系统综合训练----设计报告附录1:电路原理图
13
附录2:程序参考清单
#define uchar unsigned char; //为了定义变量方便
#define uint unsigned int; //为了定义变量方便
//四盏灯
sbit P13 = P1^3;
sbit P35 = P3^5;
sbit P36 = P3^6;
sbit P37 = P3^7;
//蜂鸣器
sbit beep = P1^1;
uchar position;
uchar tt; //进入中断函数的次数,用于定时1S
static uchar second; //时钟的秒
static uchar minute; //时钟的分
static uchar hour; //时钟的小时
static uchar set_second; //设置闹钟的秒
static uchar set_minute; //设置闹钟的分
static uchar set_hour; //设置闹钟的小时
static uchar t_mode; //变量,用于记录按键的第几个模式
//------------------------------------------------------
void XS(int xs,int xm); //显示秒表的函数
void set_miaobiao(); //设置秒表的功能函数,暂停,复位,清零
int m=0,s=0; //记录秒表的1/100秒位的次数,记录秒表的1秒位的次数,是用来显示的作用。
static char d1,d2,d3,d4;
//-------------------------------------------------------
uchar code table[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //0--9
uchar beepTimes[23][2]=
{{6,50},{7,0},{7,25},{8,20},{8,30},{9,15},{9,25},{10,10},{10,30},{11,15},{11,25},{12,10},{13,20},{1 3,30},{14,15},{14,25},{15,10},{16,30},{17,0},{17,50},{18,0},{21,30},{23,0}};
//作息时间,可调
sbit smg_q = P2^4; //四个数码管
sbit smg_b = P2^5;
sbit smg_s = P2^6;
sbit smg_g = P2^7;
sbit mode=P2^0; //按键定义
sbit up=P2^1;
sbit down=P2^2;
sbit ent=P3^2;
void keyscan(); //检测按键是否按下
void setMinutes() ; //设置时钟的分钟
void setHours(); //设置时钟的小时
void display(unsigned char hour,unsigned char minute); //显示时钟
void delay(unsigned int timer); //延时函数
void init(); //初始化函数,初始化一些变量,如定时器,小时分钟等
void dongtaiTime();//控制时间变化的函数,当60秒过后,分钟要加1,当60分钟过后,小时要加1 void N_clock(); //设置作息时间的闹钟
void MyClock(); //控制时间变化的函数,当10个1/100秒过后,1/10秒上的位置要加1,当10个1/10秒过后,秒要加1
void set_clock_m();//设置闹钟的分钟
void set_clock_h();//设置闹钟的小时
void nao();//设置闹钟到点就响
void setClock();//设置闹钟
//主函数入口
void main()
{
init();
while(1)
{
dongtaiTime();
if(mode==0)
{
delay(1);
if(mode==0)
{
t_mode++;
while(!mode);
if(t_mode>5)
t_mode=0;
}
}
switch(t_mode)
{
case 0: TR1=0;TR0=1; dongtaiTime(); display(hour,minute); N_clock(); nao(); P3=0xff; P13=1; break;
case 1: TR1=0;TR0=1;display(hour,minute);setHours(); P13=0; beep=1; break; //set hours
case 2: TR1=0;TR0=1;display(hour,minute);setMinutes(); P13=1; P35=0; beep=1; break;
case 3: TR1=0;TR0=1;setClock(); P13=0; P35=0;beep=1; break;
case 4: TR1=0;TR0=1;set_clock_m(); display(set_hour,set_minute); P13=1; P35=1;P36=0; beep=1; break;
case 5: TR0=1; XS(m,s); set_miaobiao(); P13=0; P35=1; P36=0;beep=1; break;
}
delay(1);
}
}
void N_clock()
{
static unsigned int i;
for(i=0;i<23;i++)
{
if(hour==beepTimes[i][0] && minute==beepTimes[i][1])
{
beep=0;
delay(1);
} else {
beep=1;
}
}
}
void setClock()
{
display(set_hour,set_minute);
set_clock_h();
}
void nao()
{
//响
if(set_hour==hour && set_minute==minute)
{
beep=0;
}else{
beep=1;
}
}
void set_clock_m()
{
if(up==0)
{
TR0=0;
set_minute++;
if(set_minute==60)
set_minute=0;
delay(200) ;
TR0=1;
}
if(down==0)
{
TR0=0;
set_minute--;
if(set_minute<0)
set_minute=59;
delay(200) ;
TR0=1;
}
}
void set_clock_h()
{
if(up==0)
{
TR0=0;
set_hour++;
if(set_hour==24)
set_hour=0;
delay(200) ;
TR0=1;
}
if(down==0)
{
TR0=0;
set_hour--;
if(set_hour<0)
set_hour=23;
delay(200) ;
TR0=1;
}
}
void dongtaiTime()
{
if(tt==20)
{ tt=0;
second++;
if(second==60)
{
second=0;
minute++;
if(minute==60)
{
minute=0;
hour++;
if(hour==24)
hour=0;
}
}
}
}
void setHours()
{
if(up==0)
{
TR0=0;
hour++;
if(hour==24)
hour=0;
delay(200) ;
TR0=1;
}
if(down==0)
{
TR0=0;
hour--;
if(hour<0)
hour=23;
delay(200) ;
TR0=1;
}
}
void setMinutes()
{
if(up==0)
{
TR0=0;
minute++;
if(minute==60)
minute=0;
delay(200) ;
TR0=1;
}
if(down==0)
{
TR0=0;
minute--;
if(minute<0)
minute=59;
delay(200) ;
TR0=1;
}
}
void init()
{
hour= 9; minute =23; second =58;
tt=0;
t_mode=0;
position=0;
smg_q=1;
smg_b=1;
smg_s=1;
smg_g=1;
mode=1;
up=1;
set_second=0;
set_minute=0;
set_hour=0;
TMOD=0X11;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
EA=1;
ET0=1;
ET1=1;
TR0=1;
TR1=0; //秒表先不开启
}
void display(unsigned char hour,unsigned char minute) {
P0=0xFF;
switch(position)
{
case 0:
smg_g=1;
smg_q=0;
P0=table[hour/10];
delay(3);
smg_q=1;
break;
case 1:
smg_q=1;
smg_b=0;
P0=table[hour%10];
if(tt>=10)
P0|=0x80; //小数点以半秒的时间闪烁delay(3);
smg_b=1;
break;
case 2:
smg_b=1;
smg_s=0;
P0=table[minute/10];
delay(3);
smg_s=1;
break;
case 3:
smg_s=1;
smg_g=0;
P0=table[minute%10];
delay(3);
smg_g=1;
break;
}
position++;
if(position>3)
position=0;
}
void delay(unsigned int time)
{
unsigned int x,y;
for(x=time;x>0;x--)
for(y=105;y>0;y--);
}
void t0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
tt++;
}
void int1() interrupt 3 //?????
{
TH1=(65536-50000)/256; TL1=(65536-50000)%256;
m++;
if(m==100)
{
m=0;
s++;
if(s==100)
{
s=0;
}}}
void XS(int xs,int xm )
{
d1=(xs/1)%10; d2=(xs/10)%10; d3=(xm/1)%10; d4=(xm/10)%10;
P0=table[d1]; smg_g=0; delay(1);smg_g=1;
P0=table[d2]; smg_s=0; delay(1); smg_s=1;
P0=table[d3]|0x80; smg_b=0; delay(1);smg_b=1;
P0=table[d4]; smg_q=0; delay(1);smg_q=1;
}
void set_miaobiao()
{
if(up==0)
{
delay(1);
if(up==0)
{
TR1=~TR1;
while(!up);
}
}
if(down==0)
{
delay(1);
if(down==0)
{
TR1=0;
m=0;s=0;
while(!down);
}
}
}。