本文為大家?guī)?lái)利用AT89S52型單片機(jī)智能電子稱(chēng)系統(tǒng)設(shè)計(jì)。
AT89S52型單片機(jī)介紹
AT89S52是一個(gè)8位單片機(jī),片內(nèi)ROM全部采用FLASH ROM技術(shù),與MCS-51系列完全兼容,它能以3V的超低電壓工作,晶振時(shí)鐘最高可達(dá)24MHz。AT89S52是標(biāo)準(zhǔn)的40引腳雙列直插式集成電路芯片,有4個(gè)八位的并行雙向I/O端口,分別記作P0、P1、P2、P3。第31引腳需要接高電位使單片機(jī)選用內(nèi)部程序存儲(chǔ)器;第9引腳是復(fù)位引腳,要接一個(gè)上電手動(dòng)復(fù)位電路;第40腳為電源端VCC,接+5V電源,第20引腳為接地端VSS,通常在VCC和VSS引腳之間接0.1μF高頻濾波電容。第18、19腳之間接上一個(gè)12MHz的晶振為單片機(jī)提供時(shí)鐘信號(hào)。
AT89S52型單片機(jī)引腳功能
引腳說(shuō)明
VCC:電源電壓
P0口:P0口是一組8位漏極開(kāi)路型雙向I/O口,作為輸出口用時(shí),每個(gè)引腳能驅(qū)動(dòng)8個(gè)TTL邏輯門(mén)電路。當(dāng)對(duì)0端口寫(xiě)入1時(shí),可以作為高阻抗輸入端使用。
當(dāng)P0口訪問(wèn)外部程序存儲(chǔ)器或數(shù)據(jù)存儲(chǔ)器時(shí),它還可設(shè)定成地址數(shù)據(jù)總線復(fù)用的形式。在這種模式下,P0口具有內(nèi)部上拉電阻。
在EPROM編程時(shí),P0口接收指令字節(jié),同時(shí)輸出指令字節(jié)在程序校驗(yàn)時(shí)。程序校驗(yàn)時(shí)需要外接上拉電阻。
P1口:P1口是一帶有內(nèi)部上拉電阻的8位雙向I/O口。P1口的輸出緩沖能接受或輸出4個(gè)TTL邏輯門(mén)電路。當(dāng)對(duì)P1口寫(xiě)1時(shí),它們被內(nèi)部的上拉電阻拉升為高電平,此時(shí)可以作為輸入端使用。當(dāng)作為輸入端使用時(shí),P1口因?yàn)閮?nèi)部存在上拉電阻,所以當(dāng)外部被拉低時(shí)會(huì)輸出一個(gè)低電流(IIL)。
P2口:P2是一帶有內(nèi)部上拉電阻的8位雙向的I/O端口。P2口的輸出緩沖能驅(qū)動(dòng)4個(gè)TTL邏輯門(mén)電路。當(dāng)向P2口寫(xiě)1時(shí),通過(guò)內(nèi)部上拉電阻把端口拉到高電平,此時(shí)可以用作輸入口。作為輸入口,因?yàn)閮?nèi)部存在上拉電阻,某個(gè)引腳被外部信號(hào)拉低時(shí)會(huì)輸出電流(IIL)。
P2口在訪問(wèn)外部程序存儲(chǔ)器或16位地址的外部數(shù)據(jù)存儲(chǔ)器(例如MOVX @ DPTR)時(shí),P2口送出高8位地址數(shù)據(jù)。在這種情況下,P2口使用強(qiáng)大的內(nèi)部上拉電阻功能當(dāng)輸出1時(shí)。當(dāng)利用8位地址線訪問(wèn)外部數(shù)據(jù)存儲(chǔ)器時(shí)(例MOVX @R1),P2口輸出特殊功能寄存器的內(nèi)容。當(dāng)EPROM編程或校驗(yàn)時(shí),P2口同時(shí)接收高8位地址和一些控制信號(hào)。
P3口:P3是一帶有內(nèi)部上拉電阻的8位雙向的I/O端口。P3口的輸出緩沖能驅(qū)動(dòng)4個(gè)TTL邏輯門(mén)電路。當(dāng)向P3口寫(xiě)1時(shí),通過(guò)內(nèi)部上拉電阻把端口拉到高電平,此時(shí)可以用作輸入口。作為輸入口,因?yàn)閮?nèi)部存在上拉電阻,某個(gè)引腳被外部信號(hào)拉低時(shí)會(huì)輸出電流(IIL)。
P3口同時(shí)具有多種特殊功能,具體如下表所示:
RST:復(fù)位輸入。當(dāng)振蕩器工作時(shí),RST引腳出現(xiàn)兩個(gè)機(jī)器周期的高電平將使單片機(jī)復(fù)位。
ALE/PROG:當(dāng)訪問(wèn)外部存儲(chǔ)器時(shí),地址鎖存允許是一輸出脈沖,用以鎖存地址的低8位字節(jié)。當(dāng)在Flash編程時(shí)還可以作為編程脈沖輸出(PROG)。 一般情況下,ALE是以晶振頻率的1/6輸出,可以用作外部時(shí)鐘或定時(shí)目的。但也要注意,每當(dāng)訪問(wèn)外部數(shù)據(jù)存儲(chǔ)器時(shí)將跳過(guò)一個(gè)ALE脈沖。
PSEN:程序存儲(chǔ)允許時(shí)外部程序存儲(chǔ)器的讀選通信號(hào)。當(dāng)AT89C52執(zhí)行外部程序存儲(chǔ)器的指令時(shí),每個(gè)機(jī)器周期PSEN兩次有效,除了當(dāng)訪問(wèn)外部數(shù)據(jù)存儲(chǔ)器時(shí),PSEN將跳過(guò)兩個(gè)信號(hào)。
EA/VPP:外部訪問(wèn)允許。為了使單片機(jī)能夠有效的傳送外部數(shù)據(jù)存儲(chǔ)器從0000H到FFFH單元的指令,EA必須同GND相連接。需要主要的是,如果加密位1被編程,復(fù)位時(shí)EA端會(huì)自動(dòng)內(nèi)部鎖存。當(dāng)執(zhí)行內(nèi)部編程指令時(shí),EA應(yīng)該接到VCC端。
XTAL1:振蕩器反相放大器以及內(nèi)部時(shí)鐘電路的輸入端。 XTAL2:振蕩器反相放大器的輸出端。
電子秤的工作原理
當(dāng)被稱(chēng)物體放置在秤體的秤臺(tái)上時(shí),其重量便通過(guò)秤體傳遞到稱(chēng)重傳感器,傳感器隨之產(chǎn)生力-電效應(yīng),將物體的重量轉(zhuǎn)換成與被稱(chēng)物體重量成一定函數(shù)關(guān)系(一般成正比關(guān)系)的電信號(hào)(電壓或電流等)。此信號(hào)由放大電路進(jìn)行放大、經(jīng)濾波后再由模/數(shù)(A/D)器進(jìn)行轉(zhuǎn)換,數(shù)字信號(hào)再送到微處器的CPU處理,CPU不斷掃描鍵盤(pán)和各種功能開(kāi)關(guān),根據(jù)鍵盤(pán)輸入內(nèi)容和各種功能開(kāi)關(guān)的狀態(tài)進(jìn)行必要的判斷、分析、由儀表的軟件來(lái)控制各種運(yùn)算。運(yùn)算結(jié)果送到內(nèi)存貯器,需要顯示時(shí),CPU發(fā)出指令,從內(nèi)存貯器中讀出送到顯示器顯示,或送打印機(jī)打印。一般地信號(hào)的放大、濾波、A/D轉(zhuǎn)換以及信號(hào)各種運(yùn)算處理都在儀表中完成。
電子秤設(shè)計(jì)的基本思路
將電子秤大致能劃分為三大部分,數(shù)據(jù)采集模塊、控制器模塊和人機(jī)交互界面模塊。其中數(shù)據(jù)采集模塊由壓力傳感器、信號(hào)的前級(jí)處理和A/D轉(zhuǎn)換部分組成。轉(zhuǎn)換后的數(shù)字信號(hào)送給控制器處理,由控制器完成對(duì)該數(shù)字量的處理,驅(qū)動(dòng)顯示模塊完成人機(jī)間的信息交換。此外添加了一個(gè)過(guò)載、欠量報(bào)警提示的特殊功能。
部分電路
雙積分式A/D轉(zhuǎn)換電路
(它由積分器、比較器、模擬電子開(kāi)關(guān),積分電阻、積分電容、自動(dòng)回零電阻、電容組成。其中VG是模擬地,VFR是基準(zhǔn)電壓(相對(duì)于VG為負(fù)值),VX是檢測(cè)電壓)
主控電路的設(shè)計(jì)
P1口和P2.0~P2.6口作為地址總線,其中P1口作為低地址線和數(shù)據(jù)總線復(fù)用,P2.0~P2.6口做高地址線。P2.7作為62256的片選控制總線,ALE接鎖存器74LS373的使能端。P3.6和P3.7作為外部數(shù)據(jù)存儲(chǔ)器寫(xiě)/讀選通信號(hào)輸出端分別接62256的/WE和/OE端。
主控電路圖如下:
信號(hào)處理電路
以下為濾波放大電路圖:
電容C5、C6用來(lái)濾除采樣信號(hào)電壓中的高頻噪聲,電容C7、C84用來(lái)濾除采樣信號(hào)電壓中的低頻噪聲。
前端信號(hào)處理電路設(shè)計(jì)如下圖
鍵盤(pán)輸入控制電路及LCD顯示電路
圖中P1.5口接/CS;P1.6口接CLK;P1.0口接DIO;P3.2口接/KEY,利用中斷0通知AT89S52讀數(shù)。
鍵盤(pán)控制芯片ZLG7289 控制鍵盤(pán)的掃描,當(dāng)監(jiān)測(cè)到有鍵按下后ZLG7289 的9腳便產(chǎn)生一個(gè)低電平通知單片機(jī),單片機(jī)可以采用查詢或者中斷方式將數(shù)據(jù)通過(guò)P3.0口以串行方式讀入。
報(bào)警電路的設(shè)計(jì)
程序
1 主程序設(shè)計(jì)
uint max_weight;//最大稱(chēng)量
uchar dsel;//分度值
uchar dp;//小數(shù)點(diǎn)
float beilv;//倍率
ulong zero_save;//傳感器零位值
}bdf;
uint code num_ten[4]={1,10,100,1000};
uchar code adcount2[4]={2,4,5};//數(shù)據(jù)處理進(jìn)平均次數(shù)
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;//啟動(dòng)零位跟蹤標(biāo)記
bit b_serial;//串口發(fā)送完標(biāo)記
bit b_followdelay;//第一次不進(jìn)行零位跟蹤
bit b_steady;//穩(wěn)定標(biāo)記
void (* data task)(void);//函數(shù)指針變量,接受下一步要做的任務(wù)
uint idata fendushu;//分度數(shù)
uchar weight_led[6] ;//重量窗顯示緩存
uchar idata temp_var;
uchar weight_dp;//小數(shù)點(diǎn)位數(shù)
uchar fu_number;//負(fù)號(hào)顯示位置
uchar wdcount;//穩(wěn)定計(jì)數(shù)
uchar adup_count;//異常值計(jì)數(shù)
uchar addcount3;//累加次數(shù)
extern void key_scan(void);//按鍵掃描
extern void weight_disp(void);//重量計(jì)算,超載報(bào)警
extern void start_set(void);//單片機(jī)初始化設(shè)置
extern void adc (void);//讀取AD值
extern void ad_processor(void);//AD數(shù)據(jù)濾波處理
extern void fun_weight(void);//正常稱(chēng)重狀態(tài)
extern void bd_start(void);//重量或電壓標(biāo)定選擇
extern void dy_disp(void);//電壓顯示
extern void led_disp(ulong temp,uchar num);
extern uchar get_jiaoyan(uchar *address,uchar num);//計(jì)算校驗(yàn)字
extern void neima(void);
void delay60ms(uchar time);//40ms延時(shí)
void fendu_val(void);//分度數(shù)運(yùn)算
void check_canshu(void);//讀參數(shù),并校驗(yàn)是否正確
void ver_disp(void);//顯示版本號(hào)
void seg_check(void);//筆畫(huà)檢測(cè)
/******************************************/
void main (void)
{
start_set(); //單片機(jī)初始化
beep_time=3; //開(kāi)機(jī)鳴叫
flash_num=6; //沒(méi)有閃爍位
spi_sys(); //ad芯片初始化
check_canshu(); //讀參數(shù),并校驗(yàn)是否正確
if(bdf.shuduval》2) //若是異常值,用默認(rèn)值
bdf.shuduval=1;
addcount3=4;
bdf_dp_temp=bdf.dp; //保存小數(shù)點(diǎn)(標(biāo)定修改參數(shù)時(shí)用)
bdf_dsel_temp=bdf.dsel;//保存分度值(標(biāo)定修改參數(shù)時(shí)用)
key_scan(); //標(biāo)定按鍵掃描
switch(key_temp) //功能鍵處理函數(shù)
case 0xc0:b_biaoding=1;task=bd_start ; break;//
default:
bdf.dp=0;
ver_disp();//顯示版本號(hào)
seg_check();//筆畫(huà)檢測(cè)
fendu_val();//分度數(shù)運(yùn)算
zero_current=ad_steady;//保存當(dāng)前零位值
task=fun_weight;
break;
}
do
{ //主循環(huán)程序
adc(); //A/D采樣
ad_processor();//數(shù)據(jù)處理
zero_follow(); //零位跟蹤程序
neima(); //內(nèi)碼計(jì)算
weight_disp(); //重量顯示
key_scan(); //按鍵掃描
(* task)(); //任務(wù)切換函數(shù)
while(1);
/*****************************************************************/
void fendu_val(void)//分度數(shù)運(yùn)算
{ 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;//半個(gè)分度的原始碼
follow_bound=i*half_sel_bound;//計(jì)算零位跟蹤時(shí)的原始碼,按3000分度
time_weight=200;
void ver_disp(void)//顯示版本號(hào)及最大量程
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延時(shí)
beep_time=3;
led_disp(bdf.max_weight,5);//顯示最大量程
weight_led[0]=15;// F
delay60ms(20);//40ms延時(shí)
2、信號(hào)采樣與A/D轉(zhuǎn)換子程序的設(shè)計(jì)
extern uchar code adcount2[3];
extern bit bAd;//已產(chǎn)生AD值
extern bit b_warnled;
extern bit b_steady;
extern bit b_up_last;
extern uchar adup_count;
extern ulong idata ad_steady;//AD數(shù)據(jù)處理后的穩(wěn)定值
extern uchar add_count;//AD累加計(jì)數(shù)器
extern ulong idata add_val;//AD累加值
extern uchar wdcount;
extern uchar adup_count;//AD異常值計(jì)數(shù)
extern uchar addcount3;
extern ulong idata up_val;
extern ulong idata adval;//AD芯片采樣值
extern ulong idata lvbo[6];
extern uchar idata follow_time;//零位跟蹤時(shí)間
extern uchar idata time_weight;//重量為0時(shí),消隱時(shí)間
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();//時(shí)間計(jì)數(shù)器自減
//--------------------------------------------------------
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、鍵盤(pán)/顯示子程序設(shè)計(jì)
extern bit b_keyok;//有按鍵產(chǎn)生標(biāo)記
extern bit b_longdown;//長(zhǎng)按下標(biāo)記
extern uchar key_num;//鍵值
extern uchar key_temp;//臨時(shí)鍵值
extern uchar key_count;//鍵長(zhǎng)按計(jì)數(shù)
extern uchar key_dly;//鍵去抖動(dòng)延時(shí)
extern uchar beep_time;//蜂鳴時(shí)間
void key_scan1();////按鍵松開(kāi)或沒(méi)有按下處理
/****************************************************/
oid disp_t1(void) interrupt 3 using 1//顯示中斷程序
uchar temp;
TR1 =0;
P_OE=1;//高阻態(tài),禁止輸出
if((disp_number==(5-bdf.dp))&(bdf.dp!=0))//這一位是否有小數(shù)點(diǎn)
temp=0x08;//小數(shù)點(diǎn)段碼
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;}//不鳴叫時(shí)置高,減小電流
if(key_dly)//按鍵去抖動(dòng)延時(shí)
key_dly--;
if(flash_num《6)
if(flash_time)//閃爍計(jì)時(shí)
flash_time--;
{ b_flash=!b_flash;flash_time=20;}//時(shí)間到,置閃爍標(biāo)記
TH1 =0xf8;
TL1 =0x18;
TR1 =1 ;
評(píng)論