電子秤可以實現基本的稱重功能(稱重範圍為0~9.999Kg, 重量誤差不大於±0.005Kg),並發揮部分的顯示購物清單的功能, 可以設置日期和設定十種商品的單價, 還具有超量程和欠量程的報警功能。
電子秤的工作原理當被稱物體放置在秤體的秤臺上時, 其重量便通過秤體傳遞到稱重感測器, 感測器隨之產生力-電效應, 將物體的重量轉換成與被稱物體重量成一定函數關係(一般成正比關係)的電信號(電壓或電流等)。 此信號由放大電路進行放大、經濾波後再由模/數(A/D)器進行轉換, 數位信號再送到微處器的CPU處理,
電子秤設計的要求
1) 稱重範圍:不超過9.999Kg
2) 測量精度:≤ 0.005Kg
3) 顯示方式:LCD顯示所稱量的物品重量, 同時還可顯示物品的名稱, 數量, 單價, 金額和所有物品的總金額。
4) 使用操作:鍵盤輸入資料, 操作簡單方便。
5) 特殊功能:具有去皮功能以及能將金額累加計算;當物品重量超過電子秤量程, 即超載情況或者是物品重量小於A/D轉換器所能轉換的最小精度,
電子秤設計的基本思路
將電子秤大致能劃分為三大部分, 資料獲取模組、控制器模組和人機交互介面模組。 其中資料獲取模組由壓力感測器、信號的前級處理和A/D轉換部分組成。 轉換後的數位信號送給控制器處理, 由控制器完成對該數位量的處理, 驅動顯示模組完成人機間的資訊交換。 此外添加了一個超載、欠量報警提示的特殊功能。
部分電路雙積分式A/D轉換電路(它由積分器、比較器、類比電子開關, 積分電阻、積分電容、自動回零電阻、電容組成。 其中VG是模擬地, VFR是基準電壓(相對於VG為負值), VX是檢測電壓)
主控電路的設計
P1口和P2.0~P2.6口作為位址匯流排, 其中P1口作為低位址線和資料匯流排複用, P2.0~P2.6口做高地址線。 P2.7作為62256的片選控制匯流排, ALE接鎖存器74LS373的使能端。 P3.6和P3.7作為外部資料記憶體寫/讀選通信號輸出端分別接62256的/WE和/OE端。
主控電路圖如下:
信號處理電路
以下為濾波放大電路圖:電容C5、C6用來濾除採樣信號電壓中的高頻雜訊,
電容C7、C84用來濾除採樣信號電壓中的低頻雜訊
前端信號處理電路設計如下圖
鍵盤輸入控制電路及LCD顯示電路
圖中P1.5口接/CS;P1.6口接CLK;P1.0口接DIO;P3.2口接/KEY,利用中斷0通知AT89S52讀數。
鍵盤控制晶片ZLG7289 控制鍵盤的掃描,當監測到有鍵按下後ZLG7289 的9腳便產生一個低電平通知單片機,單片機可以採用查詢或者中斷方式將資料通過P3.0口以串列方式讀入。
報警電路的設計
程式1 主程序設計
uint max_weight;//最大稱量
uchar dsel;//分度值
uchar dp;//小數點
float beilv;//倍率
ulong zero_save;//感測器零位值
}bdf;
uint code num_ten[4]={1,10,100,1000};
uchar code adcount2[4]={2,4,5};//資料處理進平均次數
uchar code tab_dsel[4]={1,2,5,10};//分度值表
//0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9
uchar code tab[]={0xB7,0x03,0xD6,0xC7,0x63,0xE5,0xF5,0x83,0xF7,0xE7,
//A , b , C , d , E , F , 暗, - , t , P
0xF3,0x75,0xB4,0x57,0xF4,0xF0,0x00,0x40,0x74,0xF2,
//H , L , o , J , r , n , U, =, - i
0x73,0x34,0x55,0x07,0x50,0x51,0x37,0x44,0x04,0x01};
//顯示位元碼表
//0, 1, 2, 3, 4, 5, 6
uchar code digit[]={0xfe,0xdf,0xef,0xfd,0xfb,0xbf,0xF7};//顯示位元碼表
sbit P_OE =P2^1;//顯示控制
sbit P_LE =P2^0;
sbit buz0 =P3^6;//蜂鳴器
sbit buz1 =P3^7;
/******************************************************/
bit b_follow;//啟動零位元跟蹤標記
bit b_serial;//串口發送完標記
bit b_followdelay;//第一次不進行零位跟蹤
bit b_steady;//穩定標記
/******************************************************/
void (* data task)(void);//函數指標變數,接受下一步要做的任務
uint idata fendushu;//分度數
uchar weight_led[6] ;//重量窗顯示緩存
uchar idata temp_var;
uchar weight_dp;//小數點位數
uchar fu_number;//負號顯示位置
uchar wdcount;//穩定計數
uchar adup_count;//異常值計數
uchar addcount3;//累加次數
/******************************************************/
extern void key_scan(void);//按鍵掃描
extern void weight_disp(void);//重量計算,超載報警
extern void start_set(void);//單片機初始化設置
extern void adc (void);//讀取AD值
extern void ad_processor(void);//AD資料濾波處理
extern void fun_weight(void);//正常稱重狀態
extern void bd_start(void);//重量或電壓標定選擇
extern void dy_disp(void);//電壓顯示
extern void led_disp(ulong temp,uchar num);
extern uchar get_jiaoyan(uchar *address,uchar num);//計算校驗字
extern void neima(void);
void delay60ms(uchar time);//40ms延時
void fendu_val(void);//分度數運算
void check_canshu(void);//讀參數,並校驗是否正確
void ver_disp(void);//顯示版本號
void seg_check(void);//筆劃檢測
/******************************************/
void main (void)
{
start_set(); //單片機初始化
beep_time=3; //開機鳴叫
flash_num=6; //沒有閃爍位
spi_sys(); //ad晶片初始化
check_canshu(); //讀參數,並校驗是否正確
if(bdf.shuduval>2) //若是異常值,用預設值
bdf.shuduval=1;
addcount3=4;
bdf_dp_temp=bdf.dp; //保存小數點(標定修改參數時用)
bdf_dsel_temp=bdf.dsel;//保存分度值(標定修改參數時用)
key_scan(); //標定按鍵掃描
switch(key_temp) //功能鍵處理函數
{
case 0xc0:b_biaoding=1;task=bd_start ; break;//
default:
bdf.dp=0;
ver_disp();//顯示版本號
seg_check();//筆劃檢測
fendu_val();//分度數運算
zero_current=ad_steady;//保存當前零位值
task=fun_weight;
break;
}
do
{ //主迴圈程式
adc(); //A/D採樣
ad_processor();//資料處理
zero_follow(); //零位元跟蹤程式
neima(); //內碼計算
weight_disp(); //重量顯示
key_scan(); //按鍵掃描
(* task)(); //任務切換函數
}
while(1);
}
/*****************************************************************/
void fendu_val(void)//分度數運算
{ uchar i;
ulong temp;
temp=(ulong)bdf.max_weight*num_ten[bdf_dp_temp];
fendushu=temp/bdf.dsel;
i=fendushu/3000;
if (i==0)
i=1;
half_sel_bound=5/bdf.beilv;//半個分度的原始碼
follow_bound=i*half_sel_bound;//計算零位跟蹤時的原始碼,按3000分度
time_weight=200;
}
/*****************************************************************/
void ver_disp(void)//顯示版本號及最大量程
{
weight_led[0]=7;// 7
weight_led[1]=1;// 1
weight_led[2]=2;// 2
weight_led[3]=17;// -
weight_led[4]=0;// 0
weight_led[5]=5;// 5
fun_led=0xff;
delay60ms(15);//40ms延時
beep_time=3;
led_disp(bdf.max_weight,5);//顯示最大量程
weight_led[0]=15;// F
delay60ms(20);//40ms延時
2、信號採樣與A/D轉換副程式的設計
extern uchar code adcount2[3];
extern bit bAd;//已產生AD值
extern bit b_warnled;
extern bit b_steady;
extern bit b_up_last;
extern uchar adup_count;
extern ulong idata ad_steady;//AD資料處理後的穩定值
extern uchar add_count;//AD累加計數器
extern ulong idata add_val;//AD累加值
extern uchar wdcount;
extern uchar adup_count;//AD異常值計數
extern uchar addcount3;
extern ulong idata up_val;
extern ulong idata adval;//AD晶片採樣值
extern ulong idata lvbo[6];
extern uchar idata follow_time;//零位跟蹤時間
extern uchar idata time_weight;//重量為0時,消隱時間
void time(void);
ulong buf_left(ulong temp);
/*******************************************/
//
void ad_processor(void)
{ ulong temp1;
ulong temp2;
uchar i;
bit b_up;
if(bAd)
{
bAd=0;
time();//時間計數器自減
//--------------------------------------------------------
adval=adval>>4;
add_val=add_val+adval;//感測器累加濾波
add_count++;
if(add_count
return;
temp1=add_val/addcount3; //累加n次平均
add_count=0;
add_val=0;//感測器累加清零
i=(uchar)(temp1>>16)+1;
3、鍵盤/顯示副程式設計
extern bit b_keyok;//有按鍵產生標記
extern bit b_longdown;//長按下標記
extern uchar key_num;//鍵值
extern uchar key_temp;//臨時鍵值
extern uchar key_count;//鍵長按計數
extern uchar key_dly;//鍵去抖動延時
extern uchar beep_time;//蜂鳴時間
void key_scan1();////按鍵鬆開或沒有按下處理
/****************************************************/
oid disp_t1(void) interrupt 3 using 1//顯示中斷程式
{
uchar temp;
TR1 =0;
P_OE=1;//高阻態,禁止輸出
if((disp_number==(5-bdf.dp))&(bdf.dp!=0))//這一位是否有小數點
temp=0x08;//小數點段碼
else
temp=0;
if(disp_number==6)//指示燈顯示不用查表
P0=fun_led;//
else
{
if((disp_number==fu_number)&&b_fuhao)
temp=temp|0x40;
if((disp_number==flash_num)&b_flash)//是否有閃爍位
P0=0x0;
else
P0=tab[weight_led[disp_number]]|temp;//查表取段碼
}
P_LE=1;
P_LE=0;//573鎖存段碼
P0=digit[disp_number];//送位碼
P_OE=0;//573輸出有效
disp_number++;
if(disp_number==7)//是否顯示最後一位元
{
disp_number=0;
if(beep_time)//是否要鳴叫
{
if(!TR0)
{buz0=~buz1;TR0 =1;}
beep_time--;
}
else
{TR0=0;buz0=1;buz1=1;}//不鳴叫時置高,減小電流
if(key_dly)//按鍵去抖動延時
key_dly--;
if(flash_num
{
if(flash_time)//閃爍計時
flash_time--;
else
{ b_flash=!b_flash;flash_time=20;}//時間到,置閃爍標記
}
}
TH1 =0xf8;
TL1 =0x18;
TR1 =1 ;
}
本文素材來自電子發燒友論壇
新版大學生電子設計競賽單片機應用技能指導 (用好單片機,參賽事半功倍!) 藍和慧 電子工業 ¥34.3 購買
圖中P1.5口接/CS;P1.6口接CLK;P1.0口接DIO;P3.2口接/KEY,利用中斷0通知AT89S52讀數。
鍵盤控制晶片ZLG7289 控制鍵盤的掃描,當監測到有鍵按下後ZLG7289 的9腳便產生一個低電平通知單片機,單片機可以採用查詢或者中斷方式將資料通過P3.0口以串列方式讀入。
報警電路的設計
程式1 主程序設計
uint max_weight;//最大稱量
uchar dsel;//分度值
uchar dp;//小數點
float beilv;//倍率
ulong zero_save;//感測器零位值
}bdf;
uint code num_ten[4]={1,10,100,1000};
uchar code adcount2[4]={2,4,5};//資料處理進平均次數
uchar code tab_dsel[4]={1,2,5,10};//分度值表
//0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9
uchar code tab[]={0xB7,0x03,0xD6,0xC7,0x63,0xE5,0xF5,0x83,0xF7,0xE7,
//A , b , C , d , E , F , 暗, - , t , P
0xF3,0x75,0xB4,0x57,0xF4,0xF0,0x00,0x40,0x74,0xF2,
//H , L , o , J , r , n , U, =, - i
0x73,0x34,0x55,0x07,0x50,0x51,0x37,0x44,0x04,0x01};
//顯示位元碼表
//0, 1, 2, 3, 4, 5, 6
uchar code digit[]={0xfe,0xdf,0xef,0xfd,0xfb,0xbf,0xF7};//顯示位元碼表
sbit P_OE =P2^1;//顯示控制
sbit P_LE =P2^0;
sbit buz0 =P3^6;//蜂鳴器
sbit buz1 =P3^7;
/******************************************************/
bit b_follow;//啟動零位元跟蹤標記
bit b_serial;//串口發送完標記
bit b_followdelay;//第一次不進行零位跟蹤
bit b_steady;//穩定標記
/******************************************************/
void (* data task)(void);//函數指標變數,接受下一步要做的任務
uint idata fendushu;//分度數
uchar weight_led[6] ;//重量窗顯示緩存
uchar idata temp_var;
uchar weight_dp;//小數點位數
uchar fu_number;//負號顯示位置
uchar wdcount;//穩定計數
uchar adup_count;//異常值計數
uchar addcount3;//累加次數
/******************************************************/
extern void key_scan(void);//按鍵掃描
extern void weight_disp(void);//重量計算,超載報警
extern void start_set(void);//單片機初始化設置
extern void adc (void);//讀取AD值
extern void ad_processor(void);//AD資料濾波處理
extern void fun_weight(void);//正常稱重狀態
extern void bd_start(void);//重量或電壓標定選擇
extern void dy_disp(void);//電壓顯示
extern void led_disp(ulong temp,uchar num);
extern uchar get_jiaoyan(uchar *address,uchar num);//計算校驗字
extern void neima(void);
void delay60ms(uchar time);//40ms延時
void fendu_val(void);//分度數運算
void check_canshu(void);//讀參數,並校驗是否正確
void ver_disp(void);//顯示版本號
void seg_check(void);//筆劃檢測
/******************************************/
void main (void)
{
start_set(); //單片機初始化
beep_time=3; //開機鳴叫
flash_num=6; //沒有閃爍位
spi_sys(); //ad晶片初始化
check_canshu(); //讀參數,並校驗是否正確
if(bdf.shuduval>2) //若是異常值,用預設值
bdf.shuduval=1;
addcount3=4;
bdf_dp_temp=bdf.dp; //保存小數點(標定修改參數時用)
bdf_dsel_temp=bdf.dsel;//保存分度值(標定修改參數時用)
key_scan(); //標定按鍵掃描
switch(key_temp) //功能鍵處理函數
{
case 0xc0:b_biaoding=1;task=bd_start ; break;//
default:
bdf.dp=0;
ver_disp();//顯示版本號
seg_check();//筆劃檢測
fendu_val();//分度數運算
zero_current=ad_steady;//保存當前零位值
task=fun_weight;
break;
}
do
{ //主迴圈程式
adc(); //A/D採樣
ad_processor();//資料處理
zero_follow(); //零位元跟蹤程式
neima(); //內碼計算
weight_disp(); //重量顯示
key_scan(); //按鍵掃描
(* task)(); //任務切換函數
}
while(1);
}
/*****************************************************************/
void fendu_val(void)//分度數運算
{ uchar i;
ulong temp;
temp=(ulong)bdf.max_weight*num_ten[bdf_dp_temp];
fendushu=temp/bdf.dsel;
i=fendushu/3000;
if (i==0)
i=1;
half_sel_bound=5/bdf.beilv;//半個分度的原始碼
follow_bound=i*half_sel_bound;//計算零位跟蹤時的原始碼,按3000分度
time_weight=200;
}
/*****************************************************************/
void ver_disp(void)//顯示版本號及最大量程
{
weight_led[0]=7;// 7
weight_led[1]=1;// 1
weight_led[2]=2;// 2
weight_led[3]=17;// -
weight_led[4]=0;// 0
weight_led[5]=5;// 5
fun_led=0xff;
delay60ms(15);//40ms延時
beep_time=3;
led_disp(bdf.max_weight,5);//顯示最大量程
weight_led[0]=15;// F
delay60ms(20);//40ms延時
2、信號採樣與A/D轉換副程式的設計
extern uchar code adcount2[3];
extern bit bAd;//已產生AD值
extern bit b_warnled;
extern bit b_steady;
extern bit b_up_last;
extern uchar adup_count;
extern ulong idata ad_steady;//AD資料處理後的穩定值
extern uchar add_count;//AD累加計數器
extern ulong idata add_val;//AD累加值
extern uchar wdcount;
extern uchar adup_count;//AD異常值計數
extern uchar addcount3;
extern ulong idata up_val;
extern ulong idata adval;//AD晶片採樣值
extern ulong idata lvbo[6];
extern uchar idata follow_time;//零位跟蹤時間
extern uchar idata time_weight;//重量為0時,消隱時間
void time(void);
ulong buf_left(ulong temp);
/*******************************************/
//
void ad_processor(void)
{ ulong temp1;
ulong temp2;
uchar i;
bit b_up;
if(bAd)
{
bAd=0;
time();//時間計數器自減
//--------------------------------------------------------
adval=adval>>4;
add_val=add_val+adval;//感測器累加濾波
add_count++;
if(add_count
return;
temp1=add_val/addcount3; //累加n次平均
add_count=0;
add_val=0;//感測器累加清零
i=(uchar)(temp1>>16)+1;
3、鍵盤/顯示副程式設計
extern bit b_keyok;//有按鍵產生標記
extern bit b_longdown;//長按下標記
extern uchar key_num;//鍵值
extern uchar key_temp;//臨時鍵值
extern uchar key_count;//鍵長按計數
extern uchar key_dly;//鍵去抖動延時
extern uchar beep_time;//蜂鳴時間
void key_scan1();////按鍵鬆開或沒有按下處理
/****************************************************/
oid disp_t1(void) interrupt 3 using 1//顯示中斷程式
{
uchar temp;
TR1 =0;
P_OE=1;//高阻態,禁止輸出
if((disp_number==(5-bdf.dp))&(bdf.dp!=0))//這一位是否有小數點
temp=0x08;//小數點段碼
else
temp=0;
if(disp_number==6)//指示燈顯示不用查表
P0=fun_led;//
else
{
if((disp_number==fu_number)&&b_fuhao)
temp=temp|0x40;
if((disp_number==flash_num)&b_flash)//是否有閃爍位
P0=0x0;
else
P0=tab[weight_led[disp_number]]|temp;//查表取段碼
}
P_LE=1;
P_LE=0;//573鎖存段碼
P0=digit[disp_number];//送位碼
P_OE=0;//573輸出有效
disp_number++;
if(disp_number==7)//是否顯示最後一位元
{
disp_number=0;
if(beep_time)//是否要鳴叫
{
if(!TR0)
{buz0=~buz1;TR0 =1;}
beep_time--;
}
else
{TR0=0;buz0=1;buz1=1;}//不鳴叫時置高,減小電流
if(key_dly)//按鍵去抖動延時
key_dly--;
if(flash_num
{
if(flash_time)//閃爍計時
flash_time--;
else
{ b_flash=!b_flash;flash_time=20;}//時間到,置閃爍標記
}
}
TH1 =0xf8;
TL1 =0x18;
TR1 =1 ;
}
本文素材來自電子發燒友論壇
新版大學生電子設計競賽單片機應用技能指導 (用好單片機,參賽事半功倍!) 藍和慧 電子工業 ¥34.3 購買