与各位分享我的代码 1.系统功能 1.1可测0~5V的8路输入电压值; 1.2在LED数码管上轮流显示; 1.3单路选择显示; 2.系统硬件设计 2.1 单片机采用PIC16F877 2.2 键盘为4×4行列式键盘,按键设有10个数字键0……9,和5个功能键依次是:各通道轮流显示键、单通道显示键、向左滚动显示键、显示启动/停止键、回车键。 2.3有3位LED管,左边1位用于指示显示通道,右边2位显示电压值,保留到小数点后面1位。 3系统软件设计 3.1键盘管理程序(包括键扫描、键处理程序); 3.2LED动态显示程序; 3.3各通道轮流显示,共显示8个通道,每通道显示1s; 3.4 单通道显示,仅显示指定通道电压,并保持到其他功能键按下。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- //作者:云树阿云
- #include <htc.h>
- #include <pic.h>
- #define uchar unsigned char
- #define uint unsigned int
- __CONFIG(0x3b32);//状态字
- uchar table[]={0x00,0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};//数码管显示字符表
- uchar channel[]={0x41,0x49,0x51,0x59,0x61,0x69,0x71,0x79};//代表8个通道被按下的状态表
- uchar key_num;//按键标志位
- uchar disp_num;//通道标志位
- uchar left_num;
- uchar loop_num;
- uint volval=0;//电压值
- uint enter=0;//回车被按下标志位
- uint on_off=0;//开机标志位
- uint loop_disp=0;//循环显示标志位
- uint single_disp=0;//单通道显示标志位
- uint left_move=0;//左移显示标志位
- uint a;//用于显示的换算位
- uint b;//用于显示的换算位
- uint c;//用于显示的换算位
- uint d;//用于左移显示的转移中间值
- uchar e=2;
- uchar onkey_num;
- void delay(uint x)//延时程序
- {uint times,num;
- for(times=x;times>0;times--)
- for(num=110;num>0;num--);
- }
- void display(uint i,uint j)//显示程序
- {
- a=i/10;//通过电压值和通道值算出需要显示的值
- b=i-a*10;//通过电压值和通道值算出需要显示的值
- a=a+10;//为电压第一位加上小数点
- c=j;
- if(enter==0)
- {a=-1;
- b=-1;
- //c=-1;
- }
- TRISD=0x00;//设置输出端口
- TRISB=0x00;//设置输出端口
- delay(1);//延时
- RB0=0;//选择需要亮起的数码管
- RB1=1;
- RB2=1;
- PORTD=table[c+1];//输出需要显示的数字
- delay(1);//延时
- RB0=1;//选择需要亮起的数码管
- RB1=0;
- RB2=1;
- PORTD=table[a+1];
- delay(1);//延时
- RB0=1;//选择需要亮起的数码管
- RB1=1;
- RB2=0;
- PORTD=table[b+1];//输出需要显示的数字
- }
- void getab(uint i,uint j)//左移显示时获得当前的a,b,c值
- { a=i/10;
- b=i-a*10;
- a=a+10;
- c=j;
- }
-
- void leftdisplay()//左移显示模式的显示程序,类似显示程序
- {
- TRISD=0x00;
- TRISB=0x00;
- delay(1);
- RB0=0;
- RB1=1;
- RB2=1;
- PORTD=table[c+1];
- delay(1);
- RB0=1;
- RB1=0;
- RB2=1;
- PORTD=table[a+1];
- delay(1);
- RB0=1;
- RB1=1;
- RB2=0;
- PORTD=table[b+1];
- }
-
- void leftmove()//实现左移显示的程序(交换abc)
-
- { if(left_num==8)
- {
- left_num=0;
- ADCON0=channel[0];
- uint adval;
- GO=1;
- while(GO)
- adval=ADRESH;
- adval=adval<<8|ADRESL;
- volval=adval/20;
- a=-1;
- b=volval/10;
- b=b+10;
- c=left_num;
- }
- else{
- //disp_num++;
- ADCON0=channel[left_num];
-
- uint adval;
- GO=1;
- while(GO)
- adval=ADRESH;
- adval=adval<<8|ADRESL;
- volval=adval/20;
- a=-1;
- b=volval/10;
- b=b+10;
- c=left_num;
- }
- }
- void scan()//扫描程序获得key_num
- { TRISC=0xf0;//C端口高四位输出,低四位输入
- PORTC=0xfe;//首先扫描第一列
- key_num=PORTC;//读取C端口低四位,获得key_num
- key_num=key_num&0xf0;//判断低四位是否有1存在
- if (key_num!=0xf0)//如果低四位有1(第一行有键被按下)
- { delay(10);//去抖动
- key_num=PORTC;//重新读取
- key_num=key_num&0xf0;//得到低四位中为1的位,其他位置0
- if (key_num!=0xf0)
- {
- key_num=key_num|0x0e;//加上高四位中被扫描的值,获得代表被按下键的值:key_num
- }
- }
- else//其他列依次判断
- {
- PORTC=0xfd;
- key_num=PORTC;
- key_num=key_num&0xf0;
- if (key_num!=0xf0)
- { delay(10);
- key_num=PORTC;
- key_num=key_num&0xf0;
- if (key_num!=0xf0)
- {
- key_num=key_num|0x0d;
- }
- }
- else
- {
- PORTC=0xfb;
- key_num=PORTC;
- key_num=key_num&0xf0;
- if (key_num!=0xf0)
- { delay(10);
- key_num=PORTC;
- key_num=key_num&0xf0;
- if (key_num!=0xf0)
- {
- key_num=key_num|0x0b;
- }
- }
- else
- {
- PORTC=0xf7;
- key_num=PORTC;
- key_num=key_num&0xf0;
- if (key_num!=0xf0)
- { delay(10);
- key_num=PORTC;
- key_num=key_num&0xf0;
- if (key_num!=0xf0)
- {
- key_num=key_num|0x07;
- }
- }
- }
- }
- }
- }
- void switched()//根据key_num改变相应标志位
- {
- switch(key_num)
- {case 0xee:disp_num=7;enter=0;break;//通道选择
- case 0xed:disp_num=4;enter=0;break;//通道选择
- case 0xeb:disp_num=1;enter=0;break;//通道选择
- case 0xe7:if(onkey_num!=key_num){on_off=!on_off;enter=0;}break;
- //on_off=1; break;//开机
- //case 0xde:disp_num=7;enter=0;break;//通道选择
- case 0xdd:disp_num=5;enter=0;break;//通道选择
- case 0xdb:disp_num=2;enter=0;break;//通道选择
- case 0xd7:disp_num=0;enter=0;break;//通道选择
- //case 0xbe:disp_num=7;enter=0;break;//通道选择
- case 0xbd:disp_num=6;enter=0;break;//通道选择
- case 0xbb:disp_num=3;enter=0;break;//通道选择
- case 0xb7:enter=1;break;//回车键
- case 0x7e:loop_disp=1;single_disp=0;left_move=0;enter=0;break;//循环显示功能
- case 0x7d:loop_disp=0;single_disp=1;left_move=0;enter=0;break;//单通道显示功能
- case 0x7b:loop_disp=0;single_disp=0;left_move=1;enter=0;break;//左移显示功能
- //case 0x77:on_off=0;break;//关机
- }
- }
- void measure()//AD转化程序&完成相应功能
- {
- TRISA=0xff;
- ADCON0=channel[disp_num];
- ADCON1=0x80;
- if(enter==1&&single_disp==1)
- {
- uint adval;
- GO=1;
- while(GO)
- adval=ADRESH;
- adval=adval<<8|ADRESL;
- volval=adval/20;
- onkey_num=key_num;
- scan();
- switched();
- display(volval,disp_num);
- }
- //display(99,disp_num);
- while(enter==1&&left_move==1&&on_off==1)
- {left_num=disp_num;
- while(left_move==1&&on_off==1&&left_num!=8)
- {onkey_num=key_num;
- scan();
- switched();
- //
- ADCON0=channel[left_num];
- uint adval;
- GO=1;
- while(GO)
- adval=ADRESH;
- adval=adval<<8|ADRESL;
- volval=adval/20;
- getab(volval,left_num);
- while(e!=0)
- {
- uint disp_times=650;
- while(disp_times!=0&&left_move==1)
- {onkey_num=key_num;
- scan();
- switched();
- //left_num=disp_num;
- leftdisplay();
- disp_times--;
- }
- e--;
- if(e==1)
- {
- left_num++;
- leftmove();
- }
- }
- e=2;
- }
- left_num=0;
- }
-
-
- if(enter==1&&loop_disp==1&&on_off==1)
- {loop_num=disp_num;
- while(loop_disp==1&&on_off==1)
- {
- while(loop_num!=8&&loop_disp==1&&on_off==1)
- {
- uint disp_times=525;//循环次数,完成该次数后刚好显示了一秒钟
- while(disp_times!=0&&loop_disp==1&&on_off==1)//循环显示程序
- {onkey_num=key_num;
- scan();//扫描
- switched();//改变状态字
- ADCON0=channel[loop_num];//AD转换
- uint adval;
- GO=1;
- while(GO)
- adval=ADRESH;
- adval=adval<<8|ADRESL;
- volval=adval/20;
- //getab(volval,loop_num);
- //leftdisplay;
- display(volval,loop_num);//显示
- disp_times--;//循环次数自减
- }
- loop_num++;//显示了1秒钟后,通道号加一
- }
- loop_num=0;//disp_num等于8的时候置0
- }
- }
- while(enter==0&&(loop_disp==1||left_move==1))
- {onkey_num=key_num;
- scan();//扫描
- switched();//改变状态字
- display(0,-1);
- }
- }
- void main()//主程序
- {
- while(1)
- { onkey_num=key_num;
- scan();
- switched();
- //display(volval,disp_num);
- while(on_off==1)
- {onkey_num=key_num;
- scan();
- switched();
- //left_num=disp_num;
- measure();
- display(volval,disp_num);
- }
- c=-1;
- a=-1;
- b=-1;
- leftdisplay();
- }
- }
复制代码
全部资料51hei下载地址:
电压表备份 试验品.rar
(35.2 KB, 下载次数: 156)
|