Recently Microsoft has released a Windows 10 IoT Core preview image to run on the Raspberry Pi 2 allowing us to build Windows 10 Universal Apps running on the Raspberry Pi 2. Connect the Raspberry Pi 2 to a breadboard using the GPIO and we can build all kind of devices. This article describes how a series of leds can be driven by using the 74HC595 shift resister circuit. We won’t go into the details on how to setup your device, more information about setting up your device can be found on the Windows Internet of Things (IoT) website. https://dev.windows.com/en-us/iot

What is a Shift Resistor

A shift register is a device that allows additional inputs or outputs to be added to a microcontroller. This is accomplished by converting data between parallel and serial formats. A microprocessor communicates with a shift register using serial information, and the shift register gathers or outputs information in a parallel (multi-pin) format. Shift registers come in two basic types, either SIPO, Serial-In-Parallel-Out, or PISO, Parallel-In-Serial-Out. This article will focus on the 74HC595 which is SIPO type and is useful for controlling a large number of outputs. The PISO type is good for gathering a large number of inputs, like buttons. Shift registers are often used for the purpose of saving pins on a microcontroller. Every microcontroller has a limited number of pins for general inputs and outputs (GPIO).

How does it work

The shift register can be controlled using 3 GPIO pins only.
574px-SN74HC595-pinout

SDI
(Serial) Input for the next pin that gets shifted in.

SRCLK
(Serial Clock) When this pin is pulled high, it will shift the register.

RCLK
(Register Clock) Needs to be pulled high to set the output to the new shift register values, this must be pulled high directly after SRCLK has gone LOW again.

Writing a byte in which each bit will control one output (Qx) will contain 8 writes followed by a serial clock pulse to shift the register. When the register is setup correctly, a clock pulse to the register clock will enable the new output values (Qa – Qh).

The prototype

Setup the breadboard according to the picture shown below.

The code

Start a new Background Application (IoT) and replace the StartupTask with the code. If you decide to rename your task, make sure you also change the name of the task in the Package.appxmanifest. Add a reference to the Windows IoT extensions for the UWP and set the platform to ARM.

    public sealed class StartupTask : IBackgroundTask
    {
        private GpioPin PinSDI;     // Serial Digital Input
        private GpioPin PinRCLK;    // Register Clock
        private GpioPin PinSRCLK;   // Serial Clock

        public async void Run(IBackgroundTaskInstance taskInstance)
        {
            var deferral = taskInstance.GetDeferral();
            try
            {
                await DoWork();
            }
            finally
            {
                deferral.Complete();
            }
        }

        private async Task DoWork()
        {
            var LED = new byte[] { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

            var gpio = GpioController.GetDefault();

            // setup the pins
            PinSDI = gpio.OpenPin(22);
            PinSDI.SetDriveMode(Windows.Devices.Gpio.GpioPinDriveMode.Output);

            PinRCLK = gpio.OpenPin(18);
            PinRCLK.SetDriveMode(Windows.Devices.Gpio.GpioPinDriveMode.Output);

            PinSRCLK = gpio.OpenPin(27);
            PinSRCLK.SetDriveMode(Windows.Devices.Gpio.GpioPinDriveMode.Output);

            // initialize the pins to low
            PinSDI.Write(GpioPinValue.Low);
            PinRCLK.Write(GpioPinValue.Low);
            PinSRCLK.Write(GpioPinValue.Low);

            // main loop
            while (true)
            {
                // flow the leds
                foreach (var led in LED)
                {
                    SIPO(led);
                    PulseRCLK();

                    await Task.Delay(50);
                }

                // make the leds flash
                for (var i = 0; i < 3; i++)
                {
                    SIPO(0xff);
                    PulseRCLK();
                    await Task.Delay(100);
                    SIPO(0x00);
                    PulseRCLK();
                    await Task.Delay(100);
                }
                await Task.Delay(500);

                // flow the leds in reverse order
                foreach (var led in LED.Reverse())
                {
                    SIPO(led);
                    PulseRCLK();

                    await Task.Delay(50);
                }
            }
        }

        // Serial-In-Parallel-Out
        void SIPO(byte b)
        {
            for (var i = 0; i < 8; i++)
            {
                PinSDI.Write((b & (0x80 >> i)) > 0 ? GpioPinValue.High : GpioPinValue.Low);
                PulseSRCLK();
            }
        }

        // Pulse Register Clock
        void PulseRCLK()
        {
            PinRCLK.Write(GpioPinValue.Low);
            PinRCLK.Write(GpioPinValue.High);
        }

        // Pulse Serial Clock
        void PulseSRCLK()
        {
            PinSRCLK.Write(GpioPinValue.Low);
            PinSRCLK.Write(GpioPinValue.High);
        }
    }

The result