Shift Library

WiringPi includes a shift library which more or less mimics the one in the Arduino system. This allows you to shift 8-bit data values out of the Pi, or into the Pi from devices such as shift-registers (e.g. 74×595) and so-on, although it can also be used in some bit-banging scenarios.

To use, you need to make sure your program includes the following files:

#include <wiringPi.h>
#include <wiringShift.h>

Then the following two functions are avalable:

  • uint8_t shiftIn (uint8_t dPin, uint8_t cPin, uint8_t order) ;

This shifts an 8-bit data value in with the data appearing on the dPin and the clock being sent out on the cPin. Order is either LSBFIRST or MSBFIRST. The data is sampled after the cPin goes high. (So cPin high, sample data, cPin low, repeat for 8 bits) The 8-bit value is returned by the function.

  • void shiftOut (uint8_t dPin, uint8_t cPin, uint8_t order, uint8_t val) ;

The shifts an 8-bit data value val out with the data being sent out on dPin and the clock being sent out on the cPin. order is as above. Data is clocked out on the rising or falling edge – ie. dPin is set, then cPin is taken high then low – repeated for the 8 bits.

Comments

Shift Library — 24 Comments

  1. Would it be possible to add an option to the wiringPi library that gives us the ability to use 595 shift registers as additional GPIO’s. Another idea is a kernel module that creates additional GPIO’s using one or more 595’s.

    An example of my thoughts using wiringPi:

    wiringPiSetup();
    shiftSetup(1);
    //How many 595 are connected.
    //This would make additional GPIO’s 8 till 15

    pinMode(8, OUTPUT);
    pinMode(9, OUTPUT);
    pinMode(10, OUTPUT);

    //The library knows that there are only 3
    //pins initialized (in this script) so
    //after 3 assignments the latch should be
    //called. However the script needs to know
    //what pins are initialized in other scripts

    digitalWrite(8, 1);
    digitalWrite(9, 0);
    digitalWrite(10, 1);

    //This would send a binary of 10100000 to the 595.

    digitalWrite(8, 0);
    digitalWrite(9, 1);
    digitalWrite(10, 0);

    //This would send a binary of 01000000 to the 595.

    • Something like that is certianly possible, and I have some 595’s waiting for an experiment or 2…

      I think I might be tempted to do something like:

      setup595 (data, clock, latch) ;

      to create the interface, then

      output595 (x) ;

      where ‘x’ is an 8-bit value.

      and/or:

      output595bit (x, y) ;

      where x would be the bit (0-7) and y the value (0,1)

      To set individual bits, you need to keep a copy of the current output values, and always clock in 8 bits at a time, so output595bit () would call output595() …

      Just some thoughts…

      -Gordon

  2. Isn’t it possible to create a adapter for the output595bit function so we can still use the digitalWrite function. This way, existing code can be reused by just altering the input or output pin number. To ideas:

    1. Set a certain 595 pin as a emulated GPIO pin > 7:
    setup595(0, 1, 2);
    //set595toGPIO(595pin, emulatedGPIOPin);
    set595toGPIO(0,100);
    digitalWrite(100,1) == output595bit(0,1);

    2. Map the 595 pins when calling the setup595 function as GPIO pin > 7:
    setup595(0, 1, 2);
    //The program automatically maps the 595 pins to emulated GPIO pins
    digitalWrite(8,1);
    //This should set pin 0 of the 595 to HIGH.

    And is it possible that the setup595 function knows which other programs are using the same 595? Currently i’m using a TSOP4838 for my remote controllers, a 433.92Mhz sender and a separate receiver for my KaKu devices. These are driven by 3 separate c++ programs. I would like to be able to use 1 595 to drive these 3 (and more later on) devices with 3 separate scripts.

    Program 1:

    setup595(0, 1, 2);
    output595bit(0,1)

    Program 2:

    setup595(0, 1, 2);
    output595bit(1,1);

    Program 3:

    setup595(0, 1, 2);
    output595bit(2,1);

    Program 4:
    setup595(0, 1, 2);
    output595bit(2,1);
    //ERROR: 595 pin 2 already in use by program 3.

    • Well, nothing’s set in-stone ๐Ÿ˜‰

      Hoewever I have some ideas and been doing some tests for another GPIO expander type chips – SPI and I2C based devices, and adding in an enumeration for pin numbers is part of that project, so it shouldn’t be too hard to include the shift registers as a “poor mans GPO (no input!) expander” type of interface…

      Watch this space as they say ๐Ÿ˜‰

      -Gordon

    • Should be easy to use – you’ll need 2 rd GPIO pin to act as the latch though, and need to call it twice with 2 different 8-bit values to shift them out, then toggle the latch to cause both shift registers to transfer the data at the same time.

      -Gordon

  3. Hi Gordon!

    First of all thank you for the amazing examples!
    I guess you spend a lots of time with these to build them up, well done!

    I already made some code with the GPIO which controls leds and I used your examples, but I wanted to move on more deeply.

    I googled that how to control a lots of leds and I ended up with 74595 shift register. I bought few of them and I’d like to write some code to control leds. Unfortunately I have not found a single example in C/C++ to control this shift register. I wired up the hardware part already.

    So I tried to use this python code although I don’t have any experience in it: https://github.com/rasathus/pigredients but some library are missing, so it’s a no go for me.

    However I’d like to use C++ because I used to code in C ages ago, so at least I’m familiar with the language structure.

    So my question is did you do any examples with 74595 shift register that I would use to play with it?
    I’d really appreciate if you would help me out with this.
    I’ve got the main files for the 74595 how it works but I’ve never done this, so I got lost of course.

    Unfortunately the only code that I found is just related to arduino not raspberry pi.

    • There is a shiftOut () function in wiringPi that you can use. You’ll need to give it 2 pins to work with – one is the clock, the other is the data. You’ll need a 3rd pin to latch the 74×595 – so shiftOut() will send 8 bits, then toggle the latch pin.

      The small down-side right now is that this code runs at full-speed – or as full speed as it can do – so it will end up clocking the data out at about 10MHz! So keep your wires short and tidy.

      I have it on my to-do list to make a slower clocked version…

      Your Arduino code ought to work almost unchanged on the Pi though – use the same shiftOut () function call (you’ll need to make sure the pins are outputs beforehand though).

      -Gordon

      • Thank you for your help! I didn’t know the shiftOut () could work on raspberry pi. I’ll have a look arduino codes and try them out.
        If I would have some hints for example how to light up first and second output on 74595 then I’ll be ready to go easily.
        But too much dark fields just right now, anyway I’ll keep trying and I do more research in this filed.
        Thanks again!

        Laz

        • You need to keep a software copy of the 8-bit output register in the 595. then to set a bit, OR in the bit, shift out the while 8 bits, and toggle the latch. To clear a bit, AND it with the inverse, then shift the 8 bits out and toggle latch again.

          -Gordon

  4. Hi

    How would one (or two) of the SN74HC595 be wired up to the Pi, I don’t really understand the explanation above.

    Thanks

    • One is easy. You need 3 pins. One for the clock, one for the data and one for the latch. You output an 8-bit data byte to the shift register by wiggling the clock 8 times while sending the data one bit at a time on the data pin. When all bits have been clocked in, you wiggle the latch – that transfers all 8 bits simultansly to the output pins on the device.

      To use 2 shift-registers, you can pick another set of 3 pins and off you go, however the ‘595 has a serial data out pin so you can connect multiple ‘595’s in series, all the the same clock and latch pins, just one data pin going to the first shift register. The down-side is that you need to clock data to all of them – so with 2 in series, you treat it as one 16-bit shift register. With 3 in series then it’s a 24-bit one, and so on.

      I have some plans to make some diagrams for this at some point though, but google about and you’ll find lots of examples – particularly in the Arduno forums, etc.

      -Gordon

  5. How can I make the previous led to keep HIGH state that it doesnt go off when i light up the next led?

    • ALmost impossible to know what you’re trying to do here, however I’m guessing that you have a 595 shift register connected up – what you need to do is to keep a copy of your output register, then change the value in that, then shift out those 8-bits again.

      So –

      output |= 0x10 ; // Set bit 5
      shiftOut (... output) ;
      output &= ~0x10 ; // Clear bit 5
      shiftOut (... output) ;

      and so on.

      -Gordon

          • I have the 595 shift register and i am controlling with it 7 leds. I need to get the leds turn from led 1 to led 7 in order so that the previous leds doesn’t turn off. Like bar graph.

          • Well – you need to do what I suggested earlier – you keep a copy of the output register in your program, you update the copy, then shift that copy into the shift register. (then toggle the latch). That way you can keep bits set that are already set, or just clear the bits you want to clear, leaving the others set.

            I can’t do much more than just re-print the code I sent earlier:

            If you have the output value in a variable called ‘output’ then to set a bit:

            output |= 0x10 ; // Set bit 5
            shiftOut (... output) ;

            and to clear a bit:

            output &= ~0x10 ; // Clear bit 5
            shiftOut (... output) ;

            -Gordon

  6. cant get it to work, what is it that i’m missing?
    thanks for you great work!

    #include
    #include

    int main (void)
    {
    wiringPiSetup();
    pinMode(dataPin, OUTPUT);
    pinMode(clockPin, OUTPUT);
    pinMode(latchPin, OUTPUT);
    int dPin =2;
    int cPin =0;
    int order =1;
    int val =00110011;
    shiftOut(uint8_t dPin, uint8_t cPin, uint8_t order, uint8_t val);
    return 0 ;
    }

    • The shiftOut() in wiringPi runs pretty fast – sometimes too fast, depending on your wiring, etc.

      However, if you’re using the 595 shift-register, you need more than just shiftOut() – you need to make sure the latch pin is in the right state – especially after you do the shiftOut – then you need to toggle the latch to transfer the latch into the output register inside the 595.

      You may be interested in wiringPi v2 – which I’m going to push out soon – that has direct control of 595 type shift registers built-in. If you want to test a beta, drop me an email.

      -Gordon

  7. Hi,
    Im sorry to bother you with something so easy but I tried to make it worked and I don’t find any documentation, information and the good syntaxes for this.
    Would you be so kind and tell me where I can find any doc concerning the function uint8_t shiftIn (uint8_t dPin, uint8_t cPin, uint8_t order) ; ?
    Thank you very much.
    Here you have what I tried to do : (I never succeeded to go inside the function)

    Thank you very much!

    #include
    #include “wiringPi.h”
    #include “wiringShift.h”
    #include
    #include

    #define inputClockPin 12
    #define inputLatchPin 13
    #define inputDataPin 14

    #define outputDataPin 11
    #define outputLatchPin 10
    #define outputClockPin 6

    int main (void)
    {
    int bit ;
    int val;
    uint8_t shiftIn (uint8_t dPin, uint8_t cPin, uint8_t order) {
    int i;
    int tmp = 0;
    uint8_t dataIn = 0;
    digitalWrite(inputLatchPin, HIGH);
    delayMicroseconds(300);
    digitalWrite(inputLatchPin, LOW);

    for (i = 7; i >= 0; i–) {
    digitalWrite(cPin, LOW);
    delayMicroseconds(300);
    tmp = digitalRead(dPin);
    if (tmp) {
    dataIn = dataIn | (1 << i);
    }
    digitalWrite(cPin, HIGH);
    delayMicroseconds(100);
    }

    return dataIn;

    }

    }

  8. I’m sorry, I should have told you that I’m trying to use a 74HC165 as inputs which are working with Arduino. ๐Ÿ™‚