1、基础认识
一个gpio脚配合软件可以实现高,低,高阻三种状态的区分,那么
最多可以实现三种指纹硬件的兼容.
软件逻辑:
1》先给PIN一个高电平,然后读出该PIN的电平到val1;
2》再给PIN一个低电平,然后读出该PIN的电平到val2;
若:
val1 == 1 && val2 == 1 ==》PIN外接高电平;
val1== 0 && val2 == 0 ==》PIN外接低电平;
val1 == 1 && val2 == 0 ==》PIN脚高阻态,或者悬空态;
代码实现:
fp_pin = of_get_named_gpio(np, label, 0);
if (fp_pin <= 0) {
klog("%s:fp pin gpio config err!\n", __func__);
return -1;
}
// HIGH
gpio_direction_input(fp_pin);
gpio_direction_output(fp_pin, 1);
val1 = gpio_get_value(fp_pin);
// LOW
gpio_direction_input(fp_pin);
gpio_direction_output(fp_pin, 0);
val2 = gpio_get_value(fp_pin);
klog("%s: (%d, %d, %d)\n", __func__, fp_pin, val1, val2);
if (val1 == 1 && val2 == 0) {
klog("#~~~~ High impedance!~~~~ \n");
ret = __HIGH_IMPEDANCE;
}
else if (val1 == 0 && val2 == 0) {
klog("#~~~~ LOW~~~~ \n");
ret = __LOW;
}
else if (val1 == 1 && val2 == 1) {
klog("~~~~ HIGH ~~~~ \n");
ret = __HIGH;
gpio_direction_input(fp_pin);
gpio_direction_output(fp_pin, 1);
}
else {
klog("Err -what the fuck ??? \n");
return -1;
}
2、原理推导
如上等效电路图分析:
Vi 表示PIN脚外接指纹模组的电压,我们最终需要知道的结果就是这个电压是高还是低;
Vcc表示单片机输出高电平时候的等效电路;
V0表示单片机读取的电压值等效电路
R1表示指纹模组接到GPIO PIN脚的限流电阻,这个值通常很小,大概是0-10欧;
R2表示单片机输出高电平时候的内阻,这个值通常也比较小以输出功率6mA算,大概是(1.8v/6)*10^3=300欧,可以看出R2 远大于R1
R3是单片机对地阻抗,通常是几k到几十k欧,可以看出远大于R1,R2
从以上推导:
V0 = Vi/R1 + vcc/R2 - 1/R3 - 1/R2 - 1/R1
R1 << R2
R3 >> R2
场景1:
若Vi接高电平:
那么Vi =1.8v,单片机给高电平,那么Vcc = 1.8v,那么:V0 ~= 1.8*(1/R1+1/R2) - 1/R1 -1/R2
由于R1 << R2,那么V0的值主要是由R1决定,所以V0的值主要由Vi决定,当R1==0时候,V0==Vi
同理可证
只要R1取值合适,不管Vi接高电平还是低电平,V0的值主要由Vi决定,可以判断Vi外接高电平.
场景2:
若Vi接地呢?
那么就跟下图这个分析是一样了,等价于上图的R1跟R3并联了(相当于下图的R2),当R1<<R2的时候(上图中的R1,R2,R3),V0由R1决定,也就是跟接Vi高电平一个道理,V0由外部决定,这个时候就可以判断Vi外接地了.
场景3:
若Vi接的模组悬空呢?
Vi == 0
那么V0 ~= Vcc/R2 ==》,R2本身就是单片机的输出阻抗,如此当然是单片机给高就是高,单片机给低那V0就是低了。这个时候就可以判断Vi是悬空,也就是所谓高阻了。