您的位置:首頁>科技>正文

利用AT89S52型單片機智慧電子稱系統

功能簡介

電子秤可以實現基本的稱重功能(稱重範圍為0~9.999Kg, 重量誤差不大於±0.005Kg),並發揮部分的顯示購物清單的功能, 可以設置日期和設定十種商品的單價, 還具有超量程和欠量程的報警功能。

電子秤的工作原理

當被稱物體放置在秤體的秤臺上時, 其重量便通過秤體傳遞到稱重感測器, 感測器隨之產生力-電效應, 將物體的重量轉換成與被稱物體重量成一定函數關係(一般成正比關係)的電信號(電壓或電流等)。 此信號由放大電路進行放大、經濾波後再由模/數(A/D)器進行轉換, 數位信號再送到微處器的CPU處理,

CPU不斷掃描鍵盤和各種功能開關, 根據鍵盤輸入內容和各種功能開關的狀態進行必要的判斷、分析、由儀錶的軟體來控制各種運算。 運算結果送到內存貯器, 需要顯示時, CPU發出指令, 從內存貯器中讀出送到顯示器顯示, 或送印表機列印。 一般地信號的放大、濾波、A/D轉換以及信號各種運算處理都在儀錶中完成。

電子秤設計的要求及基本思路

電子秤設計的要求

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 購買

Next Article
喜欢就按个赞吧!!!
点击关闭提示