arduinobit-manipulationspishift-register

Toggle a single bit on Arduino + 74HC165 + SPI


Please, help me. I'm trying to connect the 74HC165 (8-bit input shift register) to Arduino UNO via SPI to check the state of 8 buttons. The response is going to be processe to change variable "controls", but it doesn't work properly.

Here is the code:

#include <SPI.h>

/*  Latch contact */
enum { REG_LATCH = 8 };
int speed = 100;

/*  Variable to store the Controls state for further transfer */
static uint8_t controls = 0;

void setup()
{
  /*  Turn ON the UART  */
  Serial.begin(9600);
  /*  Turn On the SPI */
  SPI.begin();
  pinMode(REG_LATCH, OUTPUT);
  digitalWrite(REG_LATCH, HIGH);
}

void loop()
{
  /*  Storing the previous system state   */
  static uint8_t previous_input = 00000000;

  digitalWrite(REG_LATCH, LOW);
  digitalWrite(REG_LATCH, HIGH);

  /*  Read the inputs from shift register */  
  uint8_t input = SPI.transfer(0);

  /* If anything has ben changed - report to UART */

  if (input != previous_input)
    {  
      /*  Remebmer changed positions */
      uint8_t changed = input ^ previous_input;

      /*  Remember current state */
      previous_input = input;       

      Serial.println("Buttons State:\t\tControls State:");
      /* Run trough all inputs from shift register  */
      for (int i = 0; i < 8; i++)
        {   
          /* Print the state of currently checked input*/
          Serial.print(input & 1);
          /* If button is pressed and previously it was not, then  */
          if ((input & 1) & (changed & 1))
            {
              /* Highlight the current changes in system */
              Serial.print("_");                            
              /* Toggle controls in this position */
              controls = controls ^ (1 << i);
             }; /*Otherwise do nothing*/

          /*  Move to next bit of inputs. */
          input >>= 1;
          changed >>= 1;
        };

      Serial.print("\t\t");  
      for (int i = 0; i < 8; i++)
        {   
          /* Print current control  */
          Serial.print(controls);
          controls >>= 1;
        }
      Serial.println();       
  }
}

And what it writes to the Serial:

1) After pressing button 1:

Buttons State:      Controls State:
1_0000000       10000000

2) When it releases:

Buttons State:      Controls State:
00000000        00000000

3) After pressing button 7:

Buttons State:      Controls State:
0000001_0       64321684210

4) After its releasing:

Buttons State:      Controls State:
00000000        00000000

5) After pressing button 1:

Buttons State:      Controls State:
1_0000000       10000000

6) When it releases:

Buttons State:      Controls State:
00000000        00000000

How it supposed to work:

1) After pressing button 1:

Buttons State:      Controls State:
    1_0000000       10000000

2) After its release:

Buttons State:      Controls State:
    00000000        10000000

3) After pressing button 7:

Buttons State:      Controls State:
0000001_0       10000010

4) After its releasing

Buttons State:      Controls State:
00000000        10000010

5) After next pressing of button 1:

Buttons State:      Controls State:
    1_0000000       00000010

6) After its releasing:

Buttons State:      Controls State:
    00000000        00000010

Help me, please. What am I doing wrong?


Solution

  • First check your shift register is connected correctly. The best way of distinguishing hardware issues with software issues is to plug an oscilloscope on the output pin of your shift register.

    Your REG_LATCH pin must be plugged to pin1 of your shift register (assuming we are talking about this one http://www.nxp.com/documents/data_sheet/74HC_HCT165.pdf).

    The way it works is that you must pull this pin down, transfer data then pull it up. Thus the sequence is rather:

      digitalWrite(REG_LATCH, LOW);
      /*  Read the inputs from shift register */  
      uint8_t input = SPI.transfer(0);
      digitalWrite(REG_LATCH, HIGH);
    

    Then instead of shifting index and changed in your loop, I would have used this:

    input & i
    changed & i
    

    or

    input & (7 - i)
    changed & (7 - i)
    

    depending on the order your want to handle your bits.