本文為大家帶來利用AT89S52型單片機智能電子稱系統設計。
AT89S52型單片機介紹
AT89S52是一個8位單片機,片內ROM全部采用FLASH ROM技術,與MCS-51系列完全兼容,它能以3V的超低電壓工作,晶振時鐘最高可達24MHz。AT89S52是標準的40引腳雙列直插式集成電路芯片,有4個八位的并行雙向I/O端口,分別記作P0、P1、P2、P3。第31引腳需要接高電位使單片機選用內部程序存儲器;第9引腳是復位引腳,要接一個上電手動復位電路;第40腳為電源端VCC,接+5V電源,第20引腳為接地端VSS,通常在VCC和VSS引腳之間接0.1μF高頻濾波電容。第18、19腳之間接上一個12MHz的晶振為單片機提供時鐘信號。
AT89S52型單片機引腳功能
引腳說明
VCC:電源電壓
P0口:P0口是一組8位漏極開路型雙向I/O口,作為輸出口用時,每個引腳能驅動8個TTL邏輯門電路。當對0端口寫入1時,可以作為高阻抗輸入端使用。
當P0口訪問外部程序存儲器或數據存儲器時,它還可設定成地址數據總線復用的形式。在這種模式下,P0口具有內部上拉電阻。
在EPROM編程時,P0口接收指令字節,同時輸出指令字節在程序校驗時。程序校驗時需要外接上拉電阻。
P1口:P1口是一帶有內部上拉電阻的8位雙向I/O口。P1口的輸出緩沖能接受或輸出4個TTL邏輯門電路。當對P1口寫1時,它們被內部的上拉電阻拉升為高電平,此時可以作為輸入端使用。當作為輸入端使用時,P1口因為內部存在上拉電阻,所以當外部被拉低時會輸出一個低電流(IIL)。
P2口:P2是一帶有內部上拉電阻的8位雙向的I/O端口。P2口的輸出緩沖能驅動4個TTL邏輯門電路。當向P2口寫1時,通過內部上拉電阻把端口拉到高電平,此時可以用作輸入口。作為輸入口,因為內部存在上拉電阻,某個引腳被外部信號拉低時會輸出電流(IIL)。
P2口在訪問外部程序存儲器或16位地址的外部數據存儲器(例如MOVX @ DPTR)時,P2口送出高8位地址數據。在這種情況下,P2口使用強大的內部上拉電阻功能當輸出1時。當利用8位地址線訪問外部數據存儲器時(例MOVX @R1),P2口輸出特殊功能寄存器的內容。當EPROM編程或校驗時,P2口同時接收高8位地址和一些控制信號。
P3口:P3是一帶有內部上拉電阻的8位雙向的I/O端口。P3口的輸出緩沖能驅動4個TTL邏輯門電路。當向P3口寫1時,通過內部上拉電阻把端口拉到高電平,此時可以用作輸入口。作為輸入口,因為內部存在上拉電阻,某個引腳被外部信號拉低時會輸出電流(IIL)。
P3口同時具有多種特殊功能,具體如下表所示:
RST:復位輸入。當振蕩器工作時,RST引腳出現兩個機器周期的高電平將使單片機復位。
ALE/PROG:當訪問外部存儲器時,地址鎖存允許是一輸出脈沖,用以鎖存地址的低8位字節。當在Flash編程時還可以作為編程脈沖輸出(PROG)。 一般情況下,ALE是以晶振頻率的1/6輸出,可以用作外部時鐘或定時目的。但也要注意,每當訪問外部數據存儲器時將跳過一個ALE脈沖。
PSEN:程序存儲允許時外部程序存儲器的讀選通信號。當AT89C52執行外部程序存儲器的指令時,每個機器周期PSEN兩次有效,除了當訪問外部數據存儲器時,PSEN將跳過兩個信號。
EA/VPP:外部訪問允許。為了使單片機能夠有效的傳送外部數據存儲器從0000H到FFFH單元的指令,EA必須同GND相連接。需要主要的是,如果加密位1被編程,復位時EA端會自動內部鎖存。當執行內部編程指令時,EA應該接到VCC端。
XTAL1:振蕩器反相放大器以及內部時鐘電路的輸入端。 XTAL2:振蕩器反相放大器的輸出端。
電子秤的工作原理
當被稱物體放置在秤體的秤臺上時,其重量便通過秤體傳遞到稱重傳感器,傳感器隨之產生力-電效應,將物體的重量轉換成與被稱物體重量成一定函數關系(一般成正比關系)的電信號(電壓或電流等)。此信號由放大電路進行放大、經濾波后再由模/數(A/D)器進行轉換,數字信號再送到微處器的CPU處理,CPU不斷掃描鍵盤和各種功能開關,根據鍵盤輸入內容和各種功能開關的狀態進行必要的判斷、分析、由儀表的軟件來控制各種運算。運算結果送到內存貯器,需要顯示時,CPU發出指令,從內存貯器中讀出送到顯示器顯示,或送打印機打印。一般地信號的放大、濾波、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《addcount3)
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;//
if((disp_number==fu_number)&&b_fuhao)
temp=temp|0x40;
if((disp_number==flash_num)&b_flash)//是否有閃爍位
P0=0x0;
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--;
{TR0=0;buz0=1;buz1=1;}//不鳴叫時置高,減小電流
if(key_dly)//按鍵去抖動延時
key_dly--;
if(flash_num《6)
if(flash_time)//閃爍計時
flash_time--;
{ b_flash=!b_flash;flash_time=20;}//時間到,置閃爍標記
TH1 =0xf8;
TL1 =0x18;
TR1 =1 ;
評論