黄金会员
主题
帖子
积分6574
阅读权限40
注册时间2009-11-12
最后登录1970-1-1
在线时间 小时
|
本帖最后由 locky_z 于 2010-3-2 13:52 编辑
参考AVR - Transistortester的电路图,用STC12C5412AD重新做,程序是重新编写,没有参考M8的源程序
这个着重改进的地方是管子参数的测量,加多一档基极电流量程,使测出的管子参数更准确。总电路图如下:
因为不知道手头的LCD是否正常,因此没有接LCD显示,而是通过串口输出到PC机的串口进行显示。
这个电路中STC12C5410还剩下6只IO脚,足够可以驱动4线接口的LCD,只需加上LCD显示代码即可。
原理简述如下电路:
以X测量端子为例
它由4个输出端子(PX1 PX2 PX3 PX)驱动,这4个端子是mcu的IO端口,
这里关键是利用IO端口可以设置为1或者0的推勉输出状态,也可以设置为高阻抗输出状态,当设置为高阻抗输出时,等于该IO口接的那个电阻悬空了,也就不影响其他电路。
PX1接470欧电阻,一般用于接集电极测量状态
PX2 PX3分别接120K和680K,被测管的基极电流就由这两只电阻提供,分成2个基极电阻目的是为了产生足够大的基极电流范围。
PX是没有接电阻,直接由IO端口驱动,主要用于接被测管的发射极或者源极。
制作中原本以为,PX1输出1时,PX1这一点的电压就是5V,如果要测量470欧上的电流时,只需直接测出VX2这一点电压,再用5减VX2,就可以知道470欧上的电压了。 但实际上,档PX1输出5mA电流时,PX1这一点的电压已经掉落到4.7V了。因此不能认为PX1输出1时,PX1这一点电压为5V,必须用多一个AD通道来测出PX1这一点的实际电压。
因此X测量端子有2个采样点需要电压测量,分别是VX1和VX2,用于测量470欧上的电压,以便换算出集电极电流Ic.
但PX2 PX3就不需了,因为这两个通道接的是120K以上的电阻,吸取的电流极少,因此PX2,PX3这两个点的电压值就是0或者5V。
VX2这一路ADC实际上和PX是同一个端口,因为需要使用PX输出时,此时PX肯定接发射极,没必要测出这一点电压;而当需要VX2测量时,X端子肯定不会当发射极的,即PX肯定是高阻抗状态,不会影响这端口的ADC测量。
管子识别的原理是归纳出各种器件的真值表,
例如将X Y Z端子分别设置成0或者1的状态,共有6种组合状态,测量MOS和JFET管时的真值表如下
判断上面管的程序如下
code unsigned char FETTABLE[6]={0x1,0x4,0x5,0x10,0x11,0x14};
//对应 X Y Z为 001 010 011 100 101 110
//=================================================
bit IsFET()
{
char acBuf[16];
unsigned char i,state,state2,j,Pin;
int v1,v2,v3;
state=0;
for(i=0;i<12;i++)
SetPortZ(i);
//设置所有输出为高阻
// 按001 ~ 110 这6种顺序分别设置X Y Z通道 ,并测量,
//只要 导通 则记录其状态,
for(i=0,state2=0x20;i<6;i++)
{j=FETTABLE;
SetPort(PZ1,j&0x3);
j>>=2;
SetPort(PY1,j&0x3);
j>>=2;
SetPort(PX1,j&0x3);
GetVoltage(1);
v1=abs(Voltage[VX1]-Voltage[VX2]);
v2=abs(Voltage[VY1]-Voltage[VY2]);
v3=abs(Voltage[VZ1]-Voltage[VZ2]);
if (v1+v2+v3>7)
{state|=state2;}
state2>>=1;
}
//根据上面测出的状态 判断出管脚和类型 并用源极接120K电阻方式 测量夹断电压
v1=v2=0;
for(i=0;i<12;i++)
SetPortZ(i);
//设置所有输出为高阻
state2=0;
v1=v2=v3=0;
switch (state)
{case 0x13:
// NMOS X->G Y->S Z->D
state2=5;
Pin=16;
TestMOS(state2,PinX,PinZ,PinY,&v1,&v2,&v3);
break;
case 0x23:
// NMOS x->G Y->D Z->S
state2=5;
Pin=15;
TestMOS(state2,PinX,PinY,PinZ,&v1,&v2,&v3);
.......... //省略....
default:
return 0;
}
void TestMOS(unsigned char type, unsigned char G,unsigned char D,unsigned char S,int *Vth,int *Vgs,int *I)
函数是 测出被测管的夹断电压Vth,以及源极接470欧时的Vgs以及Id。
需要外面传入GDS这3只脚分别是对应XYZ那一个通道。
而BJT管以及二极管、电阻则用2端测量方式,即设置XYZ其中某一个端子为高阻状态,其余两个端子分别为0和1,以便判断出其结的极性以及管脚,
其真值表如下
code unsigned char DIODETABLE[6]={0x12,0x6,0x24,0x21,0x18,0x09};
// 对应 X Y Z为 10Z 01Z Z10 Z01 1Z0 0Z1
code unsigned char DIODEVOLTAGETABLE[6]={VY2,VX2,VZ2,VY2,VZ2,VX2};
//============================== 判断是否BJT Diobe Resist
bit IsQDR()
{
char acBuf[16];
unsigned char i,state,state2,vH,Pin;
int VBE,HFE,IC;
state=0;
for(i=0;i<12;i++)
SetPortZ(i);
//设置所有输出为高阻
//下面设置 X Y Z分别输出 0 1 Z(共6种组合),得到被测管状态,根据状态判断被测管是啥类型 引脚如何
for(i=0,state2=0x20;i<6;i++)
{vH=DIODETABLE;
SetPort(PZ1,vH&0x3);
vH>>=2;
SetPort(PY1,vH&0x3);
vH>>=2;
SetPort(PX1,vH&0x3);
GetADC(DIODEVOLTAGETABLE);
vH=ADC_DATA;
if (vH>0) //Vh是10bitAD结果数据中的高8bit,如果等于1,已经表示是有4×5=20mV了。
state |=state2;
else
{ // 如果被测器件是大电阻,那么Vh这个电压也会很低,所以再切换到120K方式来判断。
SetPortZ(PX1);
SetPortZ(PY1);
SetPortZ(PZ1);
vH=DIODETABLE;
SetPort(PZ2,vH&0x3);
//切换到 120K
vH>>=2;
SetPort(PY2,vH&0x3);
vH>>=2;
SetPort(PX2,vH&0x3);
GetADC(DIODEVOLTAGETABLE);
vH=ADC_DATA;
if (vH>3)
state |=state2;
SetPortZ(PX2);
SetPortZ(PY2);
SetPortZ(PZ2);
}
state2>>=1;
}
for(i=0;i<12;i++)
SetPortZ(i);
//设置所有输出为高阻
state2=0;
HFE=VBE=IC=0;
switch (state)
{case 0x22: // NPN X=B NPN管 基极是X
state2=1;
if (TestBJT(1,PinX,PinY,PinZ,&VBE,&HFE,&IC)) //尝试BCE 如果管子导通,则TestBJT返回1, 并测出参数
{Pin=1;}
else if (TestBJT(1,PinX,PinZ,PinY,&VBE,&HFE,&IC)) //否则尝试BEC,
{Pin=2;} //BEC
else
{Pin=0;} // 如果仍旧不通,当作NPN, 只给出B极是那个脚,不给出其他脚状态。
break;
....
case 0x30: //Resist
if (!TestResist(PinX,PinY,&VBE,&IC)) return 0; //是电阻,测出电阻参数,
state2=4;
Pin=9;
break;
。。。
//==================================== 测量NPN PNP 的 Vbe Hfe Ic参数 ==============================
// type=1 为NPN 0-> PNP
// B存放 对应X Y Z那个端口
// C E 同上
//函数返回: 如果可以测出参数,返回1, 同时VBE HFE IC存放测量结果
bit TestBJT(unsigned char type,unsigned char B,unsigned char C,unsigned char E,int *VBE,int *HFE,int *IC)
{unsigned char i,vc;
long RB,vrc;
if (type) //type=1 NPN
{SetPort(P680K[B],1); // 首先尝试 RB=680K
SetPort(P470[C],1); // 集电极接470欧的通道置 +5V
SetPort(PP0[E],0); //发射极置0V,这里使用PX而不是PX1,这样就将E通道的470欧 旁路掉
GetADC(Vn2[C]); // 读集电极电压
vc=ADC_DATA;
if (vc<=0xFa) //如果集电极电压小于4.88V,说明此时Ic已经足够大,认为管子导通了,
{ if (vc>235) // 如果集电极电压大于4.6V,说明此时Ic小于0.8mA,就切换到RB=120K
{SetPort(P120K[B],1); //RB=120K set 1
SetPortZ(P680K[B]); //680K 这档设置为高阻。
RB=4085; // 其实 RB=120K*16/470=4085 这里扩大16倍,以便避免浮点运算
}
else
RB=23149; // 其实 RB=680K*16 / 470=23149
GetVoltage(24); //24次AD采样平均
*VBE=(long)5000*(Voltage[Vn2[B]]-Voltage[VH[E]])/1024; // 换算成mV单位
vrc=Voltage[VH[C]]-Voltage[Vn2[C]];
*HFE=(RB* vrc / (1024-Voltage[Vn2[B]]))/16; //因为RB增大了16倍,所以要除于 16
*IC=(long)4883 *vrc/470; //此时的集电极电流 以uA为单位 4883其实是 5,000,000uV / 1024 = 4883
return 1;
}
return 0;
}
// PNP
else
{SetPort(P680K[B],0);
SetPort(P470[C],0); //PNP管 集电极接地
SetPort(PP0[E],1); //发射极接+5V
GetADC(Vn2[C]);
vc=ADC_DATA;
if (vc>=6) //if v more then 0.12V mean BJT open
{
if (vc<20) // if v less 20(0.4V) mean Ic less 0.8mA then change RB=120K
{SetPortZ(P680K[B]);
SetPort(P120K[B],0);
RB=4085;
}
else
RB=23149;
GetVoltage(24);
*VBE=(long)5000*(Voltage[VH[E]]-Voltage[Vn2[B]])/1024;
vrc=Voltage[Vn2[C]]-Voltage[VH[C]];
*HFE=RB* vrc /(Voltage[Vn2[B]])/16;
*IC=vrc*4883/470; //uA
return 1;
}
return 0;
}
}
下面是C的源程序以及hex文件
编译出来是5022字节,你可以扩充更多器件识别和LCD显示进去。 |
评分
-
查看全部评分
|