|
|
View previous topic :: View next topic |
Author |
Message |
zzeroo
Joined: 17 Jun 2013 Posts: 18
|
4x5 LED Matrix with 8bit shift registers PCH/PIC18F26K22 |
Posted: Tue Jun 24, 2014 3:57 am |
|
|
Hello,
I'm looking for ideas for a fitting data model for the following problem.
I have a 4 colum, 5 row led matrix. They are connected via three 8bit 74HCT594 shift registers. The last 4 ports of the last shift register are not connected.
The first 5 bit are the first row of my LED matrix, the next 5bit are the next row and so on.
A additional problem comes at that. The hardware design does not allow me to clear the memory of the shift and the storage register.
The required pins are not connected to the MCU.
This means that to keep track of the current LED status I have to use a 24bit buffer in memory. And on each update I must shift in the whole 24bit (20 for each LED one + 4 bit not used) and latch them out.
What type of data structure should I use. My first experiment with a struct like the following results in an Quote: | Error#35 Number of bits is out of range |
Code: |
struct LEDMap {
unsigned char row1 :5;
unsigned char row2 :5;
unsigned char row3 :5;
unsigned char row4 :5;
unsigned char notUsed :4;
};
|
I want later to set some LED with a function like Code: | void LED(int row, int column, char color); |
Update:
the target MCU is a PIC18F26K22 and my
CCS Version=5.010
Compiler=PCH
Last edited by zzeroo on Tue Jun 24, 2014 5:14 am; edited 2 times in total |
|
|
zzeroo
Joined: 17 Jun 2013 Posts: 18
|
Re: 4x5 LED Matrix with 8bit shift registers |
Posted: Tue Jun 24, 2014 4:55 am |
|
|
Here is a gcc version how I think it could work. But the 24 bit datatype doesn't fit in my PCH
Code: | #include <stdio.h>
struct LEDBuffer {
int bits :24;
};
void LED(int row, int column, struct LEDBuffer *buffer) {
int num = ( ( row-1 ) * 5 ) + (column-1);
buffer->bits |= 1 << num;
}
// Here the shift_register is feeded but for demonstration I print it out
void send_buffer(struct LEDBuffer *buffer) {
int i;
int data = buffer->bits;
for(i=0; i<24; i++) {
if(data & 0x01)
printf("%d", 1);
else
printf("%d", 0);
data >>= 1;
}
puts("");
}
int main(void) {
struct LEDBuffer buffer = {0};
send_buffer(&buffer);
LED(1,1,&buffer);
LED(1,2,&buffer);
LED(1,3,&buffer);
LED(1,4,&buffer);
LED(1,5,&buffer);
LED(4,1,&buffer);
LED(4,2,&buffer);
LED(4,3,&buffer);
LED(4,4,&buffer);
LED(4,5,&buffer);
send_buffer(&buffer);
return 0;
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9219 Location: Greensville,Ontario
|
|
Posted: Tue Jun 24, 2014 5:07 am |
|
|
Can you please supply a good link to the datasheet for the 74954 shift registers you're using? Google didn't find anything !
tks
jay |
|
|
zzeroo
Joined: 17 Jun 2013 Posts: 18
|
|
Posted: Tue Jun 24, 2014 5:14 am |
|
|
temtronic wrote: | Can you please supply a good link to the datasheet for the 74954 shift registers you're using? Google didn't find anything !
tks
jay |
http://www.nxp.com/documents/data_sheet/74HC_HCT594.pdf
Sorry it a 74HCT594. But the shift register is not the problem |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Jun 24, 2014 5:38 am |
|
|
I assume you have a typo, please confirm your shift register is a 74594.
I am confused by you calling your display a 4*5 matrix.
It seems your LEDs are wired as a 20*1 linear network.
Using the CCS supplied driver you simply store a copy of your LED status in a 3 byte array.
Mike |
|
|
zzeroo
Joined: 17 Jun 2013 Posts: 18
|
|
Posted: Tue Jun 24, 2014 6:01 am |
|
|
Mike Walne wrote: | I assume you have a typo, please confirm your shift register is a 74594.
I am confused by you calling your display a 4*5 matrix.
It seems your LEDs are wired as a 20*1 linear network.
Using the CCS supplied driver you simply store a copy of your LED status in a 3 byte array.
Mike |
Yes all true. And as you can see from my questions, I am not a professional embedded C programmer. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
Re: 4x5 LED Matrix with 8bit shift registers |
Posted: Tue Jun 24, 2014 6:45 am |
|
|
zzeroo wrote: | But the 24 bit datatype doesn't fit in my PCH
Code: |
struct LEDBuffer {
int bits :24;
}; |
|
No, it won't. Ints are eight bit by default (16 bits with PCD). This code is probably assuming an int is 32, e.g. a PC or an ARM. In any case CCS C doesn't like bit fields that cross byte boundaries. So even if you declared it as an int32 it wouldn't work.
A better way to do this would be to forget the bit field and treat it as a simple 32 bit integer, and use bit_set(), bit_clear() and bit_test() which are much more efficient, i.e. faster, than the bit shifts in the original code. |
|
|
zzeroo
Joined: 17 Jun 2013 Posts: 18
|
|
Posted: Tue Jun 24, 2014 7:27 am |
|
|
Thank you all. This is my first solution. What do you think about?
Code: | // Device header
#include <18F26K22.h>
#FUSES NOWDT //No Watch Dog Timer
#use delay(clock=11052000,crystal=11052000)
#define DATA_IN PIN_A5
#define CLOCK PIN_A4
#define LATCH PIN_A3
// This memory portion stores the state of each LED
struct LEDBuffer {
unsigned long long bits;
};
// Set all needed PIN's low. For a clean start.
void init_shift_registers() {
output_low(DATA_IN);
output_low(CLOCK);
output_low(LATCH);
}
// This function latch out the shift register
void latch_out(){
output_high(LATCH);
output_low(LATCH);
}
// "Enable" one LED in buffer memory
void LED(int row, int column, struct LEDBuffer *buffer) {
long long num = ( ( row-1 ) * 5 ) + ( column-1 );
bit_set(buffer->bits, num);
}
// Clock in the buffer memory bit for bit. And transfer shift register data to
// storage register and enable the outputs, (latch out).
void send_buffer(struct LEDBuffer *buffer) {
int i;
long long data = buffer->bits << 4; // This four bit shift is needed because
// the first 4 bits are not connected on my hardware
for(i=0; i<24; i++) {
if( data & 0x01) {
output_high(DATA_IN);
} else {
output_low(DATA_IN);
}
output_high(CLOCK); // Positive clock pulse
output_low(CLOCK);
data >>= 1; // Get next bit in MSB position
}
latch_out();
}
void main(void) {
init_shift_registers();
// Initialize the LEDBuffer and set all bits to zero
// This structure represents all shift registers memory
struct LEDBuffer buffer = {0};
LED(1,4,&buffer);
LED(2,3,&buffer);
LED(3,2,&buffer);
LED(4,2,&buffer);
send_buffer(&buffer);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19484
|
|
Posted: Tue Jun 24, 2014 9:05 am |
|
|
I think you are trying to make things more complex than they need to be.
You are 'hooked' on making the data structure in the PIC have some resemblance to the matrix, when it doesn't need/want to have this.
All that matters is that your 'clock out' function sends the right bits.
So simply have an array of four bytes.
Have the low five bits of each one represent one line of the LED.
Then have your send function, simply loop through the five low bits of each of these in turn, sending these, then send the four dummy bits, by just issuing clocks.
You don't need to ever store the extra dummy bits, or worry that the blocks of bits in the PIC have gaps between them.
So something like (totally theoretical)....:
Code: |
char lines[4];
#define PULSE_CLOCK output_high(CLOCK);delay_cycles(1);output_low(CLOCK)
void send_lines()
{
int8 line_no;
int8 mask;
int8 ctr;
for (line_no=0;line_no<4;line_no++);
{
mask=1;
for (ctr=0;ctr<5;ctr++)
{
if ((mask & lines[line_no]!=0)
output_high(DATA_BIT);
else
output_low(DATA_BIT);
PULSE_CLOCK;
mask*=2;
}
}
for (ctr=0;ctr<4;ctr++)
{ //output four extra dummy bits
PULSE_CLOCK;
}
}
|
Then if you put 1 into each of the four 'lines', the first LED gets lit in each line, 2, the next one etc..
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|