CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

74595 Usage Problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
debaruah



Joined: 20 Aug 2015
Posts: 4

View user's profile Send private message

74595 Usage Problem
PostPosted: Fri Aug 21, 2015 7:50 am     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Fri Aug 21, 2015 1:25 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Aug 21, 2015 2:41 pm     Reply with quote

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: 19338

View user's profile Send private message

PostPosted: Fri Aug 21, 2015 11:21 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Aug 22, 2015 6:56 am     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Sat Aug 22, 2015 10:40 am     Reply with quote

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: 19338

View user's profile Send private message

PostPosted: Sat Aug 22, 2015 1:52 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Aug 22, 2015 2:52 pm     Reply with quote

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: 19338

View user's profile Send private message

PostPosted: Sun Aug 23, 2015 12:53 am     Reply with quote

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!...
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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