|
|
View previous topic :: View next topic |
Author |
Message |
debaruah
Joined: 20 Aug 2015 Posts: 4
|
74595 Usage Problem |
Posted: Fri Aug 21, 2015 7:50 am |
|
|
Hi,
I have a problem with 74595 driver usage.
For 2 74HC595 IC,
Code: |
#IFNDEF EXP_OUT_ENABLE
#define EXP_OUT_ENABLE PIN_C1
#define EXP_OUT_CLOCK PIN_C0
#define EXP_OUT_DO PIN_C2
#define NUMBER_OF_74595 2
#ENDIF
|
My data for 74595 buffer:
Code: |
byte animationOutput[8] =
{
0,0,
85,85,
170,170,
255,255
};
|
I want to have continuous data output, so
Code: |
while(1)
{
unsigned int sRCounter=0;
for(sRCounter=0;sRCounter<4;sRCounter++)
{
write_expanded_outputs(animationOutput+2*sRCounter); //write_expanded_outputs(animationOutput+NUMBER_OF_74595*sRCounter);
delay_ms(1000);
}
}
|
First "for(;;)" cycle(for sRCounter=0,1,2,3) is Ok, but the next ones are Problem. Any idea? |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri Aug 21, 2015 1:25 pm |
|
|
i don't want to sound dismissive but the driver you refer to is VERY robust
in terms of MORE than 8 outputs ( a single 74hc595 ) or just 8......
the driver description says ONE thing about multiple chips using multiple 3 pin pairs but the code says otherwise. it is written properly to do more and better :
with sufficient clock speed it IS the smart way to do this
when you daisy chain n*8 bits by using a serial data pass through for multiples of 8 expander chips and never committing more than 3 data lines to n chips in total.
i'm a bit unclear out your problem.
POST your schematic and compiler version and what MicroCHIP part?
and what are you expecting this to evaluate to?
Code: | animationOutput+2*sRCounter |
|
|
|
debaruah
Joined: 20 Aug 2015 Posts: 4
|
|
Posted: Fri Aug 21, 2015 2:41 pm |
|
|
Hi asmboy,
SR outputs for first "while()" cycle;
0,0, OK
85,85, OK
170,170, OK
255,255 OK
But second and subsequent "while()" cycles, code is running, but SR outputs did not work right for my array. (animationOutput[]) I think i have problem with my array pointer.
Simple sch.
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Fri Aug 21, 2015 11:21 pm |
|
|
The answer is very simple.
If you look at the 74595 driver, it rotates the array that is used.
Problem is that sending the same array again, results in the data being output one bit out of position.
You have to send a new copy of the data each time.
So:
Code: |
int16 animationOutput[4] =
{ 0, 0x5555, 0xAAAA, 0xFFFF };
//then
while(1)
{
unsigned int sRCounter;
int16 val_to_send;
for(sRCounter=0;sRCounter<4;sRCounter++)
{
val_to_send=animationOuput[sRCounter];
write_expanded_outputs(&val_to_send);
delay_ms(1000);
}
}
|
The driver assumes the value is being recalculated each time it is called. |
|
|
debaruah
Joined: 20 Aug 2015 Posts: 4
|
|
Posted: Sat Aug 22, 2015 6:56 am |
|
|
i changed the *.c driver. it seem ok.
1. choice
Code: |
void write_my_expanded_outputs(BYTE* eo) {
BYTE i,j;
output_low(EXP_OUT_CLOCK);
output_low(EXP_OUT_ENABLE);
for(i=0;i<NUMBER_OF_74595;++i) {
for(j=0;j<8;j++)
{
if(!bit_test(*(eo+i),j))
output_low(EXP_OUT_DO);
else
output_high(EXP_OUT_DO);
output_high(EXP_OUT_CLOCK);
output_low(EXP_OUT_CLOCK);
}
}
output_high(EXP_OUT_ENABLE);
output_low(EXP_OUT_ENABLE);
}
|
2. choice
Code: |
void write_my2_expanded_outputs(BYTE* eo) {
BYTE i;
output_low(EXP_OUT_CLOCK);
output_low(EXP_OUT_ENABLE);
for(i=0;i<NUMBER_OF_74595*8;++i) { // Clock out bits from the eo array
if(bit_test(*(eo+(i/8)),i%8)==0)
output_low(EXP_OUT_DO);
else
output_high(EXP_OUT_DO);
output_high(EXP_OUT_CLOCK);
output_low(EXP_OUT_CLOCK);
}
output_high(EXP_OUT_ENABLE);
output_low(EXP_OUT_ENABLE);
}
|
Thanks. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sat Aug 22, 2015 10:40 am |
|
|
i feel so dull at missing the use variable indirection in the function.
its one reason i use PICS with lotsa ram & fast clocks.
I would personally have modified the library function so the
compiler is always working on a trashable COPY of the passed data. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sat Aug 22, 2015 1:52 pm |
|
|
The reason it uses the pointer to the source, is so that it can handle any size of data. Problem with using a local copy, is that you then need to cope with all the different possible sizes.
The bit test solution is fine, but slow.
It rotates it's test mask, from 'scratch' every pass.
Better really, just to have a local mask variable, and rotate this.
The assumption in the original driver, is simply that you will always be 'preparing' a byte/bytes to output each time. |
|
|
debaruah
Joined: 20 Aug 2015 Posts: 4
|
|
Posted: Sat Aug 22, 2015 2:52 pm |
|
|
I think it unnecessary to prepare all the data for each time. Even if you want to change a single data, you need to prepare all data (copy all of them to new buffer)
Driver which is using mask process,
Code: |
void write_my3_expanded_outputs(BYTE* eo) {
BYTE i,j;
output_low(EXP_OUT_CLOCK);
output_low(EXP_OUT_ENABLE);
for(i=0;i<NUMBER_OF_74595;++i) {
for(j=0;j<8;j++)
{
//if(!bit_test(*(eo+i),j))
if((*(eo+i)&(1<<j))==0)
output_low(EXP_OUT_DO);
else
output_high(EXP_OUT_DO);
output_high(EXP_OUT_CLOCK);
output_low(EXP_OUT_CLOCK);
}
}
output_high(EXP_OUT_ENABLE);
output_low(EXP_OUT_ENABLE);
}
|
Thanks. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sun Aug 23, 2015 12:53 am |
|
|
Not quite.
The point is that you rotate the mask 'j' times each time round the loop. This is a waste.
Instead initialise the mask, and rotate it once each time round. This way you only use eight rotations, when rotating it each time (which is also what bit test does), you rotate 0, 1, 2, 3, 4, 5, 6, 7 times a total of 28 rotations....
Code: |
void write_my3_expanded_outputs(BYTE* eo) {
BYTE i,j,mask,temp;
output_low(EXP_OUT_CLOCK);
output_low(EXP_OUT_ENABLE);
for(i=0;i<NUMBER_OF_74595;++i)
{
mask=1;
temp=eo[i];
for(j=0;j<8;j++)
{
if((temp&mask)==0)
output_low(EXP_OUT_DO);
else
output_high(EXP_OUT_DO);
output_high(EXP_OUT_CLOCK);
output_low(EXP_OUT_CLOCK);
mask<<=1; //rotate mask _once_.
}
}
output_high(EXP_OUT_ENABLE);
output_low(EXP_OUT_ENABLE);
}
|
I also copy the byte currently being tested into 'temp'. This way there only has to be one table lookup per byte, instead of doing such a lookup for every bit. Uses one byte more RAM in the routine, but saves perhaps 70 instructions per byte!...
Try running an instruction count for the routine in MPLAB, and be surprised at just how much faster this approach is!... |
|
|
|
|
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
|