基于51单片机的智能电子秤系统设计(含代码仿真及论文)
资源内容介绍
论文见主页文章http://t.csdn.cn/IurRu!!!!本设计以STC89C52RC单片机为主控单元,使用8 位AD转换芯片 ADC0832对采集到的模拟量进行A/D转换,转换后的数据送到单片机进行处理显示,数据显示由 LCD12864 液晶实现。具有以下特点:称重范围为0~5Kg,误差不大于±0.005Kg;具备测量物体质量并通过显示模块显示的功能;能够通过物体的单价计算出物体数量的总价格;具备去皮功能,方便计算物体的实际重力;当测量重量超出报警阈值时,蜂鸣进行过载报警。通过实验验证,本文设计的基于51单片机的智能电子秤系统具有较高的精度和稳定,满足了商业、家庭和实验室等领域的需求,具有较强的实用价值和广阔的应用前景。关键词:51单片机;智能电子秤;称重传感器;误差分析 #include<reg51.h>#include<intrins.h>#include <ZM.h>#define LCD P0#define GPIO_KEY P1sbit price_add1=P1^0;sbit price_reduce1=P1^1;sbit price_add2=P1^2;sbit price_reduce2=P1^3;sbit weight_reduce=P1^4;sbit weigth_clear=P1^5;sbit warning_add=P1^6;sbit warning_reduce=P1^7;sbit EN=P2^0;sbit RW=P2^1;sbit RS=P2^2;sbit CS1=P2^3;sbit CS2=P2^4;sbit BUSY=P0^0;sbit beep=P2^7;sbit ADCS =P3^5; sbit ADDI =P3^7; sbit ADDO =P3^7; sbit ADCLK =P3^6; unsigned char a,i,j,k,ad_data;float press=0.0,press_r=0.0;float warning=2.5;int b;int num=1,num_t=0; float sum=0;float price1=10;float weight_temp=0;void delay(unsigned char a){unsigned char i,j;for(i=0;i<a;i++)for(j=0;j<100;j++){;}}void temer1() interrupt 2{EX1=0; if(price_add1==0)//涨价按键1按下,单价增长0.5{while(!price_add1);price1=price1+0.5;}else if(price_add2==0)//涨价按键2按下,单价增长1{while(!price_add2);price1=price1+1;}else if(price_reduce1==0)//降价按键1按下,单价下降0.5{while(!price_reduce1);price1=price1-0.5;}else if(price_reduce2==0)//降价按键2按下,单价下降1{while(!price_reduce2);price1=price1-1;}else if(weight_reduce==0)//去皮按键按下,去除皮重{while(!weight_reduce);weight_temp=press;}else if(weigth_clear==0)//去皮清零按键按下,清除皮重{while(!weigth_clear);weight_temp=0;}else if(warning_add==0)//报警值增加按键按下,报警值增加0.5{while(!warning_add);warning+=0.5;}else if(warning_reduce==0)//报警值减少按键按下,报警值减少0.5{while(!warning_reduce);warning-=0.5;} delay(100); EX1=1; } void weight_alarm(void){ if(press_r>warning) { beep=0; //则启动报警 } else beep=1; }//采集并返回unsigned char Adc0832(unsigned char channel) //AD转换,返回结果{ unsigned char j,i=0,ndat=0; unsigned int dat=0; if(channel==0)channel=2; if(channel==1)channel=3; ADDI=1; _nop_(); _nop_(); ADCS=0;//拉低CS端 _nop_(); _nop_(); ADCLK=1;//拉高CLK端 _nop_(); _nop_(); ADCLK=0;//拉低CLK端,形成下降沿1 _nop_(); _nop_(); ADCLK=1;//拉高CLK端 ADDI=channel&0x1; _nop_(); _nop_(); ADCLK=0;//拉低CLK端,形成下降沿2 _nop_(); _nop_(); ADCLK=1;//拉高CLK端 ADDI=(channel>>1)&0x1; _nop_(); _nop_(); ADCLK=0;//拉低CLK端,形成下降沿3 ADDI=1;//控制命令结束 _nop_(); _nop_(); dat=0; for(i=0;i<8;i++) { dat|=ADDO;//收数据 ADCLK=1; _nop_(); _nop_(); ADCLK=0;//形成一次时钟脉冲 _nop_(); _nop_(); dat<<=1; if(i==7)dat|=ADDO; } for(i=0;i<8;i++) { j=0; j=j|ADDO;//收数据 ADCLK=1; _nop_(); _nop_(); ADCLK=0;//形成一次时钟脉冲 _nop_(); _nop_(); j=j<<7; ndat=ndat|j; if(i<7)ndat>>=1; } ADCS=1;//拉低CS端 ADCLK=0;//拉低CLK端 ADDO=1;//拉高数据端,回到初始状态 dat<<=8; dat|=ndat; return(dat); //return ad k }void data_pro(void){ if(0<ad_data<256) { int vary=ad_data; press=(0.019531*vary); } }void total(float w,float p){sum=w*p;}unsigned char t1[6]={"000.00"};void turn(float t_float){int temp=(int)t_float;t1[0]=temp/100+0X30;t1[1]=(temp%100)/10+0X30;t1[2]=temp%10+0X30;temp=(int)(t_float*100);t1[4]=(temp%100)/10+0X30;t1[5]=temp%10+0X30;}void checkbusy(void){ EN=1;RW=1;RS=0;LCD=0XFF;if(BUSY);}void writecode(unsigned char dat) //写命令{ checkbusy();EN=1;RW=0;RS=0;LCD=dat;EN=1;EN=0;}void writedata(unsigned char dat) //写数据{checkbusy();EN=1;RW=0;RS=1;LCD=dat;EN=1;EN=0;}void displayzifu(unsigned char page,unsigned char lineaddress,int n, unsigned char table[]){unsigned char temp[16];if(lineaddress<0X80){CS1=1;CS2=0;}for(j=0;j<n;j++) {if(lineaddress>=0X80){CS1=0;CS2=1;lineaddress=lineaddress-0X40;}b=table[j]-0X20;for(k=0;k<16;k++){temp[k]=ch2[b][k];}writecode(page);writecode(lineaddress);for(i=0;i<8;i++){writedata(temp[i]);}writecode(page+1);writecode(lineaddress);for(i=8;i<16;i++) {writedata(temp[i]);}lineaddress+=8; }}void clear(unsigned char page,unsigned char lineaddress,int n, unsigned char table[]){ unsigned char temp[16]; if(lineaddress<0X80) {CS1=1; CS2=0;} for(j=0;j<n;j++) { if(lineaddress>=0X80) { CS1=0; CS2=1; lineaddress=lineaddress-0X40; } b=table[j]-0X20; for(k=0;k<16;k++) {temp[k]=ch2[b][k];} writecode(page); writecode(lineaddress); for(i=0;i<8;i++) { writedata(temp[i]);} writecode(page+1); writecode(lineaddress); for(i=8;i<16;i++) { writedata(temp[i]);} lineaddress+=8; }}void displayhanzi(unsigned char page,unsigned char lineaddress,int n, unsigned char table[][16]){unsigned char temp[32];if(lineaddress<0X80) {CS1=1;//leftCS2=0;}for(j=0;j<n;j++) { if(lineaddress>=0X80){CS1=0;//right CS2=1;lineaddress=lineaddress-0X40;}for(k=0;k<16;k++){temp[k]=table[j][k];}j+=1;for(k=0;k<16;k++){temp[16+k]=table[j][k];} writecode(page); writecode(lineaddress);for(i=0;i<16;i++) { writedata(temp[i]);}writecode(page+1);writecode(lineaddress);for(i=16;i<32;i++) {writedata(temp[i]);}lineaddress+=16; }}void lcdinti(){ writecode(0X3f);//显示开关关 writecode(0XC0);//修改显示起始行 writecode(0XB8);//修改页地址,x地址 writecode(0X40);//修改列地址,y地址 }void main(){ unsigned char t[3]={'/','K','G'};char m=':';EA=1; EX1=1;lcdinti();//LCD初始化 clear(0XB8,0X40,16,&table2);clear(0XBa,0X40,16,&table2);clear(0XBc,0X40,16,&table2);clear(0XBe,0X40,16,&table2);displayhanzi(0XB8,0X40,8,&TITLE); turn(warning);displayzifu(0XB8,0X78,5,&t1[1]);displayzifu(0XB8,0xB0,2,&t[1]);displayhanzi(0XBa,0X40,4,&WEIGHT);displayzifu(0XBa,0X60,1,&m);displayhanzi(0XBc,0X40,4,&PRICE);displayzifu(0XBc,0X60,1,&m);displayhanzi(0XBE,0X40,4,&TOTAL);displayzifu(0XBe,0X60,1,&m);while(1){ad_data =Adc0832(0); //采样值存储单元初始化为0data_pro();press_r=press-weight_temp; weight_alarm();turn(warning);displayzifu(0XB8,0X78,5,&t1[1]);delay(100);turn(press_r);displayzifu(0XBa,0X68,5,&t1[1]);displayzifu(0xba,0xB0,2,&t[1]);delay(100);turn(price1);displayzifu(0XBc,0X68,6,&t1[0]);displayhanzi(0xbc,0x98,2,&YUAN);displayzifu(0XBc,0XA8,3,&t);delay(100); total(press_r,price1);turn(sum);displayzifu(0XBe,0X68,6,&t1);displayhanzi(0xbe,0xB0,2,&YUAN);delay(100);}}