这个算是开发中的小技巧了,也不知道如何起标题。
通常为了节省单片机的引脚,我我们同城会使用比较多的数字电路来扩展,比如74hc574的D触发器,74ls138的38译码器,3态八路缓冲器/线路驱动器74hc541,还有就是串进并出的74hc595.
当然还有与非门、与门、或门等等最基本的数字逻辑电路来构成gpio的扩展。
数字电路的扩展的理解:
这里有两点比较值得注意的, 1、很多时候,8个引脚会控制16个引脚,通过d触发器来进行选择哪个8路,而且有可能前级的触发器引脚也是有几个(比如3个)来控制的,因此引脚1的上升沿输出的时候,就不能影响到引脚2的电平,因此前三个引脚在真值表设计的时候,就要注意,1上升沿的时候,2引脚保持高电平或保持低电平,反过来同理。
2、38译码器当中也有使能端的,比如74ls138,只有e3=H,E1=L,E2=L的情况下,就会正常输出某一路低电平,而如果上述三个是能引尖叫有一个电平不正常就会输出全H。这样就可以两个引脚同时互斥的控制两个38译码器。从而到达引脚的扩展。
软件编程 通常硬件工程师在设计的时候是有一定的规律的,但是不一定十分符合软件的编写,因为涉及到pcb的布局等,因此需要软件来完成。 举个例子:
D触发器的输出引脚是这样的,对应到电路上面某一个设备的序号是红色标注的,很明显,不太符合我们软件上面的操作,我们希望Q0-Q7按顺序递增,但是很无奈,实际是乱序的,因此可以保存一个枚举,把后面的乱序的做一个整理。
举个例子: 左边是实物上器件的序号,右边是D触发器的引脚序号。 typedef enum { VAT0=5 VAT1=0 VAT2=2 VAT3=1 . . VAT6=7 VAT7=4 };
然后定义一个数组: const static vat_conv[]= { [0] = VAT0 [1] = VAT1 [2] = VAT2 [3] = VAT3 . . . };
从这个数组可以看到,我要控制0通道的设备,实际上,软件是操作VAT0的引脚。省去了穷举法的if语句。
最后在函数中的参数如下: void set( uint8_t ch) { set_driver(vat_conv[ch]); }
这样,set函数参数ch可以直接是0-7,具体的驱动由set_driver来完成,期间用数组来转换即可,非常类似以前数码管的操作。 总不可能用穷举法的方式,点亮1,输出8bit数据,点亮2,在数据,8个if语句,多浪费。