I am developing a sketch to use the Shift Register 74HC165 into a much larger project.
I developed this sketch based on the sketch ShiftRegSN74HC165 in the playground. Arduino Playground - HomePage
The shift register is read every 15millis using interrupt 2.
/*
* S_74HC165_Buttons
*
* Program to shift in the bit values from a SN74HC165N 8-bit
* parallel-in/serial-out shift register.
*
*/
/* ARduino PIN assignment
Digital 8 74HC165 Connects to Parallel load pin (1) of the 165
Digital 9 74HC165 Connects to Clock Enable pin (15) of the 165
Digital 11 74HC165 Connects to the Q7 pin the 165 serial (SER) input (datapin) (9) of the 165
Digital 12 74HC165 Connects to the Clock pin the 165 the shift register clock (2) of the 165
*/
/* How many shift register chips are daisy-chained.
*/
#define NUMBER_OF_SHIFT_CHIPS 1
/* Width of data (how many ext lines).
*/
#define DATA_WIDTH NUMBER_OF_SHIFT_CHIPS * 8
/* Width of pulse to trigger the shift register to read and latch.
*/
#define PULSE_WIDTH_USEC 5
/* Optional delay between shift register reads.
*/
#define POLL_DELAY_MSEC 1
/* You will need to change the "int" to "long" If the
* NUMBER_OF_SHIFT_CHIPS is higher than 2.
*/
#define BYTES_VAL_T volatile unsigned int
byte ploadPin = 8; // Connects to Parallel load pin the 165
byte clockEnablePin = 9; // Connects to Clock Enable pin the 165
byte dataPin = 11; // Connects to the Q7 pin the 165
byte clockPin = 12; // Connects to the Clock pin the 165
BYTES_VAL_T pinValues; // Containt the current state of each input into the 74HC154
BYTES_VAL_T oldPinValues; // Containt the previous state of each input into the 74HC165
/************************** BUTTON **************************/
typedef struct BUTTON
{
byte pressed; // Track if the button is pressed
byte released; // track if the button was released
byte previous_state; // Used in the check_status function
byte current_state; // Used in the check_status function
byte holding; // Used in the check_status function
};
BUTTON t_button[DATA_WIDTH]; // Define an array to containt button's data (as per the structure)
/****************************** SETUP **********************/
void setup()
{
Serial.begin(9600);
/* Initialize our digital pins...
*/
pinMode(ploadPin, OUTPUT);
pinMode(clockEnablePin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, INPUT);
digitalWrite(clockPin, LOW);
digitalWrite(ploadPin, HIGH);
/* Read in and display the pin states at startup.
*/
pinValues = read_shift_regs();
display_pin_values();
oldPinValues = pinValues;
// Run timer2 interrupt every 15 ms
TCCR2A = 0;
TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;
//Timer2 Overflow Interrupt Enable
TIMSK2 |= 1<<TOIE2;
}
/****************************** LOOP **********************/
void loop()
{
/* The button is read using an interrup
we only have to verified if the button states have changed.
If there was a chagee in state, display which ones changed.
*/
//Serial.println (pinValues,BIN); // For debugging
update_inputs_state();
/* If only the changes (pressed or released NO holding) are required then use the following if */
/*if(pinValues != oldPinValues)
// If there was a change in state, we could display which ones changed.
{
update_inputs_state();
Serial.print("*Pin value change detected*\r\n"); // Only if required
display_pin_values(); // only if required
}
*/
oldPinValues = pinValues;
}
/****************************** SETUP **********************/
BYTES_VAL_T read_shift_regs()
/* This function is essentially a "shift-in" routine reading the
* serial Data from the shift register chips and representing
* the state of those pins in an unsigned integer (or long).
*/
{
byte bitVal;
BYTES_VAL_T bytesVal = 0;
/* Trigger a parallel Load to latch the state of the data lines,
*/
digitalWrite(clockEnablePin, HIGH);
digitalWrite(ploadPin, LOW);
delayMicroseconds(PULSE_WIDTH_USEC);
digitalWrite(ploadPin, HIGH);
digitalWrite(clockEnablePin, LOW);
/* Loop to read each bit value from the serial out line
* of the SN74HC165N.
*/
for(int i = 0; i < DATA_WIDTH; i++)
{
bitVal = digitalRead(dataPin);
/* Set the corresponding bit in bytesVal. */
bytesVal |= (bitVal << ((DATA_WIDTH-1) - i));
/* Pulse the Clock (rising edge shifts the next bit). */
digitalWrite(clockPin, HIGH);
delayMicroseconds(PULSE_WIDTH_USEC);
digitalWrite(clockPin, LOW);
}
pinValues = bytesVal;
}; // End read_shift_regs()
/****************************** DISPLAY PIN VALUES **********************/
void display_pin_values()
/* Dump the list of zones along with their current status.
*/
{
Serial.print("Pin States:\r\n");
for(int i = 0; i < DATA_WIDTH; i++)
{
Serial.print(" Pin-");
Serial.print(i);
Serial.print(": ");
if((pinValues >> i) & 1)
Serial.print("HIGH");
else
Serial.print("LOW");
Serial.print("\r\n");
}
Serial.print("\r\n");
} // End isplay_pin_values()
/****************************** INTERRUPT **********************/
SIGNAL(TIMER2_OVF_vect)
{
read_shift_regs();
}
/**************************** UPDATE STATE OF INPUTS ******************/
void update_inputs_state(){
byte i =0;
for (i = 0; i < DATA_WIDTH; i++) { // For each input
t_button[i].current_state = bitRead(pinValues, i); // read the value for the inputs
if ((t_button[i].previous_state == LOW) && (t_button[i].current_state == LOW)){ // nothing happen
t_button[i].pressed = 0;
t_button[i].released = 0;
}
else if ((t_button[i].previous_state == HIGH) && (t_button[i].current_state == HIGH)){ // holding
t_button[i].pressed = 1;
t_button[i].holding = 1;
button_holding(i);
}
else if ((t_button[i].previous_state == LOW) && (t_button[i].current_state == HIGH)){ // pressed
t_button[i].pressed = 1;
t_button[i].holding = 0;
button_pressing(i);
}
else if ((t_button[i].previous_state == HIGH) && (t_button[i].current_state == LOW)){ // released
t_button[i].pressed = 0;
t_button[i].holding = 0;
t_button[i].released = 1;
button_releasing(i);
}
t_button[i].previous_state = t_button[i].current_state; // keep tracking state of the buttons
delay(POLL_DELAY_MSEC);
}
} // End update_button_state()
/**************************** Function on Pressing ******************/
void button_pressing(byte i){
Serial.print ("Do something on a button "); Serial.print(i); Serial.println (" being pressed ");
} // End button_pressing)
/**************************** Function on Holding ******************/
void button_holding(byte i){
Serial.print ("Do something on a button "); Serial.print(i); Serial.println (" being hold ");
} // End button_holding()
/**************************** Function on Releasing ******************/
void button_releasing(byte i){
Serial.print ("Do something on a button "); Serial.print(i); Serial.println (" being released ");
} // End button_releasing()
I need clarification of the following;
Hardware: I am using resistors of 10K for each button. Are these necessary? Is this the right value for the resistors ? Is there another way to ground them?
Software : The original program uses two delays,
/* Width of pulse to trigger the shift register to read and latch.
*/
#define PULSE_WIDTH_USEC 5/* Optional delay between shift register reads.
*/
#define POLL_DELAY_MSEC 1
One is documented as optional, I removed both from the sketch without seeing any difference in the behavior of the sketch.
I cannot understand from the product data sheet. Can someone explain what these are and if they are necessary.
Thank you