Click here to Skip to main content
15,868,420 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hey guys I'm writing a C code in Atmel Studio 6.0 with GCC C compiler. Essentially I'm doing USART communication on a microcontroller, and I found a sample code(a header file) that handles sending/receiving (Tx/Rx) using a circular receiving buffer from an Atmel employee's blog
http://www.fourwalledcubicle.com/files/LightweightRingBuff.h[^]

Code excerpt that works:

Besides initializing the Buffer and other functions, it insert the char type data it receives into the Buffer as such:
C++
static inline void RingBuffer_Insert(RingBuff_t* const Buffer,
                                         const RingBuff_Data_t Data)  // type of Data: uint8_t
    {
        *Buffer->In = Data;//store the char data in the Buffer.

        if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
          Buffer->In = Buffer->Buffer;

        ATOMIC_BLOCK(ATOMIC_RESTORESTATE)  // ignore this detail, not relevant to topic
        {
            Buffer->Count++;
        }
    }

and here's the function in the header file to get'em out
C++
static inline RingBuff_Data_t RingBuffer_Remove(RingBuff_t* const Buffer)
        {
            RingBuff_Data_t Data = *Buffer->Out;

            if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
              Buffer->Out = Buffer->Buffer;

            ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
            {
                Buffer->Count--;
            }

            return Data;
        }


And then in main.c we can use this to read out chars in the Buffer
C++
// Print contents of the buffer one character at a time
     while (BufferCount--)
       putc(RingBuffer_Remove(&Buffer));


My goal: I'm trying to wait until an entire string of chars is stored in the Buffer (terminated with a '\0' or '\n'? ), read out the string, and maybe parse it.


Code excerpt that doesn't work:

Now as an absolute C newbie, here's what I have attempted to do (buggy code with blatantly wrong pointer usage coming thru) Just to illustrate what I hope to achieve:
C++
int main( void ) {
 //... some initialization
RingBuffer_InitBuffer(&Buffer);
unsigned char holder;

while(true) {
if(usart_kbhit()) // this detects the receiving flag in USART register
  {	holder = usart_getchar();  //holder is char type. Stores the char received 
       //in the Rx register
	RingBuffer_Insert(&Buffer, holder); // function above
        
        if (holder == '\n')   { // I suppose I can send  '\n'  as the last char to 
          //terminate my string?
	 //now I'm trying to read the chars in Buffer and store'em in 
         // 'Command_String' which I suppose should be a char [] ??
         // Not so sure about how I should define 'Command_String'

        uint16_t BufferCount = RingBuffer_GetCount(&Buffer); // get the char count
       
        char Command_String[BufferCount];  //  I know this is seriously wrong in 
         //terms of how the pointer should be used.
					
        while (BufferCount--)
	  strcat(Command_String,RingBuffer_Remove(&Buffer)); // trying to append 
          // the char that I read off the Buffer to Command_String
          // but this doesn't work.
			
	  // Not working .  RingBuffer_Remove() gives a string, strcat requires  
          //pointer??  
			
						
	if strncmp(Command_String,"ABC\n",4) // my attempt to compare the string I 
         //get in Command_String with a hard-coded list of commands 
        tell_the_microcontroller_to_do_stuff (); // if received "ABC" then do stuff
                                }
   }
             }
                  }


Sorry about the long post but all I need are some comments about the way I read out the string from Buffer, store it in Command_String, and compare Command_String with "ABC"


Here's my code without the wordy comments

C#
while(true) {
      // if a key has been pressed, then process it
if(usart_kbhit())   {
   holder = usart_getchar();

   RingBuffer_Insert(&Buffer, holder);

   if (holder == '\n')   {
uint16_t BufferCount = RingBuffer_GetCount(&Buffer);
 char Command_String[BufferCount] ;

   while (BufferCount--)
               strcat(Command_String,RingBuffer_Remove(&Buffer));
   // Not working .


   if strncmp(Command_String,"ABC\n",4)
    tell_the_microcontroller_to_do_stuff ();

                                }
   }
             }
                  }



Thank you
Posted
Updated 17-Dec-12 10:40am
v8
Comments
SandiegoSSD 17-Dec-12 16:03pm    
I guess I should narrow down my question to : I have some doubts about what type I should use for that "Command_String", which holds the char data read from Buffer. Also some clarification on whether I should be checking '\n' or '\0' as the string terminator? (while this checking happens on the microcontroller side, on my VB GUI which sends data to the microcontroller, I can send either \n or \0 whichever is necessary)

1 solution

char Command_String[BufferCount] ;

  while (BufferCount--)
              strcat(Command_String,RingBuffer_Remove(&Buffer));


That won't work in C. You cannot allocate an array of char on the stack (as auto variable) with a variable length. The length must be know at compile time. So either allocate an array of fixed size, say the maximim chunk of chars you expect in a row, or you must allocate the space from the heap, and later free it, e.g.
char* pBuffer = malloc (bufferCount);
...
free (pBuffer);

As for your question about '\n' or '\0' as terminator, that depends entirely on your situation. Ususally, you want to wait for '\0' on a USART. But that depends on your buffering mechanism any what your trying to accomplish.
 
Share this answer
 
Comments
SandiegoSSD 17-Dec-12 18:29pm    
Thank you for the heads up

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900