Reading 10 bytes data from URAT rx_cb using Timer day

Go To Last Post
29 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I created atmel start project using samv71q21 controller and  added asynchronous USART driver for receiving data, here i used timer interrupt to maintain the delay for receiving all bytes.

 

the code as follows:

 

struct io_descriptor *debug;
static struct timer_task     task;

char buffer[20] ;
uint8_t buff[255];
volatile uint16_t flag1 = 0, flag2 = 0;
uint16_t jdx = 0;

 

void timer_cb(const struct timer_task *const timer_task)
{
    flag2 = 1;    
}

 

void rx_cb(const struct usart_async_descriptor *const io_descriptor)
{
    uint16_t idx = 0;
            
    for (idx = 0; idx < io_descriptor->rx.write_index; idx++)
    {
        buff[idx] = io_descriptor->rx.buf[idx];        
    }
    
//    flag1 = 1;
    timer_add_task(&TIMER_0, &task);    
}

 

void initialisation(void)
{
    //UART initialisation
    usart_async_register_callback(&USART_0, USART_ASYNC_RXC_CB, rx_cb);
    usart_async_get_io_descriptor(&USART_0, &debug);
    usart_async_enable(&USART_0);
    
    //Timer initialisation
    task.cb = timer_cb ;
    task.interval = 100;
    task.mode = TIMER_TASK_REPEAT;    
    timer_start(&TIMER_0);
    
}

int main(void)
{
    /* Initializes MCU, drivers and middle ware */
    atmel_start_init();
    
    initialisation();
    io_write(debug, (uint8_t *)"\n\r********************SEED COUNTER******************\n\r", 54);
  

    /* Replace with your application code */
    while (1)
    {
        if (flag2 == 1)
        {
           
                io_write(debug, (uint8_t*)buff,strlen(buff));
                flag2 = 0;    
           }
            
        }
        
    }
}

 

here after receiving data it is going to rx_cb and storing data from ring buffer and going to timer callback. for 1 byte data it is working fine , but when i passed the 10 bytes of data it is not receiving all 10 bytes.

 

something is going wrong in timer delay for receiving all bytes i am not getting where is mistake . please help me to resolve the issue?

 

please help me to resolve the issue...

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dump the timer - there is no need to use a timer on top of the async USART driver.  It adds unnecessary complexity.  Plus timer_add_task() should be called once during initialization, not every time the rx_cb() function is invoked.

 

Instead have the rx_cb() function push all available received characters into a ring buffer.  This will happen at the interrupt level.  Then have the main loop check for characters in the ring buffer, pop out any available, and write them out the transmitter.  Just be careful to protect the ring buffer from simultaneous access from both main() and interrupts (ie. rx_cb()).

Last Edited: Thu. Oct 25, 2018 - 01:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The io_descriptor->rx is already a ring buffer, it can be read in main just as well (using io_read or using the ring buffer API).

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why dont you just use an interrupt for the sercom for receive complete.  In that way you wont lose anything.  just frame the 10 bytes with some start and end words to reset the counter where you store the bytes received. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

Thank you for your reply. now i removed the timer call back and in rx_cb only i am receiving complete data and setting the flag .if flag is set , i am processing the data in the main

 

code as follows:

 

char buffer[20] ;
uint8_t buff[255];
volatile uint16_t flag1 = 0, flag2 = 0;
uint16_t jdx = 0, len = 0;

 

void rx_cb(const struct usart_async_descriptor *const io_descriptor)
{
    
    uint16_t idx = 0;        
    for (idx = 0; idx < io_descriptor->rx.write_index; idx++)
    {
        buff[idx] = io_descriptor->rx.buf[idx];        
    }
    
    flag2 = 1;
        
}

 

void initialisation(void)
{
    //UART initialisation
    usart_async_register_callback(&USART_0, USART_ASYNC_RXC_CB, rx_cb);
    usart_async_get_io_descriptor(&USART_0, &debug);
    usart_async_enable(&USART_0);
        
}

 

nt main(void)
{
    /* Initializes MCU, drivers and middle ware */
    atmel_start_init();
    
    initialisation();
    io_write(debug, (uint8_t *)"\n\r********************SEED COUNTER******************\n\r", 54);

    gpio_set_pin_level(LED1, true);

    /* Replace with your application code */
    while (1)
    {
        if (flag2 == 1)
        {
            
            if ((buff[0] == 49) && (buff[1] == 50) && (buff[2] == 51) && (buff[3] == 52)&& (buff[4] == 53))
            {
                gpio_set_pin_level(LED1, false);
                flag2 = 0;    
            }
             
        }
        
    }
}

here if i send 10 bytes of data means it  is receiving data in the rx_cb. i can see the buffer content in the step running.

 

after receiving it is coming to main and checking flag , flag is setting and entering the first condition but it is not entering into second condition even the buffer content are same.

 

for example i sent 5 bytes of data 12345 from hyper terminal. it is receiving the content like 

buff[0] = 49;   //ascii format

buff[1] = 50;

buff[2] = 51;

buff[3] = 52;

buff[4] = 53;

 

because of that i am comparing the received data with 49 50 51 52 53 .

 

why this condition is not entering and LED is not glowing ?

 

please help me to resolve the problem... it is very much needed for me

 

 

 

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

volatile could be needed for buff,  (depends on the optimization setting). 

 

Note you can't read the from the ring buffer like that once it starts to wrap (use io_read or the API as mentioned).

Also, the compiler is happy to translate ASCII for you so for 49 you write the character constant '1'.

BTW, memcmp(buff, "12345", 5 ) == 0 is a more compact way to test.

it is very much needed for me

Why?

 

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

Thank u lajon for Your reply. I need one more clarification for my application implementation. My application includes Master and slave communication because of that i  am using USART asynchronous mode and rx_cb to receive the data from master.here from rx_cb iam receiving the data completely if i send once or twice but if i want to receive continuous data send from the master data is missing , so i used timer interrupt to provide some delay while receiving, so from that i can receive complete data , even  the master sending data continue....

 

here i am not getting how to use timer interrupt(timer callback) with rx_cb...

 

code as follows:

 

#include <atmel_start.h>
#include <string.h>
#include <stdio.h>

 

struct io_descriptor *debug;
static struct timer_task     task;

char buffer[20]  ;
uint8_t buff[255];
volatile uint16_t RX_flag = 0;
uint16_t RX_timer_ctr = 0, Rx_ptr = 0;
uint16_t jdx = 0, len = 0;
 

//Timer call back
void timer_cb(const struct timer_task *const timer_task)
{
    if (RX_flag == 1)
    {
        RX_timer_ctr++;
        if (RX_timer_ctr > 100)
        {
            RX_timer_ctr = 0;
            RX_flag = 8;
        }
    }
            
}

//RX call back

void rx_cb(const struct usart_async_descriptor *const io_descriptor)
{
    
    uint16_t idx = 0;        
    for (idx = 0; idx < io_descriptor->rx.write_index; idx++)
    {
        buff[idx + Rx_ptr] = io_descriptor->rx.buf[idx];
        Rx_ptr++;        
    }
    
    RX_flag = 1;
    RX_timer_ctr = 0;
}

void initialisation(void)
{
    //UART initialisation
    usart_async_register_callback(&USART_0, USART_ASYNC_RXC_CB, rx_cb);
    usart_async_get_io_descriptor(&USART_0, &debug);
    usart_async_enable(&USART_0);
    
    //Timer initialisation
    task.cb = timer_cb ;
    task.interval = 1;
    task.mode = TIMER_TASK_REPEAT;    
    
    timer_start(&TIMER_0);
    timer_add_task(&TIMER_0, &task);        
}
int main(void)
{
    /* Initializes MCU, drivers and middle ware */
    atmel_start_init();
    
    initialisation();
    io_write(debug, (uint8_t *)"\n\r********************SEED COUNTER******************\n\r", 54);
    gpio_set_pin_level(LED1, true);
    
    /* Replace with your application code */
    while (1)
    {
        if (RX_flag == 8)
        {
            
            io_write(debug, (uint8_t*)buff,strlen(buff));
        //    delay_ms(10);
    
            RX_flag = 0;
            Rx_ptr = 0;
        
        }
        
    }
}

 

This code iam trying ,here for step running i observed it is going to dummy handler why it is like?

 

some thing i am making mistake... please help me?

 

How to use timer to read the complete data from rx_cb .... any other method  is there to implement my application/

 

if anybody knows please share it , it is needed for me...

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

If i want to read ring buffer content using io_read(); function, it is possible to read in rx_cb ?? it is possible to read in main??

 

here i should read only 1 byte at time ? or multiple bytes

 

ie. io_read(&USART_0.io, (uint8_t)&buff[0], 10); like this can i use? or only 1 byte at place of 10?

 

if i want to clear the buffer after processing means how can i do it?

 

please clarify these.... much needed for me

 

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It makes sense to read in main based on some condition (that you can check in the rx_cb and set a flag there). The condition could, e.g., be number of characters in the buffer or reception of some specific character (like '\n').

Again, please look at the thread I linked before:

 

https://community.atmel.com/comment/2375141#comment-2375141
 

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

one more clarification i needed once i received the data , i need to clear the buffer to receive coming data, here the complete data is not receiving at one time. where i should clear the buffer...

 

 if i cleared buffer every time means data will loss.

 

while (1)
    {
        
        
        if (RX_flag == 8)
        {
            
            io_write(debug, (uint8_t*)buff, strlen(buff));
            RX_flag = 0;  
            
        }
        
    }
}

after io_write if i cleared buffer means it is not working..

 

where i need to clear buffer

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What buffer do you think needs to be cleared? Where are you reading now? 

BTW, you should post code using the code  button "Add Code", it looks like <>

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

In the Application there is 2 buffers, one is ring buffer which is storing when the rx_cb (interrupt) triggered it will happen at interrupt level, one more buffer is user defined buffer for which i am strong ring buffer content and processing after processing i am clearing it.

 

once i send 10bytes of data it is storing into ring buffer, if i send next 10bytes means it will store for next locations of ring buffer..... how can i clear first 10 byte ring buffer location before i receiving next 10bytes of data....

 

Please clarify this.....

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is no need to clear the ring buffer, you should read the available data with io_read. And as mentioned it makes sense to do this in main (the ring buffer is pretty useless if you read one character at a time in the callback).

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

usart_async_flush_rx_buffer(&USART_0); what is purpose of this function??

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It would be used to discard every received byte currently in the buffer. But I don't know why you would need that.

/Lars

 

Last Edited: Wed. Oct 31, 2018 - 01:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok thanks . just i want to know the use of that.

 

In this application only i got one more confusion, if i send 12345 bytes from hyper terminal , why it will receive as ascii only?

 

is there any settings to change the format of receiving the data??

 

please clarify this?

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Terminals send the text you type typically but you can prepare and send a file with arbitrary data (I guess, I don't have hyper terminal). Realterm is another terminal program that might be better for this kind of testing.

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I am tried the bytes sending using real term also, i am sending 12345 bytes as shown below:

 

 

here if i send data by using send Numbers option it is not receiving and not printing received data, if i send by using Send ASCII option it is receiving and printing.

 

I thought atmel is receiving the data and decoded as ASCII , that's why it is receiving data in ascii format(if i paused step running and checked buffer content means it is ascii) .

 

Is there any setting in atmel studio to set the received data decoding format....

 

one way i checked tools->options->extension->terminal window from that i can change the received data decoding format... but here i  not found terminal window option

 

please suggest any other solution is there to set the decoding method.........

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No there is no setting, there is no decoding. It's up to your code to any conversion needed.

Sender sends ASCII: collect the chars in a buffer and convert to an integer (e.g., with the atoi function).

Sender sends binary: you build the value (e.g., for a 16 bit int sent with LSB first) buff[0] + (buff[1] << 8)

If you had implemented that and need to test it with Realterm by sending the decimal value 12345 (hex 3039) you would have to enter 0x39 0x30 (or 57 48) and "Send Numbers".

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you lajon , i got it and i am using real term for passing multiple  hex bytes, actually i am sending multiple hex data from real term,receiving the data comparing it and creating one frame and sending to master, for comparison i need  understand how it is receiving data ??

 

i think it is possible to compare with hex values??

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You might need to clarify the question because from this

actually i am sending multiple hex data from real term,receiving the data comparing it...

I understand you already know how to compare.

 ...i need  understand how it is receiving data ?

What is "it"?

 

Comparing with hex values is just

 

if (buff[0] == 0x39) {

}

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I mean to say that i am sending the multiple hex bytes from real term. for example if i send 0x12  0x13 0x14  0x15 0x16 means i can see the received buffer content 18 19 20 21 22 (it is in decimal format) .

i.e

buff[0] = 18, buff[1] = 19, buff[2] = 20, buff[3] = 21 , buff[4] = 22

 

can i compare like this

 

if(buff[0] == 0x12)

{

 

}

 

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, I already wrote that in the previous post. But since you ask this it means you don't know C and then I have to say programming a samv71q21 is not the best way to learn C. Much better done in a PC. 

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I working on C since from 2 years and handling 2 projects in company. i am new to this IDE so asked same question again and again. thanks i got clarified.

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

As per your guidance i am receiving data in the main only when the flag will set in rx_cb ie:

 

void rx_cb(const struct usart_async_descriptor *const io_descriptor)
{
   
    if (ringbuffer_num(&io_descriptor->rx))
    {
        flag = 1;
    }

}

 

while(1)

{

        if (flag == 1)
        {
           
                io_read(debug, buff, 10);
               flag = 0;
         }

Processing Data;

clearing the buffer;

}

 

here if i  sent 10 bytes of data means, 1 byte only receiving for 1 time...

 

i think for every byte it is going to rx_cb and flag is setting and coming to main and reading one byte....i need to process complete 10 bytes

 

here i need to wait until i receive all bytes???  i need to provide delay?? or any other options are there?

 

please help me to resolve it.

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
void rx_cb(const struct usart_async_descriptor *const io_descriptor)
{
   
    if (ringbuffer_num(&io_descriptor->rx) >= 10)
    {
        flag = 1;
    }

}

maybe?

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for your reply.

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi lajon,

 

I need one more clarification about USART asynchronous mode. can i use both rx_cb and tx_cb in only one usart.

 

it is possible to use both call backs for 1 USART or i need to use separately.

 

if it is possible to use both in one USART how can i handle both call backs??

 

please help me to resolve it.........

Megha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I need one more suggestion regarding about Asynchronous mode of USART,  i am using tx_cb to identify the complete data send from buffer, here tx_cb will generate for each byte or end of the buffer??

 

please clarify when tx_cb will generate ??

 

i need to clear buffer after complete transfer of data , how can i handle that??

 

please anyone can help me resolve the problem.....

Megha