有木有哪個大佬指導(dǎo)我修改�。�!
(1)輸出電流范圍:200mA~2000mA; (2)可設(shè)置并顯示輸出電流給定值,要求輸出電流與給定值偏差的絕對值≤給定值的1%+10 mA; (3)具有“+”、“-”步進(jìn)調(diào)整功能,步進(jìn)≤10mA; (4)改變負(fù)載電阻,輸出電壓在10V以內(nèi)變化時,要求輸出電流變化的絕對值≤輸出電流值的1%+10 mA; (5)輸出電流范圍為20mA~2000mA,步進(jìn)1mA; (6)設(shè)計、制作測量并顯示輸出電流的裝置 (可同時或交替顯示電流的給定值和實測值),測量誤差的絕對值≤測量值的0.1%+3個字; (7)改變負(fù)載電阻,輸出電壓在10V以內(nèi)變化時,要求輸出電流變化的絕對值≤輸出電流值的0.1%+1 mA; (8)另附:源程序 附錄2程序清單;************************************************************ ;****;在本次課程設(shè)計的程序中,我用到的是液晶顯示器,其使能*** ;****;端接單片機的P3.0,P3.1,P3.2引腳,用到了DA轉(zhuǎn)換等需要 *** ;****;的暫存單元分別為30H到35H,其中還有一些必要的標(biāo)志位存*** ;****;在在36H到4AH單元。按鍵接單片機的P2.0到P2.7,液晶顯示*** ;****;顯示器數(shù)據(jù)口接單片機的P0.0到P0.7,本數(shù)控直流電流源有加 *** ;****;減調(diào)整,采用閉環(huán)控制系統(tǒng)進(jìn)行調(diào)整,精確度更高。 *** ;************************************************************ #include<reg52.h> #define uchar unsigned char #define uint unsigned int
sbit rs=P3^0; sbit rw=P3^1; sbit lcden=P3^2; //液晶顯示屏相關(guān)位定義 sbit AD_OUT=P1^0; sbit AD_IN=P1^1; sbit AD_CS=P1^2; sbit AD_CLOCK=P1^3; sbit DA_IN=P3^3; sbit DA_CK=P3^4; sbit DA_CS=P3^5; sbit x=P1^4; uchar code table1[]="Are you sure "; uchar code table2[]=" to set I? "; uchar code table3[]=" ERROR!RESET! "; unsigned long int temp0,temp1; uint ADCdat,i,AD_DAstart; float Voltage1,Voltage2,r; int vol,rtt; uchar set,volarry0[4],volarry1[4],rt[2]; char iset[5]={0,0,2,0,0,};
void led_init(); //函數(shù)聲明 void delayms(uint z); void delay(uint t); void write_com(uchar com); void write_date(uchar date); void display_AD(); uint read2543(uchar port); void Send1456(uint DACdat); void keyscan(); ;************************************************************ ;****; 主程序 **** ;************************************************************ main() { led_init(); i=20; display_AD(); Send1456(20); while(1) { keyscan(); if(AD_DAstart==1) { display_AD(); Send1456(iset[1]*1000+iset[2]*100+iset[3]*10+iset[4]); } } } void delayms(uint z) //延時函數(shù),參數(shù)為z { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); //z=1測試為大約1微秒 } void delay(uint t) //極短延時 { while(t--); } void write_com(uchar com) //寫命令函數(shù) { rs=0; //rs置0表示寫命令 lcden=0; //按時序圖置低 P0=com; //位聲明,按原理圖接P0口,輸入數(shù)據(jù) lcden=1; //置高 delayms(5); //時序圖中須有thd2時間延時 lcden=0; //按時序圖置低 } void write_date(uchar date) //寫數(shù)據(jù)函數(shù) { rs=1; //rs置1表示寫數(shù)據(jù) lcden=0; P0=date; //將數(shù)據(jù)賦到P0口 delayms(5); lcden=1; delayms(5); lcden=0; } void led_init() //初始化函數(shù) { lcden=0; rw=0; write_com(0x38); //顯示模式設(shè)置:16X2顯示,5X7點陣,8位數(shù)據(jù) write_com(0x0c); // 開顯示,關(guān)光標(biāo),光標(biāo)不閃爍 write_com(0x06); // 寫一個數(shù)據(jù)后地址指針加一,光標(biāo)加一 write_com(0x01); // 數(shù)據(jù)指針及數(shù)據(jù)清0 write_com(0x80); // 設(shè)置數(shù)據(jù)地址指針,第一行 write_com(0x80+5); write_date(0x6d); write_date(0x41); write_com(0x80); write_date(0x53); write_date(0x30+iset[1]); write_date(0x30+iset[2]); write_date(0x30+iset[3]); write_date(0x30+iset[4]); } ;************************************************************ ;****; A/D轉(zhuǎn)換子程序 **** ;************************************************************ void display_AD() { uchar num; temp0+= read2543(0x00); //進(jìn)行AD轉(zhuǎn)換 temp1+= read2543(0x01); i--; //取20次AD轉(zhuǎn)換的結(jié)果,求平均值 if(i==0) { ADCdat=temp1/20; temp1=0; Voltage2=(ADCdat*5.0)/4096; //基準(zhǔn)電壓為5.0V vol=(int)((Voltage2*4)*1000);// 擴大1000倍 volarry1[3]=vol/1000; volarry1[2]=vol%1000/100; volarry1[1]=vol%100/10; volarry1[0]=vol%10; ADCdat=temp0/20; temp0=0; i=20; Voltage1=(ADCdat*5.0)/4096; //基準(zhǔn)電壓為5.0V vol=(int)(Voltage1*1000+1);// 擴大1000倍 volarry0[3]=vol/1000; volarry0[2]=vol%1000/100; volarry0[1]=vol%100/10; volarry0[0]=vol%10; write_com(0x80+0x40); write_date(0x54); write_date(0x30+volarry0[3]); write_date(0x30+volarry0[2]); write_date(0x30+volarry0[1]); write_date(0x30+volarry0[0]); write_date(0x6d); write_date(0x41); if(vol>2000||vol<200||volarry1[3]>10||volarry1[3]==10) { write_com(0x01); // 數(shù)據(jù)指針及數(shù)據(jù)清0 write_com(0x80); // 設(shè)置數(shù)據(jù)地址指針,第一行 for(num=0;num<16;num++) { write_date(table3[num]); delayms(1); //循環(huán)方式寫第一行數(shù)據(jù) } set=1; AD_DAstart=0; } else { write_com(0x80+0x40+13); write_date(0x4f); write_date(0x4b); write_date(0x21); write_com(0x80+9); write_date(0x30+volarry1[3]); write_date(0x2e); write_date(0x30+volarry1[2]); write_date(0x30+volarry1[1]); write_date(0x30+volarry1[0]); write_date(0x56); r=Voltage2*4/Voltage1; rtt=(int)(r*10); rt[1]=rtt/10; rt[0]=rtt%10; write_com(0x80+0x49); write_date(0x30+rt[1]); write_date(0x52); write_date(0x30+rt[0]); } } } ;************************************************************ ;****; D/A轉(zhuǎn)換子程序 **** ;************************************************************ uint read2543(uchar port) //DA轉(zhuǎn)換子程序 { uint ad=0,j; AD_CLOCK=0; AD_CS=0; port<<=4; delay(50); for(j=0;j<12;j++) { if(AD_OUT) { ad=0x01; } AD_IN=(bit)(port&0x80); AD_CLOCK=1; delay(6); AD_CLOCK=0; delay(3); port<<=1; ad<<=1; } AD_CS=1; ad>>=1; return(ad); } void Send1456(uint DACdat) { uchar i=0; DA_CK=0; delay(2); DA_CS=0; delay(2); for(i=0;i<12;i++) { DA_IN=(bit)(DACdat&0x800); DA_CK=1; DACdat<<=1; DA_CK=0; } DA_CS=1; DA_CS=0; } ;************************************************************ ;****; 按鍵鍵掃子程序 **** ;************************************************************ void keyscan() //矩陣鍵盤 { uchar temp,keycount,num; // 定義局部變量 P2=0xfe; // 檢測最上面一行各鍵是否有按鍵按下 temp=P2; // 將P2口的值賦給temp temp=temp&0xf0; // 位與 if(temp!=0xf0) { delayms(100); temp=P2; temp=temp&0xf0; if(temp!=0xf0) //確認(rèn)被按下,防止抖動 { temp=P2; switch(temp) { case 0xee: //檢測到7被按下 if(keycount!=0) { write_date(0x30+7); iset[keycount++]=7; } break; case 0xde: //檢測到8被按下 if(keycount!=0) { write_date(0x30+8); iset[keycount++]=8; } break; case 0xbe: //檢測到9被按下 if(keycount!=0) { write_date(0x30+9); iset[keycount++]=9; } break; case 0x7e: //檢測到取消鍵被按下 write_com(0x01); // 數(shù)據(jù)指針及數(shù)據(jù)清0 write_com(0x0c); write_com(0x80+5); write_date(0x6d); write_date(0x41); write_com(0x80); write_date(0x53); write_date(0x30+iset[1]); write_date(0x30+iset[2]); write_date(0x30+iset[3]); write_date(0x30+iset[4]); AD_DAstart=1; } while(temp!=0xf0) //松手檢測 { temp=P2; temp=P2&0xf0; } } } P2=0xfd; // 檢測最二行各鍵是否有按鍵按下 temp=P2; // 將P2口的值賦給temp temp=temp&0xf0; // 位與 if(temp!=0xf0) { delayms(100); temp=P2; temp=temp&0xf0; if(temp!=0xf0) //確認(rèn)被按下,防止抖動 { temp=P2; switch(temp) { case 0xed: //檢測到4被按下 if(keycount!=0) { write_date(0x30+4); iset[keycount++]=4; } break; case 0xdd: //檢測到5被按下 if(keycount!=0) { write_date(0x30+5); iset[keycount++]=5; } break; case 0xbd: //檢測到6被按下 if(keycount!=0) { write_date(0x30+6); iset[keycount++]=6; } break; case 0x7d: //檢測到+被按下 iset[4]++; if(iset[4]==10) { iset[4]=0; iset[3]++; if(iset[3]==10) { iset[3]=0; iset[2]++; if(iset[2]==10) { iset[2]=0; iset[1]++; } } } write_com(0x80+5); write_date(0x6d); write_date(0x41); write_com(0x80); write_date(0x53); write_date(0x30+iset[1]); write_date(0x30+iset[2]); write_date(0x30+iset[3]); write_date(0x30+iset[4]); AD_DAstart=1; break; } while(temp!=0xf0) //松手檢測 { temp=P2; temp=P2&0xf0; } } } P2=0xfb; // 檢測第三行各鍵是否有按鍵按下 temp=P2; // 將P2口的值賦給temp temp=temp&0xf0; // 位與 if(temp!=0xf0) { delayms(100); temp=P2; temp=temp&0xf0; if(temp!=0xf0) //確認(rèn)被按下,防止抖動 { temp=P2; switch(temp) { case 0xeb: //檢測到1被按下 if(keycount!=0) { write_date(0x30+1); iset[keycount++]=1; } break; case 0xdb: //檢測到2被按下 if(keycount!=0) { write_date(0x30+2); iset[keycount++]=2; } break; case 0xbb: //檢測到3被按下 if(keycount!=0) { write_date(0x30+3); iset[keycount++]=3; } break; case 0x7b: //檢測到-被按下 iset[4]--; if(iset[4]==-1) { iset[4]=9; iset[3]--; if(iset[3]==-1) { iset[3]=9; iset[2]--; if(iset[2]==-1) { iset[2]=9; iset[1]--; } } } write_com(0x80+5); write_date(0x6d); write_date(0x41); write_com(0x80); write_date(0x53); write_date(0x30+iset[1]); write_date(0x30+iset[2]); write_date(0x30+iset[3]); write_date(0x30+iset[4]); AD_DAstart=1; break; } while(temp!=0xf0) //松手檢測 { temp=P2; temp=P2&0xf0; } } } P2=0xf7; // 檢測第四行各鍵是否有按鍵按下 temp=P2; // 將P2口的值賦給temp temp=temp&0xf0; // 位與 if(temp!=0xf0) { delayms(100); temp=P2; temp=temp&0xf0; if(temp!=0xf0) //確認(rèn)被按下,防止抖動 { temp=P2; switch(temp) { case 0xe7: //檢測到0被按下 if(keycount!=0) { write_date(0x30); iset[keycount++]=0; } break; case 0xd7: //檢測到刪除鍵被按下 if(keycount<5&&keycount>0) { if(keycount!=1) keycount--; write_com(0x80+keycount); } break; case 0xb7: //檢測到確認(rèn)鍵被按下 if(set==1) { write_com(0x01); // 數(shù)據(jù)指針及數(shù)據(jù)清0 write_com(0x80+5); write_date(0x6d); write_date(0x41); write_com(0x80); write_date(0x53); write_com(0x0f); write_com(0x80+1); set=0; keycount=1; } break; case 0x77: write_com(0x01); // 數(shù)據(jù)指針及數(shù)據(jù)清0 write_com(0x80); // 設(shè)置數(shù)據(jù)地址指針,第一行 for(num=0;num<16;num++) { write_date(table1[num]); delayms(1); //循環(huán)方式寫第一行數(shù)據(jù) } set=1; write_com(0x80+0x40); // 設(shè)置數(shù)據(jù)地址指針,第二行 for(num=0;num<16;num++) { write_date(table2[num]); delayms(1); //循環(huán)方式寫第二行數(shù)據(jù) } AD_DAstart=0; break; } while(temp!=0xf0) //松手檢測 { temp=P2; temp=P2&0xf0; } } } if(keycount==5) { keycount=0; AD_DAstart=1; write_com(0x0c); } }。
|