Encyclopedia of Fire Safety

Shift registers. Using shift registers in display devices Using shift registers

Sometimes you need a LOT of output ports. Especially if we want to do something with LEDs. Some fancy garland. What to do? Take this case ATMega128 with its fifty conclusions? Excessive - for lamers. Install i 2 with a port expander? Expensive. For majors. Here, good old discrete logic comes to the rescue from the age-old depths. This time, a penny shift register will help us out. Let me take, for example, 74HC164 aka, for lovers of Soviet trash microcircuits in an indestructible stone case, our KM555IR8.

From the MK, as you can see, only four outputs are required. With one (RESET) we reset the register state. From the second (Data) a byte comes out bit by bit, and the clock CLC ensures the advancement of bits through the register. There are three registers themselves. They are connected by a steam locomotive. When the first one overflows, the bits from it spill out into the second, then into the third. Total, 24 outputs.
The cathodes of the diodes are connected together through a transistor and as soon as there is a word, we give the Ready signal and light up all these tops.

Filling the register is simple:
1) Lift and hold RESET in 1
2) We issue the first (most significant) bit to Data.
3) Lower it to 0 and raise the clock output to 1. On a rising edge, the register is entered and the entire chain is shifted by one step.
4) Repeat from the second point until all the bits are given out.

And to reset, just drop it Reset to zero for a couple of microseconds.
It's simple :)

ZY
A circle at the register input means that the input is inverse. Those. gave zero - it worked
The triangle at the input shows which edge will trigger. It’s easy to remember: _/ \_ is, like, an impulse. And the triangle, like an arrow, points to the desired front. ->_/ \_ leading (rising edge) and _/ \_<- задний (нисходящий фронт)

Shift registers or shift registers are a series-connected chain of flip-flops.

Those. in shift registers, all flip-flops are connected in a daisy chain (the output of each previous flip-flop is connected to the D input of the next flip-flop). The clock inputs of all flip-flops (C) are interconnected. As a result, such a flip-flop can be considered as a delay line, the input signal of which is sequentially rewritten from flip-flop to flip-flop at the edge of clock signal C. The information inputs and outputs of flip-flops may or may not be output, depending on the function performed by the register.

The main mode of their operation is a shift of bits of the code written into these triggers. That is, based on a clock signal, the contents of each previous trigger are rewritten into the next trigger in order in the chain. The code stored in the register is shifted by one bit towards the most significant bits or towards the least significant bits with each clock cycle, which gives the name to registers of this type.

In the diagrams, the letters RG serve as the register symbol. For shift registers, the shift direction is also specified:

· → right (the main mode that all shift registers have);

· ← left (only some reversible shift registers have this mode);

· ↔ reversible (bidirectional), i.e., the recorded information can be shifted along the trigger line to the right or left. To enable the shift mode, a special control input is provided.

The direction of the shift is reflected by the internal structure of the shift registers (Fig. 4.14) and the rewriting of signals sequentially along the chain of flip-flops. In this case, flip-flops, quite naturally, are numbered from left to right, for example, from 0 to 7 (or from 1 to 8) for 8-bit registers. As a result, shifting information by a register to the right is a shift towards bits with higher numbers, and shifting information by register to the left is a shift towards bits having lower numbers.

However, as you know, in any binary number the most significant bits are on the left, and the least significant bits are on the right. Therefore, shifting a binary number to the right will be a shift towards the low-order bits, and shifting to the left will be a shift towards the high-order bits. The developer of a digital device must keep this feature in mind.

Shift registers can perform storage and conversion functions.

They can be used to construct multipliers and divisors of numbers in the binary number system, because shifting a binary number to the left by one digit corresponds to multiplying it by two, and shifting it to the right corresponds to dividing it by two.


Shift registers are widely used to perform various temporary transformations of digital information: sequential accumulation of serial digital information with subsequent simultaneous output (conversion of serial digital information into parallel code) or simultaneous reception (parallel reception) of information with subsequent sequential output (conversion of parallel code into serial code).

Shift registers can also serve as delay elements for a signal represented in digital form: registers with sequential reception (input) and output delay the transmission of information by m+1 clock cycles (m+1 is the number of register bits) of computer time.

Shift registers are most often implemented on D-flip-flops (Fig. 4.15, a) or RS-flip-flops (Fig. 4.15, b), where an inverter is turned on to enter information into the first digit (the first digit is a D-trigger).

It should be noted that all shift registers are built on the basis of two-stage flip-flops or synchronized by the edge of a clock pulse.

Shift registers can also be built on single-stage flip-flops. In this case, two flip-flops must be used in each register bit, which are controlled by two time-shifted clock pulses. If single-stage triggers were used in the register, one per digit, then the register operation rule would be violated: at the very first shift pulse, information, having been written to the first digit, would move to the second, then to the third, etc.

The width of shift registers, like storage registers, is determined by the number of flip-flops included in them.

Let us consider the operation of the shift register using the example of the circuit shown in Fig. Fig.4.15.

It can be assumed that at the beginning all register flip-flops are in a logical zero state, i.e. Q0=0, Q1=0, Q2=0, Q3=0. If there is a logical 0 at the input of the D-flip-flop T1, then the arrival of clock pulses at the inputs “C” of the flip-flops does not change their state.

As follows from Fig. 4.15, clock pulses arrive at the corresponding inputs of all register triggers simultaneously and record in them what takes place at their information inputs. At the information inputs of triggers T2, T3, T4 there are logical “0” levels, because The information inputs of subsequent flip-flops are connected to the outputs of previous flip-flops, which are in a logical “0” state, and according to the example, the “D” input of the first flip-flop is supplied with “0” from an external information source.

When the first trigger “1” is applied to input “D”, with the arrival of the first clock pulse, “1” will be written to this trigger, and “0” will be written to the other triggers, because by the time the front of the clock pulse arrived, a logical “0” was present at the output of trigger T1 “still”. Thus, the information (that bit) that was at its input “D” at the moment the front of the clock pulse arrived, etc. is written to the T1 trigger.

When the second clock pulse arrives, the logical “1” from the output of the first trigger is written to the second trigger, and as a result, the initially written “1” is shifted from trigger T1 to trigger T2, from trigger T2 to trigger T3, etc. Thus. , a sequential shift of the information arriving at the register input (in a serial code) is made by one bit to the right in each clock cycle.

After m clock pulses arrive, the register is completely filled with the bits of the number entered through the serial input “D”.

During the next four clock pulses, a sequential bit-by-bit output is made from the register of the written number, after which the register is completely cleared (the register will be completely cleared only if the level “0” is applied to its input in the output mode of the written number).

Reversible shift registers combine the properties of forward and reverse shift registers.

According to the clock signal, the contents of each previous trigger are rewritten into the next trigger in order in the chain. The code stored in the register is shifted by one digit towards the higher digits or towards the lower digits with each clock cycle, which gives the name to registers of this type.

In connection with the name of the direction of shift in shift registers There is often confusion. There are two types of shift: to the right (the main mode that everyone has shift registers) and to the left (only some, reverse, have this mode shift registers). These names reflect the internal structure shift registers(Fig. 8.14) and rewriting signals sequentially along a chain of triggers. In this case, flip-flops, quite naturally, are numbered from left to right, for example, from 0 to 7 (or from 1 to 8) for 8-bit registers. As a result, shifting information by a register to the right is a shift towards bits with higher numbers, and shifting information by register to the left is a shift towards bits having lower numbers.

However, as you know, in any binary number the most significant bits are on the left, and the least significant bits are on the right. Therefore, shifting a binary number to the right will be a shift towards the low-order bits, and shifting to the left will be a shift towards the high-order bits. This is a contradiction, not someone’s malicious intent, it just happened historically, and the developer of digital equipment must remember this.


Rice. 8.14.

The standard series of digital microcircuits includes several types shift registers, differing in possible operating modes, write, read and shift modes, as well as the type of output stages (2C or 3C). Majority shift registers has eight digits. In Fig. 8.15 shows four types of microcircuits as an example shift registers.

The IR8 register is the simplest of shift registers. It is an 8-bit delay line, that is, it has only one information input, to which serial shifted information is supplied (more precisely, two inputs combined using the 2I function), and eight parallel outputs. The shift towards outputs with higher numbers is carried out along the leading edge clock signal C. There is also a reset input –R, upon which a zero signal resets all register outputs to zero. Truth table register IR8 is given in table. 8.5.


Rice. 8.15.Table 8.5. Truth table shift register IR8
Inputs Exits
-R C D1 D2 Q0 Q1 Q7
0 X X X 0 0 0
1 0 X X Don't change
1 1 X X Don't change
1 0 1 1 1 1 Q0 Q6
1 0 1 0 X 0 Q0 Q6
1 0 1 X 0 0 Q0 Q6

The IR9 register performs the inverse function of the IR8 register. If IR8 converts input serial information into output parallel, then register IR9 converts input parallel information into output serial information. However, the essence of the shift does not change, it’s just that in IR9 all internal triggers have parallel inputs, and only one, the last trigger, has an output (both direct and inverse). The input code is written to the register based on a zero signal at the -WR input. The shift is carried out on a positive edge on one of the two clock inputs C1 and C2, combined

At some point in time, you will inevitably run into the problem of not having enough pins on your Arduino to meet the needs of your project or prototype. The solution to this problem? Shift register, or rather Arduino shift register 74hc595.

Anyone who has done Arduino projects where they use a lot of LEDs has realized that they are largely limited by the Arduino pins and cannot create huge projects that require a large number of pins. In our particular project, 16 LEDs are controlled by just three Arduino pins. The key element is the Arduino 74hc595 shift register. Each 74HC595 shift register can accept up to 8 LEDs, and using sequential chains of registers, you can increase the board contacts from a conventional 3 to an infinite number.

Before we start connecting the chip, let's look at how the process works.

The first thing to clear up is the concept of "bits" for those of you who are not familiar with binary code. When we talk about "bits", we mean one of the numbers that makes up a binary value. Unlike ordinary numbers, we usually consider the first bit to be the largest. So, if we take the binary value 10100010, the first bit is actually 0 and the eighth bit is 1. It should also be noted, unless it was implied, each bit can only be 0 or 1.

The chip contains eight pins that we can use for output, each of which is associated with a bit in a register. In the case of the 74HC595 shift register, we look at them from QA to QH.

To write these outputs through the Arduino we have to send a binary value to the shift register and from that number the shift register can determine which outputs to use. For example, if we sent the binary value 10100010, the contacts highlighted in green in the image above will be active and those highlighted in red will be inactive.

This means that the rightmost bit is mapped to QH and the leftmost bit is mapped to QA. An output is considered active when the bit associated with it is set to 1. It is important to remember this as otherwise you will have a very hard time knowing which pins you are using.

Now that we have a basic understanding of how we use bit offset to specify which pins to use, we can start connecting it to our Arduino.

We start with 8 LEDs

For the first part of the lesson we will need the following components:

  • Arduino Uno
  • Bread board
  • Arduino shift register 74HC595
  • 8 LEDs
  • 8 resistors - 220 ohms should be enough
  • Wires/jumpers

Start by placing the shift register on your layout, ensuring that each side is on a separate side of the layout, as shown below.

With the lettering facing up, pins 1-8 on the left side from top to bottom and 16 - 9 on the right side from top to bottom, as shown in the picture below.

Assembling the circuit

First, connect pins 16 (VCC) and 10 (SRCLR) to the 5v output on the Arduino and connect pins 8 (GND) and 13 (OE) to the Gnd pin on the Arduino. Pin 13 (OE) is used to enable the outputs as it is an active low pin which we can connect directly to ground.

Next we need to connect three pins that we will use to control the shift register:

  • Pin 11 (SRCLK) of the 74HC595 shift register to pin 11 on the Arduino - this will be called the "sync pin"
  • Pin 12 (RCLK) of the shift register to pin 12 on the Arduino - this will be referred to as the "latch pin"
  • Pin 14 (SER) of the shift register to pin 13 on the Arduino - this will be called the "data pin"

All three of these pins are used to perform the bit shifting mentioned earlier in this tutorial. Luckily, Arduino provides a helper function specifically for shift registers called shiftOut that will handle almost everything for us, but we'll come back to that when we look at the code.

Now we just need to connect all the output pins to our LEDs, ensuring that a resistor is placed in front of the LEDs to reduce the current and that the cathodes of the LEDs are pointed towards ground.

To keep wire clutter to a minimum, we placed the resistors and LEDs on a separate breadboard, however, you can use a single breadboard.

When placing the LEDs, make sure they are connected in order so that QA is connected to the first LED and QH is connected to the last LED, otherwise our code will not turn on the LEDs in the correct order. When you're finished, you should have something like this:

Sketch for Arduino

Now we are ready to upload the code. Connect your Arduino to your computer and download the following sketch for 74hc595 Arduino to it:

Int latchPin = 12; int clockPin = 11; int dataPin = 13; byte leds = 0; int currentLED = 0; void setup() ( pinMode(latchPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); leds = 0; ) void loop() ( leds = 0; if (currentLED == 7) ( currentLED = 0; ) else ( currentLED++; ) bitSet(leds, currentLED); shiftOut(dataPin, clockPin, leds); digitalWrite(latchPin, HIGH);

First, let's define the following at the top of the sketch:

  • Pin locations: synchronizer, latch and data
  • A byte that will store the bits that tell the shift register which pin to use
  • A variable that will keep track of which LED we should turn on

In method setup we simply initialize the pin modes and LED variable.

In method loop(loop) we clear the bits in the variable leds at the beginning of each iteration, so all bits are set to 0 since we only want to turn on one LED at a time. After this we increment or restart the current variable currentLED to then turn on the correct LED again.

After these two operations, we move on to the more important part - bit shifting. First we start by calling the method bitSet. We pass to the method bitSet a byte that stores bits, and a variable currentLED.

This method allows us to set individual bits of a byte by specifying their position. For example, if we want to manually set a byte to 10010 , we could use the following calls since the bits we need to set to 1 are the second from the right (which is position 1 when we start at position 0) and the fifth from the right, which is at position 4:

BitSet(leds, 1); bitSet(leds, 4);

So every time we increment the current variable currentLED and pass it to the method bitSet, we set the bit to the left of the previous one to 1 each time and thus tell the shift register to activate the output to the left of the previous one.

After setting the bits, we write to the latch pin to indicate to the shift register that we are going to send data to it. Once we do this we call the method shiftOut, which is Arduino. This method is designed specifically to use shift registers and allows you to simply shift bits in a single call. To do this, we pass data and synchronization as the first two parameters, then we pass a constant LSBFIRST, which tells the method that the first bit should be the least significant bit, and then we go through the byte containing the bits we actually want to move into the shift register.

Once we've finished shifting the bits, we access the latch pin again (using HIGH this time) to indicate that we've sent all the data. Once the write operation is complete, the corresponding LED will light up and then delay for 250 milliseconds before repeating itself.

16 LEDs

Now let's move on to a more complex circuit using a 74hc595 Arduino for 16 LEDs.

Details

By and large, in this case we double the number of all components, except, of course, Arduino Uno:

  • Arduino UNO (x1)
  • 74HC595 shift register (x2)
  • LEDs (x16)
  • 220 ohm resistors (x16)
  • Wires/jumpers
  • Two development boards (one with 400 pins, the second with 830 pins)
  • Potentiometer to control brightness (optional)

Connection diagram

The connection diagram is already larger than with 8 LEDs and one 74HC595 shift register.

Assemble the circuit as in the figure above and connect the first shift register as follows:

  • GND (pin 8) to ground
  • Vcc (pin 16) - 5V
  • OE (pin 13) to ground (GND)
  • MR (pin 10) - 5 V
  • DS (pin 14) - pin 11 of Arduino
  • SH_CP (pin 11) to Arduino pin 12
  • ST_CP (pin 12) to pin 8 of Arduino

Connect the second shift register in the same way, but connect DS (pin 14) to the first pin 9 of the register. After this, connect pins 1, 2, 3, 4, 5, 6, 7 and 15 from both registers and LEDs. This connection makes all pins always active and addressable, however, when you turn on the Arduino, some of the LEDs may be turned on. The solution for this is to connect MR (pin 10) and OE (pin 13) to the Arduino directly, but this way you have to sacrifice 2 pins of the arduino.

To add more shift registers, connect them together as a second register. Always connect the MR and OE pins directly to the Arduino pin and the DS pin to the previous register. If you want to adjust the brightness of the LEDs, please connect a potentiometer as shown in the picture above to control the resistance for all the LEDs. However, this is optional and you can do without it.

Sketch for Arduino

Sketch variants are usually designed for a limited number of shift registers, because There is no universal function/method for this. The code below has been reworked so that you can use an unlimited number of shift registers:

int latchPin = 8; int clockPin = 12; int dataPin = 11; int numOfRegisters = 2; byte* registerState; long effectId = 0; long prevEffect = 0; long effectRepeat = 0; long effectSpeed ​​= 30; void setup() ( //Initialize array registerState = new byte; for (size_t i = 0; i< numOfRegisters; i++) { registerState[i] = 0; } //set pins to output so you can control the shift register pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); } void loop() { do{ effectId = random(6); } while (effectId == prevEffect); prevEffect = effectId; switch (effectId) { case 0: effectRepeat = random(1, 2); break; case 1: effectRepeat = random(1, 2); break; case 3: effectRepeat = random(1, 5); break; case 4: effectRepeat = random(1, 2); break; case 5: effectRepeat = random(1, 2); break; } for (int i = 0; i < effectRepeat; i++) { effectSpeed = random(10, 90); switch (effectId) { case 0: effectA(effectSpeed); break; case 1: effectB(effectSpeed); break; case 3: effectC(effectSpeed); break; case 4: effectD(effectSpeed); break; case 6: effectE(effectSpeed); break; } } } void effectA(int speed){ for (int i = 0; i < 16; i++){ for (int k = i; k < 16; k++){ regWrite(k, HIGH); delay(speed); regWrite(k, LOW); } regWrite(i, HIGH); } } void effectB(int speed){ for (int i = 15; i > < i; k++){ regWrite(k, HIGH); delay(speed); regWrite(k, LOW); } regWrite(i, HIGH); } } void effectC(int speed){ int prevI = 0; for (int i = 0; i < 16; i++){ regWrite(prevI, LOW); regWrite(i, HIGH); prevI = i; delay(speed); } for (int i = 15; i >= 0; i--)( regWrite(prevI, LOW); regWrite(i, HIGH); prevI = i; delay(speed); ) ) void effectD(int speed)( for (int i = 0; i< 8; i++){ for (int k = i; k < 8; k++) { regWrite(k, HIGH); regWrite(15 - k, HIGH); delay(speed); regWrite(k, LOW); regWrite(15 - k, LOW); } regWrite(i, HIGH); regWrite(15 - i, HIGH); } } void effectE(int speed){ for (int i = 7; i >= 0; i--)( for (int k = 0; k<= i; k++) { regWrite(k, HIGH); regWrite(15 - k, HIGH); delay(speed); regWrite(k, LOW); regWrite(15 - k, LOW); } regWrite(i, HIGH); regWrite(15 - i, HIGH); } } void regWrite(int pin, bool state){ //Determines register int reg = pin / 8; //Determines pin for actual register int actualPin = pin - (8 * reg); //Begin session digitalWrite(latchPin, LOW); for (int i = 0; i < numOfRegisters; i++){ //Get actual states for register byte* states = ®isterState[i]; //Update state if (i == reg){ bitWrite(*states, actualPin, state); } //Write shiftOut(dataPin, clockPin, MSBFIRST, *states); } //End session digitalWrite(latchPin, HIGH); }

The code adds several effects for these 16 LEDs. If you want to add more LEDs, connect more shift registers like above and change the value numOfRegisters in the code.

You can also use this code for more than just LEDs, if you just need more pins for your Arduino, use the regWrite(int pin, bool state) function to write the state of any pin. And there is no limit to how many shift registers you use, just change the value of numOfRegisters and the rest is already automated.

This review is dedicated, in fact, to novice Arduino users or those who want to get involved in this business. We will talk about increasing the number of microcontroller outputs using a shift register, and this does not require large expenses (compared to buying an Arduino Mega, for example). The simplest application is to blink the LEDs, so let's try this in practice.

When I started getting acquainted with microcontrollers (in fact, I still continue to “begin to get acquainted”), one of the first questions was: how can you control the same hundred, thousand LEDs with only a dozen outputs on the controller? Yes, you can use signal multiplexing, counter-connection and many other tricks, but still the maximum number of connected LEDs is limited, and it is necessary to look for another solution. And they suggested one of the options to me - “take one, two, ten shift register chips and have fun.” It was decided to immediately order them, and in the future even assemble an LED cube using them. I really had to abandon the latter; I found a simpler option, but this is the topic of another review.
I ordered 20 pieces of 74HC595N at once, fortunately they cost mere pennies. The letter N at the end of the marking means that the microcircuit is in a DIP-16 package, very convenient for experiments on a breadboard; you don’t even need to solder anything. It looks like this:




What is this microcircuit? It is an eight-bit serial-in, serial-out, or parallel-out shift register with a latch flip-flop and three-state output.
Simply put, using just 3 controller outputs you can control 8 shift register outputs. And if the microcircuits are connected in series one after another, then the number of controlled outputs can be increased to any reasonable limit (I haven’t found a maximum number, but hundreds seem to be combined without problems; if anyone knows what the maximum number of microcircuits included in a cascade depends on, it would be interesting find out in the comments).
Data is transmitted to the chip serially. Bits 0 and 1 are transferred to the register one after another, the bits are read when a clock pulse arrives. Transmitted 8 bits - received 8 output states at the register outputs. When the 74HC595 is cascaded (if 16, 24, etc. outputs are required), the data from the first register is transferred to the next.
The register output can not only be in a logical 0 or 1 state, but also be in a high impedance state when the output is disconnected from the circuit. Only all outputs can be transferred to this state at once. This is rarely used, but can be useful when switching control to another controller, for example.

Input/output pinout

Q0…Q7 – register outputs, can be in state 0, 1 or high impedance
GND – ground
Q7′ – output for serial connection of registers.
MR – register reset
SH_CP – clock input
ST_CP – data latching input
OE – input converting outputs from high impedance to operating state
DS – data input
VCC – power supply 2-6 volts

All that remains is to check the work; to do this, we will assemble a circuit that is popular among beginners. GND (pin 8) is connected to ground, Vcc (pin 16) to 5V power, OE (pin 13) to ground, MR (pin 10) to 5V power. The shift register is now powered up and all outputs are active. Now it’s time to connect the microcircuit to the Arduino: connect the DS data input (pin 14) to the 9th digital output of the Arduino, the SH_CP clock input (pin 11) to the 10th digital output, the ST_CP latch input (pin 12) to the 8th Arduino pin. It is recommended to place a 0.1 µF capacitor between ground and the latch to minimize noise.
It remains to connect the LEDs - through 150-300 Ohm resistors we connect them from the register outputs to ground. That's all. Here is a diagram I found for those who like visual materials (please note that the pinout of the real microcircuit and the schematic image on this diagram are different!)


I assembled the circuit on a breadboard and it turned out like this.

assembled circuit








In Arduino, it is convenient to use the shiftOut() function, which outputs a byte of information to the input/output port sequentially (bit by bit). . We load the test code into Arduino and get a counter from 0 to 255 in binary form:
int latchPin = 8; //ST_CP int clockPin = 10; //SH_CP int dataPin = 9; //DS void setup() ( pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); ) void loop() ( for (int numberToDisplay = 0; numberToDisplay< 256; numberToDisplay++) { // установка синхронизации "защелки" на LOW digitalWrite(latchPin, LOW); // передаем последовательно на вход данных shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay); //"защелкиваем" регистр, устанавливаем значения на выходах digitalWrite(latchPin, HIGH); delay(500); } }
This is how it happened for me, everything works as expected:


Thus, with minimal use of controller pins, you can control a large number of LEDs (or something else). Everything would be fine, but I’ll also tell you about the shortcomings. As you can see, the current for each LED must be limited by a resistor, and when building large LED matrices this becomes quite labor-intensive. There is a more interesting solution for controlling LEDs - the DM13A driver, which is a shift register and also limits the current at each output. I’ll tell you about it next time, and as a bonus - my very first LED cube, 5x5x5, assembled on a simplified element base, without the use of 74HC595.

I'm planning to buy +37 Add to favorites I liked the review +35 +61

Related publications