有木有哪個大佬指導我修改!!!
(1)輸出電流范圍:200mA~2000mA; (2)可設置并顯示輸出電流給定值,要求輸出電流與給定值偏差的絕對值≤給定值的1%+10 mA; (3)具有“+”、“-”步進調整功能,步進≤10mA; (4)改變負載電阻,輸出電壓在10V以內變化時,要求輸出電流變化的絕對值≤輸出電流值的1%+10 mA; (5)輸出電流范圍為20mA~2000mA,步進1mA; (6)設計、制作測量并顯示輸出電流的裝置 (可同時或交替顯示電流的給定值和實測值),測量誤差的絕對值≤測量值的0.1%+3個字; (7)改變負載電阻,輸出電壓在10V以內變化時,要求輸出電流變化的絕對值≤輸出電流值的0.1%+1 mA; (8)另附:源程序 附錄2程序清單;************************************************************ ;****;在本次課程設計的程序中,我用到的是液晶顯示器,其使能*** ;****;端接單片機的P3.0,P3.1,P3.2引腳,用到了DA轉換等需要 *** ;****;的暫存單元分別為30H到35H,其中還有一些必要的標志位存*** ;****;在在36H到4AH單元。按鍵接單片機的P2.0到P2.7,液晶顯示*** ;****;顯示器數據口接單片機的P0.0到P0.7,本數控直流電流源有加 *** ;****;減調整,采用閉環控制系統進行調整,精確度更高。 *** ;************************************************************ #include<reg52.h> #define uchar unsigned char #define uint unsigned int
sbit rs=P3^0; sbit rw=P3^1; sbit lcden=P3^2; //液晶顯示屏相關位定義 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(); //函數聲明 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) //延時函數,參數為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) //寫命令函數 { rs=0; //rs置0表示寫命令 lcden=0; //按時序圖置低 P0=com; //位聲明,按原理圖接P0口,輸入數據 lcden=1; //置高 delayms(5); //時序圖中須有thd2時間延時 lcden=0; //按時序圖置低 } void write_date(uchar date) //寫數據函數 { rs=1; //rs置1表示寫數據 lcden=0; P0=date; //將數據賦到P0口 delayms(5); lcden=1; delayms(5); lcden=0; } void led_init() //初始化函數 { lcden=0; rw=0; write_com(0x38); //顯示模式設置:16X2顯示,5X7點陣,8位數據 write_com(0x0c); // 開顯示,關光標,光標不閃爍 write_com(0x06); // 寫一個數據后地址指針加一,光標加一 write_com(0x01); // 數據指針及數據清0 write_com(0x80); // 設置數據地址指針,第一行 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轉換子程序 **** ;************************************************************ void display_AD() { uchar num; temp0+= read2543(0x00); //進行AD轉換 temp1+= read2543(0x01); i--; //取20次AD轉換的結果,求平均值 if(i==0) { ADCdat=temp1/20; temp1=0; Voltage2=(ADCdat*5.0)/4096; //基準電壓為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; //基準電壓為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); // 數據指針及數據清0 write_com(0x80); // 設置數據地址指針,第一行 for(num=0;num<16;num++) { write_date(table3[num]); delayms(1); //循環方式寫第一行數據 } 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轉換子程序 **** ;************************************************************ uint read2543(uchar port) //DA轉換子程序 { 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) //確認被按下,防止抖動 { 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); // 數據指針及數據清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) //確認被按下,防止抖動 { 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) //確認被按下,防止抖動 { 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) //確認被按下,防止抖動 { 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: //檢測到確認鍵被按下 if(set==1) { write_com(0x01); // 數據指針及數據清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); // 數據指針及數據清0 write_com(0x80); // 設置數據地址指針,第一行 for(num=0;num<16;num++) { write_date(table1[num]); delayms(1); //循環方式寫第一行數據 } set=1; write_com(0x80+0x40); // 設置數據地址指針,第二行 for(num=0;num<16;num++) { write_date(table2[num]); delayms(1); //循環方式寫第二行數據 } AD_DAstart=0; break; } while(temp!=0xf0) //松手檢測 { temp=P2; temp=P2&0xf0; } } } if(keycount==5) { keycount=0; AD_DAstart=1; write_com(0x0c); } }。
|