一 实习目的
1.通过对单片机小系统的设计、焊接、装配,掌握电路原理图及电子线路的基本焊接装配工艺、规范及注意事项;
2.通过对系统板的测试,了解系统板的工作原理及性能,掌握元器件及系统故障的排除方法; 3.掌握程序编制及调试方法,完成系统初始化、存储器操作、端口操作、键盘、显示等程序的编制及调试(汇编语言、C语言均可);
4.通过单片机系统的硬件焊接、调试,程序的编制、调试及运行,与理论及实验的有机结合和指导教师的补充介绍,使学生掌握测控系统的工作原理、开发方法; 5.培养学生解决实际问题的能力,提高对理论知识的感性认识。
二 实习意义
通过本实习不但可以单片机的软硬件的综合调试方法,而且可以熟练掌握电路原理图,激发对单片机智能型的探索精神,提高学生的综合素质,培养学生应用单片机实现工业控制系统的设计、开发与调试的能力。在制作学习过程中,不但可以掌握软硬件的综合调试方法,而且可以是学生对单片机智能性产生强烈的欲望达到最大限度的掌握微机应用技术,软件及接口设计和数据采集与处理的技能,培养电综合实践素质的目的。
三 系统基本组成及工作原理
3.1 系统基本组成
最小系统包括单片机的晶振、复位、电源、下载电路,以及简单的输入输出等模块,其框图如图1所示。在基本档完成的前提下设计完成扩展模块,使显示信息更丰富,其框图如图2所示。
图1 最小系统框图
1
电源模块 乐曲演奏琴键模块 键盘模块 复位 STC89C52RC 喇叭 显示驱动 四位LED显示 循环灯模块 串口下载、通讯模块 晶振 图2 扩展总框图
3.2 系统工作原理
在单片机的P3口接12个发光二极管,通过外部中断、定时中断和位扫描等程序控制实现每个发光二极管指示灯闪烁。将全部行线至于低电平,检验列线的状态,只要有一列的电平为底,则表示键盘中键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中;若所有列线均为高电平,则表示键盘中无按键按下。
四 系统硬件设计
4.1电路设计
利用单片机的P1口扩展一个4×4的矩阵键盘;单片机的P3.0和P3.1连接联机通讯模块; P2.0-P2.3口作四位数码显示接口;P3.2—P3.7口做交通灯和循环灯接口。电路最小系统原理和模块如图3所示。电路系统原理图如图附录1所示
图3-1
2
图3-2
五 系统软件设计
5.1主程序设计
主程序包括5个部分,以状态号标识系统所处的状态。在上电初始化后即进入状态号的轮询扫描,状态号的值决定了子程序的入口。其中子程序分别为:循环灯点亮(状态号为1)、四位数码显示倒计时(状态号为2)、交通灯控制(状态号为3)、电子琴演奏(状态号为4)。
开始 初始化 状态号设为默认1 取得状态号n,根据n值,选择程序分支 n=1, 执行状态1处理程序 n=2, 执行状态2处理程序 n=3, 执行状态3处理程序 n=4, 执行状态4处理程序 n=5,执行状态5处理图5 主程序流程框图、
PC机(状态号位5)主程序流程框图如图5所示: 5.2 功能子程序设计
5.2.1循环灯控制模块
利用查表法,定时器定时实现任意历程跑马灯的控制。
5.2.2四位数码显示模块
编程实现千位数秒倒计时。
3
5.2.3交通灯控制模块
利用模块1和模块2的硬件电路模拟实现十字路口交通等的管理功能,要求有黄灯闪烁警示功能。
信号灯控制系统:南北线有红黄绿三只信号灯,东西线有红黄绿三只信号灯。
表1 交通灯切换控制顺序表 时间(秒) 30 10 30 10
南北线 绿黄红 亮灭灭 灭闪灭 灭灭亮 灭灭亮
东西线 绿黄红 灭灭亮 灭灭亮 亮灭灭 灭闪灭
4
5.2.4 电子琴模块
该模块的硬件电路,可以利用单片机的1位IO口接一只三极管来驱动蜂鸣器,演奏编好的乐谱;或者实现利用按键模拟电子琴演奏。
利用定时器控制单片机引脚发出一定频率(声波频率20Hz~20000Hz)的方波信号,就可使喇叭发出单调的声音,也可以产生DO,RE,ME,FA,SO,LA,XI等音阶在内的各种频率声音。 乐曲演奏模块
通过编程将乐谱输入输入单片机,由外接扬声器奏出悦耳动听的音乐。
5
5.2.5 PC通讯
六 实习总结、体会
通过这次单片机实习,我不仅加深了对单片机理论的理解,将理论很好地应用到实际当中去,而且我还学会了如何去培养我们的创新精神,从而不断地战胜自己,超越自己。创新可以是在原有的基础上进行改进,使之功能不断完善,成为真真正自己的东西。
首先在做本次实习的过程中,我感触最深的当属查阅大量的设计资料了。为了让自己的设计更加完善,查阅这方面的设计资料是十分必要的,同时也是必不可少的。我们是在做单片机实习,但我们不是艺术家,他们可以抛开实际尽情在幻想的世界里翱翔,而我们一切都要有据可依,有理可寻,不切实际的构想永远只能是构想,永远无法升级为设计。 其次,在这次课程设计中,我们运用到了以前所学的专业课知识,如:C语言、模拟和数字电路知识等。虽然过去从未独立应用过它们,但在学习的过程中带着问题去学我发现效率很高,这是我做这次课程设计的又一收获。
最后,在实习之前,我们要对所用单片机的内部结构有一个系统的了解,知道该单片机内有哪些资源;要有一个清晰的思路和一个完整的的软件流程图;在设计程序时,不能妄想一次就将整个程序设计好,反复修改、不断改进是程序设计的必经之路;要养成注释程序的好习惯,一个程序的完美与否不仅仅是实现功能,而应该让人一看就能明白你的思路,这样也为资料的保存和交流提供了方便;在实习过程中遇到问题是很正常的,但我们应该将每次遇到的问题记录下来,并分析清楚,以免下次再碰到同样的问题。但是从中学到的知识会让我受益终身。发现、提出、分析、解决问题和实践能力提高都会受益于我在以后的学习、工作和生活中。
6
参考文献
1.彭伟.单片机C语言程序设计实训100例——基于8051+Proteus仿真.北京:电子工业出版社,2011
2.郭天祥.新概念51单片机C语言教程——入门、提高、开发、拓展全攻略.北京:电子工业出版社,2009
3.刘建清.轻松玩转51单片机C语言.北京:北京航空航天大学出版社,2010 4.谭浩强.C程序设计.北京:清华大学出版社,1991
5.求是科技. 单片机典型模块设计实例导航。北京:人民邮电出版社,2004 6.潘新民,王燕芳.单片微型计算机实用系统设计.北京:电子工业出版社,2011 7.胡汉才.单片微机原理及其接口技术.清华大学出版社,2010(推荐教材) 8.宏晶科技 STC Microcontroller Handbook, 2007 9.单片机教程网http://www.51hei.com/
附件1单片机实习最小系统原理总图 附件2 实习材料清单
附件3实习工作进展及完成记录表 附件4 调试通过的源程序清单
7
附件1 原理总图
附件2 单片机实习最小系统设计材料清单 材料名称 规格 数量 电阻 电阻 电阻 电容 电容 电解性电容 电解性电容 芯片 芯片 三极管 发光二极管 发光二极管 发光二极管 9键插座 喇叭 多功能电路板 管座 管座 按钮 晶振 排阻 4位液晶数码管 10k 1k 200 30pf 1uf 220uf 10uf AT89C51 NAX232 LED-RED LED-GREEN LED-YELLOW CONN-D9F SOUNDER 40位 16位 12M 8*10k 1 7 12 2 4 1 1 1 1 5 4 4 4 1 1 1 1 1 16 1 1 1 备注 pnp 共阳极 说明 R1 R2-R8 R10-R21 C1 C2 C4-C7 C3 C8 Q1-Q5 D1 D2 D9 D10 D3 D4 D11 D12 D5 D6 D13 D14 RP1 8
实习工具清单
工具 电烙铁 钳子 钳子 规格 尖口 圆口 数量 1 1 1 附件4 源程序清单
1. 循环灯点亮
#include #define uchar unsigned char #define uint unsigned int uchar code led_table[] = { 0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff, 0xfb,0xf3,0xe7,0xcf,0x9f,0x3f,0x7f,0xff, 0xfb,0xf3,0xe3,0xc7,0x8f,0x1f,0x3e,0x7f,0xff,0xff, 0xcf,0xb7,0x7b,0xff,0xff,0x7b,0xb7,0xcf,0xff }; int su_du=1500; void lighting_led() { static uchar i; static uint m; m++; if (i==34) i=0; if(m == su_du) { m=0; P3 = led_table[i++]; } if (m >su_du) m = 0; } 2.四位数码显示 (1)#include \"daojishi.h\" #include \"timer0.h\" bit daojishi_OK = 0; int jishi=0; void _Dao_Ji_Shi() { static uchar Minute_buf =2; if (daojishi_OK == 1) { if (Minute_buf != shi_zhong) { jishi--; if(jishi < 0) { jishi = 0; daojishi_OK = 0; } } Minute_buf = shi_zhong; } } (2)#include \"REG52.h\" #include \"timer0.h\" typedef unsigned char BYTE; typedef unsigned int WORD; //----------------------------------------------- /* define constants */ #define FOSC 12000000L #define T1MS (65536-FOSC/12/1000) //1ms timer calculation method in 12T mode /* define SFR */ sbit we1=P2^3; sbit we2=P2^2; sbit we3=P2^1; sbit we4=P2^0; /* define variables */ BYTE code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8 ,0x80,0x90,0x88,0x83,0xa7,0xa1,0x86,0x8e}; WORD count; //1000 times counter WORD shi_zhong = 0; WORD beep_delay_count; 9 bit seg_flag; bit search_key_flag; //----------------------------------------------- 1000 -> 1s { count = 0; //reset void seg_display(WORD dat) { switch(count % 4) { case 0: P0 = 0xff; we1=0;we2=1;we3=1;we4=1; P0=table[dat/1000]; break; case 1: P0 = 0xff; we1=1;we2=0;we3=1;we4=1; P0=table[dat%1000/100]; break; case 2: P0 = 0xff; we1=1;we2=1;we3=0;we4=1; P0=table[dat%100/10]; break; case 3: P0 = 0xff; we1=1;we2=1;we3=1;we4=0; P0=table[dat%10]; break; default :; } } /* Timer0 interrupt routine */ void tm0_isr() interrupt 1 { TL0 = T1MS; //reload timer0 low byte TH0 = T1MS >> 8; //reload timer0 high byte if(TR1 == 1)beep_delay_count++; if (count++ == 1000) //1ms * counter shi_zhong++; } seg_flag = 1; if(count%10 == 0) search_key_flag = 1; } //----------------------------------------------- void tm0_int() { TMOD = 0x01; timer0 as mode1 (16-bit) TL0 = T1MS; timer0 low byte TH0 = T1MS >> 8; timer0 high byte TR0 = 1; start running ET0 = 1; timer0 interrupt EA = 1; global interrupt switch count = 0; counter } 3.交通灯控制 #include sbit YELLOW_A = P3^6; sbit YELLOW_B = P3^7; uchar dao_ji_shi=0; uchar Operation_Type = 1; void Traffic_lignt() { dao_ji_shi = 29-shi_zhong %30; //set //initial //initial //timer0 //enable //open //initial 10 switch(Operation_Type) { case 1: RED_A=1;YELLOW_A=1;GREEN_A=0;//A绿灯、B红灯亮 RED_B=0;YELLOW_B=1;GREEN_B=1; if( dao_ji_shi< 11)//十秒 { Operation_Type = 2; } break; case 2: if(dao_ji_shi ==10 ||dao_ji_shi ==8||dao_ji_shi ==6 ||dao_ji_shi ==4||dao_ji_shi == 2||dao_ji_shi==0) { YELLOW_A = 0; }else YELLOW_A = 1; //A黄灯闪烁5s if(dao_ji_shi ==29) Operation_Type = 3; RED_A=1;GREEN_A=0;//A 绿 灯、B红灯亮 RED_B=0;GREEN_B=1; break; case 3: RED_A=0;YELLOW_A=1;GREEN_A=1;//A红灯、B绿灯亮 RED_B=1;YELLOW_B=1;GREEN_B=0; if( dao_ji_shi < 11)//十秒 { Operation_Type = 4; } break; case 4: //B黄灯闪 烁5s if(dao_ji_shi ==10 ||dao_ji_shi ==8||dao_ji_shi ==6 ||dao_ji_shi ==4||dao_ji_shi ==2||dao_ji_shi==0) { YELLOW_B = 0; }else YELLOW_B = 1; RED_A=0;GREEN_A=1;//A红灯、B绿灯 RED_B=1;GREEN_B=0; if(dao_ji_shi ==29) Operation_Type = 1; break; default:break; } } 4.电子琴、乐曲演奏 #include #include \"key.h\" #define uchar unsigned char #define uint unsigned int sbit beep=P2^4; uint code Tone_Delay_Table[]= //音符延时 {64021,64103,64260,64400,64524,64580,64684,64 777, 64820,64898,64968,65030,65058,65110,65157,65178}; uchar code DSY_Table[]= // 数码管 {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80, 0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xBF}; //第一段 uchar code song1_Tone[]={ 0,1,2,3,4,5,5,6,7,8,9,10,11,12,13,14 ,15,15,14,13, 12,11,10,9,8,7,6,5,4,3,2,1,0xff}; uchar code song1_Time[]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1, 11 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xff}; //第二段 uchar code song2_Tone[]={ 3,5,5,3,2,1,2,3,5,3,2,3,5,5,3,2,1,2,3 ,2,1,1,0xff}; uchar code song2_Time[]={2,1,1,2,1,1,1,2,1,1,1,2,1,1,2,1,1,1,2, 1,1,1,0xff}; //第三段 uchar code song3_Tone[]={1,3,3,3,3,5,4,2,5,3,7,6,5,5,7,4,4,3,6, 7,2,1,0xff}; uchar code song3_Time[]={2,1,1,2,1,1,1,2,1,1,1,2,1,1,2,1,1,1,2, 1,1,1,0xff}; //音乐片段引索,音符引索 uchar song_index=0,Tone_index=0; //指针 uchar *song_Tone_Pointer,*song_Time_Pointer; //取音符位置 uchar i=0; uchar KeyNo; //按键 uchar inter_cont=0; void Dian_zi_qin() { if(Key_value != 0) { TR1=1; KeyNo= Key_value; beep_delay_count=0; } else if(beep_delay_count >= 200 ) { beep = 1; TR1=0; } if (inter_cont >0) { switch(inter_cont-1) { case 0:song_Tone_Pointer=song1_Tone; song_Time_Pointer=song1_Time; break; case 1:song_Tone_Pointer=song2_Tone; song_Time_Pointer=song2_Time; break; case 2:song_Tone_Pointer=song3_Tone; song_Time_Pointer=song3_Time; break; default :break; } Tone_index=song_Tone_Pointer[i]; if(Tone_index==0xff) { TR1=0; i=0; } else { TR1=1; } if(beep_delay_count >= song_Time_Pointer[i]*200 ) { beep = 1; beep_delay_count=0; i++; } } } /* Timer0 interrupt routine */ void tm1_isr() interrupt 3 { if(inter_cont == 0) { TH1=Tone_Delay_Table[KeyNo]>>8; TL1=Tone_Delay_Table[KeyNo]; } else //if(inter_cont == 0) { TL1 = Tone_Delay_Table[Tone_index]; //reload timer1 low byte 12 TH1 = #define SPACE_PARITY 4 //Space parity Tone_Delay_Table[Tone_index]>>8 ; #define PARITYBIT EVEN_PARITY //Testing //reload timer1 high byte } beep=~beep; } //----------------------------------------------- void tm1_int() { TMOD = TMOD|0x10; //set timer1 as mode1 (16-bit) TL1 = Tone_Delay_Table[Tone_index]; //reload timer1 low byte TH1 = Tone_Delay_Table[Tone_index]>>8 ; //reload timer1 high byte TR1 = 0; //timer1 start running ET1 = 1; //enable timer1 interrupt EA = 1; //open global interrupt switch } 5.联机通讯 #include //sfr T2CON = 0xC8; //timer2 control register //sfr RCAP2L = 0xCA; //sfr RCAP2H = 0xCB; //sfr TL2 = 0xCC; //sfr TH2 = 0xCD; #define uchar unsigned char #define uint unsigned int #define FOSC 12000000L //System frequency #define BAUD 2400 //UART baudrate /*Define UART parity mode*/ #define NONE_PARITY 0 //None parity #define ODD_PARITY 1 //Odd parity #define EVEN_PARITY 2 //Even parity #define MARK_PARITY 3 //Mark parity even parity bit busy; void SendData(uchar dat); void SendString(char *s); void Uart_int() { #if (PARITYBIT == NONE_PARITY) SCON = 0x50; //8-bit variable UART #elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY) SCON = 0xda; //9-bit variable UART, parity bit initial to 1 #elif (PARITYBIT == SPACE_PARITY) SCON = 0xd2; //9-bit variable UART, parity bit initial to 0 #endif TL2 = RCAP2L = (65536-(FOSC/32/BAUD)); //Set auto-reload vaule TH2 = RCAP2H = (65536-(FOSC/32/BAUD)) >> 8; T2CON = 0x34; //Timer2 start run ES = 1; //Enable UART interrupt EA = 1; //Open master interrupt switch } void Uart() { if (shi_zhong%3 == 0 ) { SendString(\"12电气本!\\r\\n\"); shi_zhong++; } } /*---------------------------- UART interrupt service routine ----------------------------*/ void Uart_Isr() interrupt 4 { 13 if (RI) { RI = 0; //Clear receive interrupt flag // bit9 = RB8; //P2.2 show parity bit } if (TI) { TI = 0; //Clear transmit interrupt flag busy = 0; //Clear transmit busy flag } } /*---------------------------- Send a byte data to UART Input: dat (data to be sent) Output:None ----------------------------*/ void SendData(uchar dat) { while (busy); //Wait for the completion of the previous data is sent ACC = dat; //Calculate the even parity bit P (PSW.0) if (P) //Set the parity bit according to P { #if (PARITYBIT == ODD_PARITY) TB8 = 0; //Set parity bit to 0 #elif (PARITYBIT == EVEN_PARITY) TB8 = 1; //Set parity bit to 1 #endif } else { #if (PARITYBIT == ODD_PARITY) TB8 = 1; //Set parity bit to 1 #elif (PARITYBIT == EVEN_PARITY) TB8 = 0; //Set parity bit to 0 #endif } busy = 1; SBUF = ACC; //Send data to UART buffer } /*---------------------------- Send a string to UART Input: s (address of string) Output:None ----------------------------*/ void SendString(char *s) { while (*s) //Check the end of the string { SendData(*s++); //Send current char and increment string ptr } } 6.按键 #include static uchar k_yanchi=0; //高四位置0,放入四行 P1=0x0F; //Delayms(10); k_yanchi++; if(k_yanchi >= 18) { //按键后00001111将变成0000XXXX,14 X中1个为0,3个仍为1,下面抑或会把3个1变0.唯一一个0变1 Tmp=P1^0X0F; //判断按键发生于0-3哪一列 switch(Tmp) { case 1:k=0;break; case 2:k=1;break; case 4:k=2;break; case 8:k=3;break; default:return 0;//无键按下 } //低四位0,放入四列 P1=0xf0; // Delayms(10); if (k_yanchi >= 20) { k_yanchi = 0; //按键后11110000将变成 xxxx0000,X中1个为0,3个仍为1,下面会将高四位移至低四位 Tmp=P1^0Xf0; //对0-3行分别附加起始值0.4.8.12 switch(Tmp>>4) { case 1:k+=0;break; case 2:k+=4;break; case 4:k+=8;break; case 8:k+=12;break; default:return 0; } KeyNo=k+1; } } return KeyNo; } void Key_serve() { Key_value = Key_get(); switch(Model) { case lighting: if( Key_value == 0 ) ; else if (Key_value ==13 ) { Model++; P3=0xff; Key_value=0; } else if (Key_value == 8)//减速 { su_du = su_du +200; if(su_du >5000) su_du =5000; Key_value=0; } else if (Key_value == 4)//加速 { su_du = su_du -200; if(su_du <400) su_du =400; Key_value=0; } break; case daojishi: if (Key_value != 0&&jishi > 1000) jishi = 0; if (Key_value ==13 ) Model++; else if(daojishi_OK == 0) switch(Key_value) { case 0:break; case 1: jishi=jishi*10+1; //数字键1 break; case 2: jishi=jishi*10+2; //数字键2 break; case 3: jishi=jishi*10+3; //数字键3 break; case 5: jishi=jishi*10+4; 15 //数字键4 //数字键5 //数字键6 //数字键7 //数字键8 //数字键9 //数字键0 //确定键键 //加 //减 0; //修改 break; case 6: jishi=jishi*10+5; break; case 7: jishi=jishi*10+6; break; case 9: jishi=jishi*10+7; break; case 10: jishi=jishi*10+8; break; case 11: jishi=jishi*10+9; break; case 14: jishi=jishi*10; break; case 15: daojishi_OK = 1; break; case 4: jishi++; break; case 8: jishi--; break; case 16: //daojishi_OK = jishi = 0; break; default: break; } else if (Key_value ==16) daojishi_OK = 0; Key_value = 0; break; case traffic: if (Key_value ==13 ) Model++; P3=0xff; Key_value = 0; break; case dianziqin: //电子琴 if (Key_value ==13 ) { Model++; Key_value = 0; } else if (Key_value ==16 ) { inter_cont++; if (inter_cont>=2) inter_cont = 0; Key_value = 0; } break; case uart: if (Key_value ==13 ) Model=1; Key_value = 0; break; default: break; } } 7.源程序 #include 16 #include \"uart.h\" #define uchar unsigned char #define uint unsigned int #define traffic 3 #define lighting 1 #define daojishi 2 #define dianziqin 4 #define uart 5 extern void Uart(); extern void Uart_int(); void main() { PT1 = 1 ; tm0_int(); tm1_int(); Uart_int(); while(1) { if(seg_flag == 1) { seg_flag = 0; switch(Model)//数码管显示切换 { case lighting: seg_display(1); break; case daojishi: seg_display(jishi); //seg_display(Key_value); break; case traffic: seg_display(dao_ji_shi%100+dao_ji_shi*100); break; case dianziqin: seg_display(4); break; case uart: seg_display(5); break; default: break; } } } } if(search_key_flag == 1)//按键执行 { search_key_flag = 0; Key_serve(); } switch(Model)//功能切换 { case lighting: lighting_led(); break; case traffic: Traffic_lignt(); break; case daojishi: _Dao_Ji_Shi(); break; case dianziqin: Dian_zi_qin(); break; case uart: Uart(); break; default: break; } 17 因篇幅问题不能全部显示,请点此查看更多更全内容