440 likes | 645 Views
11.1 单片机电子时钟的设计. B. 11.2 多路数字电压表的设计. A. 第 11 章 单片机应用系统设计实例. 11.1 单片机电子时钟的设计. 通常通过用单片机设计电子时钟有两种方法: 1 、通过单片机内部的定时器 / 计数器。 这种方法硬件线路简单,采用软件编程实现时钟计数,一般称为软时钟。系统的功能一般与软件设计相关,通常用在对时间精度要求不高的场合; 2 、采用时钟芯片。 它的功能强大,功能部件集成在芯片内部,自动产生时钟等相关功能。硬件成本相对较高,软件编程简单。通常用在对时钟精度要求较高的场合。 .
E N D
11.1 单片机电子时钟的设计 B 11.2 多路数字电压表的设计 A 第11章 单片机应用系统设计实例
11.1 单片机电子时钟的设计 通常通过用单片机设计电子时钟有两种方法: 1、通过单片机内部的定时器/计数器。这种方法硬件线路简单,采用软件编程实现时钟计数,一般称为软时钟。系统的功能一般与软件设计相关,通常用在对时间精度要求不高的场合; 2、采用时钟芯片。它的功能强大,功能部件集成在芯片内部,自动产生时钟等相关功能。硬件成本相对较高,软件编程简单。通常用在对时钟精度要求较高的场合。 11.1.1 软时钟的基本原理 软时钟是利用单片机内部的定时器/计数器来实现,它的处理过程如下:首先设定单片机内部的一个定时器/计数器工作于定时方式,对机器周期计数形成基准时间(如50ms或10ms),然后用另一个定时器/计数器或软件计数的方法对基准时间计数形成秒(对50ms记数20次或10ms计数100次),秒计60次形成分,分计60次形成小时,小时计24次则计满一天。然后通过数码管把它们的内容在相应位置显示出来即可。
11.1.2 系统硬件电路的设计 阴极 共阳极 驱动取反 AT89C52
11.1.3 系统软件程序的设计 电子时钟的软件系统由主程序和子程序组成,主程序程序包含初始化参数设置、按键处理、数码管显示模块等,在设计时各个模块都采用子程序结构设计,在主程序中调用。由于定时器/计数器采用中断方式处理,因此还要编写定时器/中断服务子程序,在定时器/计数器中断服务程序中对时钟进行调整。
开始 显示单元清零 T0、T1设为16位计数模式 允许T0中断 调用显示子程序 否 按下键否? 是 进入功能程序 一.主程序 主程序执行流程如图,主程序先对显示单元和定时器/计数器初始化,然后重复调用数码管显示模块和按键处理模块,当有键按下,则转入相应的功能程序。
二.数码管显示模块 本系统共用8个数码管,从右到左依次显示秒个位、秒十位、横线、分个位、分十位、横线、时个位和时十位。数码管显示的信息用8个内存单元存放,这8个内存单元称为显示缓冲区,其中秒个位和秒十位、分个位和分十位、时个位和时十位分别由秒数据、分数据和小时数据分拆得到。在本系统中数码管显示采用软件译码动态显示。在存储器中首先建立一张显示信息的字段码表,显示时,先从显示缓冲区中取出显示的信息,然后通过查表程序在字段码表中查出所显示的信息的字段码,从P0口输出,同时在P2口将对应的位选码输出选中显示的数码管,就能在相应的数码管上显示显示缓冲区的内容。 三.定时器/计数器T0中断服务程序 定时器/计数器T0用于时间计时。选择方式1,重复定时,定时时间设为50ms,定时时间到则中断,在中断服务程序中用一个计数器对50ms计数,计20次则对秒单元加1,秒单元加到60则对分单元加1,同时秒单元清0;分单元加到60则对时单元加1,同时分单元清0;时单元加到24则对时单元清0,标志一天时间计满。在对各单元计数的同时,把它们的值放到存储单元的指定位置。定时器/计数器T0中断服务程序流程图如图。
开始 现场保护,重置初值 启动下一个50ms 50ms 计数器加1 否 50ms 计数器=20? 是 秒单元加1,50ms计数器清0,秒写入秒个位和秒十位 否 秒单元=60? 是 分单元加1,秒单元清0,分写入分个位和分十位 否 分单元=60? 是 时单元加1,分单元清0,时写入时个位和时十位 否 时单元=24? 时单元清0 是 中断返回 定时器/计数器T0中断服务程序
四.按键处理模块 按键处理设置为:如没有按键,则时钟正常走时。当按下K0按键时,进入调分状态,时钟停止走动;按K1可K2按键可进行加1或减1操作;继续按K0键可分别进行分和小时的调整;最后按K0键将退出调整状态,时钟开始计时运行。
五.汇编语言源程序清单 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
;延时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
;数码管显示程序 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位显示
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”,“-”的七段共阳极字段码
;定时器/计数器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
;按键处理程序 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
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下调分
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
六.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;
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去抖
//数码管显示函数 • 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; • } • }
//定时器、计数器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( ); • } • }
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路循环显示,也可单路显示,单路显示可通过按键选择显示的通道数。
11.2.2 系统硬件电路的设计 共阳极 2MHz 1MHz 2分频
开始 初始化 调用A/D转换子程序 调用显示子程序 11.2.3 系统软件程序的设计 一.主程序 主程序包含初始化部分、调用A/D转换子程序和调用显示程序,如下图。初始化包含存放通道数据的缓冲区初始化和显示缓冲区初始化。另外,对于单路显示和循环显示,系统设置了一个标志位00H控制,初始化时00H位设置为0,默认为循环显示,当它为1时改变为单路显示控制,00H位通过单路/循环按键控制。
二.A/D转换子程序 A/D转换子程序用于对ADC0809八路输入模拟电压进行A/D转换,并将转换的数值存入8个相应的存储单元中,如下图。A/D转换子程序每隔一定时间调用一次,也即隔一段时间对输入电压采样一次。 三.显示子程序 LED数码管采样软件译码动态扫描方式。在显示子程序中包含多路循环显示程序和单路显示程序,多路循环显示程序把8个存储单元的数值依次取出送到四个数码管上显示,每一路显示1秒。单路显示程序只对当前选中的一路数据进行显示。每路数据显示时需经过转换变成十进制BCD码,放于四个数码管的显示缓冲区中。单路或循环显示通过标志位00H控制。在显示控制程序中加入了对单路或循环按键和通道选择按键的判断。
开始 否 是 启动一次转换 A/D转换结束EOC=1? 是 否 取数据(OE=0) 0809通道地址加1 地址数小于8? 返回
四.汇编语言源程序清单 ;测量电压最大值为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时单路显示
;主程序入口 • 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 ;调用显示程序
;显示子程序 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
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
;显示数据转换为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
;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 ;点亮小数点
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 ;共阳极七段字段码表
;延时子程序 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
;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 读取结果 查询方式 启动转换
;按键检测子程序 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
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
五.C语言源程序清单 //测量电压最大值为5V,显示最大值为5.00V //使用AT89C52单片机,12MHz晶振,P0口读入A/D值,P2口为A/D转换控制口 //数码管为共阳极连接,P1口为字段码口,P3口为位选口 //KEY1(P3.5)为单路/循环显示转换按键 //KEY2(P3.6)为单路显示时当前通道选择按键 //FLAG为单路/循环显示控制位,当为0时循环显示,为1时单路显示
#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; //循环或单路显示标志位
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++) ; }
//检测按键子函数 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) ; } } }
//显示扫描子函数 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; } }
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( ); //检测按键 }
//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; //通道地址恢复初值 }
//主函数 main( ) { P0=0xff; //初始化端口 P2=0x00; P1=0xff; //初始化为0通道 P3=0xff; while(1) {test( ); //测量转换数据 scan( ); //显示数据 } }