Pages: [1]   Go Down
Author Topic: Library for management of multiple 74HC595  (Read 397 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 1
Posts: 53
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

As I recently had to use a number of these I thought I'd put up some decent library for easily manage several chips.
So, after piecing together some bits of code, here it is, doxygen documented and with example code for the classic "Knight Rider" led toy smiley-grin

Just unzip it in your 'libraries' folder and you're good to go smiley-wink

Feel free to use it and comments are welcome smiley-wink

Pedro.

* sn74hc595.zip (117.41 KB - downloaded 29 times.)
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12451
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Very well done,

my remarks
1)
boolean registers[NBR_OF_REGISTERS];  takes a byte for every boolean
So you can reduce the internal storage here with a factor 8 when using individual bits of storage byte(s)

2)
void SN74HC595::clearRegisters()  does not write them immediately? 
This means the registers are not in sync with the e.g. LEDS?
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Jr. Member
**
Karma: 1
Posts: 53
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Very well done,

my remarks
1)
boolean registers[NBR_OF_REGISTERS];  takes a byte for every boolean
So you can reduce the internal storage here with a factor 8 when using individual bits of storage byte(s)

2)
void SN74HC595::clearRegisters()  does not write them immediately? 
This means the registers are not in sync with the e.g. LEDS?

Thank you and points well taken smiley-wink
Will modify code to accommodate bitsets and immediate clear (call to writeRegisters() ) of registers smiley-wink
Will post asap.
BR,
Pedro
Logged

Offline Offline
Jr. Member
**
Karma: 1
Posts: 53
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

mmm... come to think about turning that array of bools into a bitsets ...
One would have to parcel per chip (1 byte per chip), then all the code for managing that...
In the end it'd require more bytes of code then the addition of several chips.
It seems a de-optimization to me... the added code (plus loss of atomicity) make it less efficient.

Anyway, I'd love to be proven wrong with some efficient code for managing bitsets smiley-wink
BR,
Pedro
« Last Edit: January 02, 2014, 07:58:27 am by pdoriam » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12451
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
mmm... come to think about turning that array of bools into a bitsets ...
One would have to parcel per chip (1 byte per chip), then all the code for managing that...
In the end it'd require more bytes of code then the addition of several chips.
It seems a de-optimization to me... the added code (plus loss of atomicity) make it less efficient.

It is not so simple, it is RAM (more global vars) versus FLASH (more code)
RAM you have only 2K - FLash you have 32K

Quote
Anyway, I'd love to be proven wrong with some efficient code for managing bitsets
knight rider example:
original code: 1414 bytes flash 24 bytes RAM
new code 1407 bytes flash 17 bytes RAM

Gain is not spectacular, but still 7 bytes FLASH and 7 bytes RAM (about 1%)
 
Please confirm correct working of this modification (I did just a compile, not tested with 595's
Code: (595.h)
/*
* sn74hc595.h
*
*  Created on: Jan 1, 2014
*      Author: Pedro Doria Meunier
*     Details: SN75HC595 management class. Supports multiple chips.
*/

/*
SN74HC595 SHIFT REGISTER
========================

    ----_----
Q1  |1      16| Vcc
Q2  |2   7  15| Q0
Q3  |3   4  14| DS
Q4  |4   H  13| OE'
Q5  |5   C  12| STCP
Q6  |6   5  11| SHCP
Q7  |7   9  10| MR'
GND |8   5   9| Q7S
    ---------

Q0 - Q7 : Parallel data outputs
DS : Serial data input
OE' : Output enable (active LOW)
STCP : Storage register clock input
SHCP : Shift register clock input
MR' : Master reset (active LOW)
Q7S : Serial data output

Connection to micro controller (MC):
- DS (pin 14) to MC's data pin
- STCP (pin 12) to MC's latch pin
- SHCP (pin 11) to MC's clock pin

Daisy chaining:
- connect Q7S (pin 9) to next chip's DS (pin 14).
- connect STCP (pin 12) to next chip's.
- connect SHCP (pin 11) to next chip's.
Note: serially connect a 0.1uF capacitor between both STCP lines to common ground
    for added stability (i.e. prevent bits from shifting in during MC's boot)
*/

#ifndef sn74hc595_H_
#define sn74hc595_H_
#include "Arduino.h"

// change NBR_OF_595_CHIPS to accommodate your setup.
#define NBR_OF_595_CHIPS 1
#define NBR_OF_REGISTERS (NBR_OF_595_CHIPS * 8)

class SN74HC595 {
public:
    SN74HC595 ( uint8_t latchPin, uint8_t clockPin, uint8_t dataPin );
    void setRegister ( uint8_t index, uint8_t value );
    bool getRegister ( uint8_t index );
    void clearRegisters();
    void writeRegisters();


private:
    uint8_t latchPin;
    uint8_t clockPin;
    uint8_t dataPin;
    uint8_t registers[NBR_OF_595_CHIPS];  // CHANGED
};

#endif /* sn74hc595_H_ */



Code: (595.cpp)
/*
* sn74hc595.cpp
*
*  Created on: Jan 1, 2014
*      Author: Pedro Doria Meunier
*     Details: SN75HC595 management class. Supports multiple chips.
*/
#include "sn74hc595.h"

/**
* \brief SN74HC595
* \details Class constructor. Initializes pins for communicating with the SN74HC595 chip.
* @param latchPin
* @param clockPin
* @param dataPin
*/
SN74HC595::SN74HC595 ( uint8_t latchPin, uint8_t clockPin, uint8_t dataPin )
{
    this->latchPin = latchPin;
    this->clockPin = clockPin;
    this->dataPin  = dataPin;

    pinMode(latchPin, OUTPUT);
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);
}

/**
* \brief setRegister ( uint8_t index, uint8_t value )
* \details Set a single register. Quietly fails if register < 0 or register > (NBR_OF_REGISTERS-1)
* \memberof SN74HC595
* \note must call writeRegisters() after calling this function to apply changes
* @param index
* @param value
*/
void SN74HC595::setRegister ( uint8_t index, uint8_t value )
{
    if (index < NBR_OF_REGISTERS)
    {
        registers[index >> 3] = (value == 0) ? 0 : 0x01 << (index & 7);
    }
}

/**
* \brief getRegister ( uint8_t index )
* \details gets the current state of a register.
* \memberof SN74HC595
* @param index
* @return true if register is set. false if otherwise or register > (NBR_OF_REGISTERS-1)
*/
bool SN74HC595::getRegister ( uint8_t index )
{
    if (index < NBR_OF_REGISTERS)
    {
        return ( (registers[index >> 3] >> (index & 7 )) & 0x01 );
    }
    return false;
}

/**
* \brief writeRegisters()
* \details write all registers at once on all connected SN74HC595
* \memberof SN74HC595
*/
void SN74HC595::writeRegisters()
{
    // signal 74HC595 we're sending data
    digitalWrite(latchPin, LOW);

    for (int i = NBR_OF_REGISTERS - 1; i >= 0; i--)
    {
        digitalWrite(clockPin, LOW);
        digitalWrite(dataPin, getRegister(i) );
        digitalWrite(clockPin, HIGH);
    }
    digitalWrite(latchPin, HIGH);
}

/**
* \brief clearRegisters()
* \details clears all registers on all connected SN74HC595
* \memberof SN74HC595
*/
void SN74HC595::clearRegisters()
{
    for (int i = NBR_OF_REGISTERS - 1; i >=  0; i--)
    {
        setRegister(i, 0);
    }
}
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Pages: [1]   Go Up
Jump to: