[CODE]Control a 7 segment display with a shift register

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:

Hope you find it useful!

xerpi:

/* 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.

I would rewrite your code slightly:

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.