|

楼主 |
发表于 2017-11-22 20:03:30
|
显示全部楼层
本帖最后由 LHZ07206 于 2017-11-22 20:37 编辑
由于图片说明字体显示不全,发个完整文档:
一、显示器功能:
利用单片机,对编码器反馈脉冲或其它脉冲信号进行计数,如果用于起重机械,可以显示起升的高度,如果用于其它方面,可以显示行程距离或对物品进行计数。
二、技术要点:
1、由于数据需要连续动态显示,而且显示的位数不固定,要从一位数逐步跳变为多位数,因此设计了加一、减一程序,用C语言编程成为独立的函数模块,在中断程序中根据需要进行调用。
2、使用电源监控芯片监测系统工作电压,在掉电的瞬间通知单片机对数据进行存储操作。
3、无需内置电池,利用I2C总线,使用E2PEOM元件AT24C08对当前数据进行存储,实现了断电记忆。
三、设计思路:
本装置由以下几部分组成:数字脉冲输入电路(包括光电耦合、方向判别)、计数及运算控制电路(脉冲计数、零点设置、断电记忆)、驱动电路(数码管显示及预置报警)。
1、获取编码器反馈脉冲,根据电机转速、编码器脉冲数、减速箱变比和钢丝卷筒直径,可以测算出钢丝绳每运行0.01米所需的脉冲个数,将此数值作为单片机计数中断值固化在程序中,通过数码管将高度值以厘米级的精度动态显示出来,最大可显示到正负999.99米(根据需要可以任意扩展)。
2、设“零点设置”按钮,此按钮的作用在于:(1)更换钢丝绳后用来校准取物装置的零点位置。(2)无论吊钩在什么位置,都可利用此按钮将显示器置零,以当前位置为零点,显示某一段起升或下降的距离。
3、断电记忆当前位置。如果不采取措施,在起重机工作中出现断电的情况下,则需重新设置零点位置。为了保存掉电前吊钩的位置数据,利用电源监控芯片MAX708监测工作电压,在掉电的瞬间触发外部中断,单片机执行中断服务程序,将现场实时数据写入E2PEOM中。上电复位后,则先从E2PEOM中读出数据送到显示器,实现了现场数据的恢复。
4、I2C总线的软件实现。由于E2PEOM元件AT24C08与AT89S52单片机的连接采用I2C总线,而廉价的普通单片机不带有I2C总线接口,因此本系统采用普通I/O口通过软件模拟I2C总线协议,虽然软件编程上稍微复杂一些,但是与自带锂电池的NVRAM芯片相比,降低了成本,是一种廉价、实用的方法。
四、具体电路及程序:
1、具体电路如图所示:
(1)本装置采用MAX7219驱动数码管显示器实现数据的连续显示,MAX7219是一种串行接口8位LED显示驱动器,仅需使用单片机3个引脚,即可实现对8位LED数码管的显示控制和驱动,线路非常简单,控制简单方便。对MAX7219的控制编程主要分为:初始化子程序(主要是对MAX7219的显示模式、显示亮度、显示位数等进行初始化),以及送显子程序。
(2)数据信号的采集,将编码器的反馈信号,输入高速光耦6N137,6N137是一款用于单通道的高速光耦合器,转换速率高达10MBit/s。A、B两路脉冲信号经过光耦输出分别接至双D触发器74HC74 的时钟端CLK和控制端D,正转时,A信号的相位超前B信号90°,Q输出端始终为高电平。反转时,A信号的相位延后B信号90°,Q输出端始终为低电平。因此,通过读取Q的电压高低,就可以判别光电编码器的转向,进行加、减计算,同时将A脉冲输入到单片机的P3.2引脚进行计数。根据电机的转速、减速箱的变比、钢丝卷筒的直径,可以测算出经过多少个脉冲,等于实际高度1厘米的距离。将此脉冲数作为单片机的外部中断计数计数值,在中断程序中调用加一或减一函数。
(3)为了保存掉电前吊钩的位置数据,利用E2PROM元件AT24C08和电源监控芯片MAX708实现掉电数据保存。24C系列串行EEPROM具有断电以后存储的数据不消失的特点,而且体积小、功耗低、占用I/O口线少,读写操作相对简单。既可由软件对其内容进行随机读写,又可在芯片断电的情况下长期保存片内信息,本系统采用普通I/O口通过软件模拟I2C总线协议,在掉电前将实时数据写入E2PEOM中,上电复位后,则先从E2PEOM中读出数据送到显示器,实现了现场数据的恢复。掉电检测功能由芯片MAX708实现,MAX708是一种微处理器电源监控芯片,可同时输出高电平有效和低电平有效的复位信号。复位信号可由VCC 电压、手动复位输入或由独立的比较器触发。独立的比较器可用于监视第二个电源信号,域值为1.25 V、用于电源失效或低电压报警,为处理器提供电压跌落的预警功能。
2、程序设计:(MAX7219、AT24C08通信协议及部分函数定义省略)根据某种起重机的需要,计算出127个脉冲进行加一操作。
#include <AT89X52.H>
#include <intrins.h>
#include <absacc.h>
#define uchar unsigned char
uchar sh[6]={0x00,0x00,0x00,0x00,0x00,0x00};
uchar ql[6]={0x00,0x00,0x00,0x00,0x00,0x00};
void timer0(void)interrupt 1 /*计数器中断服务函数,判断正转,调用*/
/*加、减1程序*/
{
while((sh[0]==0)&&(sh[1]==0)&&(sh[2]==0)&&(sh[3]==0)&&(sh[4]==0))
{
if(p1_5==1)
{
sh[5]=0x00;
jia_yi();
}
else
{
sh[5]=0x0a;
jia_yi();
}
}
if(sh[5]==0x00)
{
if(p1_5==1)
jia_yi();
else
jian_yi();
}
else
{
if(p1_5==1)
jian_yi();
else
jia_yi();
}
}
void int0(void) interrupt 0 /*外部中断服务函数, 判外部清零按键*/
{
uchar *w;
w=ql;
write_nbyte(0xa0,0x00,w,6);
sh[0]=0;
sh[1]=0;
sh[2]=0;
sh[3]=0;
sh[4]=0;
sh[5]=0;
p3_2=1;
}
void int1(void) interrupt 2 /*用MAX708检测电源电压,掉电时触发*/
/*中断程序*/
{
uchar *s;
s=sh;
write_nbyte(0xa0,0x00,s,6);
}
void main()
{
uchar *s;
s=sh;
EX1=0; /*关外中断1*/
IT1=1; /*设外中断1为后沿负跳有效*/
IT0=1; /*设外中断0为后沿负跳有效*/
EX0=1; /*允许外中断0*/
IE1=1;
IE0=0;
p3_2=1;
p1_5=1;
TMOD=0x06; /*计数器工作在方式2*/
TH0=0x81; /*对TH0 TL0 赋值,计满127进入中断*/
TL0=0x81;
TR0=1;
ET0=1; /*允许计数中断*/
EA=1;
Init_Max7219();
x24c02_init();
read_nbyte(0xa0,0x00,s,6); /*从总线读取数据*/
EX1=1; /*读完数据后再开预警中断*/
while(1)
{
Init_Max7219();
Write_Max7219(0x01,sh[0]);
Write_Max7219(0x02,sh[1]);
Write_Max7219(0x03,sh[2]);
Write_Max7219(0x04,sh[3]);
Write_Max7219(0x05,sh[4]);
Write_Max7219(0x06,sh[5]);
}
}
|
|