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 CCS Technical Support

rs232 communication knicks overall performance
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
pfo



Joined: 22 Feb 2004
Posts: 16
Location: vienna, austria.

View user's profile Send private message Visit poster's website ICQ Number

rs232 communication knicks overall performance
PostPosted: Mon Feb 23, 2004 3:37 am     Reply with quote

hi!

my code looks like that:
Code:
 
while(1)
{
             do stuff (); // it takes ~ 100uS to do it ...
             printf("blah blah"); // rs232 @ 115kbaud
}


it seems that the main loop spends the whole execution time in the printf(), would buffered interrupt driven transmission give me a little more performance? or is a faster baud rate the solution?
TSchultz



Joined: 08 Sep 2003
Posts: 66
Location: Toronto, Canada

View user's profile Send private message

PostPosted: Mon Feb 23, 2004 6:30 am     Reply with quote

The communications is not the problem, but rather the method. The printf will have to sit in a loop an wait for each character to be sent and complete the entire string before finishing. If you can't wait this long use a buffer and interrupt based transmit routines, this will resolve this problem.

I have done numerous jobs with 115200 bps communications on a multi-drop RS-485 8 bit interface and have no problems with communications preventing the code from running. I do however use interrupt based receive and transmit routines.

The overhead for the routine(s) would then be as follows;
- build the buffer contents
- start the transmittion by enabling the TX interrupt and sending the first byte
- do whatever you want while the buffer is being sent
+ interrupt overhead to send a new byte when buffer is full, approx 70 instructions

It is helpfull to set a couple of flags so the rest of the program knows what is happening with the buffers, ie if TX and/or RX are busy or done.
Guest








could you provide some code?
PostPosted: Mon Feb 23, 2004 9:36 am     Reply with quote

would u be so kind an provide some code for this method?

thx!
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

PostPosted: Mon Feb 23, 2004 10:29 am     Reply with quote

I posted an example for MODBUS that uses a buffer and is interupt based. The trick is to print to a buffer and then send the buffer until you get to the last character.
pfo



Joined: 22 Feb 2004
Posts: 16
Location: vienna, austria.

View user's profile Send private message Visit poster's website ICQ Number

PostPosted: Mon Feb 23, 2004 1:12 pm     Reply with quote

i used the code that's provided in the examples, but it doesn't seem to increase my overall performance ... that's my code:
Code:

#include <18F452.h>
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000) // 20MHz OSC
#use rs232(baud=115400, xmit=PIN_C6, rcv=PIN_C7)

static   int16 overflow;
static   int16 value=0;
static   int16 ticks;
#include "D:\pcc_work\drivers\MCP3208.C"


#define T_BUFFER_SIZE 384
byte t_buffer[T_BUFFER_SIZE];
byte t_next_in = 0;
byte t_next_out = 0;
int32 ios=0;

#int_tbe
void serial_isr() {
  // ios++;
   putc(t_buffer[t_next_out]);
   t_next_out=(t_next_out+1) % T_BUFFER_SIZE;
   if(t_next_in==t_next_out)
     disable_interrupts(int_tbe);

}

void bputc(char c) {
   short restart;
   int ni;

   restart=t_next_in==t_next_out;
   t_buffer[t_next_in]=c;
   ni=(t_next_in+1) % T_BUFFER_SIZE;
   while(ni==t_next_out);
   t_next_in=ni;
   if(restart)
     enable_interrupts(int_tbe);
}




#define MEDIAN_FILTER_LENGTH 32
struct median_data
{
   int16 accel_reading[MEDIAN_FILTER_LENGTH];
   int8 index;
   int32 running_sum;
   int16 average;
};


void update_running_average (struct median_data *sptr)
{
   
   sptr->running_sum = sptr->running_sum - sptr->accel_reading[sptr->index];

   
   sptr->accel_reading[sptr->index] = read_adc();

   azu
   sptr->running_sum = sptr->running_sum + sptr->accel_reading[sptr->index];

   
   sptr->average = (int16) ((sptr->running_sum) / MEDIAN_FILTER_LENGTH); 

   
   if(++(sptr->index) > (MEDIAN_FILTER_LENGTH-1))
   {
      sptr->index = 0;
   }
return;
}



void main(void)
{
struct median_data X={0};
struct median_data Y={0};


setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports(ALL_ANALOG);

enable_interrupts(global);

 

printf(bputc,"\r\n\Running...\r\n");
//minmal conversion time is 12*T_ad with t_ad beeing 1.6uS +
//the time taken to trigger the conversion, and the time taken to read it. //Typically perhaps 15 instructions.
//this means that the global conversion time is ~ 12*1.6uS+15*0.2uS (instruction time = 0.2uS) -> ~ 27.2 uS

      while(TRUE)
         {
            // first channel is set
         
            set_adc_channel(0);          //friggin 16uS
            update_running_average(&X);  //~ 40uS
            printf(bputc,"\r\n%lu",X.average);
           
            //set 2nd channel
            set_adc_channel(1);  // another f...  16uS
            update_running_average(&Y); //~40uS
            printf(bputc," %lu",Y.average);
         }
}
pfo



Joined: 22 Feb 2004
Posts: 16
Location: vienna, austria.

View user's profile Send private message Visit poster's website ICQ Number

PostPosted: Mon Feb 23, 2004 2:11 pm     Reply with quote

i capture the output to a file, and w/ w/o the file just contains ~ 70K entries after 60secs ... :(

it just gets slower when i use a larger buffer or use more printfs!


Last edited by pfo on Mon Feb 23, 2004 2:33 pm; edited 1 time in total
Gerrit



Joined: 15 Sep 2003
Posts: 58

View user's profile Send private message

PostPosted: Mon Feb 23, 2004 2:18 pm     Reply with quote

pfo,

Is it 70000 records or 70000 characters in 60 seconds ?

First check if the printf(%ul is the problem

just disable all AD parts and use:

printf("\r\n12345"); // for the first and
printf(" 67890"); // for the second command

what is the tru puth now ?



Gerrit
pfo



Joined: 22 Feb 2004
Posts: 16
Location: vienna, austria.

View user's profile Send private message Visit poster's website ICQ Number

PostPosted: Mon Feb 23, 2004 2:34 pm     Reply with quote

Gerrit wrote:
pfo,

Is it 70000 records or 70000 characters in 60 seconds ?

First check if the printf(%ul is the problem

just disable all AD parts and use:

printf("\r\n12345"); // for the first and
printf(" 67890"); // for the second command

what is the tru puth now ?



Gerrit


its records ...
pfo



Joined: 22 Feb 2004
Posts: 16
Location: vienna, austria.

View user's profile Send private message Visit poster's website ICQ Number

PostPosted: Mon Feb 23, 2004 2:40 pm     Reply with quote

Gerrit wrote:
pfo,

Is it 70000 records or 70000 characters in 60 seconds ?

First check if the printf(%ul is the problem

just disable all AD parts and use:

printf("\r\n12345"); // for the first and
printf(" 67890"); // for the second command

what is the tru puth now ?



Gerrit


it tried it with printf(bputc,"\r\n12345"); and so on ...
the file now just contains ~ 69K records, -> ~same performance!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 23, 2004 3:14 pm     Reply with quote

Quote:
printf(bputc,"\r\n%lu",X.average);
printf(bputc," %lu",Y.average);

Let's assume that these statements together put out an
average of 10 characters per record. That assumes
4 characters for each "average" value, and 2 chars
for the carriage return and linefeed.

At 115400 baud, you're going to get 11540 x 60 = 692,400 chars/minute.

If each record takes an average of 10 chars, then divide 692K
by 10, to get the number of records per minute.
It's about 69K, which is what you're seeing. So you're hitting
the limits of the baud rate.
pfo



Joined: 22 Feb 2004
Posts: 16
Location: vienna, austria.

View user's profile Send private message Visit poster's website ICQ Number

PostPosted: Mon Feb 23, 2004 3:27 pm     Reply with quote

PCM programmer wrote:
Quote:
printf(bputc,"\r\n%lu",X.average);
printf(bputc," %lu",Y.average);

Let's assume that these statements together put out an
average of 10 characters per record. That assumes
4 characters for each "average" value, and 2 chars
for the carriage return and linefeed.

At 115400 baud, you're going to get 11540 x 60 = 692,400 chars/minute.

If each record takes an average of 10 chars, then divide 692K
by 10, to get the number of records per minute.
It's about 69K, which is what you're seeing. So you're hitting
the limits of the baud rate.


is there a method of proving the the average computation takes realy place and that i sample ~ 10KHz (for both channels) and that the rs232 comm is thre real slow part of the while statement?
pfo



Joined: 22 Feb 2004
Posts: 16
Location: vienna, austria.

View user's profile Send private message Visit poster's website ICQ Number

PostPosted: Mon Feb 23, 2004 4:01 pm     Reply with quote

i now put a new variable in the update_running_average() function and after 1 minute its value is ~ 22K (-> 11K samples/channel/minute) ....

:((

who could i improve this? i nead at least ~ 5K samples per channel pre seconds ...

and there is no performance difference between a "normal" printf(" blah") and a printf(bputc, "blah"); why?
adcount is ~ 39K after 60 seconds (it's a int16).

does pcwh use the 8x8 hw mulitpy unit?


Last edited by pfo on Mon Feb 23, 2004 4:15 pm; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 23, 2004 4:10 pm     Reply with quote

Quote:
Is there a method of proving the the average computation takes realy place and that i sample ~ 10KHz (for both channels) and that the rs232 comm is thre real slow part of the while statement?


I guess you want to calculate your loop speed, without the printfs,
to find out how fast your other code really runs.

I would do this with a stopwatch and a counter variable.
Run the following program. When it prompts you to press
a key, do so, and start your stopwatch. After 10 seconds
passes on your stopwatch, click it to stop, and also hit
the Enter key to stop the program at the same time.
The program will display the number of loops that have
occurred during the 10 second period. Divide that number
by 10 to get the number of loops per second.

Let's say the result is 10,000 loops per second. Then
take the reciprocal, to get the timer per loop, which is
then 1/10,000 = 100 usec.



Code:
void main(void)
{
struct median_data X={0};
struct median_data Y={0};

int32 counter;

setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports(ALL_ANALOG);
enable_interrupts(global);
 

printf(bputc,"\r\n\Press Enter to start.\r\n");
getc();  // Wait for a keypress

counter = 0;

while(TRUE)
   {
    // first channel is set
         
    set_adc_channel(0);          //friggin 16uS
    update_running_average(&X);  //~ 40uS
//    printf(bputc,"\r\n%lu",X.average);
           
   // Set 2nd channel
   set_adc_channel(1);  // another f...  16uS
   update_running_average(&Y); //~40uS
//   printf(bputc," %lu",Y.average);

   counter++;
   
   if(kbhit())   // Was another key pressed ?
      break;     // Exit loop if so
  }

getc();  // Get the key and discard it.
printf("Counter = %lu\n\r", counter);

while(1);

}
pfo



Joined: 22 Feb 2004
Posts: 16
Location: vienna, austria.

View user's profile Send private message Visit poster's website ICQ Number

PostPosted: Mon Feb 23, 2004 4:27 pm     Reply with quote

PCM programmer wrote:
Quote:
Is there a method of proving the the average computation takes realy place and that i sample ~ 10KHz (for both channels) and that the rs232 comm is thre real slow part of the while statement?


I guess you want to calculate your loop speed, without the printfs,
to find out how fast your other code really runs.

I would do this with a stopwatch and a counter variable.
Run the following program. When it prompts you to press
a key, do so, and start your stopwatch. After 10 seconds
passes on your stopwatch, click it to stop, and also hit
the Enter key to stop the program at the same time.
The program will display the number of loops that have
occurred during the 10 second period. Divide that number
by 10 to get the number of loops per second.

Let's say the result is 10,000 loops per second. Then
take the reciprocal, to get the timer per loop, which is
then 1/10,000 = 100 usec.



Code:
void main(void)
{
struct median_data X={0};
struct median_data Y={0};

int32 counter;

setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports(ALL_ANALOG);
enable_interrupts(global);
 

printf(bputc,"\r\n\Press Enter to start.\r\n");
getc();  // Wait for a keypress

counter = 0;

while(TRUE)
   {
    // first channel is set
         
    set_adc_channel(0);          //friggin 16uS
    update_running_average(&X);  //~ 40uS
//    printf(bputc,"\r\n%lu",X.average);
           
   // Set 2nd channel
   set_adc_channel(1);  // another f...  17uS
   update_running_average(&Y); //~40uS
//   printf(bputc," %lu",Y.average);

   counter++;
   
   if(kbhit())   // Was another key pressed ?
      break;     // Exit loop if so
  }

getc();  // Get the key and discard it.
printf("Counter = %lu\n\r", counter);

while(1);

}

the result is ~ 660 counts in 1 secs -> ~ 147us :(
what could i do better to make it run faster?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 23, 2004 4:29 pm     Reply with quote

Quote:
who could i improve this? i nead at least ~ 5K samples per channel pre seconds ...

and there is no performance difference between a "normal" printf(" blah") and a printf(bputc, "blah"); why?
adcount is ~ 39K after 60 seconds (it's a int16).


As I demonstrated above, the basic limit on data throughput
is due to your baudrate, and your record length.

It might be better if you told us what your overall problem is,
and then we might offer solutions. It appears that you're
trying to sample an audio waveform.

Possible solutions:
1. Maybe you have to use two PICs -- one per channel.
2. Instead of sending data as ASCII characters, send it
as binary values. For example, to send 65535 in decimal
takes 5 ASCII chars. But to send it in binary, takes only
two chars: FF FF
You could use a "00" byte as a record separator, or just use
a fixed record length and don't use a separator.
Your throughput would go way up.
Let the PC convert the data back to some useful form later.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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