资源描述
生产实习报告-用单片机开发版设计一个数码管电子时钟
电信071-28-郭春龙
东北石油大学
实习总结报告
实习类型 生产实习
实习单位 电子科学学院实习基地
实习起止时间 2010年7月12日至2010年7月31日
指导教师
所在院(系) 电子科学学院
班 级
学生姓名
学 号
2010年 7月 31日
数码管电子时钟
一 实习目的与要求
实习目的:
用单片机开发版设计一个数码管电子时钟
要求:
1 用C语言编写实验程序
2时钟必须显示 小时、分钟、秒
3时钟的时分秒可以上下调东
4按照protel原理图焊接开发板原件
二 单片机开发板原理及各部分功能说明
原理:单片机到底是什么呢?就是一个电脑,只不过是微型的,麻雀虽小,五脏俱全:它内部也用和电脑功能类似的模块,比如CPU,内存,并行总线,还有和硬盘作用相同的存储器件,不同的是它的这些部件性能都相对我们的家用电脑弱很多,不过价钱也是低的,一般不超过10元即可......用它来做一些控制电器一类不是很复杂的工作足矣了。我们现在用的全自动滚筒洗衣机,排烟罩VCD等等的家电里面都可以看到它的身影!......它主要是作为控制部分的核心部件。
它是一种在线式实时控制计算机,在线式就是现场控制,需要的是有较强的抗干扰能力,较低的成本,这也是和离线式计算机的(比如家用PC)的主要区别。
单片机是靠程序的,并且可以修改。通过不同的程序实现不同的功能,尤其是特殊的独特的一些功能,这是别的器件需要费很大力气才能做到的,有些则是花大力气也很难做到的。单片机的通过你编写的程序可以实现高智能,高效率,以及高可靠性!
部分电路功能
1.时钟电路:DS1302
(1)实时时钟,可对秒、分、时、日、周、月以及带闰年补偿的年进行计 数 ;
(2) 用于高速数据暂存的 31*8 位的 RAM ;
(3) 最少引脚的串行 I/O ;
(4) 2.5-5.5V 的电压工作范围;
(5) 2.5V 时耗电小于 300nA ;
(6) 用于时钟或 RAM 数据读 / 写的单字节或多字节(脉冲方式)数据传送方式;
(7) 简单的 3 线接口;
(8) 可选的慢速充电(至 Vcc1 )的能力。
DS1302引脚图
2. 电源电路
电源电路图
该电路由USB输入+5V电源,后接6脚按钮开关,LED电源指示。
3.晶振电路
晶振电路图
4.复位电路
复位电路图
5.232电平转换电路
电平转换电路图
第一部分是电荷泵电路。由1、2、3、4、5、6脚和4只电容构成。功能是产生+12v和-12v两个电源,提供给RS-232串口电平的需要。
第二部分是数据转换通道。由7、8、9、10、11、12、13、14脚构成两个数据通道。
其中13脚(R1IN)、12脚(R1OUT)、11脚(T1IN)、14脚(T1OUT)为第一数据通道。
8脚(R2IN)、9脚(R2OUT)、10脚(T2IN)、7脚(T2OUT)为第二数据通道。
TTL/CMOS数据从T1IN、T2IN输入转换成RS-232数据从T1OUT、T2OUT送到电脑DB9插头;DB9插头的RS-232数据从R1IN、R2IN输入转换成TTL/CMOS数据后从R1OUT、R2OUT输出。
第三部分是供电。15脚GND、16脚VCC(+5v)。
6. LCD显示电路
通过调节R4来改变液晶的对比度。P0口接并行数据传送,P1.0接数据\命令选择端,P1.1口接液晶读\写选择端,P1.2为液晶使能信号输入端。
液晶显示电路图
7.掉电存储模块
存储模块电路图
8.按钮调节电路
按钮调节电路
三 硬件调试
1、首先是焊接的顺序问题。当初板子做好以后,我一口气就把所有的元件焊上去了,这样对于没有调试过的板子,就很难找到原因。所以焊接的顺序很重要,应该是应该按功能划分的器件进行焊接,顺序是功能部件的焊接--调试(OK)--另一功能部件的焊接,这样容易找到问题的所在。
2、如果在调试按功能划分的器件上出现问题,可以按以下步骤进行:
1)检查原理图连接是否正确
2)检查原理图与PCB图是否一致
3)检查原理图与器件的DATASHEET上引脚是否一致
4)用万用表检查是否有虚焊,引脚短路现象
5)查询器件的DATASHEET,分析一下时序是否一致,同时分析一下命令字是否正确(注意,命令字的顺序很重要,前些日子调试INTEL e28F640这款flash是的时候,在对其擦除和写操作的时候,就碰到了这样的问题)
6)有条件的可以用示波器。如我就是通过示波器对SRAM各个引脚进行检查,发现地址线都是有信号的,而数据线无信号出现,才找到问题所在。
7)飞线。用别的的口线进行控制,看看能不能对其进行正常操作,多试验,才能找到问题出现在什么地方。
3、多观察,多思考。如我前些日子在调试320×240点阵LCD的时候,发现怎么也不能出现图像,后来在偶然的机会下,发现LCD在MPU的CS2口线下,出现闪动的情况,猜测这时候有数据写入到LCD中,仔细研究才发现,MPU的DATA0-7线与74LVC245的A0-7连接在一起,MPU的通过一个GAL16V8或是与非门等芯片进行逻辑组合后与74LVC245的OE引脚相连,这样MPU只有在某一地址范围内才可以进行数据读写操作。所以在调试过程中,对于出现的任何现象都不要放过,问题的解决就是从一些小的现象入手的。山重水复疑无路,柳暗花明又一村。
4、有可能的情况下,最好焊两块板子以上,这样才好有个比较,硬件上很小的问题有很多时候是很难发现的。
5、软件的调试要和硬件配合进行,往往问题可能不是硬件上的
四 软件开发
1、设计思路
采用24小时标准计时制,显示时、分妙;6位LED数码管从左到右分别显示时、分、秒(各占用2位),开始计时时为000000,到235959后变成000000。计时过程具有报时功能,当时间到达整点前5妙进行蜂鸣报时。
有校时功能,可以分别对时及时进行单独校时,使其校正到标准时间;键盘上选定3个键分别作为小时、分、秒的调校键。每按一次键,对应的显示值便加1。
分、秒、加到59后变为00;小时加到23后再按键即变为00再调校时均摊不向上一单位进位(例如分加到59后变为00;但小时不发生改变)。
2、设计方法
① 通过AT89C52的P2口控制数码管的段选,决定显示的数值;
②通过AT89C52的P1口及38译码器控制数码管的位选,决定显示哪一位数码管;
③通过AT89C52的P0口与1*4矩阵键盘连接执行相应功能;
④led发光二极管在闹钟定的时间到达时点亮;
⑤因为P0口没有上拉电阻,所以与排阻相连。
3、实验程序:
#include <reg51.h>
#include <intrins.h>
unsigned char data dis_digit;
unsigned char key_s, key_v;
unsigned char code dis_code[11]={0xc0,0xf9,0xa4,0xb0, // 0, 1, 2, 3
0x99,0x92,0x82,0xf8,0x80,0x90, 0xff};// 4, 5, 6, 7, 8, 9, off
unsigned char data dis_buf[8];
unsigned char data dis_index;
char hour,min,sec;
unsigned char sec100;
sbit K1 = P3^2;
sbit K2 = P3^3;
sbit K3=P3^4;
sbit K4=P3^5;
//sbit JJ=P2^0;
bit scan_key();
void proc_key();
void inc_sec();
void inc_min();
void inc_hour();
//加
bit scan_key1();
void proc_key1();
void inc_sec1();
void inc_min1();
void inc_hour1();
//加
void display();
void delayms(unsigned char ms);
void main(void)
{
P0 = 0xff;
P1 = 0xff;
TMOD = 0x11; // 定时器0, 1工作模式1, 16位定时方式
TH1 = 0xdc;
TL1 = 0;
TH0 = 0xFC;
TL0 = 0x17;
hour = 12;
min = 00;
sec = 00;
sec100 = 0;
dis_buf[7] = dis_code[hour / 10]; // 时十位
dis_buf[6] = dis_code[hour % 10]; // 时个位
dis_buf[4] = dis_code[min / 10]; // 分十位
dis_buf[3] = dis_code[min % 10]; // 分个位
dis_buf[0] = dis_code[sec / 10]; // 秒十位
dis_buf[1] = dis_code[sec % 10]; // 秒个位
dis_buf[2] = 0xbf; // 显示"-"
dis_buf[5] = 0xbf; // 显示"-"
dis_digit = 0xfe;
dis_index = 0;
TCON = 0x01;
IE = 0x8a; // 使能timer0,1 中断
TR0 = 1;
TR1 = 1;
key_v = 0x03;
while(1)
{
/*if(scan_key())
{
delayms(10);
if(scan_key())
{
key_v = key_s;
proc_key();
}
} */
//加
if(scan_key1())
{
delayms(10);
if(scan_key1())
{
key_v = key_s;
proc_key1();
}
}//加
}
}
bit scan_key()
{
key_s = 0x00;
key_s |= K2;
key_s <<= 1;
key_s |= K1;
return(key_s ^ key_v);
}
//加
bit scan_key1()
{
key_s = 0x00;
key_s |= K4;
key_s <<= 1;
key_s |= K3;
return(key_s ^ key_v);
}
//加
void proc_key()
{
EA = 0;
if((key_v & 0x01) == 0) // K1
{
hour++;
if(hour > 23)
{
hour = 0;
}
if(hour > 9)
dis_buf[7] = dis_code[hour / 10]; // 时十位
else
dis_buf[7] = 0xff; // 当小时的十位为0时不显示
dis_buf[6] = dis_code[hour % 10]; // 时个位
}
else if((key_v & 0x02) == 0) // K2
{
min++;
// JJ=0;
if(min > 59)
{
min = 0;
}
dis_buf[4] = dis_code[min / 10]; // 分十位
dis_buf[3] = dis_code[min % 10]; // 分个位
}
EA = 1;
}
//加
void proc_key1()
{
EA = 0;
if((key_v & 0x01) == 0) // K1
{
hour--;
if(hour < 0)
{
hour = 23;
}
if(hour > 9)
dis_buf[7] = dis_code[hour / 10]; // 时十位
else
dis_buf[7] = 0xff; // 当小时的十位为0时不显示
dis_buf[6] = dis_code[hour % 10]; // 时个位
if(min > 59)
{
min = 0;
}
// JJ=1;
}
else if((key_v & 0x02) == 0) // K2
{
min--;
// JJ=0;
if(min < 0)
{
min = 59;
}
dis_buf[4] = dis_code[min / 10]; // 分十位
dis_buf[3] = dis_code[min % 10]; // 分个位
}
EA = 1;
}
//加
void timer0() interrupt 1
// 定时器0中断服务程序, 用于数码管的动态扫描
// dis_index --- 显示索引, 用于标识当前显示的数码管和缓冲区的偏移量
// dis_digit --- 位选通值, 传送到P2口用于选通当前数码管的数值, 如等于0xfe时,
// 选通P2.0口数码管
// dis_buf --- 显于缓冲区基地址
{
TH0 = 0xFC;
TL0 = 0x17;
P1 = 0xff; // 先关闭所有数码管
P0 = dis_buf[dis_index]; // 显示代码传送到P0口
P1 = dis_digit; //
dis_digit = _crol_(dis_digit,1); // 位选通值左移, 下次中断时选通下一位数码管
dis_index++; //
dis_index &= 0x07; // 8个数码管全部扫描完一遍之后,再回到第一个开始下一次扫描
}
void timer1() interrupt 3
{
TH1 = 0xdc;
sec100++;
if(sec100 >= 100)
{
sec100 = 0;
inc_sec();
}
}
void inc_sec()
{
sec++;
if(sec > 59)
{
sec = 0;
inc_min();
}
dis_buf[1] = dis_code[sec / 10]; // 秒十位
dis_buf[0] = dis_code[sec % 10]; // 秒个位
}
void inc_min()
{
min++;
if(min > 59)
{
min = 0;
inc_hour();
}
dis_buf[4] = dis_code[min / 10]; // 分十位
dis_buf[3] = dis_code[min % 10]; // 分个位
}
void inc_hour()
{
hour++;
if(hour > 23)
{
hour = 0;
}
if(hour > 9)
dis_buf[7] = dis_code[hour / 10]; // 时十位
else
dis_buf[7] = 0xff; // 当小时的十位为0时不显示
dis_buf[6] = dis_code[hour % 10]; // 时个位
}
void delayms(unsigned char ms)
// 延时子程序
{
unsigned char i;
while(ms--)
{
for(i = 0; i < 120; i++);
}
}
五 心得体会
在做本次实习的过程中,我感触最深的当属查阅大量的设计资料了。为了让自己的设计更加完善,查阅这方面的设计资料是十分必要的,同时也是必不可少的。我们是在做单片机实习,但我们不是艺术家,他们可以抛开实际尽情在幻想的世界里翱翔,而我们一切都要有据可依,有理可寻,不切实际的构想永远只能是构想,永远无法升级为设计。 在这次课程设计中,我们运用到了以前所学的专业课知识,如:C语言、模拟和数字电路知识等。虽然过去从未独立应用过它们,但在学习的过程中带着问题去学我发现效率很高,这是我做这次课程设计的又一收获。 在实习之前,我们要对所用单片机的内部结构有一个系统的了解,知道该单片机内有哪些资源;要有一个清晰的思路和一个完整的的软件流程图;在设计程序时,不能妄想一次就将整个程序设计好,反复修改、不断改进是程序设计的必经之路;要养成注释程序的好习惯,一个程序的完美与否不仅仅是实现功能,而应该让人一看就能明白你的思路,这样也为资料的保存和交流提供了方便;在实习过程中遇到问题是很正常的,但我们应该将每次遇到的问题记录下来,并分析清楚,以免下次再碰到同样的问题。但是从中学到的知识会让我受益终身。发现、提出、分析、解决问题和实践能力提高都会受益于我在以后的学习、工作和生活中。
指导教师评语及成绩评定:
成绩: 指导教师签字:
年 月 日
tgKQcWA3PtGZ7R4I30kA1DkaGhn3XtKknBYCUDxqA7FHYi2CHhI92tgKQcWA3PtGshLs50cLmTWN60eo8Wgqv7XAv2OHUm32WGeaUwYDIAWGMeR4I30kA1DkaGhn3XtKknBYCUDxqA7FHYi2CHhI92tgKQcWA3PtGZ7R4I30kA1DkaGtgKQcWA3PtGZ7R4I30kA1DkaGhn3XtKknBYCUDxqA7FHYi2CHhI92tgKQcWA3PtGshLs50cLmTWN60eo8Wgqv7XAv2OHUm32WGeaUwYDIAWGMeR4I30kA1DkaGhn3XtKknBYCUDxqA7FHYi2CHhI92tgKQcWA3PtGZ7R4I30kA1DkaGtgKQcWA3PtGZ7R4I30kA1DkaGhn3XtKknBYCUDxqA7FHYi2CHhI92tgKQcWA3PtGshLs50cLmTWN60eo8Wgqv7XAv2OHUm32WGeaUwYDIAWGeR4I30kA1DkaGhn3XtKknBYCUDxqA7FHYi2CHhI92tgKQcWA3PtGZ7R4I30kA1DkaGtgKQcWA3PtGZ7R4I30kA1DkaGhn3XtKknBYCUDxqA7FHYi2CHhI92tgKQcWA3PtGshLs50cLmTWN60eo8Wgqv7XAv2OHUm32WGeaUwYDIAWGMeR4I30kA1DkaGhn3XtKknBYCUDxqA7FHYi2CHhI92tgKQcWA3PtGZ7R4I30kA1DkaGtgKQcWA3PtGZ7R4I30kA1DkaGhn3XtKknBYCUDxqA7FHYi2CHhI92tgKQcWA3PtGshLs50cLmTWN60eo8Wgqv7XAv2OHUm32WGeaUwYDIAWGMeR4I30kA1DkaGhn3XtKknBYCUDxqA7FHYi2CHhI92tgKQcWA3PtGZ7R4I30kA1DkaGtgKQcWA3PtGZ7R4I30kA1DkaGhn3XtKknBYCUDxqA7FHYi2CHhI92tgKQcWA3PtGshLs50cLmTWN60eo8Wgqv7XAv2OHUm32WGeaUwYDIAWGMeR4I30kA1DkaGhn3XtKknBYCUDxqA7FHYi2CHhI92tgKQcWA3PtGZ7R4I30kA1DkaG
展开阅读全文