Go Down

Topic: small serial tx function (Read 651 times) previous topic - next topic

dcb

Sep 26, 2008, 07:27 pm Last Edit: Sep 26, 2008, 07:29 pm by dcb Reason: 1
I wanted to add serial output to my project, but don't have much space to spare.  Bringing in Serial costs over 1400 bytes just to transmit debug/logging data over the wire.  So I came up with this function which adds only 66 bytes.  

It only sends strings so that's part of why it's smaller    and it only transmits/cant use it in conjunction with Serial (why would you?)/and would need tweaking to work on a atmega8 or a non 16mhz chip.  But maybe someone has a need for it.

Code: [Select]

#define myubbr (16000000/16/9600-1)
void simpletx( char * string ){
 if (UCSR0B != (1<<TXEN0)){ //do we need to init the uart?
    UBRR0H = (unsigned char)(myubbr>>8);
    UBRR0L = (unsigned char)myubbr;
    UCSR0B = (1<<TXEN0);//Enable transmitter
    UCSR0C = (3<<UCSZ00);//N81
 }
 byte x = 0;      
 char c = string[x];      
 while(c != 0){  
   while ( !( UCSR0A & (1<<UDRE0)) );
   UDR0 = c; //send the data
   x++;      
   c = string[x];      
 }      
}

void setup(){}

void loop(){
 simpletx("Hello\n");
 delay(500);
}

mikalhart

Hey, dcb, that is indeed cool and potentially quite useful.  Thanks for sharing!  I gather it's hardcoded for 9600 baud, but that could easily be adjusted by changing the definition of myubbr?

Here's the same function trimmed down to 56 bytes: :)

Quote
#define myubbr (16000000/16/9600-1)
void simpletx( char * string ){
 if (UCSR0B != (1<<TXEN0)){ //do we need to init the uart?
    UBRR0H = (unsigned char)(myubbr>>8);
    UBRR0L = (unsigned char)myubbr;
    UCSR0B = (1<<TXEN0);//Enable transmitter
    UCSR0C = (3<<UCSZ00);//N81
 }
 while (*string)
 {
   while ( !( UCSR0A & (1<<UDRE0)) );
   UDR0 = *string++; //send the data
 }
}


Mikal

mem

#2
Sep 26, 2008, 09:42 pm Last Edit: Sep 26, 2008, 10:02 pm by mem Reason: 1
Quote
#define myubbr (16000000/16/9600-1)
void simpletx( char * string ){
if (UCSR0B != (1<<TXEN0)){ //do we need to init the uart?
   UBRR0H = (unsigned char)(myubbr>>8);
   UBRR0L = (unsigned char)myubbr;
   UCSR0B = (1<<TXEN0);//Enable transmitter
   UCSR0C = (3<<UCSZ00);//N81
}
while (*string)
{
  while ( !( UCSR0A & (1<<UDRE0)) );
  UDR0 = *string++; //send the data
}
}

Hi Mikal, it doesn't look like the while loop will terminate,  I think *string is always true for any non null string

mikalhart

#3
Sep 26, 2008, 10:39 pm Last Edit: Sep 26, 2008, 10:42 pm by mikalhart Reason: 1
Hi mem,

Quote
Hi Mikal, it doesn't look like the while loop will terminate.

Hmm... I think it will.  At least it worked for the one 5-second test I did. :D

No seriously, the (outer) loop will always terminate because string is being incremented at every iteration, and so eventually *string, the while loop test condition, will attain a value of 0 when it gets to the end of the string.

Try dcb's test program:

Code: [Select]
void setup(){}
void loop()
{
 simpletx("Hello\n");
 delay(500);
}


It works great with both revisions of simpletx().  I like that tiny function!  Thanks.

Mikal

PS: You often see this kind of technique in old C strcpy code, like:

Code: [Select]
void strcpy(char *to, char *from)
{
 while (*to++ = *from++); // !
}


M

dcb

Cute,   That seems to work too :)  Except I count 56 bytes ;)

mikalhart

#5
Sep 26, 2008, 10:44 pm Last Edit: Sep 26, 2008, 10:46 pm by mikalhart Reason: 1
Quote
56 bytes

Yup, that's right!  Same here!

M

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy