Pages: [1]   Go Down
Author Topic: [CODE]Control a 7 segment display with a shift register  (Read 1430 times)
0 Members and 1 Guest are viewing this topic.
Town near Barcelona
Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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  smiley-lol
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!
« Last Edit: November 30, 2012, 01:46:49 pm by xerpi » Logged

Student. I like coding and gaming (not as much as coding smiley-razz).

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 212
Posts: 8952
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
/* 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.
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I would rewrite your code slightly:

Code:
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.
Logged

Pages: [1]   Go Up
Jump to: