© Stewart Watkiss 2020
S. WatkissLearn Electronics with Raspberry Pihttps://doi.org/10.1007/978-1-4842-6348-8_11

11. Understanding Digital Logic

Stewart Watkiss1 
(1)
Redditch, UK
 

Digital logic is the basis around how all digital electronics work including the basic building blocks for creating a computer such as a Raspberry Pi. It’s an interesting subject, but there is too much to cover just using practical projects. This chapter is therefore going to be more about the theory rather than learning through practical projects. At the end of the chapter, there will still be a practical element, which is based around 7-segment LED displays.

Some of the concepts on here are better explained through animation. I have created some videos which explain some of these concepts, which are on my website at www.penguintutor.com/electronics/digital.

Digital Logic and Binary

When talking about digital electronics, such as microprocessors and computers, information is represented by switches that turn the voltage between high and low. This has already been covered when using the GPIO ports where the output has been turned on or off which represent the high and low states. On the Raspberry Pi, there is no way of turning a GPIO port partway on; PWM was used to create the illusion of the port being partly turned on, but that was actually achieved by turning the output high and low quickly.

With only a single output, it is only possible to hold a tiny amount of data, but when multiple outputs are used together or a switch is turned on and off in a specific sequence, this can be used to represent anything you want. To provide meaningful data, the information is stored and manipulated using the binary numeral system.

Binary is a base-two number system with each digit either a 0 (which is represented in electronics as a logic low, such as 0V) or a 1 (which is represented in electronics as a logic high, such as 3.3V). Within processors, the information is grouped into multiple bits; it was common to have 8 bits which makes a byte, although most computers now are either 32-bit or 64-bit. Using a single byte which is 8 bits long, it is possible to represent up to 256 different values, which go from 000000002 (decimal 0) to 111111112 (decimal 255). Showing each entry as individual bits takes up a lot of characters, so it is common to show these as hexadecimal values, where 4 bits is replaced by a single hexadecimal character from 0 to F (where letters are used for values above 9). The maximum 8-bit number of is 111111112, represented as FF16. You may have already used hexadecimal values when dealing with colors in HTML.

The information in the binary numbers can be in parallel, which is across multiple wires known as a bus, or transmitted as a serial signal over a single wire. A bus is used internally within a processor and for connecting to memory, whereas serial transmission is normally used for connecting to external devices such as over USB .

Logic Gates

The basic building blocks used to create digital circuits are logic gates. There are four primary logic gates – NOT, AND, OR, and XOR, which can then be combined to create more complicated circuits. These are represented by circuit symbols used in schematic diagrams, as with other symbols, there are different standards. There are two shown for each, one of which is based around a distinctive shape for each gate and the other is based on a rectangular block. The logic gates are available packaged in integrated circuit (typically, 4 to 8 in a single IC) or are incorporated into more complicated circuits, which use the logic gates as building blocks.

NOT Gate (Inverter)

A NOT gate is also known as an inverter. It changes a low signal to a high signal and vice versa. The common circuit symbols are shown in Figure 11-1. In these symbols, the circle on the output indicates that these are inverting. An alternative symbol uses the same rectangular block as the symbol on the right but with a triangle in place of the circle.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig1_HTML.jpg
Figure 11-1

Circuit symbols for a logic NOT gate

The truth table is used to indicate the status of the output based on the inputs. In the case of the NOT gate, there are only two different states, which are shown in Figure 11-2.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig2_HTML.jpg
Figure 11-2

Truth table for a NOT gate

The truth table shows all possible inputs (A) and the corresponding outputs (X). The inputs are denoted by letters from the start of the alphabet, whereas the outputs are denoted by letters near the end of the alphabet; this is a convention that makes it easy to understand the difference between inputs and outputs.

A NOT gate can be created using a MOSFET. A basic inverting circuit has already been covered in Chapter 6 when creating a MOSFET buffer. When used previously, the inverting aspect was a side effect of the way the MOSFET worked rather than something we wanted. In this case, it is the desired effect. The basic circuit is shown in Figure 11-3.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig3_HTML.jpg
Figure 11-3

Example circuit for a MOSFET NOT gate

When the input is low, the MOSFET is switched off. The output is pulled high through resistor RL. When the input is high, the transistor switches on pulling the output low.

The circuit shown is just an illustration of how a NOT gate can be created. The circuit within a logic gate IC is more complicated than this. The output stage normally includes a p-type MOSFET in place of the resistor RL. The p-type MOSFET would operate the opposite to the n-type MOSFET. This means that the output is actively pulled up and pulled down instead of using a passive pull-up resistor. This allows the output to drive a bigger load and maintains the logic levels better. Using a n-type and p-type MOSFET in this way is known as CMOS (complementary metal-oxide-semiconductor). The input stage may also include additional components such as additional diodes to protect against a higher input voltage or static electricity.

AND Gate

The next logic gate is the AND gate. The AND gate has at least two inputs and only gives a high output when all the inputs are high. The logic symbol is shown in Figure 11-4.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig4_HTML.jpg
Figure 11-4

Circuit symbols for a logic AND gate

The truth table is shown in Figure 11-5. As you can see, the output is 0 for all inputs, except where A AND B are both 1.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig5_HTML.jpg
Figure 11-5

Truth table for an AND gate

The diagram in Figure 11-6 shows a circuit which can act as an AND gate. This is a conceptual circuit to demonstrate how an AND gate functions; an actual logic gate is more complex. As you can see from the diagram, to complete the path between the supply voltage at the top and the output X, both MOSFETs need to be switched on; therefore, both A and B must be high.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig6_HTML.jpg
Figure 11-6

Circuit demonstrating how an AND gate works

OR Gate

The OR gate has two or more inputs and has a high output if one or more of the inputs is high. The logic symbols for the OR gate are shown in Figure 11-7.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig7_HTML.jpg
Figure 11-7

Circuit symbols for a logic AND gate

The truth table for the OR gate is shown in Figure 11-8.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig8_HTML.jpg
Figure 11-8

Truth table for an OR gate

The diagram in Figure 11-9 shows a circuit which can act as an OR gate. This is a conceptual circuit to demonstrate how an OR gate functions; an actual logic gate is more complex.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig9_HTML.jpg
Figure 11-9

Circuit demonstrating how an OR gate works

As you can see from this diagram, there are two paths between the positive supply and the output. If either of the MOSFETs is turned on, then the output is high.

XOR Gate

The XOR gate is an abbreviation of exclusive OR. This will provide a high output when only one of the inputs is high. The symbols for the XOR gate are shown in Figure 11-10.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig10_HTML.jpg
Figure 11-10

Circuit symbols for a logic AND gate

The truth table is shown in Figure 11-11, which shows a high output when A or B is high but not if both A and B are high.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig11_HTML.jpg
Figure 11-11

Truth table for an XOR gate

Although previously I included XOR as a primary logic gate, it can actually be made up using other logic gates. This is shown in the circuit in Figure 11-12, which shows an XOR gate made up of NOT, AND, and OR gates.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig12_HTML.jpg
Figure 11-12

Logic circuit for an XOR gate using NOT, AND, and OR gates

This logic circuit diagram is significant as it shows how more complex operations can be made by joining logic gates together. In this case, the top AND gate has a high output if A is high and B is low. The bottom AND gate has a high output if A is low and B is high. Then the OR gate gives a high output if either of the two AND gates is high. This way, the output X is high when one input is high and the other is low.

NAND and NOR

Previously, I listed the four primary logic gates as NOT, AND, OR, and XOR; however, perhaps more important are the NAND and NOR gates. The NAND gate is effectively an AND gate, followed by a NOT gate, and the NOR gate is an OR gate, followed by a NOT gate. These are known as the complements of the AND and OR gates. These were made popular because they could be created more simply, but also could mimic the other logic gates. In that way, it is possible to take a circuit that uses any of the four logic gates and replace it with a circuit that uses just NAND or NOT gates. This was significant when circuits were created using logic ICs.

The circuit symbols are the same as the AND and OR gates, but with a circle or sometimes a triangle on the output. Some common symbols for the NAND are NOR gates, shown in Figure 11-13.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig13_HTML.jpg
Figure 11-13

Circuit symbols for logic NAND and NOR gates

Creating Logic Circuits – Adder

Using the different logic gates, it is possible to combine them into a more complicated circuit. An important function in microprocessors is the ability to add numbers together. Addition forms the basis of many mathematical operations in a computer and is also needed for counters which keep track of whereabouts the next instruction is in the program code.

The most basic form of adder circuit is known as a half adder. This is shown in Figure 11-14 created using an XOR and a AND gate.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig14_HTML.jpg
Figure 11-14

Half adder circuit

If both A and B are low, then both outputs are low. If one is high and the other low, then the sum is high, and carry is low. If both inputs are high, then the sum is low, but the carry is high. This is shown in the truth table in Figure 11-15.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig15_HTML.jpg
Figure 11-15

Truth table for a half adder

The reason that this is known as a half adder is because while there is a carry out, there is no carry in. If we want to use this on a more inputs (such as an 8-bit number), then there needs to be some way of including the carry in from the lower bit.

The improved circuit to support carry in as well is the full adder with the circuit shown in Figure 11-16.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig16_HTML.jpg
Figure 11-16

Full adder circuit

The full adder circuit is labeled with CIN for carry in, S for the sum, and COUT for carry out. If an 8-bit adder is needed, then that can be created by copying this diagram eight times and adding the carry out of each lower bit to the carry in of the next higher bit. If you create that circuit diagram, you would have to put 20 logic symbols. If you want to create an adder for larger numbers such as 16-bit, 32-bit, or 64-bit numbers, then the circuit diagrams are going to be very large. Fortunately, this can be simplified. Just like we use a logic symbol to hide the complexity of the actual transistors inside the gate, you can simplify an adder to a single symbol. The symbol for a full adder is shown in Figure 11-17.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig17_HTML.jpg
Figure 11-17

Circuit symbol for a full adder

As you can see, the complexity of the previous circuit is hidden in a single rectangle, which is labeled with the function of the circuit. This is commonly used for many different circuits to make it easier to understand and reduce the size of the diagrams.

In the case of an 8-bit adder, the symbol could be replaced with a single block with the single input A replaced with inputs A0–A7 and the same for the B inputs and the sum outputs. There will only be one carry in and carry out as the others are used internally.

This technique for simplifying circuit diagrams can be used for any level of complexity even to the point where it is used to represent the entire computer. This has already been used in numerous diagrams in this book where the Raspberry Pi is shown as a single block.

Using multiple full adders to create an adder does have a disadvantage when it comes to speed. Logic circuits act very quickly, but when chained together, the small delays can add up. In the case of the adder, the least significant bit performs the add before passing the carry out to the next stage. The output of the next stage in the adder is dependent upon that carry out from the first stage. This is known as a ripple carry adder. It is possible to instead have a fast adder which can calculate each bit of the number simultaneously, although the circuitry is increasingly complex.

Flip-Flops

The adder circuit is an example of a combinational logic circuit. This means that (except for the delay in updating the outputs) the logic output is entirely dependent upon the inputs at the time. It is sometimes necessary to store information either as a form of short-term memory (such as a register in a processor) or so that the information is presented to other stages of the circuit when they are ready to receive it. This needs sequential logic, of which the most basic form is the flip-flop. There are several different types of flip-flops, three of which are explained as follows.

Basic Flip-Flop

The basic flip-flop can be made up using two NOR or NAND gates with feedback between the output and input. The NOR and NAND gate circuits work in a similar way, although the NOR-based circuit is triggered by a high logic signal, whereas the NAND-based circuit is based on a low logic signal. The NOR circuit is a little easier to understand, so that is the one used here. The circuit is shown in Figure 11-18.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig18_HTML.jpg
Figure 11-18

Basic flip-flop with NOR gates

The flip-flop has two inputs, called set and reset. There are two outputs Q and Q'; these are complementary outputs. The Q is the data output and Q' the complement (opposite) of that output. The set input is used to set the flip-flop to the set state (Q=1), and the reset puts the flip-flop into the reset state (Q=0). I have labeled the NOR gates as A and B; this is purely to make the explanation easier.

The output from each of the NOR gates is used as an input to the opposite gate. This is feedback used to maintain the state of the flip-flop.

The initial state cannot be determined until either set or reset is taken high. When set is taken high (S=1), at least one input of B is 1 and then the output of the B=0. Assuming R=0, the output of the A depends upon the output of B. With B=0, A=1 and so the output Q=1. If set goes to 0, then gate B still has a high input from the output of A and so B=0. As such, the flip-flop maintains the set state and Q=1.

If set is at 0 and reset is set to 1, then A=0, which sets the output Q=0. As both inputs to B are now 0, B=1. If the reset now goes to 0, then the reset state is maintained by the feedback.

If you want to get a better understanding of how a flip-flop works, then this is shown in the truth table in Figure 11-19.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig19_HTML.jpg
Figure 11-19

Truth table for a basic NOR flip-flop

This truth table is different from the previous ones, in that there are now two lines with the same inputs (S=0 and R=0) but different outputs. This is because they are dependent upon the previous state. The final entry, where set and reset are both high, is invalid as both Q and its complement are the same. This state should be avoided when using flip-flops.

This basic flip-flop is useful for understanding how a flip-flop works, although the flip-flops that are normally used also include a clock signal.

SR Flip-Flop

The basic flip-flop provides the set and reset function that the SR flip-flop uses. The flip-flops that are used in most circuits had the added ability to determine at what point in time the data is stored into the flip-flop. This is done by adding either an enable signal (which is triggered by logical level) or a clock signal (which is edge triggered), so that the state of the flip-flop only changes when ready.

This is important when the flip-flop takes an input from a previous stage where there may be a delay before the data is valid. For example, with the ripple adder, there is a state where the output may change based on its inputs, but because the carry has not yet rippled through, the output is incorrect. In this case, the enable or clock signal would only be triggered after there has been time for the adder to complete its calculation.

The circuit symbols in Figure 11-20 show three different symbols based on different types of enable or clock signal.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig20_HTML.jpg
Figure 11-20

SR flip-flops with different enable and clock types

The symbol on the left is based on an enable input. The state of the flip-flop can change only when the enable (E) is high. If that signal is set permanently high, then it will operate the same as the basic flip-flop.

You will also note that the complementary output Q' is shown as Q with a line over it. These mean the same thing, that the output is the opposite of Q. The line above the output is often used in diagrams but is difficult to include in printed text so is sometimes replaced with Q'. It is also common to see inputs with a line over them, particularly the enable pin; this indicates that the input is based on the enable being low instead of high.

The other symbols show an arrow to indicate it is an edge-triggered clock signal. The default is for a positive edge trigger (when the clock changes from low to high), and the circle denotes a negative edge trigger (when the clock changes from high to low).

Note

You may also see reference to an RS flip-flop. The RS flip-flop is the same as the SR flip-flop in normal operations. They behave differently in the condition where set and reset are high. If this condition is triggered, then with the SR flip-flop the set takes precedent and with the RS flip-flop the reset takes precedent.

D Flip-Flop

The SR flip-flop is useful if you have a separate set and reset signal. It is often the case that you have a single input based on the output of a previous logic circuit. In that case, a D flip-flop is used, where D stands for data. The D flip-flop will store the data on its input based on the clock trigger. The symbol for a D flip-flop is shown in Figure 11-21.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig21_HTML.jpg
Figure 11-21

Symbol for a D flip-flop

One side effect of the D flip-flop is that it no longer has the invalid state, where both set and reset are triggered together. It does still have the state at the beginning when the status is undetermined.

Other Flip-Flops

There are other flip-flops and variations on the ones already shown. Some flip-flops have both enable and clock inputs allowing the clock to be connected to the system clock but only updating when enabled. Some also have additional inputs to set the flip-flop to a pre-determined state to avoid the unknown state when first turned on.

Connecting eight flip-flops side by side but sharing a single clock is known as an 8-bit latch, also known as an 8-bit register. Registers are a fundamental part of how computers work, allowing data to be held temporarily when retrieving from memory or for use as the input or output of any calculations within the processor.

Shift Register

Another use of flip-flops is to create a shift register, which is useful for converting serial data to parallel data. This will be used in an example circuit to reduce the number of pins needed to connect 7-segment LED displays to the Raspberry Pi GPIO.

To create the shift register, multiple D flip-flops are connected, with the output from one stage becoming the input to the next stage. This is shown in Figure 11-22.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig22_HTML.jpg
Figure 11-22

Shift register circuit

The example shows four stages in the shift register, although I will describe this in terms of an 8-bit shift register, which will be used for the practical example. As you can see, each of the flip-flops is connected using the output from the previous (Q) as the input to the next stage (D). They all share a common clock, so data is transferred simultaneously at each stage. The serial data goes into the first D flip-flop and is saved on the first clock pulse. The serial input is then set to the next bit of information, and on the next clock pulse, the data that is on the first flip-flop is passed to the next one and the new data is stored on the first flip-flop. This continues until all the data is shifted in; for an 8-bit shift register, this takes eight clock pulses. At that point, parallel out is now a parallel version of the serial data. There is also a serial data out which can be used for connecting to another shift register. This allows multiple shift registers to be connected without needing any additional outputs from the Raspberry Pi (or other driving circuit), but that is at the cost of time as that means that more data needs to be shifted through the shift registers.

In most circumstances, you would not want to see the data going through the shift register, so the parallel output should not change until all 8 bits have been sent through the register. To do this, we need an output register, or a latch, which is another use of the D flip-flop. In effect for each bit of data, there will be one D flip-flop for shifting the data in and one D flip-flop for latching that data to the output. A second clock is needed for the output, but that only triggers once for every eight pulses of the serial clock.

This is shown in Figure 11-23, which shows a high-level representation of the components.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig23_HTML.jpg
Figure 11-23

Shift to parallel shift register with latch

This diagram shows the shift register used to convert the serial data into parallel data, which is then fed into the latch. The shift register and latch have their own clock signal so that the latch only updates the parallel data out when the latch clock is triggered.

If you are looking to buy a shift register as an integrated circuit, then you do not need to buy the latch separately as the IC will include both. It may also have additional circuitry for output enable and sometimes an additional output buffer stage for driving large currents. One such example is the TPIC6B595 8-bit shift register, which is used in the next circuit.

Shift Register LED Circuit

After covering the theory of digital logic, it is now possible to put that into practice in a useful circuit. This will be a shift register that will provide eight outputs from the Raspberry Pi using only three pins from the GPIO. This will be used to drive LEDs.

The shift register will be provided by an integrated circuit, TPIC6B595. This is a shift register with built-in latch. One of the intended uses of this IC is in automobile dashboard displays, where it can be used to drive the LED warning lights. This is achieved through an open-drain output on the parallel data outputs. An open-drain output is where instead of having a push-pull output that is used for many CMOS logic gates, the outputs do not have any connection to the positive voltage but have MOSFET between the output and ground. This allows it to handle a larger current but cannot be used to drive other logic circuits without having a pull-up resistor (except for serial data out). Figure 11-24 shows a simplified version of an open-drain output, which would typically also include some protection diodes.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig24_HTML.jpg
Figure 11-24

Open-drain output

Another benefit to having an open-drain output is that a different supply voltage can be used for the load. This is useful if switching loads that need a different voltage.

The circuit diagram for the LED circuit is shown in Figure 11-25.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig25_HTML.jpg
Figure 11-25

Shift register LED display circuit

For this circuit, I have used a resistor network, which is eight resistors in a single package with a common connection. I have also used an LED bar graph display. The LED has ten LEDs in a single module, although I am only using eight of the LEDs for this circuit. The LED display and resistor network are for convenience, and to make it easier to see the individual lights, these can be substituted for standard 220Ω resistors and normal LEDs instead.

The program provided for this is a demonstration program to show how the shift register works. This is included in Listing 11-1, saved as shiftreg-demo.py.
from gpiozero import DigitalOutputDevice
from time import sleep
serial_pin = 22
serial_clock_pin = 23
register_clock_pin = 24
serial_out = DigitalOutputDevice(serial_pin)
serial_clock = DigitalOutputDevice(serial_clock_pin)
register_clock = DigitalOutputDevice(register_clock_pin)
def shift_bit (bit_value):
    serial_out.value = bit_value
    serial_clock.on()
    sleep(0.001)
    serial_clock.off()
def register_update ():
    register_clock.on()
    sleep(0.001)
    register_clock.off()
def shift_byte (byte_value):
    # shift data 1 bit at a time
    for i in range (0,8):
        # shift out 1 bit
        bit_value = byte_value & 0b00000001
        shift_bit (bit_value)
        byte_value >>= 1
    register_update ()
def slow_shift_byte (byte_value):
    # shift data 1 bit at a time
    for i in range (0,8):
        # shift out 1 bit
        bit_value = byte_value & 0b00000001
        shift_bit (bit_value)
        byte_value >>= 1
        register_update ()
        sleep(0.5)
print ("Resetting shift register")
shift_byte (0b00000000)
sleep(0.5)
print ("Slow shift to 00000001")
slow_shift_byte (0b00000001)
sleep(2)
print ("Slow shift to 10101011")
slow_shift_byte (0b10101011)
sleep(2)
print ("Shifting in 11001100")
shift_byte (0b11001100)
sleep(1)
print ("Shifting in 00110011")
shift_byte (0b00110011)
Listing 11-1

Shift register demonstration program

The code has four functions. The first is shift_bit, which shifts a single bit of data into the serial port. It does this by setting the serial output to the value and then sending a 1ms pulse on the serial clock signal. The next function is register_update, which sends a 1ms pulse on the register clock signal to send the value in the shift register to the output register. Using these two functions, you can manually send a bit at a time to the shift register. The next two are used to send a word at a time. The function shift_byte is the normal operation of a shift register sending 8 bits of serial data. It uses a bitwise AND (&) to extract the least significant bit and send that to the shift register. It then uses the bitwise right shift (>>=1) to shift the variable along one bit. Once all 8 bits have been sent, it calls register_update. The final function slow_shift_byte is similar to the shift_byte, but it runs register_update after each bit and has a delay, so you can see as each bit is shifted through the shift register.

The rest of the code provides a short demonstration – first resetting the shift register to all zeros and then running two slow shift examples so you can see the individual bits being pushed through the shift register. It then has two examples using normal operation where the output of the shift register does not change until all 8 bits have been sent.

The code uses binary notation (prefixed with 0b) for the demonstration, but it can be passed an integer instead and will work correctly. You can have the code run through an example of counting in binary by replacing the demonstration part of the code with the following:
print ("Counting in binary")
for i in range (0, 256):
    shift_byte (i)
    sleep (0.3)

This will count from 0 to 255, which is the full range of values that can be stored in an 8-bit number.

Logic Levels

If you build the circuit in Figure 11-25, then it will almost certainly work. However, note that I said “almost certainly”; it is technically an invalid design, so there is a chance it will not (although I expect only a slim chance it will not work). The reason that the design is invalid is because the Raspberry Pi GPIO and the TPIC6B595 are designed for different logic voltage levels. The Raspberry Pi GPIO is designed for 3.3V, whereas the TPIC6B595 for 5V. There is no danger of damage to the components, as the output is lower than the expected voltage, which may not be the case if it was the other way around. If you put the output from a 5V circuit into a 3.3V Raspberry Pi pin configured for input, then there is a high possibility you will damage the Raspberry Pi.

To understand this in detail, you need to look at the specification for both components. These details are normally taken from the datasheet, which will be explained further in Chapter 13. The details needed are the outputs from the Raspberry Pi GPIO ports and the inputs on the TPIC6B595. The table in Figure 11-26 shows these based on the relevant specifications.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig26_HTML.jpg
Figure 11-26

Table showing specified logic voltage levels

The values on the left show the logic level output from the Raspberry Pi. In the case of a logic low, the value will be no more than 0.14V and in a logic high (assuming 2mA output) will be at least 3.0V. The inputs to the TPIC6B595 are provided in terms of the supply voltage VCC. This says the input for a logic low should be no more than 0.15 x VCC and the input for a logic high should be at least 0.85 x VCC. With the supply voltage as 5V, this means that a low input must be no more than 0.75V (so the Raspberry Pi low signal is compatible) and a high voltage of at least 4.25V (of which the Raspberry Pi GPIO value is too low).

Looking at the input to the TPIC6B595, there is a range of voltages from 0.75V to 4.25V where the input voltage is out of the specified range. What happens if the voltage is in that unspecified area? In actual use, you will find that the shift register accepts a voltage much lower than the 4.25V as a high signal, but that is not guaranteed. Likewise, the Raspberry Pi GPIO high output is most likely higher than the 3.0V, nearer to 3.3V, but again that is not guaranteed.

There are different approaches that can be taken regarding this potential problem.

First, the option I have taken here is test it and see if it works. In this case, despite being out of the design specification, it does work, and it provides what I needed for this demonstration. There are several problems with this approach. Different ICs may have a different tolerance, and under different conditions, the voltage from the GPIO may be different, so it is possible for it to work on one setup, but not on another. It can also be very difficult to debug if it doesn’t work. This option of leaving the circuit as it is does however have the advantage of simplicity and so is something you may want to consider, especially if it’s just a personal project or a prototype to be developed further.

Another approach may be to reduce the voltage of the supply. As the minimum logic level is related to the supply voltage, it may be possible to reduce the supply voltage of the shift register. In the case of this IC, it can run as low as 4.5V, which gives a minimum input voltage of 3.8V. It is still not within the guaranteed output of the GPIO, but it has brought it closer and so more likely to work reliably.

If you still want to use this IC and want to ensure if it meets the design tolerances, then the last option is to increase the voltage from the GPIO using a buffer or level shifter. This has already been explained in Chapter 6, and a suitable circuit has been included in Figure 6-2. There are only three connections from the Raspberry Pi to the shift register, so that will need three MOSFETs and associated resistors.

The alternative is to look at an alternative IC, combination of ICs, or other circuit. I looked around and could not find a suitable shift register with open-drain outputs that is compatible with the 3.3V GPIO of the Raspberry Pi. I did however find a shift register with latch that is compatible with the 3.3V supply of the Raspberry Pi, which is the SN74HC595. The SN74HC595 can be run with a supply voltage of between 2 and 6 volts. Using it at 3.3V is fully compatible with the voltage level from the Raspberry Pi GPIO port. There is however one problem in that it does not have the same open-drain output and can only drive loads of around 5mA compared to the 20mA which is used for a suitable brightness from the LEDs (due to the use of extra-large LED displays). This can be resolved by adding another driver stage using either MOSFET switches or Darlington transistors as previously covered in Chapter 4. The Darlington transistors are also available in an IC, such as the ULN2803A, which has eight pairs within a single package. There are different variants of the 7N4HC595 some of which can handle larger currents and could drive the LEDs directly. The particular ones I found are surface mount devices which are not suitable for use on a breadboard, but they could be used on a PCB.

Shift Register 7-Segment LED Display Circuit

This can now be put to practical use in a circuit designed to display numbers on a 7-segment display. This could be a useful addition to the game console created in Chapter 10.

7-segment LED displays have seven rectangular LEDs, which are lit appropriately to create the image of a number. Often, they have one or more additional LEDs for showing a decimal point or a colon when used in a clock display. The eight outputs from the shift register are sufficient for showing a number and one decimal point.

The layout of a 7-segment display is shown in Figure 11-27.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig27_HTML.jpg
Figure 11-27

7-segment LED display

There are two types of LED display. The common anode has a single pin for the positive terminal (the anode), whereas the common cathode has a single pin for the negative terminal (the cathode). As these will be driven by a Darlington transistor, they need to be the common anode type. You should check the datasheet for the displays you use to check the pin-out. In my case, I used extra-large displays which have the pins on the side, whereas the smaller displays often have the pins on the top and bottom.

The circuit will use two 7-segment displays, each with their own shift register and Darlington driver ICs. They also need a resistor for each of the segments of the display. As a result, the circuit diagram is going to be quite big. The size of circuit diagrams is not really a problem as long as you are able to print it at a reasonable size or have the ability to zoom in. Unfortunately, that is not as easy when published in a book, so I have therefore split it across two diagrams. The first diagram in Figure 11-28 shows the shift registers and Darlington drivers, and the second diagram in Figure 11-29 has the 7-segment LED displays and resistors. I have used the connector symbol (circle) to indicate where the two diagrams join.
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig28_HTML.jpg
Figure 11-28

7-segment LED circuit, part one

../images/417997_2_En_11_Chapter/417997_2_En_11_Fig29_HTML.jpg
Figure 11-29

7-segment LED circuit, part two

Looking at the diagrams, there are two ground symbols, two VCC1 power supply labels, and two VCC2 labels. Where the power labels have the same reference, they are connected. This avoids having to have lines crossing the diagram, showing the power supply connection. If a separate power supply is used that is not connected, then that should be labeled different, such that Vcc1 and Vcc2 are different power supplies. In this case, Vcc2 should be a 5V supply; with only two 7-segment displays, these can be taken from the GPIO 5V ports; if more are connected, then it may need an external power supply .

You should be able to follow the rest of the diagrams as they follow the same principles as Figure 11-25, although this uses a different IC, the pins are labeled and numbered differently. The SN74HC595 datasheet uses Q for the outputs, which is fairly common, and then the serial output is marked as QH' which I’ve also labeled as Ser Out. The serial output connects to the serial input of the next shift register IC2, but the same clock signals are used, so both shift registers update at the same time. The datasheet for the Darlington driver IC (ULN2803A) labels the inputs as B and the outputs as C. There is also a common connection which can be used when switching inductive loads (such as motors), but it is not required in this case, so it is left unconnected.

I have created this on a large breadboard as shown in Figure 11-30. You will see that rather than use the jumper wires, I have used solid core wire cut to the exact length required. This takes much longer to do but becomes important when creating larger circuits .
../images/417997_2_En_11_Chapter/417997_2_En_11_Fig30_HTML.jpg
Figure 11-30

7-segment LED circuit on a breadboard

I have created code which counts from 00 to 99. The displays could be used separately, such as a score value for player 1 and player 2, or as a single number. The counter displays all the different number combinations that can be displayed. This is saved as 7segment-counter.py, shown in Listing 11-2.
from gpiozero import DigitalOutputDevice
from time import sleep
serial_pin = 22
serial_clock_pin = 23
register_clock_pin = 24
serial_out = DigitalOutputDevice(serial_pin)
serial_clock = DigitalOutputDevice(serial_clock_pin)
register_clock = DigitalOutputDevice(register_clock_pin)
number_values = [0b11111100, 0b01100000, 0b11011010,
    0b11110010, 0b01100110, 0b10110110, 0b10111110,
    0b11100000, 0b11111110, 0b11110110 ]
def shift_bit (bit_value):
    serial_out.value = bit_value
    serial_clock.on()
    sleep (0.001)
    serial_clock.off()
def register_update ():
    register_clock.on()
    sleep (0.001)
    register_clock.off()
def shift_byte (byte_value, update=True):
    # shift data 1 bit at a time
    for i in range (0,8):
        # shift out 1 bit
        bit_value = byte_value & 0b00000001
        shift_bit (bit_value)
        byte_value >>= 1
    if update == True:
        register_update ()
for i in range (0, 100):
    # tens value
    # No error checking - only works with 0 - 99
    digit_tens = i // 10 % 10
    digit_units = i - (digit_tens * 10)
    shift_byte (number_values[digit_units], False)
    shift_byte (number_values[digit_tens], True)
    sleep(0.5)
Listing 11-2

Shift register demonstration program

To create the number digits in terms of the 7-segment display, a dictionary is created, called number_values. These are the binary bit values to turn on the appropriate LED segments to create the digits from 0 to 9.

The code to send the data to the shift register is similar to the code in Listing 11-1. While using a different type of shift register, the code required to send the serial data is the same. The function shift_byte has an extra optional parameter so that the register_update can be called after both bytes have been sent.

When counting through the values, the number needs to be split into two separate digits for each display which is handled by dividing the value by 10 (using // rounds the number down) and modulo.

The one thing that isn’t included is the decimal point, which can be added by adding a 1 to the value in the number_values dictionary .

Summary

This chapter has shown the basics of digital logic gates and how they can be used to create more complicated combinational logic circuits as well as sequential logic. These are the basic building blocks of logical circuits. This also covers some of the key components that are used in a processor, including additional and registers.

The practical project has shown this can be used to expand the GPIO on the Raspberry Pi by using only three data lines to send serial data to an external shift register. This has been used to drive a bar graph LED display and then a pair of 7-segment LED displays.

The next chapter will look at how circuits can be made more permanent.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.250.223