1 / 44

第 11 章 单片机应用系统设计实例

11.1 单片机电子时钟的设计. B. 11.2 多路数字电压表的设计. A. 第 11 章 单片机应用系统设计实例. 11.1 单片机电子时钟的设计. 通常通过用单片机设计电子时钟有两种方法: 1 、通过单片机内部的定时器 / 计数器。 这种方法硬件线路简单,采用软件编程实现时钟计数,一般称为软时钟。系统的功能一般与软件设计相关,通常用在对时间精度要求不高的场合; 2 、采用时钟芯片。 它的功能强大,功能部件集成在芯片内部,自动产生时钟等相关功能。硬件成本相对较高,软件编程简单。通常用在对时钟精度要求较高的场合。 .

deiondre
Download Presentation

第 11 章 单片机应用系统设计实例

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 11.1 单片机电子时钟的设计 B 11.2 多路数字电压表的设计 A 第11章 单片机应用系统设计实例

  2. 11.1 单片机电子时钟的设计 通常通过用单片机设计电子时钟有两种方法: 1、通过单片机内部的定时器/计数器。这种方法硬件线路简单,采用软件编程实现时钟计数,一般称为软时钟。系统的功能一般与软件设计相关,通常用在对时间精度要求不高的场合; 2、采用时钟芯片。它的功能强大,功能部件集成在芯片内部,自动产生时钟等相关功能。硬件成本相对较高,软件编程简单。通常用在对时钟精度要求较高的场合。 11.1.1 软时钟的基本原理 软时钟是利用单片机内部的定时器/计数器来实现,它的处理过程如下:首先设定单片机内部的一个定时器/计数器工作于定时方式,对机器周期计数形成基准时间(如50ms或10ms),然后用另一个定时器/计数器或软件计数的方法对基准时间计数形成秒(对50ms记数20次或10ms计数100次),秒计60次形成分,分计60次形成小时,小时计24次则计满一天。然后通过数码管把它们的内容在相应位置显示出来即可。

  3. 11.1.2 系统硬件电路的设计 阴极 共阳极 驱动取反 AT89C52

  4. 11.1.3 系统软件程序的设计 电子时钟的软件系统由主程序和子程序组成,主程序程序包含初始化参数设置、按键处理、数码管显示模块等,在设计时各个模块都采用子程序结构设计,在主程序中调用。由于定时器/计数器采用中断方式处理,因此还要编写定时器/中断服务子程序,在定时器/计数器中断服务程序中对时钟进行调整。

  5. 开始 显示单元清零 T0、T1设为16位计数模式 允许T0中断 调用显示子程序 否 按下键否? 是 进入功能程序 一.主程序 主程序执行流程如图,主程序先对显示单元和定时器/计数器初始化,然后重复调用数码管显示模块和按键处理模块,当有键按下,则转入相应的功能程序。

  6. 二.数码管显示模块 本系统共用8个数码管,从右到左依次显示秒个位、秒十位、横线、分个位、分十位、横线、时个位和时十位。数码管显示的信息用8个内存单元存放,这8个内存单元称为显示缓冲区,其中秒个位和秒十位、分个位和分十位、时个位和时十位分别由秒数据、分数据和小时数据分拆得到。在本系统中数码管显示采用软件译码动态显示。在存储器中首先建立一张显示信息的字段码表,显示时,先从显示缓冲区中取出显示的信息,然后通过查表程序在字段码表中查出所显示的信息的字段码,从P0口输出,同时在P2口将对应的位选码输出选中显示的数码管,就能在相应的数码管上显示显示缓冲区的内容。 三.定时器/计数器T0中断服务程序 定时器/计数器T0用于时间计时。选择方式1,重复定时,定时时间设为50ms,定时时间到则中断,在中断服务程序中用一个计数器对50ms计数,计20次则对秒单元加1,秒单元加到60则对分单元加1,同时秒单元清0;分单元加到60则对时单元加1,同时分单元清0;时单元加到24则对时单元清0,标志一天时间计满。在对各单元计数的同时,把它们的值放到存储单元的指定位置。定时器/计数器T0中断服务程序流程图如图。

  7. 开始 现场保护,重置初值 启动下一个50ms 50ms 计数器加1 否 50ms 计数器=20? 是 秒单元加1,50ms计数器清0,秒写入秒个位和秒十位 否 秒单元=60? 是 分单元加1,秒单元清0,分写入分个位和分十位 否 分单元=60? 是 时单元加1,分单元清0,时写入时个位和时十位 否 时单元=24? 时单元清0 是 中断返回 定时器/计数器T0中断服务程序

  8. 四.按键处理模块 按键处理设置为:如没有按键,则时钟正常走时。当按下K0按键时,进入调分状态,时钟停止走动;按K1可K2按键可进行加1或减1操作;继续按K0键可分别进行分和小时的调整;最后按K0键将退出调整状态,时钟开始计时运行。

  9. 五.汇编语言源程序清单 ORG 0000H LJMP START ORG 000BH LJMP INTT0 ;主程序 START: MOV R0,#70H MOV R7,#0CH INIT: MOV @R0,#00H INC R0 DJNZ R7,INIT ;70H-7CH全部清0 MOV TMOD,#01H ;T0工作在方式1 MOV TL0,#0B0H ;T0定时50ms MOV TH0,#3CH SETB EA SETB ET0 SETB TR0 START1: LCALL SCAN ;调用显示子程序 LCALL KEYSCAN ;调用键盘子程序 SJMP START1

  10. ;延时1ms子程序 DL1MS: MOV R6,#14H ;1µs DL1: MOV R7,#19H ;1µs DL2: DJNZ R7,DL2 ;25次×2µs=50µs DJNZ R6,DL1 ;2µs RET ;2µs 1µs+(25次×2µs+3µs)×20次+2µs=1063µs =1.063ms≈1ms ;延时20ms子程序 DL20MS: ACALL SCAN ACALL SCAN ACALL SCAN RET 1T 1T 2T 2T 2T

  11. ;数码管显示程序 SCAN: MOV A,78H ;秒 MOV B,#0AH DIV AB ;A-商,B-余数 MOV 71H,A ;秒十位 MOV 70H,B ;秒个位 MOV A,79H ;分 MOV B,#0AH DIV AB MOV 74H,A MOV 73H,B MOV A,7AH ;时 MOV B,#0AH DIV AB MOV 77H,A MOV 76H,B MOV R1,#70H ;循环扫描8位显示 MOV R5,#0FEH;位选码初值 MOV R6,#08H ;8位显示

  12. SCAN1: MOV A,R5 MOV P2,A MOV A,@R1 MOV DPTR,#TAB MOVC A,@A+DPTR;远程查表 MOV P0,A;段选码 MOV A,R5 LCALL DL1MS INC R1 MOV A,R5 RR A MOV R5,A DJNZ R6,SCAN MOV P2,#0FFH MOV P0,#0FFH RET TAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H, 0F8H,80H,90H,0BFH;“0~9”,“-”的七段共阳极字段码

  13. ;定时器/计数器T0中断服务程序 INTT0: PUSH ACC ;现场保护 PUSH PSW CLR ET0 CLR TR0 MOV TL0,#0B0H ;T0定时50ms MOV TH0,#3CH SETB TR0 INC 7BH ;50ms定时到记数 MOV A,7BH CJNE A,#14H,OUTT0 ;计20次(即1s) MOV 7BH,#00 INC 78H ;秒加1 MOV A,78H CJNE A,#3CH,OUTT0 ;计60s MOV 78H,#00 INC 79H ;分加1 MOV A,79H CJNE A,#3CH,OUTT0 ;不等跳,计60分 MOV 79H,#00 INC 7AH ;时加1 MOV A,7AH CJNE A,#18H,OUTT0 ;计24时 MOV 7AH,#00 OUTT0:SETB ET0 RETI

  14. ;按键处理程序 KEYSCAN: CLR EA JNB P1.0,KEYSCAN0 ;为0跳 JNB P1.1,KEYSCAN1 JNB P1.2,KEYSCAN2 KEYOUT: SETB EA RET KEYSCAN0: LCALL DL20MS ;K0去抖 JB P1.0,KEYOUT ;为1跳 WAIT0: JNB P1.0,WAIT0 ;P1.0=0跳 INC 7CH ;K0松开后7CH加1 CLR ET0 CLR TR0 CJNE A,#03H,KEYOUT ;不等跳 ;K0 按1下或2下返回,按3下7CH清0,不能调秒 MOV 7CH,#00 SETB ET0 SETB TR0 SJMP KEYOUT

  15. KEYSCAN1: LCALL DL20MS ;K1键去抖 JB P1.1,KEYOUT WAIT1: JNB P1.1,WAIT1 ;P1.1=0跳,等待松开K1 MOV A,7CH CJNE A,#02H,KSCAN11;不等跳,K0按2下,调整分 INC 79H ;分加1 MOV A,79H CJNE A,#3CH,KEYOUT ;为60分吗? MOV 79H,#00 SJMP KEYOUT KSCAN11: INC 7AH ;时加1 MOV A,7AH CJNE A,#18H,KEYOUT ;为24时吗? MOV 7AH,#00 SJMP KEYOUT //按1下调时,按2下调分

  16. KEYSCAN2:LCALL DL20MS ;K2去抖 JB P1.2,KEYOUT ;P1.2=1跳 WAIT2: JNB P1.2,WAIT2 ;松开K2 MOV A,7CH CJNE A,#02H,KSCAN21 ;K2按2下吗?按2下调整分 DEC 79H ;分减1 MOV A,79H CJNE A,#0FFH,KEYOUT MOV 79H,#3BH ;计59分 SJMP KEYOUT KSCAN21: DEC 7AH ;时减1 MOV A,7AH CJNE A,#0FFH,KEYOUT MOV 7AH,#17H ;计23时 SJMP KEYOUT END

  17. 六.C语言源程序清单 //采用8位LED软件译码动态显示程序 //使用AT89C51单片机,12MHz晶振,P0口输出字段码,P2口输出位选码,用共阳极LED数码管,key0为调时位选择键,key1为加1键,key2为减1键 #include “reg51.h” #define char unsigned char char code dis_7[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0xb2,0xf8,0x80,0x90,0xff,0xbf};//共阳极LED数码管“0~9”、“灭”和“-”的字段码 char data scan_con[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位选择码 char data dis[8]={0x00,0x00,0x0b,0x00,0x00,0xb0,0x00,0x00};//显示缓冲区,时、分、秒初始为0,0x0b为“-”的编码 char data timedata[3]={0x00,0x00,0x00}; //分别为秒、分和小时的值 char data ms50=0x00,con=0x00,con1=0x00,con2=0x00; //计数次数初值 sbit key0=P1^0; sbit key1=P1^1; sbit key2=P1^2;

  18. while (key1==0); timedata[con]++; if (con==2) con1=24;else con1=60; if (timedata[con]>=con1) {timedata[con]=0;} } } if (con!=0) { if (key2==0) { delay1ms(10); //K2去抖 while (key2==0); timedata[con]--; if (con==2) con2=23;else con2=59; if (timedata[con]<=0) {timedata[con]=con2;} } } EA=1; } • //1ms延时函数 • delay1ms(int t) • { • int i,j; • for (i=0;i<t;i++) • for (j=0;j<120;j++) • ; • } • //按键处理函数 • keyscan( ) //按1下调分,按2下调时 • { • EA=0; • if (key0==0) //按下K0 • { • delay1ms(10); //K0去抖 • while (key0==0) • con++;TR0=0;ET0=0; • if (con>=3) • {con=0;TR0=1;ET0=1;} • } } • if (con!=0) • { if (key1==0) • {delay1ms(10); //K1去抖

  19. //数码管显示函数 • scan( ) • { • char k; • dis[0]=timedata[0]%10;dis[1]=timedata[0]/10; //秒 • dis[3]=timedata[1]%10;dis[4]=timedata[1]/10; //分 • dis[6]=timedata[2]%10;dis[7]=timedata[2]/10; //时 • for (k=0;k<8;k++) • { • P0=dis_7[dis[k]];P2=scan_con[k];delay1ms(1);P2=0xff; • } • }

  20. //定时器、计数器T0中断服务函数 void time_intt0(void) interrupt 1 { ET0=0;TR0=0;TH0=0x3c;TL0=0xb0;TR0=1; ms50++; If (ms50==20) //循环20次,计1s { ms50=0x00;timedata[0]++; //秒+1 if (timedata[0]==60) { timedata[0]=0;timedata[1]++; //分+1 if (timedata[1]==60) { timedata[1]=0;timedata[2]++; //小时+1 if (timedata[2]==24) { timedata[2]=0; } } } } ET0=1; } • //主函数 • main( ) • { • TH0=0x3c;TL0=0xb0; //T0定时50ms • TMOD=0x01;ET0=1;TR0=1;EA=1; • while (1) • { • scan( ); • keyscan( ); • } • }

  21. 11.2 多路数字电压表的设计 11.2.1 多路数字电压表的原理及功能 多路数字式电压表应用系统主要利用A/D转换器,处理过程如下:先用A/D转换器对各路电压值进行采样,得到相应的数字量,再按数字量与模拟量成正比关系运算得到对应的模拟电压值,然后把模拟值通过显示器显示出来。设计时假设待测的输入电压为8路,电压值的范畴为0~5V,要求能在四位LED数码管上轮流显示或单路选择显示。测量的最小分辨率为0.019V,测量误差为0.02V。 根据系统的功能要求,控制系统采用AT89C52单片机,A/D转换器采用ADC0809。ADC0809是8位的A/D转换器。当输入电压为5.00V时,输出的数据值为255(0FFH),因此最大分辨率为0.0196V(5/255)。ADC0809的具有8路模拟量输入端口,通过3位地址输入端能从8路中选择一路进行转换。如每隔一段时间轮流依次改变3位地址输入端的地址,就能依次对8路输入电压进行测量。LED数码管显示采用软件译码动态显示。通过按键选择可8路循环显示,也可单路显示,单路显示可通过按键选择显示的通道数。

  22. 11.2.2 系统硬件电路的设计 共阳极 2MHz 1MHz 2分频

  23. 开始 初始化 调用A/D转换子程序 调用显示子程序 11.2.3 系统软件程序的设计 一.主程序 主程序包含初始化部分、调用A/D转换子程序和调用显示程序,如下图。初始化包含存放通道数据的缓冲区初始化和显示缓冲区初始化。另外,对于单路显示和循环显示,系统设置了一个标志位00H控制,初始化时00H位设置为0,默认为循环显示,当它为1时改变为单路显示控制,00H位通过单路/循环按键控制。

  24. 二.A/D转换子程序 A/D转换子程序用于对ADC0809八路输入模拟电压进行A/D转换,并将转换的数值存入8个相应的存储单元中,如下图。A/D转换子程序每隔一定时间调用一次,也即隔一段时间对输入电压采样一次。 三.显示子程序 LED数码管采样软件译码动态扫描方式。在显示子程序中包含多路循环显示程序和单路显示程序,多路循环显示程序把8个存储单元的数值依次取出送到四个数码管上显示,每一路显示1秒。单路显示程序只对当前选中的一路数据进行显示。每路数据显示时需经过转换变成十进制BCD码,放于四个数码管的显示缓冲区中。单路或循环显示通过标志位00H控制。在显示控制程序中加入了对单路或循环按键和通道选择按键的判断。

  25. 开始 否 是 启动一次转换 A/D转换结束EOC=1? 是 否 取数据(OE=0) 0809通道地址加1 地址数小于8? 返回

  26. 四.汇编语言源程序清单 ;测量电压最大值为5V,显示最大值为5.00V ;使用AT89C52单片机,12MHz晶振,P0口读入A/D值,P2口为A/D转换控制口 ;数码管为共阳极连接,P1口为字段码口,P3口为位选口 ;P3.5为单路/循环显示转换按键,P3.6为单路显示时当前通道选择按键 ;70H-77H存放采样的8个数据,78H-7BH为显示缓冲区,分别为个位、十位、百位和当前通道值 ;00H位为单路/循环显示控制位,当为0时循环显示,为1时单路显示

  27. ;主程序入口 • ORG 0000H • LJMP START • ;主程序 • START: CLR A • MOV P2,A • MOV R0,#70H • MOV R2,#0DH • LOOPMEM: MOV @R0,A • INC R0 • DJNZ R2,LOOPMEM • MOV 20H,#00H ;00H位在20H字节中 • MOV A,#0FFH • MOV P0,A ;数据口 • MOV P1,A ;段码口 • MOV P3,A ;字位口 • MAIN: LCALL TEST ;调用A/D转换程序 • LCALL DISPLAY ;调用显示程序

  28. ;显示子程序 DISPLAY: JB 00H,DISP11 ;为1跳DISP11 MOV R3,#08H ;00H位=0循环显示 MOV R0,#70H ;首地址 MOV 7BH,#00H ;选中0通道 DISLOOP1: LCALL TUNBCD MOV R2,#0FFH DISLOOP2: LCALL DISP LCALL KEYWORK1 DJNZ R2,DISLOOP2 ;延时 INC R0 INC 7BH ;循环选中8通道 DJNZ R3,DISLOOP1 RET

  29. DISP11: MOV A,7BH ;00H位=1跳来,实现单路显示 SUBB A,#01H MOV 7BH,A ADD A,#70H MOV R0,A DISLOOP11: LCALL TUNBCD MOV R2, #0FFH DISLOOP22: LCALL DISP LCALL KEYWORK2 DJNZ R2,DISLOOP22 ;延时 INC 7BH ;通道号加1 RET

  30. ;显示数据转换为3位BCD码子程序 TUNBCD: MOV A,@R0 MOV B,#51 DIV AB ;A-商,B-余数 MOV 7AH, A ;7AH-百位 MOV A,B ;A-余数 CLR F0 SUBB A,#1AH MOV F0,C ;余数≥26,F0=C=0;余数<26,F0=C=1 MOV A,#10 MUL AB ;B-余数,余数×10=BA MOV B,#51 DIV AB ;低字节/51 JB F0,LOOP2 ;F0=1跳(余数<26) ADD A,#5 LOOP2: MOV 79H,A ;79H-十位 MOV A,B ;余数处理 CLR F0 SUBB A,#1AH MOV F0,C MOV A,#10 MUL AB MOV B,#51 DIV AB JB F0,LOOP3 ADD A,#5 LOOP3: MOV 78H,A ;78H-个位 RET

  31. ;LED扫描显示子程序 DISP: MOV R1,#78H ;个位显示 MOV R5,#0FEH ;位选初值(显示个位) PLAY: MOV P1,#0FFH MOV A,R5 ANL P3,A MOV A,@R1 MOV DPTR,#TAB MOVC A,@A+DPTR;远程查表 MOV P1,A ;输出字段口 JB P3.2,PLAY1 ;为1跳(整数位不亮) CLR P1.7 ;点亮小数点

  32. PLAY1: LCALL DL1MS INC R1 ;十位显示 MOV A,P3 JNB ACC.3,ENDOUT ;通道号位为0跳 RL A MOV R5,A MOV P3,#0FFH ENDOUT: MOV P3,#0FFH MOV P1,#0FFH RET TAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H, 82H,F8H,80H,90H,0FFH ;共阳极七段字段码表

  33. ;延时子程序 DL10MS: MOV R6,#0D0H ;1µs DL1: MOV R7,#10H ;12µs DL2: DJNZ R7,DL2 ;16次×2µs=32µs DJNZ R6,DL1 ;2µs RET ;2µs DL1MS: MOV R4,#0FFH ;1µs DL3: DJNZ R4,DL3 ;255次×2µs=510µs MOV R4,0FFH ;1µs DL4: DJNZ R4,DL4 ;510µs RET ;2µs 1T 1T 2T 2T 2T 1T 2T 1T 2T 2T

  34. ;A/D转换子程序 TEST: CLR A MOV P2,A MOV R0,#70H ;通道号地址 MOV R7,#08H ;8个通道 LCALL TESTART WAIT: JB P3.7,MOVD ;EOC=P3.7=1跳 AJMP WAIT TESTART:SETB P2.3 ;ALE=1 NOP NOP CLR P2.3 SETB P2.4 ;START=1 NOP NOP CLR P2.4 NOP NOP NOP NOP RET MOVD: SETB P2.5 ;OE=1 MOV A,P0 MOV @R0,A CLR P2.5 INC R0 ;指向下一通道 MOV A,P2 INC A ;地址加1 MOV P2,A CJNE A,#08H,TESTEND TESTEND: JC TESTCON ;C=1跳 CLR A MOV P2,A MOV A,#0FFH MOV P0,A MOV P1,A MOV P2,A RET TESTCON: LCALL TESTART LJMP WAIT 读取结果 查询方式 启动转换

  35. ;按键检测子程序 KEYWORK1: JNB P3.5,KEY1 ;K1=P3.5=0跳KEY1 KEYOUT: RET KEY1: LCALL DISP ;按下K1后调用显示程序 JB P3.5,KEYOUT ;K1=1跳(松开) WAIT11: JNB P3.5,WAIT12 ;K1=0跳 CPL 00H ;K1松开后切换显示方式 MOV R2,#0AH MOV R3,#01H RET WAIT12: LCALL DISP ;按K1后调用显示 AJMP WAIT11

  36. KEYWORK2: JNB P3.5,KEY1 ;按K1后跳 JNB P3.6,KEY2 ;K2=0跳KEY2 RET KEY2: LCALL DISP ;刷新显示 JB P3.6,KEYOUT ;K2=1跳KEYOUT WAIT22: JNB P3.6,WAIT21 ;K2=0跳WAIT21 INC 7BH ;K2=1,通道号+1 MOV A,7BH CJNE A,#08H,KEYOUT11 KEYOUT11: JC KEYOUT1 ;C=1跳KEYOUT1 MOV 7BH,#00H ;通道号≥8,7BH清0 KEYOUT1: RET WAIT21: LCALL DISP ;刷新显示 AJMP WAIT22 END

  37. 五.C语言源程序清单 //测量电压最大值为5V,显示最大值为5.00V //使用AT89C52单片机,12MHz晶振,P0口读入A/D值,P2口为A/D转换控制口 //数码管为共阳极连接,P1口为字段码口,P3口为位选口 //KEY1(P3.5)为单路/循环显示转换按键 //KEY2(P3.6)为单路显示时当前通道选择按键 //FLAG为单路/循环显示控制位,当为0时循环显示,为1时单路显示

  38. #include “reg52.h” #include “intrins.h” //调用_nop_( )延时函数 #define ad_con P2 //ADC0809的控制口 #define addata P0 //ADC0809的数据口 #define disdata P1 //数码管的字段码输出口 #define uchar unsigned char #define uint unsigned int uchar number=0x00; //存放单通道显示时的当前通道数 sbit ALE=P2^3; //ADC0809的地址锁存信号 sbit START=P2^4; //ADC0809的启动信号 sbit OE=P2^5; //ADC0809的允许信号 sbit EOC=P3^7; //ADC0809的转换结束信号 sbit KEY1=P3^5; //循环或单路显示选择按键 sbit KEY2=P3^6; //通道选择按键 sbit DISX=disdata^7; //小数点位 sbit FLAG=PSW^0; //循环或单路显示标志位

  39. uchar code dis_7[11]={0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9}; //LED的七段数码管的字段码(0-9,灭) uchar code scan_con[4]={0xfe0,0xfd,0xfb,0xf7}; //LED数码管的位选码 uchar data ad_data[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //ADC0809的8个通道转换数据缓冲区 uint data dis[5]={0x00,0x00,0x00,0x00,0x00}; //前4个为LED数码管的显示缓冲区,最后一个为暂存单元 //1ms延时子函数 delay1ms(unit t) { uint i,j; for(i=0;i<t;i++) for(j=0;j<120;j++) ; }

  40. //检测按键子函数 keytest( ) { if(KEY1==0) //检测循环或单路选择按键是否按下? {FLAG=!FLAG; //标志位取反,循环、单路显示间切换 while(KEY1==0); } if(FLAG==1) //单路显示方式,检测通道选择按键是否按下? {if(KEY2==0) { number++; //通道数+1 if(number==8) {number=0;} while(KEY2==0) ; } } }

  41. //显示扫描子函数 scan( ) { uchar k,n; int h; if(FLAG==0) //循环显示子程序 { dis[3]=0x00; //通道值清0 for(n=0;n<8;n++) //8路通道 { dis[2]=ad_data[n]/51; //当前通道数据转换为BCD码存入显示缓冲区 dis[4]=ad_data[n]%51; //余数(电压小数位)送暂存单元 dis[4]=dis[4]*10; //余数×10 dis[1]= dis[4]/51; //再除以51,结果取整送十位 dis[4]= dis[4]%51; //结果取余送暂存单元 dis[4]= dis[4]*10; //余数×10 dis[0]= dis[4]/51; //再除以51,结果取整送个位 for(h=0;h<500;h++) //每个通道显示1s {for(k=0;k<4;k++) //4位LED扫描显示 {disdata=dis_7[dis[k]]; if(k==2) {DISX=0;} //点亮小数点 P3=scan_con[k]; delay1ms(1);P3=0xff; } }

  42. dis[3]++; //通道值加1 keytest( ); //按键检测 } } if(FLAG==1) //单路显示子程序 { dis[3]=number; //当前通道数送通道显示 for(k=0;k<4;k++) {disdata=dis_7[dis[k]]; if(k==2) DISX=0; P3=scan_con[k]; delay1ms(1);P3=0xff; } keytest( ); //检测按键 }

  43. //ADC0809转换子函数 test( ) { uchar m; uchar s=0x00; //初始通道为0 ad_con=s; //第一通道地址送ADC0809控制口 for(m=0;m<8;m++) {ALE=1;_nop_();_nop_(); ALE=0; //锁存通道地址 START=1;_nop_();_nop_(); START=0; //启动转换 _nop_();_nop_() ;_nop_();_nop_(); while(EOC==0); //等待转换结束 OE=1;ad_data[m]=addata;OE=0; //读取当前通道转换0数据 s++;ad_con=s; //改变通道地址 } ad_con=0x00; //通道地址恢复初值 }

  44. //主函数 main( ) { P0=0xff; //初始化端口 P2=0x00; P1=0xff; //初始化为0通道 P3=0xff; while(1) {test( ); //测量转换数据 scan( ); //显示数据 } }

More Related