利用AT89S52型单片机智能电子称系统设计

嵌入式设计应用

132人已加入

描述

本文为大家带来利用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:电源电压

GND:地

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 ;

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分