
单片机应用实训报告
姓 名 xx
专 业 xxxxxxx
班 级 xxxxxxxxxxxxxxxxxxxx
指导教师 xxxxxxxxxxxxxxx
2014 年 1月16日
目录
1实训目的…………………………………………………………2
2实训地点………………………………………………………………2
3实训时间………………………………………………………………2
4进度安排………………………………………………………………2
5实训内容…………………………………………………………3
6实训过程…………………………………………………………4
6.1按键程序,在单片机开发板上设置K1、K2、K3、K4以及RST键相应功能……………………………………………………………………4
6.2设计数码管电子钟由59分钟计时到00……………………8
6.3 1602液晶显示器的使用……………………………………12
6.4实训问题及解决方法……………………………………………14
7 实训体会…………………………………………………………14
1 实训目的
本次实训的目的在于加深对MCS-51单片机的理解,初步掌握单片机应用系统的设计方法;掌握常用接口芯片的正确使用方法;强化单片机应用电路的设计与分析能力;提高我们在单片机应用方面的实践技能;培育学生综合运用理论知识解决问题的能力,实现理论结合实际,学以至用的原则。单片机专周实训是在学习完单片机应用技术课程之后开设的两周实训课程,在课程学习中,通过理论与实验相结合的学习,同学们已经掌握了单片机基本的使用方法,实训加强我们对单片机开发流程的认识,加深对单片机I/O口扩展与外围器件的使用,加强我们的实际动手能力与调试能力,从而实现从理论到实践的升华
(1)掌握汇编语言程序的基本结构。
(3)了解汇编语言程序设计的基本方法和思路。
(4)学会利用C语言编写单片机应用程序,并结合单片机原理图,具体实现以下三个功能:
2 实训地点
xxxxxxxxx东院实验楼411
3 实训时间
时间为2014/1/13—2014/1/17
4进度安排
2014/1/13 按键程序,在单片机开发板上设置K1、K2、K3、K4以及RST键相应功能
2014/1/14 设计数码管电子钟由59分钟计时到00
2014/1/15 显示屏设计,设计显示屏滚动字,实现显示屏显示
2014/1/16-2014/1/17 实训结束,写实训报告并上交
5 实训内容
本次实训内容包括三部分,全部都是应用单片机来进行实现的,所以我们应该对单片机有所了解。主要是单片机的最小系统的连接和使用,Keil编程软件及STC烧写软件的使用。
其中第一部分是按键显示相应功能部分,注意每一个按键所对应的程序及显示方法;
第二部分是电子钟的设计,要注意其中的程序设计时应该让其能够自动计时,并在满60的时候进位,在计满到59分钟时,可以自动的跳转到00并重新开始计时。
第三部分设计屏幕字滚动效果,要求显示自己设计的文字并显示出来。
实训单片机的电路连接图:
6实训过程
6.1按键程序,在单片机开发板上设置K1、K2、K3、K4以及RST键相应功能
6.1.1打开软件,建立工程项目,新建文件,写入代码并保存。
软件如下图:
写入程序代码如下:
#include #define uchar unsigned char #define uint unsigned int sbit K1=P3^2; //定义K1 sbit K2=P3^3; //定义K2 sbit K3=P3^4; //定义K3 sbit K4=P3^5; //定义K4 sbit P20=P2^0; uchar code DispTab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80, 0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//共阳数码管显示0~F void Delay(uint m)//延时函数 { uchar i; for(;m>0;m--) {for(i=0;i<125;i++) } } … … main() //主函数 { uchar keyValue; uchar j; P3=0xff; P2=0xf0; P0=0xc0; for(;;) { keyValue=key(); switch(keyValue) {case 0xfb: { j++; if(j>15) j=0;P0=DispTab[j]; break; } case 0xf7:P0=0xa4;break; case 0xef:P0=0xb0;break; case 0xdf:P0=0x99;break; } } } 6.1.2编译程序,生成文件并且烧写程序进入单片机,过程如下: 将单片机按照下图链接: 烧写软件如下图设置: 6.1.3程序烧写完毕后运行单片机: 令RST键实现复位功能;令K1-K4显示1111-4444 如下图显示: 6.2设计数码管电子钟由59分钟计时到00 6.2.1打开软件,建立工程项目,新建文件,写入代码并保存。 图像同上 程序编程如下: #include #include 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; unsigned char hour,min,sec; unsigned char sec100; unsigned char x; sbit K1 = P3^2; sbit K2 = P3^3; bit scan_key(); void proc_key(); void inc_sec(); void inc_min1(); void inc_min2(); void inc_hour(); void display(); void delayms(unsigned char ms); void main(void) {x=0xfe; P0 = 0xff; P2 = 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[3] = dis_code[min / 10]; // 分十位 dis_buf[2] = dis_code[min % 10]&0x7f; // 分个位 dis_buf[1] = dis_code[sec / 10]; // 秒十位 dis_buf[0] = dis_code[sec % 10]; // 秒个位 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(); } } } } bit scan_key() { key_s = 0x00; key_s |= K2; key_s <<= 1; key_s |= K1; return(key_s ^ key_v); } void proc_key() { EA = 0; if((key_v & 0x01) == 0) // K1 { inc_min2(); // JJ=1; } else if((key_v & 0x02) == 0) // K2 { min++; // JJ=0; if(min > 59) { min = 0; } dis_buf[3] = dis_code[min / 10]; // 分十位 *****3 dis_buf[2] = dis_code[min % 10]&0x7f; // 分个位 *****4 } EA = 1; } void timer0() interrupt 1 // 定时器0中断服务程序, 用于数码管的动态扫描 // dis_index --- 显示索引, 用于标识当前显示的数码管和缓冲区的偏移量 // dis_digit --- 位选通值, 传送到P2口用于选通当前数码管的数值, 如等于0xfe时, // 选通P2.0口数码管 // dis_buf --- 显于缓冲区基地址 { TH0 = 0xFC; TL0 = 0x17; P2 = 0xff; // 先关闭所有数码管 P0 = dis_buf[dis_index]; // 显示代码传送到P0口 P2 = dis_digit; // P2 = P2|0x80; 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_min1(); } dis_buf[1] = dis_code[sec / 10]; // 秒十位 *****dis_buf[1] dis_buf[0] = dis_code[sec % 10]; // 秒个位 *****dis_buf[0] } void inc_min1() { min++; if(min > 59) { min = 0; inc_hour(); } dis_buf[3] = dis_code[min / 10]; // 分十位 ********3 dis_buf[2] = dis_code[min % 10]&0x7f; // 分个位 *****4 } void inc_min2() { min--; if(min > 59) { min = 0; inc_hour(); } dis_buf[3] = dis_code[min / 10]; // 分十位 ********3 dis_buf[2] = dis_code[min % 10]&0x7f; // 分个位 *****4 } void inc_hour() { hour++; P1=x; x=x*2; if(hour > 23) { hour = 0; } void delayms(unsigned char ms) // 延时子程序 { unsigned char i; while(ms--) { for(i = 0; i < 120; i++); } } 6.2.2编译程序,生成文件并且烧写程序进入单片机,图像过程同上 6.2.3程序烧写完毕后运行单片机 在数码管上显示时钟(分钟.秒)。 设置K1、K2按键,分别设置分钟增加和减少。 显示如图所示: 6.3 1602液晶显示器的使用 6.3.1打开软件,建立工程项目,新建文件,写入代码并保存。 编程如下: #include #define uint unsigned int //预定义一下 #define uchar unsigned char sbit rs=P2^2; //1602的数据/指令选择控制线 sbit rw=P2^3; //1602的读写控制线 sbit en=P2^4; //1602的使能控制线 uchar code table[]=" wang jie "; //要显示的内容1放入数组tablel uchar code table1[]=" fhtjg "; //要显示的内容2放入数组table1 void delay(uint n) //延时函数 { uint x,y; for(x=n;x>0;x--) for(y=110;y>0;y--);} void lcd_wcom(uchar com) //1602写命令函数 { rs=0; //选择指令寄存器 rw=0; //选择写 P0=com; //把命令字送入P0 delay(5); //延时一小会儿,让1602准备接收数据 en=1; //使能线电平变化,命令送入1602的8位数据口 en=0; } void lcd_wdat(uchar dat) //1602写数据函数 { rs=1; //选择数据寄存器 rw=0; //选择写 P0=dat; //把要显示的数据送入P2 delay(5); //延时一小会儿,让1602准备接收数据 en=1; //使能线电平变化,数据送入1602的8位数据口 en=0; } void lcd_init() //1602初始化函数 { lcd_wcom(0x38); //8位数据,双列,5*7字形 lcd_wcom(0x0c); //开启显示屏,关光标,光标不闪烁 lcd_wcom(0x06); //显示地址递增,即写一个数据后,显示位置右移一位 lcd_wcom(0x01); //清屏 } void main() //主函数 { uchar n,m=0; lcd_init(); //液晶初始化 lcd_wcom(0x80); //显示地址设为80H(即00H,)上排第一位 for(m=0;m<16;m++) //将table[]中的数据依次写入1602显示 { lcd_wdat(table[m]); delay(200); } lcd_wcom(0x80+0x44); //重新设定显示地址为0xc4,即下排第5位 for(n=0;n<8;n++) //将table1[]中的数据依次写入1602显示 { lcd_wdat(table1[n]); delay(200); } while(1); //动态停机 } 6.3.2编译程序,生成文件并且烧写程序进入单片机,图像过程同上 6.3.3程序烧写完毕后运行单片机 实验现象:在液晶显示器上显示字符 如下图: 6.4 实训问题及解决方法 在为期一周的实训中,我遇到了各种各样的问题。首先,准备阶段中,不能正确的了解代码含义,而且,对于Keil编程软件不能熟练使用。并且,实现阶段中,由于在编程过程中的一些操作问题,比如忘记生成hex文件,所以不能进行烧写,又或者是在烧写的过程中出现问题,使得单片机开发板不能正确显示。 面对这些问题,首先,对于软件使用的熟练度,这需要大量的操作练习,在实现阶段结束时,对于该软件的使用熟练度,已经大大提高。并且针对实现阶段的一些操作问题,仍需要多练习,并牢记编程流程,防止步骤遗漏。 测试阶段:分别将实现每个功能的程序烧写在单片机里,观察现象。对错误程序进行相应的修改。 在实训中我们也学会了很多。项目设计、功能选定、搭建硬件工作环境、编写软件程序,程序下载测试、程序最终实现,以及在项目设计中的团队分工与合作。 7 实训体会 实训之前,比较注重于课本上的理论知识,而忽略了实际操作,通过这几天的真实演练,对单片机编程有了更深层次的了解。 通过这一个学期的单片机学习,我收获了很多关于单片机的知识,并且这些知识和日常的生活息息相关。了解了一些简单程序的录入,LED显示器、键盘、和显示器的应用和原理 经过短短一个星期的单片机应用实训,我深深体会到单片机的神奇和奥妙,也意识到自己在单片机编程上还有许多不足,这就需要我们去继续努力。 我在理论的基础上更深刻的掌握了单片机的深层内容及实际生活中的应用,实训锻炼了自己动手能力和思维能力,还有在软件方面的编程能力,让我受益匪浅,同时也暴露出一些平时学习上的问题,让我深刻反思。这些问题的发现将为我以后的学习和工作找明道路,查漏补缺为进一步学习作好准备。通过实训,让我懂得了如何编写一些简单的程序,学会了如何制作单片机应用程序,并且可以在今后的日常生活中灵活运用。 最后,在老师精心的指导下我们都已基本完成实训要求。通过这次实训,我们揭开了单片机神秘的面纱,离我们不再遥远!对于我们所学的编程知识渗透较少,之前都是老师操作为主。此次实训就不同了,我们自己动手,收获甚大! 我在理论的基础上更深刻的掌握了单片机的深层内容及实际生活中的应用,实训锻炼了自己动手能力和思维能力,还有在软件方面的编程能力,让我受益匪浅,同时也暴露出一些平时学习上的问题,让我深刻反思。这些问题的发现将为我以后的学习和工作找明道路,查漏补缺为进一步学习作好准备。通过实训,让我懂得了如何编写一些简单的程序,学会了如何制作单片机应用程序,并且可以在今后的日常生活中灵活运用。 我们要对所用单片机的内部结构有一个系统的了解,知道该单片机内有哪些资源;要有一个清晰的思路和一个完整的的软件流程图;在设计程序时,不能妄想一次就将整个程序设计好,反复修改、不断改进是程序设计的必经之路;要养成注释程序的好习惯,一个程序的完美与否不仅仅是实现功能,而应该让人一看就能明白你的思路,这样也为资料的保存和交流提供了方便;在实习过程中遇到问题是很正常的,但我们应该将每次遇到的问题记录下来,并分析清楚,以免下次再碰到同样的问题。但是从中学到的知识会让我受益终身。
