Author Topic: interrupt trigger from UART data receive  (Read 42486 times)

0 Members and 1 Guest are viewing this topic.

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
interrupt trigger from UART data receive
« on: August 02, 2008, 05:01:18 PM »
I want to set up my AVR to run a program, but if something is ever detected on the UART, it would *immediately* stop running the program and instead receive data from the UART.

How do I set up this interrupt? Is it possible? Got C sample code or links you can send me?

I tried searching google but no luck, and not quite sure what terms to look for either . . .

Offline pomprocker

  • Supreme Robot
  • *****
  • Posts: 1,431
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
    • Nerdcore - Programming, Electronics, Mechanics
Re: interrupt trigger from UART data receive
« Reply #1 on: August 02, 2008, 07:25:29 PM »
you mean like if a letter comes in, then you want it to halt and just pay attention to the uart?


I have set it up so if I hold down the 'r' key, my mcu resets, also if I hold down 'h' my robot holds its position until I let go.

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: interrupt trigger from UART data receive
« Reply #2 on: August 02, 2008, 07:32:26 PM »
I found this tutorial:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=48188&highlight=interrupt+driven+uart

Which offers code similar to this, but a bit tweaked for multiple UART avr's:

Code: [Select]
#include <avr/interrupt.h>

/*
When interrupt-driven data reception is used, the receive complete routine must read
the received data from UDRn in order to clear the RXCn Flag, otherwise a new interrupt
will occur once the interrupt routine terminates.
*/
ISR(USART_RXC1_vect) //trigger interrupt when uart1 receives data
{
// Code to be executed when the USART receives a byte here
char ReceivedByte;
ReceivedByte = UDR1; // Fetch the recieved byte value into the variable "ByteReceived"
UDR1 = ReceivedByte; // Echo back the received byte back to the computer
}

controller(void)
{
UCSR1B |= (1 << RXCIE1); // Enable the USART Recieve Complete interrupt (USART_RXCn)
//turn on the Global Interrupt Enable flag
sei();
//cli();//turn off interrupts

while(1)
{
//do stuff
}
}

It's untested, but if I don't reply back to this post in the next few weeks it means it worked.

Offline bens

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 335
  • Helpful? 3
Re: interrupt trigger from UART data receive
« Reply #3 on: August 02, 2008, 08:16:12 PM »
The serial receive interrupt is just like any other interrupt.  Set the register bit to enable serial receive interrupts and write the ISR and you're good to go...

Offline izua

  • Supreme Robot
  • *****
  • Posts: 682
  • Helpful? 0
    • izua electronics
Re: interrupt trigger from UART data receive
« Reply #4 on: August 02, 2008, 09:07:14 PM »
There's the UART_RXC interrupt, which, if enabled, triggers immediately after the stop bit's position.
Check out my homepage for in depth tutorials on microcontrollers and electronics.

Offline JesseWelling

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 707
  • Helpful? 0
  • Only You Can Build A Robot!
Re: interrupt trigger from UART data receive
« Reply #5 on: August 02, 2008, 10:17:31 PM »
AVRlib has a good example of what to do.

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: interrupt trigger from UART data receive
« Reply #6 on: August 03, 2008, 09:14:12 PM »
I'm having trouble getting the ISR to work . . . I keep getting compiler errors on this line: ISR(USART_RX_vect)

I'm using the latest WinAVR with ATmega640 (Axon).

I've tried every permutation of it:
USART_RXC_vect
UART_RXC_vect
USART_RX_vect
UART_RX_vect
USART1_RXC_vect
UART1_RXC_vect
USART1_RX_vect
UART1_RX_vect
and more . . .

They all give an error like this:
Quote
warning: 'USART_RX_vect' appears to be a misspelled signal handler

except when I use this one:
USART1_RX_vect

Which gives me this error:
Quote
Loaded plugin STK500
Loaded plugin AVR GCC
Loaded partfile: C:\Program Files\Atmel\AVR Tools\PartDescriptionFiles\ATmega640.xml
gcc plug-in: Error: Object file not found on expected location C:\My_Robots\Axon\Axon.elf
Make sure your makefile specifies the output .elf file as Axon.elf

Offline bens

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 335
  • Helpful? 3
Re: interrupt trigger from UART data receive
« Reply #7 on: August 03, 2008, 09:31:01 PM »
Since the mega640 has multiple UARTs, you probably have to specify which UART receive interrupt you want to use.  If you want to know what ISR vectors are predefined for your microcontroller, find out where you have WinAVR installed on your computer and go to the following directory:

WinAVR\avr\include\avr

and open the file iomxx0_1.h.

Near the bottom of the file you will find a list of #defines that cover all of the mega640's interrupt vectors.  The following is one segment of this section:

Quote
/* USART0, Rx Complete */
#define USART0_RX_vect         _VECTOR(25)
#define SIG_USART0_RECV         _VECTOR(25)

/* USART0 Data register Empty */
#define USART0_UDRE_vect      _VECTOR(26)
#define SIG_USART0_DATA         _VECTOR(26)

/* USART0, Tx Complete */
#define USART0_TX_vect         _VECTOR(27)
#define SIG_USART0_TRANS      _VECTOR(27)

- Ben

Offline izua

  • Supreme Robot
  • *****
  • Posts: 682
  • Helpful? 0
    • izua electronics
Re: interrupt trigger from UART data receive
« Reply #8 on: August 03, 2008, 09:35:02 PM »
ouch, error before linking :/
check the table in the first pages (it's a bookmark in the pdf, interrupts, usually right before the I/O ports bookmarks. bookmarks are accessed with in left panel).

Add that title, capitalized, spaces become underlines, with a "_vect" appended to ISR as a parameter
So, for an atmega 640 - what axon uses - it should be ISR(USART0_RX_vect) or ISR(USART1_RX_vect) and so on..

Remember to include <avr/interrupt.h> and check the default defines that come. maybe someone made a mistake while writing a header file.
Check out my homepage for in depth tutorials on microcontrollers and electronics.

Offline airman00

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 3,650
  • Helpful? 21
  • narobo.com
    • Narobo.com - Mechatronics and related
Re: interrupt trigger from UART data receive
« Reply #9 on: October 11, 2008, 11:07:39 PM »
I'm having trouble getting the ISR to work . . . I keep getting compiler errors on this line: ISR(USART_RX_vect)

They all give an error like this:
Quote
warning: 'USART_RX_vect' appears to be a misspelled signal handler

I am using the ATmega168 and I get the same type of error

I used
Code: [Select]
ISR(USART_RXC0_vect) //trigger interrupt when uart0 receives data
Anyone know the correct syntax?
Check out the Roboduino, Arduino-compatible board!


Link: http://curiousinventor.com/kits/roboduino

www.Narobo.com

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: interrupt trigger from UART data receive
« Reply #10 on: October 11, 2008, 11:19:20 PM »
I never had time to look back into this because of moving to Bangkok and all.

These two links *might* help too, but haven't had time to work through them:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=48188
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=67226

Let me know if you solve it!


edit: To prevent double posting problems:
http://www.societyofrobots.com/robotforum/index.php?topic=5500.0
« Last Edit: October 11, 2008, 11:20:11 PM by Admin »

Offline airman00

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 3,650
  • Helpful? 21
  • narobo.com
    • Narobo.com - Mechatronics and related
Re: interrupt trigger from UART data receive
« Reply #11 on: October 12, 2008, 07:14:49 AM »
First off I need to learn how to convert this ATmega8 code to code for the ATmega168
Code: [Select]

//Set data frame format: asynchronous mode,no parity, 1 stop bit, 8 bit size
UCSRC=(1<<URSEL)|(0<<UMSEL)|(0<<UPM1)|(0<<UPM0)|
(0<<USBS)|(0<<UCSZ2)|(1<<UCSZ1)|(1<<UCSZ0);

I looked in the Atmega168 datasheet and most of these registers do not exist. Can anyone provide me sample code to do asynchronous mode,no parity, 1 stop bit, 8 bit size on the ATmega 168 ?
Check out the Roboduino, Arduino-compatible board!


Link: http://curiousinventor.com/kits/roboduino

www.Narobo.com

Offline dunk

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 1,086
  • Helpful? 21
    • dunk's robot
Re: interrupt trigger from UART data receive
« Reply #12 on: October 12, 2008, 09:11:24 AM »
Quote
I looked in the Atmega168 datasheet and most of these registers do not exist.
as long as you have linked in the correct header file for the ATmega168 i think they will be there but just have slightly different names on the Atmega168.

look for the register that does the same thing in the Atmega168 datasheet as the ATmega8 register you are trying to mimic
then either look through your header files and see what that register is defined as or (messy solution) define your own.

there is nothing magic about the register names. somewhere your code will be referencing a file that defines names (like USART_RX_vect) as register addresses.
find that header file and look search for the text string "USART"...


dunk.

Offline izua

  • Supreme Robot
  • *****
  • Posts: 682
  • Helpful? 0
    • izua electronics
Re: interrupt trigger from UART data receive
« Reply #13 on: October 12, 2008, 09:17:50 AM »
Atmega8 has one usart, atmega168 has several.
The first one is denoted by 0 in the register name.
For example UCSRC becomes UCSRnC, where N is the com port which you are configuring.

Check the datasheet, the name are identical, but the n index is added.
Check out my homepage for in depth tutorials on microcontrollers and electronics.

Offline airman00

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 3,650
  • Helpful? 21
  • narobo.com
    • Narobo.com - Mechatronics and related
Re: interrupt trigger from UART data receive
« Reply #14 on: October 12, 2008, 10:24:43 AM »
I need some help .
I've been at it for hours , still nothing

Heres what I have so far
Code: [Select]
UCSR0C=(1<<URSEL)| (0<<UMSEL00)|(0<<UPM01)|(0<<UPM00)|
(0<<USBS0)|(0<<UCSZ02)|(1<<UCSZ01)|(1<<UCSZ00);

I changed everything besides URSEL , as I dont think there is a counterpart on the ATmega168. It is used to select the register to edit . Maybe just remove it from there?
Can someone please provide sample code to configure the UART, I would appreciate it tremendously.

-----------------------------------------------------------------------------------------------------------------------------
EDIT: Perhaps there is a way to use AVRlib to do the interrupt trigger?

Looking at uart.h I see this
Code: [Select]
//! Type of interrupt handler to use for uart interrupts.
 /// Value may be SIGNAL or INTERRUPT.
 /// \warning Do not change unless you know what you're doing.
 #ifndef UART_INTERRUPT_HANDLER
 #define UART_INTERRUPT_HANDLER  SIGNAL
 #endif


and in uart.c I see this:
Code: [Select]
// UART Receive Complete Interrupt Handler
UART_INTERRUPT_HANDLER(SIG_UART_RECV)
{
u08 c;

// get received char
c = inb(UDR);

// if there's a user function to handle this receive event
if(UartRxFunc)
{
// call it and pass the received data
UartRxFunc(c);
}
else
{
// otherwise do default processing
// put received char in buffer
// check if there's space
if( !bufferAddToEnd(&uartRxBuffer, c) )
{
// no space in buffer
// count overflow
uartRxOverflow++;
}
}
}
« Last Edit: October 12, 2008, 10:32:35 AM by airman00 »
Check out the Roboduino, Arduino-compatible board!


Link: http://curiousinventor.com/kits/roboduino

www.Narobo.com

Offline izua

  • Supreme Robot
  • *****
  • Posts: 682
  • Helpful? 0
    • izua electronics
Re: interrupt trigger from UART data receive
« Reply #15 on: October 12, 2008, 11:53:09 AM »
Atmega128 does not have URSEL. I'd assume mega168 doesn't have one either.

Is it that hard to open both datasheets (which you already have, since you used both chips, i hope) and compare the info on USART/Register Description/UCSRnC, or someone here has to do it for you?
Also, on mega128 and mega16, UCSR0C (respectively UCSRC) powers up with exactly the values you load into it. Do you really need to change them?

To find out the name of the interrupt, just check the table in the "interrupts" section.
Atmega128 has them as USARTn_TX/USARTn_RX/USARTn_UDRE.

edit: the method of handling interrupts is outdated.
in avrgcc the new method is:
ISR([interrupt_name_on_Interrupts_page_with_spaces_to_underscores]_vect);
« Last Edit: October 12, 2008, 11:54:24 AM by izua »
Check out my homepage for in depth tutorials on microcontrollers and electronics.

Offline airman00

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 3,650
  • Helpful? 21
  • narobo.com
    • Narobo.com - Mechatronics and related
Re: interrupt trigger from UART data receive
« Reply #16 on: October 13, 2008, 06:55:26 AM »
I will try again to figure out the registers I need

Does anyone know of a way to use AVRlib to do what I need?  ( More details in my post that is 2 posts above)

EDIT:
I did some more snooping around uart.c and it seems like it enables interrupts by itself!  I'm going to try to just throw in an ISR in Admin's UART AVRlib code .
Code: [Select]
// enable RxD/TxD and interrupts
outb(UCR, BV(RXCIE)|BV(TXCIE)|BV(RXEN)|BV(TXEN));

Also I tried doing a basic UART receive program according to the datasheet and other places online
Code: [Select]
Heres my code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "SoR_Utils.h"
#include "uart_def.h"

#define blue 49
#define F_CPU 8000000
#define BAUDRATE 2400
#define BAUD_PRESCALE (((F_CPU / (BAUDRATE * 16UL))) - 1)

int main (void)
{

   UCSR0B=(1<<RXEN0)|(1<<RXCIE0);  // Enable receiver and enable receiver interrupt

UCSR0C=(0<<UMSEL00)|(0<<UMSEL01)|(0<<UPM01)|(0<<UPM00)|

(0<<USBS0)|(0<<UCSZ02)|(1<<UCSZ01)|(1<<UCSZ00);

   UBRR0L = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
   UBRR0H = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
sei(); //Enable Interrupts

int data;
char byte;

while(1)
{

while ((UCSR0A & (1 << RXC0)) == 0) {}; // Do nothing until data have been recieved and is ready to be read from UDR
      data = UDR0; // Fetch the recieved byte value into the variable "ByteReceived"
  byte=UDR0;

if (data==blue)
{
blue_on;
}
//do stuff
}
}
« Last Edit: October 13, 2008, 03:00:41 PM by airman00 »
Check out the Roboduino, Arduino-compatible board!


Link: http://curiousinventor.com/kits/roboduino

www.Narobo.com

Offline airman00

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 3,650
  • Helpful? 21
  • narobo.com
    • Narobo.com - Mechatronics and related
Re: interrupt trigger from UART data receive
« Reply #17 on: October 13, 2008, 03:18:12 PM »
In uart.C it shows the following:

Code: [Select]
// UART Receive Complete Interrupt Handler
UART_INTERRUPT_HANDLER(SIG_UART_RECV)
{
u08 c;
// get received char
c = inb(UDR);
// if there's a user function to handle this receive event       <----- How do I make the function discussed here
if(UartRxFunc)
{
// call it and pass the received data
UartRxFunc(c);
}
}

How can I make that "user function"? Also if I make that user function does that cause uartGetByte() to not work anymore?
Check out the Roboduino, Arduino-compatible board!


Link: http://curiousinventor.com/kits/roboduino

www.Narobo.com

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,165
  • Helpful? 111
    • Webbot stuff
Re: interrupt trigger from UART data receive
« Reply #18 on: October 22, 2008, 10:19:01 AM »
Quote
How can I make that "user function"?

As follows:
Code: [Select]
void myRx(unsigned char c){
  // Do something with the character
}

After your call to initialise the uart then you can link in your code by calling:-
Code: [Select]
uartSetRxHandler(&myRx);

Quote
Also if I make that user function does that cause uartGetByte() to not work anymore?
That's correct. You will be scrapping all of the standard receive buffering. In essence it just makes 'myRx' be the receive interrupt routine.

Having said all of that. I am struggling to get the receive interrupt to happen at all on a Mega168 !! EDIT: No forget that - it was a faulty connector lead. All working
« Last Edit: October 22, 2008, 01:37:25 PM by Webbot »
Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

Offline airman00

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 3,650
  • Helpful? 21
  • narobo.com
    • Narobo.com - Mechatronics and related
Re: interrupt trigger from UART data receive
« Reply #19 on: November 24, 2008, 11:03:13 PM »
oh totally forgot to update this post

So anyways its easy to have a UART on interrupt
1. Just modify the uart.c file of AVRlib and set up your user function inside it
2. In your user function do whatever you want with the uart registers (make the interrupt as short as possible)
Check out the Roboduino, Arduino-compatible board!


Link: http://curiousinventor.com/kits/roboduino

www.Narobo.com