一乐电子

一乐电子百科

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 13038|回复: 30
收起左侧

我做的STC-Transistortester

  [复制链接]
发表于 2010-3-2 13:37 | 显示全部楼层 |阅读模式
本帖最后由 locky_z 于 2010-3-2 13:52 编辑

参考AVR - Transistortester的电路图,用STC12C5412AD重新做,程序是重新编写,没有参考M8的源程序

实物图.jpg
这个着重改进的地方是管子参数的测量,加多一档基极电流量程,使测出的管子参数更准确。总电路图如下: 1.gif
因为不知道手头的LCD是否正常,因此没有接LCD显示,而是通过串口输出到PC机的串口进行显示。
这个电路中STC12C5410还剩下6只IO脚,足够可以驱动4线接口的LCD,只需加上LCD显示代码即可。

原理简述如下电路:
原理图.gif

以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管时的真值表如下
MOS真值表.png JFET真值表.png

判断上面管的程序如下
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,以便判断出其结的极性以及管脚,
其真值表如下
其他管子真值表.png


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显示进去。

transistor.rar

12.13 KB, 下载次数: 1276, 下载积分: 一乐金币 -1

评分

参与人数 4 +24 一乐金币 +15 +2 收起 理由
lbx7272 + 3 赞一个!
hldiy + 2 + 2 + 2 精品文章
fat + 12 原创作品,了不起。
fujiachun + 10 + 10 强大,学习中

查看全部评分

发表于 2010-3-2 14:12 | 显示全部楼层
支持原创.下载来看看.谢谢了!
发表于 2010-3-2 14:14 | 显示全部楼层
可惜我没有STC单片机,收藏备用啦
发表于 2010-3-2 14:15 | 显示全部楼层

S

本帖最后由 qpzmg 于 2010-3-2 14:28 编辑

上位机软件呢?用哪个?STC89C58RD+能用吗?
发表于 2010-3-2 16:14 | 显示全部楼层
谢谢分享,正学习这个,您这样一说,好多地方都明白了
 楼主| 发表于 2010-3-2 16:47 | 显示全部楼层
上位机任意一个字符终端、串口程序都可以,56000bps,

是专门针对STC12C5410AD编写,他带8路10bit AD的,
换其他端口要改一下某些控制码
发表于 2010-3-2 17:47 | 显示全部楼层
收藏备用,这个不错,期待完善
发表于 2010-3-2 18:26 | 显示全部楼层
m8的Transistortester就是这个大大最先发现的。后来从长汀1传十,十传百。。

在后来就有人想出套件了。哈哈!

目睹一切经过。。...
客官来玩啊。
发表于 2010-3-2 21:17 | 显示全部楼层
作个记号,这两天感冒吃了药晕晕乎乎的,脑子不清醒,明天出差,过几天回来再学习。
发表于 2010-3-5 16:47 | 显示全部楼层
本帖最后由 mdy-5153 于 2010-3-5 16:50 编辑

L的程序里已经有LCD了吧?

本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2024-4-20 22:21 , Processed in 0.078922 second(s), 53 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表