Receive Interrupt

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

I am trying to receive a string of bytes (15 total) and store them into an array called receive[]. I have tested my interrupt by switching on an led when the receive pin changes but I cannot figure out how to store a string from the UDR0 register. Each packet I want to store starts with 0x41. Below is what I have now and it doesn't work.

int z = 0; //global variable

ISR(SIG_USART_RECV)
{
	z++;
	receive[z]=UDR0;
			
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Define "doesn't work" in more detail.

But when do you set z back to 0, why do you pre-increment rather than post-increent it and what are you doing to ensure it doesn't go beyond sizeof(receive) ?

BTW you may want to do a thread search here for "circular AND buffer"

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

I think the ISR declaration is not correct.You might want to take a look at this http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

It should probably be :

ISR(USART_RX_vect)
{

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

Well the old SIG_ variant will still work too - it may be deprecated but, as of now, it's still available. But you are right that for future compatability it's better to use the *_vect naming convention.

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

For what it's worth, since I am not a C guy but an assembler. But maybe this could help

In assembler I carve out a chunk of internal sram by usinf the following statement:

.dseg
RXMEM: .byte xx(xx ids the amount of bytes I need)

Then, in my code I load the z register with the name 'RXMEM' and then do a post increment after the write.

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Ok, I guess I should be completely honest...I'm not really sure how to go about coding a receive function to store bytes into an array. Like I said before, I know the interrupt is working. I also know that the packet that will be seen on the receive pin will be,

0x41,0x01,0x00,0x05,0x02,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x6C,0xB5,0x0A

If I use the code,

ISR(SIG_USART_RECV)
{
	receive[0]=UDR0;
}

it will store the first element of the array as 0x41. So it works fine if I store just the first. Now if I want to store all 16 bytes into the array, this is where I lose my head. I cannot figure out how to do this. Sorry if this is a bad posting topic but I am learning C and don't see logical way of coding this. Anything would help, if you have any previous code or any comments. Thanks

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

In general, with a circular buffer you have the storage area (declared to be some size), a head pointer or subscript, and a tail pointer or subscript. At initialization, both head and tail are pointing at the start of the buffer (or have a value of 0 if they are subscripts).

When a new entry gets entered, you put it in the buffer at the head offset and then increment head. If head then exceeds the size of the buffer, you set head back to the beginning. You may or may not want to check against the tail value initially to prevent overwriting old values.

When you take something out, it comes from tail, which you then increment. Again, if the new value of tail exceeds the size of the buffer, you move it back to the beginning. When tail equals head, such as at initialization, the buffer is empty.

If you allow overwrites, head can equal tail when the buffer is totally full. In this case you'll probably want to advance tail (i.e., toss the oldest entry), with adjustment for the maximum limits, when the overwriting entry is added.

If you need it, you can either keep a separate counter for the number of characters in the buffer, or do a little slightly tricky math to find the wrapped distance between head and tail.

Chuck Baird

"I wish I were dumber so I could be more certain about my opinions. It looks fun." -- Scott Adams

http://www.cbaird.org

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

And everyone tells me C is easy. Whoooo :P

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Quote:
And everyone tells me C is easy. Whoooo

If you are referring to Chuck's last post, there is nothing in it that is tied to C. It is simply an explanation of a circular buffer. Everything in it will apply no matter what language you implemented it in.

Regards,
Steve A.

The Board helps those that help themselves.

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

Wikipedia has a nice explanation of circular buffers.

and several of the UART code contributions in the projects section of this forum use circular buffers

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

The circular buffer data structure is a general way of handling the problem of saving incoming data for processing. It looks like in your case you have known length messages and a known start character, and so you can specialize a bit if you wish.

Let's make some assumptions which may or may not be true. Let's assume you're going to grab characters in an interrupt handler. Let's also assume you're going to process the "sentence" (bytes) in the mainline. We'll have the interrupt handler set a flag when a full message is received so the mainline will know it may be processed.

Then we have to worry about bytes coming in after a message comes in and is complete, but before the mainline gets its processing done. To solve this, we'll use double buffering. One buffer fills, then the mainline is notified. The second buffer fills while the mainline horses around with the first. And vice versa.

So here's one scenario. Declare two buffers of adequate size. Declare two flags, one for each buffer. Declare two character count variables (one per buffer). Declare a variable which indicates the active buffer. All of these will be global and volatile. Initialize the flags, counts, and active buffer to 0.

In the interrupt handler, when a character is received, look to see which buffer is active. If there is room, put the character in the buffer and increment the count; otherwise ignore it. When the end of string character is received, switch the active buffer variable, zero the count on the new active buffer, and set the ready flag for the old active buffer.

In the ever looping mainline, wait until a ready flag sets and then have at it with the corresponding buffer. Get the data done (maybe move it elsewhere) before the other buffer fills.

There are many variations on this theme. You indicated you have a recognizable start character rather than an end character; that changes the logic a little. The main difficulty with that arrangement is that the last message never gets recognized because there's not a next beginning character. Anyway, you can come up with something to work around it. What you do with characters after a buffer fills but before end of string is up to you. What you do if you switch to a buffer that hasn't been emptied by the mainline is up to you. If you recognize both start and end of message characters, what you do with characters outside the framing is up to you. Errors all, perhaps.

And in the area of efficient coding, you may want to make your flags and counts and buffers into arrays so the active buffer variable is just a subscript. Then it's trivial to extend it to triple or quadruple or whatever buffering.

As with most things computing, there are as many solutions as there are programmers.

Chuck Baird

"I wish I were dumber so I could be more certain about my opinions. It looks fun." -- Scott Adams

http://www.cbaird.org