It has been far too long since I have put up a new post so I thought I would share some techniques I've discovered while working with low pin count micro-controllers like the ATtiny85, LPC810 and the PIC16F1827. A lack of IO pins can be a limiting factor but there are a number of ways to get more functionality out of what is available. This post covers five useful techniques I have used in various projects.

Please note that the schematics in the post are only meant to give you an idea of how the technique works - you will need to adjust component selection and values to suit your specific application.

Use a Single Pin to Select Two SPI Devices

When you are using SPI based devices the number of pins required can add up very quickly especially if you have more than one in your circuit. You can share the bus lines (MISO, MOSI and SCK) but you will need a separate CE line for each device.

One Pin Select

If you only have two devices on the SPI bus you can use a single pin to switch between them by inverting the selection state to drive a second output, one device will always be selected but you at least have some control over which one it is.

The circuit to the left shows how to achieve this. The SELECT output from the CPU is passed directly to SEL0 and is used to control the select line of the first device. The SEL1 line for the second device is controlled by a NOT gate constructed from a resistor and a transistor. The resister holds SEL1 high while SELECT is low, when SELECT is high the NPN transistor is switched and SEL1 will be pulled to ground selecting the second device.

This simple construction of a NOT gate is very useful and will show up in some other circuits in this post.

Analog and Digital Input on a Single Pin

If you need a single push button in your design you can share a pin with an analog input with one small caveat - that you don't need to measure analog values that are close to 0V.

Shared Input Pin

The circuit to the left shows a good example of this - using a single pin to measure battery voltage as well as a single push button input in a battery powered circuit. In this case the battery voltage is read through a voltage divider that halves the value, giving a range of 0V to 4.5V. Because the battery will never read 0V (the processor would not be running in that case) we can connect a push button between the analog input and ground and use the 0V reading to indicate a button press.

Read Multiple Buttons from One Analog Pin

If you need more than a few buttons in your design you will find that it starts to chew up IO pins very quickly. If you only need to read the state of a single button at a time (no button combinations) you can use a single analog input.

One Pin, Many Buttons

The circuit to the left shows a design to achieve this that I discovered in the Arduino Basic Connections book and covered in detail in a previous post.

Essentially the circuit is a resistor divider, when a button is pressed it selects a different point in the resistor chain to measure which changes the ratio of the divider and the final output voltage. The 1M resistor between ground and the final output ensures the analog pin isn't floating when no buttons are pressed.

As I mentioned earlier, this circuit is only useful if only one of the buttons is pressed at once. This makes it suitable for simple menu navigation or options selection which is often all you need.

Single Pin Serial Port

I have covered this in a lot more detail in a previous post but it is worth mentioning again. If your controller does not have a hardware UART available you can still achieve reasonably high speed serial communications by implementing one in software using bit banging.

One Pin Select

Ralph Doncaster took the technique a step further to implement half duplex serial communications on a single IO pin with a handful of discrete components as shown in the circuit to the right.

There are a number of limitations with this circuit:

  • Any bit received on the RX line will be echoed on TX. This means the client will see an echo of everything that it sends. * It is half-duplex, you can only be sending or receiving - not both at the same time. * The firmware implementation needs to swap the direction of the IO pin to suit the operation being performed.

    Once implemented correctly the technique is very reliable - I use it in my serial bootloader implementation for the ATtiny85 and there is support for it in my ATtiny85 template library as well.

Generating a RESET Pulse from SCK

This is another one from Ralph Doncaster and once again relates to SPI. The specific example used by Ralph is to control the CSN pin on a NRF24L01 module from the SCK line but the technique can be adapted to other scenarios.

A number of SPI devices have a RESET input which is used to initialise the device and, in a some cases, this may need to be done under software control rather than through a power on reset circuit. The classic Nokia 5110 LCD module is a good example of this.

RESET from SCK

The circuit to the left shows how to drive the RESET pin using the SCK. In general the SCK line is oscillating as data is fed to the device, this circuit uses long (more than a few microseconds) pulses to trigger a low level on the REST output.

When SCK goes high for several microseconds, C1 will charge through R1 and switch the transistor, bringing the RESET line low. If SCK is brought low for several microseconds before being used to clock the SPI data, C1 will discharge and the transistor will be switched off allowing RESET to be pulled high by R2. High pulses on SCK of less than a few microseconds during normal SPI operation will not be enough to charge C1 - the transistor will remain switched off and RESET will be pulled high.

If you keep the SCK line low during idle periods you can control the RESET line using a long initial high pulse on SCK.

Summary

These techniques are very useful when you are trying to get the most out of the pins available to you and most of them only require a small number of additional components. If you find you are using a large combination of them in a single circuit though you should probably consider using a CPU with a higher pin count.

I would love to hear about additional methods people are using, please post your favourites in the comments.