Go Down

Topic: [CODE]Control a 7 segment display with a shift register (Read 1 time) previous topic - next topic

xerpi

Nov 30, 2012, 07:40 pm Last Edit: Nov 30, 2012, 07:46 pm by xerpi Reason: 1
Hello guys, I'm xerpi and I would like to show you a code that I wrote a few weeks ago.
The code is about using a shift register (74HC164N in particular) to control a 7 segment display. I'm not a master of Arduino so don't expect too much, I'm just learning  XD
It would be nice if you post any bugs or errors you find, it will help me (and maybe others) to improve in this world!

The code: http://pastebin.com/raw.php?i=zZituQtu
(a bit long to put it here xD)

Here a video:
http://www.youtube.com/watch?v=dlHp9r2BHUI


Hope you find it useful!
Student. I like coding and gaming (not as much as coding :P).

johnwasser


Code: [Select]

/* by xerpi */

static const byte segment_bits[11] =
{

/*
PORTD - digital 0-7
PORTB - digital 8-13
PORTC - analog  0-5

  a
---
      f | g | b
---
      e |   | c
--- .
  d   DOT

  7
---
      6 | 5 | 8
---
      1 |   | 3
--- .
  2   4

*/
0b11100111, // 0
0b10000100, // 1
0b11010011, // 2
0b11010110, // 3
0b10110100, // 4
0b01110110, // 5
0b01110111, // 6
0b11000100, // 7
0b11110111, // 8
0b11110100, // 9
0b00001000, // DOT
};

/*
1) DATA -> 0 or 1
2) CLOCK -> LOW
3) delay 1us ?¿
4) CLOCK -> HIGH (Here data enters to the register)
5) delay 1us ?¿
6) End
*/


#define _BIT(n) (1<<n)
#define _NOP() asm("nop\n")

#define DDRB_OUTPUT(pin) (DDRB |= _BIT(pin))
#define DDRB_INPUT(pin)  (DDRB &= ~_BIT(pin))

#define PORTB_HIGH(pin) (PORTB |= _BIT(pin))
#define PORTB_LOW(pin)  (PORTB &= ~_BIT(pin))

#define PINB_STATUS(pin) (PINB & _BIT(pin))

#define DATA_PIN 0 //Digital pin 8
#define CLK_PIN 1 //Digital pin 9
#define MR_PIN 2 //Digital pin 10 (not necessary)

#define RESET_MR() {PORTB_LOW(MR_PIN); _NOP(); PORTB_HIGH(MR_PIN);}
#define SEND_CLK() {PORTB_LOW(CLK_PIN);_NOP();PORTB_HIGH(CLK_PIN);_NOP();}

void sendBinary(byte number)
{
for(int i = 7; i > -1; i--)
{
(number & _BIT(i)) ? PORTB_LOW(DATA_PIN) : PORTB_HIGH(DATA_PIN);
SEND_CLK();
}
}

void sendNumber(int number)
{
if((number > -1) && (number < 11))
{
sendBinary(segment_bits[number]);
}
}

void CLEAR_ALL()
{
sendBinary(0x0);
}

void setup()
{
DDRB_OUTPUT(DATA_PIN);
DDRB_OUTPUT(CLK_PIN);
DDRB_OUTPUT(MR_PIN);

PORTB_HIGH(DATA_PIN);
PORTB_HIGH(MR_PIN);
}



void loop()
{
for(int i = 0; i < 10; i++)
{
sendNumber(i);
delay(350);

}
for(int i = 10; i > 0; i--)
{
sendNumber(i);
delay(350);
}
}



I would get rid of the Direct Port Access parts and use the Arduino library.  It would be somewhat slower but more generally useful since it would work on other Arduino models.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

dhenry

I would rewrite your code slightly:

Code: [Select]
void sendBinary(byte number)
{
        unsigned char mask = 0x80; //msb first
do {
PORTB_LOW(CLK_PIN); //clear clk
                if (number & mask) PORTB_HIGH(DATA_PIN); //send '1'
                else PORTB_LOW(DATA_PIN); //send '0'
                PORTB_HIGH(CLK_PIN); //strobe out the data
                mask = mask >> 1; //for the next bit
} while (mask);
}


On most machines, this approach provides near 50% duty cycle for the clock pin and is also faster than your routine.

Go Up