有木有哪个大佬指导我修改!!!
(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); } }。
|