1、实习步骤本单片机最小系统是以AT89S51单片机为控制核心,由驱动芯片ZLG7289 与16键的键盘矩阵实现对两个4位一体共阴数码管LED的驱动显示,由LCD1602 实现液晶显示,再通过电平转换芯片 MAX232并连接到232接口实现串口通信, 系统还包含有蜂鸣器,USB及适配器供电接口,JTAG程序下载接口,总线扩展等。 首先,用protel99se软件制作硬件电路原理图及绘制PCB板;其次,安装焊接 单片机最小系统开发板及下载线,并且进行电路调试;再次,在KeiluVision2 软件环境下调试单片机汇编程序或C语言程序,用单片机下载软件ISPLAY或 STC-ISP V31实现程序下载
2、,从而用编程实现最小系统的基本功能;最后,编写 综合程序以实现系统功能的综合以及拓展功能,其中串口通信用到电脑自带的超 级终端或AccessPort软件。单片机最小系统板焊接首先对照元件清单和电路图,检查器件是否完整,型号、规格、安装是否正 确。然后将各器件根据焊接规则焊接到电路板上,其中对于器件的摆放方向和位 置需十分注意。先焊发热器件电阻和较低的电容,再焊较大的器件,焊接JTAG 线,JTAG线里面的芯片电阻,电阻电容均为贴片封装,焊接时需小心谨慎,对 于各条线引的焊接也需谨慎,按照其对应的顺序进行焊接,焊接结束后,自行组 装。检查已经焊好的电路板和JTAG下载线是否无误:先用万用表检查电
3、路板 焊接是否都正确。当检查没有短路,断路,虚焊,漏焊等错误后,给电路板供 电,看二极管是否亮,是否有器件过热,有可能二极管或三极管会在焊接的过程 中被烧坏,那样的话就要重新焊器件。再用Keil软件给板子拷正确的程序, 检查是否能按功能正常工作。单片机系统的硬件调试和软件调试是不能分开的, 许多硬件错误是在软件调试中被发现和纠正的。软件设计在Keil软件环境下对照相关资料编写单片机最小系统开发板的有用程序, 使设计好的程序编译无误,得到hex格式文件,用程序下载软件加载到单片机芯 片中,实现仿真电路,在板上得出效果。设计工具:电脑,Keil软件,Isplay 软件,STC-ISP V31软件蜂
4、鸣器调试主要是检验程序能否下载到芯片,蜂鸣器能正常工作,掌握程序的编译下载 到芯片的方法。在Keil环境中用C语言编写简单是蜂鸣器程序或音乐播放程序。对Keil软件和程序下载软件进行相关配置设置。将编译产生的hex文件下载到芯片,检测其工作是否正常,若工作不正常,则 从软件及硬件两方面进行检查。有用的报警声程序见附录4串口通信调试实现计算机与单片机之间相互通讯功能将编写的串口调试程序经过编译,下载到单片机。串口实现功能为在计算机上能显示单片机的输出。检测串口是否能正常工作, 此阶段需用到串口软件及串口线。若不能正常工作,则需从软件和硬件两方面 进行检查。正确功能为在电脑超级终端不停显示输出内容
5、,与预期相同,工作正常。液晶显示调试保证液晶屏LCD能正常工作,输出效果有所扩展。在编写程序前,认真阅读LCD液晶屏资料,掌握LCD1602及1602液晶模块数 据手册(中文)中的液晶的使用和编程方法,了解其工作时序,及各个指令 及初始化。对照电路图中LCD连接情况,编写LCD1602移动显示程序,经编译下载至单片 机,检测输出,若无输出,则调整电位器,若仍无输出则从软件及硬件两方 面进行检查,找出错误原因,直至液晶屏能正常工作。在程序编写时应时刻注意各个指令间的延时控制。以保证液晶屏呈现效果移动 循环显示,液晶屏工作正常。之后也可用LCD做数字钟,这将在综合程序里 被用到,液晶移屏显示程序见
6、附录6数码管及键盘控制调试保证数码管能正常显示,以及按键能控制数码管的显示.在编写程序前,应认真阅读LED和ZLG7289A资料,了解和掌握其工作时序, 及各个指令及初始化,在程序编写时应时刻注意各个指令间的延时控制。对照电路图中ZLG7289模块的连接情况,编写程序,经过编译,然后下载到单 片机,检测展现效果,是否与程序预期相同。实现效果逐个闪烁,逐个消隐,键盘控制改变数据并移动,与预期相同,工作 状态正常。、再利用单片机内部时钟中断,编写数码管时钟程序,使数码管能够 实现计时功能,键盘能够控制时分秒。系统综合功能设计综合单片机开发板上的各个功能模块,以实现一个完整的系统功能:根据前面对各模
7、块功能的理解和程序编写,结合各个模块实现一个整体系统, 把各模块功能综合起来。设计一媒合系京,使数码管实现数字钟且可右移、闪烁,液晶屏实现时间、日 期的显示且可移屏,键盘能够控制系统,蜂鸣器与键盘且可整点报时,可实 现串口通信功能。鸣器调试程序本程序根据蜂鸣器与单片机P3. 3 口相连设计,可以验证单片机及下载功能 的正确.itinclude #include sbit buz = P33;unsigned char flag;void delayms(unsigned char ms)/*延时子程序*/(unsigned char i;while(ms-)for(i = 0; i 120;
8、i+);)/*主程序*/main() TMOD = OxOl; flag = 0x00; THO = 0x00; TLO = Oxff; TRO = 1; IE = 0x82; while (1) ( flag+; delayms(1); ) /*中断控制*/ void timerO() interrupt 1 using 1 (THO 二 Oxfe;TLO = frq; buz= 、buz; 串口通信调试程序(单片机到PC机) 此为串口通信程序,可在电脑上的超级终端显示相关语句,实现单片机与 电脑的相互通信。遇到的问题:在进行单片机传信息到电脑终端时,可是利用宏 文件,直接调用printf.
9、但是在实际的运用中占用大量的空间资源,而且容易出 现错误,让程序的工作不正常,因此我们改用字节的传送,利用串口一个字节一 个字节的传送,这样就大大增加了程序的可读性。include /* special function registerdeclarations */* for the intended 8051 derivative*/ itinclude /* prototype declarations for 1/0functions*/ #ifdef MONITORS1/* Debugging with Monitor-51 needs*/char code reserve 3 _a
10、t_ 0x23;/* space for serial interrupt if */ttendif/* Stop Exection with Serial Intr. isenabled */ /*The main C function. Program execution starts here after stack initialization. */ void main (void) Setup the serial port for 1200 baud at 12MHz. itifndef M0NIT0R51SCON=0x50;/* SCON: mode 1, 8-bit UART
11、, enable rcvr*/TMOD1= 0x20;/* TMOD:timer 1, mode 2, 8-bit reload*/TH1=0xe6;/* TH1:reload value for 1200 baud 12MHz*/TRI=1;/* TRI:timer 1 run*/TI二 1;/* TI:set TI to send first char of UART*/ttendif /*Note that an embedded program never exits (because there is no operating system to return to). It mus
12、t loop and execute forever.*/while (1) printf ( liu Jing longn);/* Print liu Jing long */)串口通信调试程序(PC机到单片机)#include#include#include#define uchar unsigned char#define uint unsigned intUchardataReceiveBuffer ri6 = 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x200x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20;设置
13、16 字节的串行通信接收缓 冲区uchar data BufferPointer=0;串行通信接收缓冲区指针,初始为0 bit data OnReceive=0;串行通信接收事件标志位void Send(uchar data dat);/*以下为串行通信接收中断处理函数*/ void serialport(void) interrupt 4 using 2 (uchar data c,i; if(RI) ( c二SBUF; 读取接收到的数据 if(BufferPointer16) (ReceiveBuffer BufferPointer=c; 将接收到的数据存入接 收缓冲区BufferPoin
14、ter+;else for(i=0;i15;i+)(ReceiveBuffer i二ReceiveBuffer i+1; 将缓冲区数据左 移)ReceiveBuffer 15=c; 将接收到的数据存入接收缓冲区 RI=O;清空接收标志Send(c);发送接收到的数据,以便回显OnReceive=1;接收事标志位置1 )/*以下为串口初始化函数*/void Initserialport(void)(TM0D=0x20;SCON=0x50;TH1 = 0xe6;/ TH1: reload value for 1200 baud 16MHz */ES=1; /允许串口中断EA = 1;TRI = 1
15、;/* TRI: timer 1 run)void Send(uchar data dat)(SBUF=dat;while(TI=0);TI =0;void main (void) 主函数(uchar data i;LcdReset (),/初始化 LCDInitserialport ();初始化串口DisplayListChar(0, 0, Receive Data:,13); while (1) if(OnReceive)for(i=0;i16;i+) 接收显示 (DispOneChar (i, 1, ReceiveBuffer i); OnReceive=O; )液晶移屏显示程序实现LC
16、D1602的基本显示功能,以及使其能够实现移屏功能。ttinclude ttdefine uchar unsigned charttdefine uint unsigned intuchar code dispcodel = z/happy new year!”;uchar code dispcode2 = /zthanks everyday!”;sbit RS=P20;sbit RW=P2;sbit E=P2-2;void delay(uint t) (uint k, 1;for(k=t;kO;k-)for(l=0;K=10;l+);void wcom() (RS=O;RW=0;E=0;de
17、lay(1000);E=1;)void wdata ()(RS=1;RW=0;E=0;delay(1000);E=1;void init ()初始化子程序(/ uint i;/ for(i=0;i20;i+)P0=0x38;wcom();指令码设置16X2显示,8位数据接口P0=0x0c;wcom();开显示,不显示光标,不闪烁光标P0=0x06;wcom();读或写一个字符后地址累加器加一,光标加一P0=0x01 ;wcom(); 清屏)void main() 主函数显示uchar i;init ();PO=0x80;wcom();for(i=0;i=15;i+)(PO=dispcodeli
18、;wdata ();PO=OxCO;wcom();for(i=0;i=15;i+)(P0=dispcode2iZ;wdata ();for(i=0;i=40;i+)(P0=0xlc;wcom();delay (100);ZLG7289控制键盘及数码管显示程序本程序根据ZLG7289芯片资料,来实现其对数码管和键盘的控制。首先在数 码管上显示0-7八位数,然后循环左右各移八次,再分别左移右.移各两次,而后 实现闪烁、消隐功能,再是按键时可以在数码管显示按键值,如没有按键则显示 时钟,而且可用键盘对时钟的时分秒进行校对。include ttinclude itinclude #define uch
19、ar unsigned char#define uint unsigned int/*端口定义*/sbit cs=pro;sbit CLK=Pri;sbit DI0=Pr2;sbit KEY=P3-2;需要在IXT区把KEY用跳线冒跳到INTO,其余四个跳到VCC这样,P32就相当于直接连接到keybdata uchar com_data; 定义 8 位数据 datasbit mos bit=com data;sbit low bit=com dataO;/*变量定义*/uchar half_hign;uchar half_low;uchar si, sh, ml, mh, hh, hl;uc
20、har second=0;uchar minute=O;uchar hour=12;uint s_cnt, key;/*延时子程序*/void delay_8us()(uchar i;for (i=0; il; i+);)void delay_50us()uchar i;for (i=0; i6; i+);) void delay_50ms()(uchar i, j;for(j=0;j50;j+)for(i=0;i125;i+) ;)void delay_ls ()(uchar i = 20;while(i-)delay_50ms ();void delay_2s ()(uchar i = 4
21、0;while(i-)delay_50ms ();)void delay_5s ()uchar i = 100;while(i-)delay_50ms ();/*发送单字节指令*/void send(uchar sebuf)(uchar i;com_data=sebuf;CLK=0;CS=0;delay_50us ();for(i=0;i8;i+)(delay_8us ();DI0=mos_bit;CLK=1;delay_8us ();com data=com datal;CLK=0;DIO=0;/*接收数据*/uchar receive(void)(uchar i,rebuf;CLK=1;d
22、elay_50us ();for(i=0;i8;i+)(com data=com datal;low_bit=DIO;CLK=1;delay_8us ();CLK=0;delay_8us ();rebuf=com_data;DIO =1;CS=1;return rebuf;)/*复位*/void reset (void)DIO=1;delay_50ms ();send(0xa4);CS=1;/*7289数码管显示,addr为显示位置 范围07, dat为现实内容*/ void display (uchar addr, uchar dat)(if(addr7)return;send(0xc8 +
23、 addr);delay_50us ();send(dat);CS=1;)/*功能:执行ZLG7289纯指令参数:cmd:命令字*/void ZLG(uchar t)(CS = 0;delay_50us ();send(t);CS = 1;delay_50us ();/*发送双字节命令*/void sendcommand(uchar addr, uchar dat)(send(addr);delay_50us ();send (dat);CS=1;/*获取键盘的位置码*/uchar getkeycode (uchar dat)uchar key;switch(dat)(case0x00: ke
24、y =0x00;break;case0x01: key =0x01;break;case0x02: key =0x02;break;case0x03: key =0x03;break;case0x04: key =0x04;break;case0x05: key =0x05;break;case 0x06: key = 0x06;break; case 0x07: key = 0x07;break; case 0x08: key = 0x08;break; case 0x09: key = 0x09;break; case 0x0a: key = 0x10;break; case OxOb:
25、key = Oxll;break; case 0x0c: key = 0x12;break; case OxOd: key = 0x13;break; case OxOe: key = 0x14;break; case OxOf: key = 0x15;break; default: key = Oxee;break;return key;)/*7289按键指令*/ZLG7289_Key ()uchar key, dat;send(0x15);delay_50us ();dat = receive ();delay_50us ();key = getkeycode (dat);)/*按键设定时
26、分加一 */void Set_time (void) 设定时间 if(key=OxOO) 按键 0,控制时 (delay_50ms ();if (key0x00) (hour+;if (hour=24)(hour=0;)hl=hour%10;hh=hour/10;)if(key=0x01) 按键1,控制分delay_50ms ();if(key=0x01)minute+;if(minute=60) (minute=O;)ml=minute%10; mh=minute/10;)if(key=0x02) 按键 2,控制秒(delay_50ms ();if(key=0x02) (second+;if
27、 (second=60) (second=0;sl=second%10; sh=second/10; ) hh=hour/10; hl=hour%10; mh=minute/10;ml=minute%10;sh二second/10;sl=second%10;/*定时器中断初始化*/void Init (void) 初始化子程序(IP=0x02;EXO=1;TMOD=0x02;/0. 25msTH0=0x06;TL0=0x06;EA=1;ETO=1;TRO=1;)/*中断控制*/void service_intO() interrupt 0EXO=O;TRO=O;key= ZLG7289_Key
28、();Set_time ();delay_ls();EXO=1;TRO=1;/*中断控制*/void timeO() interrupt 1 (s_cnt+;if (s_cnt-400) /Is (s_cnt=0;second+;if (second=60) (second=0;minute+;if(minute=60) (minute=0;hour+;)if(hour=24) (hour=0; )/*时钟显示*/void Disp_time(void) (do(hh=hour/10;hl=hour%10;mh=minute/10;ml=minute%10;sh二second/10;sl=se
29、cond%10;sendcommand(0x81, 0x0a); 显示一sendcommand(0x86, 0x0a);display(3, si);delay_50ms();display(2, sh);delay_50ms();display(0, ml);delay_50ms();display(7, mh);delay_50ms();display(5, hl);delay_50ms();display(4, hh);delay_50ms(); whiled);/*主函数*/main() uchar half_high;uchar half_low;uchar dat, key, n;
30、reset ();send(Oxbf) ;/* 测试指令 */CS=1;delay_5s ();sendcommand(0x88, Oxff) ; /* 禁止闪烁 /*显示 01234567*/display(0, 0x04);display(1, 0x05);display (2,0x06);display(3, 0x07);display(4, 0x00);display(5, 0x01);display(6, 0x02);display(7, 0x03);delay_5s ();delay_2s();/*循环左移*/for ( n=0; n=7; n+ ) (ZLG(0xA3);dela
31、y_2s();)delay_2s();/*循环右移*/for ( n=0; n=7; n+ ) (ZLG(0xA2);delay_2s();/*左移2位*/for ( n=0; n=l; n+ )ZLG(OxAl);delay_5s();/*右移2位*/for ( n=0; n=l; n+ )(ZLG(OxAO);delay_5s();/*闪烁控制*/dat = OxFE;for ( n=0; n8; n+ ) 逐位闪烁(sendcommand(0x88, dat);dat = 1; dat+; 数据OxFE循环左移 delay_2s();)sendcommand (0x88, 0x00);
32、八位同时闪烁delay_5s ();delay_5s();sendcommand (0x88, OxFF); 停止闪烁 delay_5s ();/*消隐控制*/dat = OxFE;for ( n=0; n8; n+ )(sendcommand(0x98, dat);dat = 1; dat+; 数据OxFE循环左移 delay_2s();)sendcommand (0x98, OxFF) ;/停止消隐delay_5s ();/*复位*/reset ();delay_5s ();reset ();display(0, 0);display(l, 0);display(2, 0);display
33、(3, 0);display(4, 0);display(5, 0);display(6, 0);display(7, 0);delay_5s();delay_5s();while (1)(while (KEY) ;/*判断是否有按键按下*/send (0x15); 读键盘数据指令delay_50us ();dat = receive ();delay_50us ();key = getkeycode(dat);half_high = key 4;half_low = key & OxOf;/*点示键盘的位置码*/display (0, half_high);display (1, half_
34、low);display(2, half_high);display (3, half_low);display(4, half_high);display (5, half_low);display(6, half_high);display (7, half_low);delay_2s();while(!KEY); 当没有键按下后显示时钟(delay_50us ();reset ();delay_50us ();InitO;delay_50ms ();Disp_time ();系统综合设计程序将LCD, LED,蜂鸣器,串口通信的综合程序。实现了单片机的总体功能。使 数码管和液晶笫一行显示
35、年月日,并且可是实现整点报和闹钟时间到的刷屏显 示,第二行显示由单片机控制的闹钟设定,并且可是显示接收到的由电脑发送的 数据。按键分别能对年月日,时分秒进行调整,开启申口通信,转换显示等功能; 蜂鸣器在每次按键时都有提示,而且能够实现整点报时功能:用口通信使电脑超 级终端。ttinclude itinclude include ttinclude ttinclude ttinclude UchardataReceiveBuffer16 = 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,0x20, 0x20, 0x20, 0x20, 0x20, 0
36、x20, 0x20, 0x20;设置 16 字节的串行通信接收 缓冲区uchar data BufferPointer=0;串行通信接收缓冲区指针,初始为0bit data 0nReceive=0;串行通信接收事件标志位ttdefine uint unsigned int#define uchar unsigned charsbit buz=P33;蜂鸣器口定义显示字符串uchar code dispcode 1 = z,Date : 2010-00-00;uchar code dispcode3口= zheng dian bao ;uchar si, sh, ml, mh, hh, hl,
37、moh, mol, dh, dl;uchar temp, t, s;uint second=0;uint minute=0;uint hour=12;uchar dat, key, k;uint s_cnt, i;uint year=2010;uint month=0;uint day=0;void riqi ();void Init ();void Disp_time ();void Sendy(uchar data dat);/*以下为串行通信接收中断处理函数*/void serialport (void) interrupt 4 using 2(uchar data c, i;if(RI
38、)c=SBUF; 读取接收到的数据if (Buf f erPo i nt er16)ReceiveBuffer BufferPointer=c; 将接收到的数据存入接收缓冲区BufferPointer+; else (for(i=0;i=12) year+;month=l;if(year=2012) year=2010; ) ) ) void Disp_time (void) LED. LCD 显示时间 (dh=day/10; dl=dayolO;hh=hour/10;hl=hour%10;mh=minute/10;ml=minute%10;sh二second/10;sl=second%10;
39、if(s1=0&sh=0&m1=0&mh=0) buz=0;delay(10000);buz=l;DisplayListChar(0, 0, dispcode3, 16);delay(20000);DisplayListChar(0, 0, dispcodel, 16);delay(1000);sendcommand (0x81, 0x0a); 数码管显示sendcommand(0x86, 0x0a);display(3, si);delay_50ms();display (2, sh) ;delay_50ms (); 秒display (0, ml) ;delay_50ms ();displ
40、ay (7, mh) ;delay_50ms (); 分display (5, hl) ;delay_50ms ();display (4, hh) ; delay_50ms (); 时液晶DispOneChar (6, 0, (year/1000)%10+0x30); 年DispOneChar (7,0, (year/100)%10+0x30);DispOneChar(8, 0, (year/10)%10+0x30);DispOneChar(9, 0, (year/l)%10+0x30);DispOneChar (10,0,);DispOneChar (11, 0, moh+0x30); 月
41、DispOneChar(12, 0, mol+0x30);DispOneChar (13, 0,;DispOneChar (14, 0, dh+0x30); 日DispOneChar(15, 0, dl+0x30);)void riqi () 日期选择显示(display(3, dl);delay_50ms();display(2, dh);delay_50ms();display (1, mol) ;delay_50ms ();display(0, moh);delay_50ms();display(5, temp=(year/100)%10);delay_50ms();display(4, temp=(year/1000)%10);delay_50ms();display(6, temp=(year/10)%10);delay_50ms;display(7, temp=(year/1)%10);delay_50ms; void main (void) 主函数LcdReset ();InitO;delay (100);while(1)读键盘Disp-time