與各位分享我的代碼 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)
2020-6-9 18:46 上傳
點擊文件名下載附件
proteus工程文件
|