[TUT] [SOFT] Using the USART - Interrupt driven serial comms

Go To Last Post
341 posts / 0 new

Pages

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

I am trying to create a program that will receive a command from user via RS-232 port (eg. 'B1' ended with a carriage return). I want to store that command in a variable so that I can compare it to a predefined list of commands and output the correct response. I am not sure how to read in the command so that I can do my comparison.

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

Start by setting up an RXC interrupt that populates a circular buffer, then you'll also have a getchar() style routine that just pulls characters after the buffer. As you strings are terminated then just loop doing getchar()s until you get '/r' (or possibly '/n') then strstr() the received string against each command.

Cliff

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

Hello Dean,
Would it be easy to make a version of your USART interrupts tutorial in PDF form, like your USART intro?

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

Sure, I've attached a PDF version to the original post. Enjoy!

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

abcminiuser wrote:
Sure, I've attached a PDF version to the original post. Enjoy!

- Dean :twisted:


Thanks Dean, for both tutorials. Something good to read while the boy is watching endless Spongebob Squarepants :D

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

First of all great tutorial ;) but I've managed to get here when I got "should-working" code ;-) Anyway I still have problem with my ATmega48. USART on polling works perfectly (4MHz external quartz enabled through fuse bits), but interrupts doesn't.

here is my code :

#define FOSC 4000000 // Clock Speed
#define BAUD 9600
#define MYUBRR ((unsigned int) (FOSC/16/BAUD-1))
#include 
#include 

volatile unsigned char data;

void PORTC_Init(void) {
	DDRC=0xff; // Port C as output
	PORTC=0x01; // first LED on, second off
}

void USART_Init( unsigned int ubrr ) {
	PRR = ~_BV(PRUSART0);
	/* Set baud rate */
	UBRR0H = (unsigned char) (ubrr>>8);
	UBRR0L = (unsigned char) ubrr;
	/* Set frame format: 8data no parity 1stop bit */
	UCSR0C = (0<<USBS0)|(1<<UCSZ00)|(1<<UCSZ01);
	UCSR0B |= (1<<UCSZ02);
	/* Enable receiver and transmitter */
	UCSR0B = (1<<RXEN0)|(1<<TXEN0);
	/* Enable receiver interrupt */
	UCSR0B |= (1<<RXCIE0);
}

ISR(USART_RX_vect) {

	PORTC ^= _BV(0);
	PORTC ^= _BV(1);

	while ( !( UCSR0A & (1<<UDRE0)) );
	UDR0 = 0x61;
}

int main (void) {
	PORTC_Init();
	USART_Init(MYUBRR);

	while ( !( UCSR0A & (1<<UDRE0)) );
	UDR0 = 0x4E;
	while ( !( UCSR0A & (1<<UDRE0)) );
	UDR0 = 0x61;
	while ( !( UCSR0A & (1<<UDRE0)) );
	UDR0 = 0x4E;
	//send NaN on USART

	sei();

	while(1);
	return 0;
}

I've got two LEDs on portC and I want them to blink when interrupt is invoked and send something back to terminal.

As for now I just can't get this working. The first 3 letters are send ("NaN") and then when I press anything on keyboard I get nothing. Well sometimes I get frame error on realterm.

I'm using ubuntu 9.04 amd64 as my main system, so I'm compiling under it. After going through all pages here I think it's a compiler problem, but I may be wrong. Anyway I'm compiling it this way :

avr-gcc easy.c -mmcu=atmega48 -o easy.hex -Wall -Wstrict-prototypes -Werror -mcall-prologues -g2 -O1

Everything loads up fine... but still no luck. I would be glad if anyone could help me here a little ;-)

EDIT :
If anyone has similar problem just copy makefile from avrstudio and run it... vuala, it works :D

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

@abcminiuser: the tutorial was very useful. By the way when i check my circuit by send for example 001 in decimal i get the response 255 .
Input Output
002 253
003 251
004 251

What does this mean? this doesn't have a pattern.. Can you tell me why I get some random values?

PS:I used the software Hterm for checking(I connected to the computer by a COM port at 9600bps 8 bit no parity just as was in the tutorial)

Thanks a lot,
Bala

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

Thanks Dean!
It was so useful for me :)

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

Hi
how to program modbus in gcc and could you tell me how to make a quary to tx and how to get rx respons from modbus through uart Smile

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

Ganapathy wrote:
how to program modbus in gcc and could you tell me how to make a quary to tx and how to get rx respons from modbus through uart Smile

GCC: http://www.freemodbus.org/index....
ICC: https://www.avrfreaks.net/index.p...

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

Thank u
I have another problem now. my program to transmit data of query but modbus couldn't response

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

hi
could you tell me. modbus are synchronous or asynchronous data transmission? plz

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

Have you heard of google? Do your homework. Enter "modbus asynchronous" into google and you will have an answer.

These are the tools that will help you with modbus troubleshooting:
http://www.modbusdriver.com/modp...
http://www.modbusdriver.com/diag...

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

Is there any way in which we can change the priorities of the interrupts?

Bittu Sarkar
Dept. of Computer Science & Engg.
Indian Institute of Technology, Kharagpur

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

No, the interrupt priority (on the regular AVR8) is fixed and cannot be changed. The best you can do would be either to selectively disable certain interrupts for short periods, or make your low priority interrupts themselves interruptable (which is dangerous).

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Hello all.
I just wondering as newbie, witch great pottencial have programing atmel product.
So maybe can you help me with this problem.
I just copy the program and made some changes.
When I open Windows Hyperterminal and send "a" or "b" everything is working, just to situatiation when I disconnect the programing LPT cable. Till LPT programing cable is connected then all is working, but when I disconnect cable the communication is not working (but hyperterminal says that is connected).

Here is Code

#define F_CPU 8000000UL

#include 
#include 

#define USART_BAUDRATE 2400
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

volatile unsigned char LED1;
int main (void)
{  
	DDRC=0xff;
    LED1=0x00;

   UCSRB |= (1 << RXEN) | (1 << TXEN);   // Turn on the transmission and reception circuitry
   UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes

   UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
   UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register

   UCSRB |= (1 << RXCIE); // Enable the USART Recieve Complete interrupt (USART_RXC)
   sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed
   for (;;) // Loop forever
   {
         // Do nothing - echoing is handled by the ISR instead of in the main loop
   }   
}

ISR(USART_RXC_vect)
{
   char ReceivedByte;

   ReceivedByte = UDR; // Fetch the recieved byte value into the variable "ByteReceived"
   	if (ReceivedByte==0x61) LED1=LED1^0b00000001;
	if (ReceivedByte==0x62) LED1=LED1^0b00000010;
	if (ReceivedByte==0x63) LED1=LED1^0b00000100;
	if (ReceivedByte==0x64) LED1=LED1^0b00001000;
	if (ReceivedByte==0x65) LED1=LED1^0b00010000;
	if (ReceivedByte==0x66) LED1=LED1^0b00100000;
    PORTC=LED1;
	UDR = ReceivedByte;// Echo back the received byte back to the computer

}

And schematics is in file.
Thanks you for help, maybe you kick my ass to next stair step
:)

Attachment(s): 

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

I forgot to write that I use internal 8Mhz oscilator
thanks

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

DragonSoul wrote:
I forgot to write that I use internal 8Mhz oscilator
thanks
That's asking for trouble with the serial interface. Please use the forum search function to find out why. It is an FAQ.

Stealing Proteus doesn't make you an engineer.

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

Quote:
but when I disconnect cable the communication is not working

Either I'm totally missing something or the obvios reply to that is "Yes, what did you expect?".
Quote:
(but hyperterminal says that is connected).

Hypertermial is probably not set up to detect if there is a physical connection. For RS232 communications this is handled by separate signal lines, typically DSR and DTR (not TxD and RxD). And something needs to keep those signals on the required levels. This can be done by the AVR (conuming two IO pins, and needing a external level adjustment arrangement). You could also arrange for a simple "loopback" of DTR to DSR at the PC side of the physical connection. And then you need to set up Hyperterminal to detect existence of connection with DTR-DSR.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Quote:
Quote:
but when I disconnect cable the communication is not working

Either I'm totally missing something or the obvios reply to that is "Yes, what did you expect?".


Sorry I forgot to write when I disconnect LPT communication cable, then RS232 communication stop working.

I develop, that when I just connect GND to GND LPT cable the communication start working and when I disconnect the GND from GND LPT cable that communication stop working. Maybe the GND from adapter witch generate 12 Volts is not real GND and of course the LPT ground is grounded to PC, but I cant develop, how to ground this system without computer.

Thank for you time

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

Where does the LPT cable go? To the AVR? Is it the LPT cable that is supplying power to the AVR perhaps?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

The LPT cable is painted on schematic as 'To PC LPT'. Is connected as explained on http://www.scienceprog.com/simplest-128-atmega-programmer/ and is used for programing ATMega8. Normally I disconect the cable and ATmega is feed with 5V through 7805 as showed on my schematics. For another application as flashing LED i disconnect programing LPT (printer) cable and procesor is working. But I develop, that when LPT cable is connected then RS232 communication is working, when I disconnect LPT cable, then communication is not working. But processor is still running. When I connect any GND to GND of LPT cable, then RS232 communication start working. Now I dont know, how I can ground GND in my room without computer.

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

On your serial port cable, do you have all three of Tx, Rx and GND connected? You have to have the serial cable's ground pin connected to your circuit ground, or the two circuits (PC and your board) will be floating in regards to one-another and the communications won't work.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

You have no common ground for the AVR and the device you are communicating with? If so: Bad. You need that.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Dean.
Yes. I have all three cable Rx, Tx and ground connected, RS232 ground is connected to my circuit ground (middle pin of 7805 see schematic).
JehanEkdalh
So you mean, that what is writen on my 12V adapter as GND is not ground, but just 0V potencial?

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

Quote:

So you mean, that what is writen on my 12V adapter as GND is not ground, but just 0V potencial?

There is no universal ground. If two devices are to interpret signals from eah other they have to share a ground, which is the "zero reference" for them.

Disconnect the LPT cable. Have the RS232 cable connected. Now measure the voltage between GND on your AVR circuit and some good, known GND on your PC. Not zero Volts? Then something in the GND circuit between the AVR and the PC is broken. Do a continuity check on the RS232 cable to make sure the GND is wired correctly to both connectors (pin 7 on a DB-25 connector, pin 5 on a DE-9 connector).

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Hi,

A question perturbs me :
I understand the interest to use interrupts and ring buffer for Rx because we cannot really control it but which is the interest to use interrupts and rint buffer for Tx ?
What can be the problems to do the Tx synchronously ?

Thank you

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

No problems doing Tx synchronously -- some people just like to buffer data before sending. This is useful in some cases where the serial data has a timeout on the receiver's end, so you buffer the data and send it as a single chunk to ensure that the receiver's timeout period doesn't expire prematurely.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Hello.
Thanks very much to JohanEkdahl and abcminiuser for help with problem with RS232 communication.
Problem was, that on the 9-pin connector witch lead to MAX232 pin 5 haved cold connection. So after measurement i develop, that GND was not in same level, but I dont know why. After resolder all connection, now all is working. Very good job with help Thanks

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

Ha! My suspicions about bad grounding was well grounded! :D

Happy that it worked out for you!

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Thanks Dean, this is another clean tutorial. This has possibly been mentioned by others: The interrupt vector table (Attiny2313) gives a source of "USART0, RX" which would be thought to be converted to "USART0_RX_vect" for use in ISR(), however it must be specified as "USART_RX_vect" as stated here:

http://www.nongnu.org/avr-libc/u...

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

hello guys! i'm jericho. i'm trying to learn avr micros, i'm studying it for about 3 weeks now and this site help me a lot!

now i'm having a hard time doing my code. i'm using atmega8 to be interfaced with a GPS module. i already made a code displaying GPS data sent to the MCU then the MCU sending the gps data to hyperterminal..

but now, i'm trying to display this in hyperterminal


time: (current GPS time)

unfortunately, i can't do it. it seems like my code is not working.. here it is..


//	atmega8	 //


#include 
#include 
#include 
#include 


#define USART_BAUDRATE 4800
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)


volatile uint8_t data, parsing_state, state;
volatile int8_t ReceivedByte[5], time[13], latitude[12];
volatile int8_t longitude[13], speed[6], date[9] ;


void init_uart()
{
	// enable Tx/Rx circuitry
	UCSRB |= (1<<RXEN) | (1<<TXEN);

	// 4800bps, 8-bit data, no parity, 1 stop bit
	UCSRC |= (1<<URSEL) | (1<<UCSZ0) | (1<<UCSZ1);

	UBRRL = BAUD_PRESCALE;
	UBRRH = (BAUD_PRESCALE>>8);
}


void gprmc_only()
{
	int8_t GPRMC[] = "$PSTMNMEACONFIG,0,4800,64,1\r\n";

	while (GPRMC[data] != 0x00)
	{
		while ((UCSRA & (1<<UDRE)) == 0) {};
		UDR = GPRMC[data++];
	}
}


void time_menu()
{	
	data = 0;

	int8_t real_time[] = "time: ";
	
	while (real_time[data] != 0x00)
	{
		while ((UCSRA & (1<<UDRE)) == 0) {};
		UDR = real_time[data++];
	}
	
	data = 0;
	
	while (time[data] != ',')
	{
		while ((UCSRA & (1<<UDRE)) == 0) {};
		UDR = time[data++];
	}

	state = 0;	
}					

int main (void)
{
	init_uart();

	state = 0;
	parsing_state = 0;
	data = 0;
	
	UCSRB |= (1<<RXCIE);	// enable Rx complete interrupt

	_delay_ms(1000);
	_delay_ms(1000);
	_delay_ms(1000);

	gprmc_only();

	sei();	// enable all interrupt

	while (1)
	{
		if (state == 1)
		{
			UCSRB |= (0<<RXCIE); // disable Rx interrupt
			
			time_menu();
	
			UCSRB |= (1<<RXCIE); // enable Tx interrupt
		}

	}
}


ISR (USART_RXC_vect)
{
	switch (parsing_state)
	{
		case 0:

			data = 0;

			ReceivedByte[data] = UDR;
			
			if (ReceivedByte[data] == '$')
				parsing_state++;
			
			else
			{
				parsing_state = 0;
				state = 0;
			}

			break;


		case 1:
	
			ReceivedByte[data] = UDR;
			
			if (ReceivedByte[data] == ',')
				parsing_state++;
			
			else 
			{
				parsing_state = 1;
				state = 0;
			}
				
			break;	


		case 2:

			data = 0;

			time[data] = UDR;

			if (time[data] == ',')
				parsing_state++;
			
			else
			{
				data++;
				parsing_state = 2;
				state = 0;
			}

			break;


		case 3:
			
			data = 0;

			ReceivedByte[data] = UDR;
			
			if (ReceivedByte[data] == ',')
				parsing_state++;

			else 
			{
				parsing_state = 3;
				state =0;
			}

			break;

		case 4:
			

			data = 0;

			latitude[data] = UDR;

			if (latitude[data] == ',')
				parsing_state++;

			else
			{
				parsing_state = 4;
				data++;
				state = 0;
			}
				
			break;

		case 5:


			data = 0;

			ReceivedByte[data] = UDR;

			if (ReceivedByte[data] == ',')
				parsing_state++;

			else 
			{
				parsing_state = 5;
				state = 0;
			}

			break;


		case 6:
			
			data = 0;

			longitude[data] = UDR;

			if (latitude[data] == ',')
				parsing_state++;

			else 
			{
				parsing_state = 6;
				data++;
				state = 0;
			}

			break;


		case 7:
	
			data = 0;
			
			ReceivedByte[data] = UDR;
			
			if (ReceivedByte[data] == ',')
				parsing_state++;
			
			else
			{ 
				parsing_state = 7;
				state = 0;
			}
				
			break;

						
		case 8:
			
			data = 0 ;

			speed[data] = UDR;

			if (speed[data] == ',')
				parsing_state++;

			else
			{
				parsing_state = 8;
				data++;
				state = 0;
			}

			break;


		case 9:
			
			data = 0;

			ReceivedByte[data] = UDR;

			if (ReceivedByte[data] == ',')
				parsing_state++;

			else 
			{
				parsing_state = 9;
				state = 0;
			}

			break;

								
		case 10:
			
			data = 0;

			date[data] = UDR;

			if (date[data] == ',')
				parsing_state++;

			else 
			{
				parsing_state = 10;
				data++;
				state = 0;
			}
			
			break;


		case 11:

			data = 0;
			
			ReceivedByte[data] = UDR;

			if (ReceivedByte[data] == 0x00)
			{
				parsing_state = 0;
				state = 1;
			}
				
			else 
			{
				parsing_state = 11;
				state = 0;
			}
			break;
		
	}

}

i hope you can tell me what's wrong with my code.. thanks!

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

Forget the interrupts and the GPS parsing to start with. Are the basics working? If you simply:

int main(void) {
  init_uart();
  while(1) {
     while ((UCSRA & (1<<UDRE)) == 0) {}; 
     UDR = 'A'; 
  }
}

do you see a stream of 'A's at 4,800 baud on your PC terminal?

If you then modify that to just have a single character RXC interrupt handler that main() echoes back does that then work?

Continue adding the program complexity back in and retesting until you find any flaw in the logic but don't expect all of such a complex program to all work right from the start.

Make a lot of use of the PC terminal for debugging. Remember that if the AVR only RX's from the GPS then as long as you stick to 4800 you can split TX/RX so TX goes to the PC terminal as a debug output and RX is the connection from the GPS

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

hi clawson! thanks for the reply!

i already did what you've said before doing this. and it worked fine. i also finished writing a code that will display the GPS data sent to the MCU then the MCU sending the data to hyperterminal. but after inserting the parsing routine, it seems stopped working..

:(

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

Quote:

but after inserting the parsing routine, it seems stopped working..

In which case you have identified the bit that requires the work - now break that into small implementation steps and try to find the point where it stops behaving as expected.

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

Hello all,
How i can extract only #GPRMC sentence from all nmea sentences ? Jericho wrote code isn't universal function for taking only gprmc. Im thinking to use data from "$" to "*" but how ?

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

Quote:
How i can extract only #GPRMC sentence

http://www.maartenlamers.com/nmea/

(it's C++ for Arduino but you should be able to convert if you need it in C)

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

How i should convert it ? i never worked with Arduino :\
Any other suggestions in c language ?

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

Quote:

Any other suggestions in c language ?

I found that after 2 minutes with Google. If I'd spent the whole 5 minutes I'm sure I could have found C code - it's not like you are the first person who wants to parse NMEA. Try "parse NEMA GPRMC C source" or similar.

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

Need some TUTorials about avr interfacing with gps, like TUT using usart.. :?

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

Quote:

Need some TUTorials about avr interfacing with gps, like TUT using usart..

Surely it's the same thing. They almost all use a 4800 baud UART link so this thread applies.

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

rnable wrote:
Need some TUTorials about avr interfacing with gps, like TUT using usart.. :?

whoops, I meant parsing gps data with avr.. :roll:

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

Quote:

I meant parsing gps data with avr..

That would be "Parsing GPS data in C", yes? C is a standardized language so, as long as you have the NMEA, you should be able to use any C code with only small changes.

Keeping the reception and the parsing divided is recommended: Getting the string is one thing. Parsing it is another. You could even develop and test the parsing code in on a PC with eg MS Visual Studio (a free Express version is available) so that you don't have to go through the relative awkwardness of debugging in AVR Studio, simulated or with on-chip debugging).

I'm fairly sure that we've had NMEA string parsing up here before. And it is almost sure that you can find C code on the web that is close to what you need.

Quote:

Need some TUTorials about avr interfacing with gps, like TUT using usart..

What you need, as I hinted about, is to try to think about the complete problem you're facing as consisting of several smaller, more manageable, problems.

The communication, getting the NMEA string is plain UART communication, and for that there is a tutorial (as you yourself has noted). Gete that working receiving the complete NMEA string.

Then create a new little project that sets up a constant NMEA string and start working on parsing that. (Steal code from the net. Or just get inspired by it.) The advantage of this approach is that you dont have the complete hardware setup running, and more importantly that you know what the string you're parsing looks like so you have a better chance of detecting bugs and debugging. When it works for that string you test it with a few variants. When you're gaining confidence in the parser, you hook the two things together.

Any successful programmer uses the principle of "divide and conquer" to solve problems. Un-experienced programmers not applying this principle most likely gets overwhelmed by the problem, or gets lost in a maze of problems and symptoms leading to an uncontrollable situation.

Going from one place to another with success is a matter of taking many small steps, rather than one giant leap. Patience is a necessary virtue of a programmer.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

As a certified newbie to AVR and and a current 8051 user(don't laugh), most of the tutorials and example code in proliferation it seems is written using GCC which is not obvious to the casual observer except for the #include . GCC is such a mountain of macros and header files that for someone (especially new)trying to decipher it into a working version using something other than GCC is a herculean and time consuming effort. Nowhere can I find anything that fully makes this known up front to someone using a commercial compiler. Mayabe I should have known...Turns out when it comes to gcc I have more money than time.

But again for beginners at AVR, it would be very helpful to put a disclaimer with the gcc stuff.

Sorry but this vent (not against anyone in particular it's just a beef with the way gcc seems "universal") has been building a while.

So feel free to torch back.

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

divide_overflow wrote:
GCC is such a mountain of macros and header files that for someone (especially new)trying to decipher it into a working version using something other than GCC is a herculean and time consuming effort.
And why is that our problem?

Typical kids. They get code for free, but than insist the get also spoon feed. If they don't get spoon feed they spread FUD like

Quote:
GCC is such a mountain of macros and header files
. Whine, whine, whine. How disgusting.

Remember, YOU decided to use that "something other". No one forced you. YOU decided to not read the GCC and avr-libc manuals. And I am sure you worked very hard to avoid reading any serious text book about C programming ("For Dummies" guides and "in 21 days" junk don't count). And may I guess, YOU decided to use oh so simple looking stuff like MikroE C or Arduino, and now you are surprised that the rest of the world doesn't feed you with code.

If you are a professional programmer, please, consider a career change. You are obviously not even capable of operating a compiler. Like a carpenter isn't able to handle a saw.

Stealing Proteus doesn't make you an engineer.

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

didvide_overflow,

I fear you may have missed the point of this Tutorial forum. Any user of any compiler is quite at liberty to submit an article about how some function is performed using their compiler. I guess if there is an error here it is that tutorial authors are encouraged to either include "[GCC]" (or whatever "[IAR]", "[CV]", ...) in the name of the thread though many just use a title such as "using GCC's PROGMEM attribute". So perhaps this tutorial should have mentioned GCC in the thread title. OTOH the techniques it presents are generally portable to any compiler with the only part that is GCC specific being the ISR syntax but presumably the users of other compilers will know the corresponding ISR syntax to use?

The propensity of GCC articles here simply reflects its wide spread usage amongst both hobbyists and professionals.

Personally I'm having a hard time understanding how GCC is "worse" in the sense of header macro usage. The standard headers of most compilers are actually very close.

Moderator.

PS feel free to write and submit your own tutorials - they are always welcome.

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

Hello,
thanks for a great tutorial here.
I'm trying to upgrade the serial code in my robot. I'm using a ATMega128. I currently use a software polling code to send & receive thru the usart.
I added a little command line routine in our code to allow me to type in commands using TeraTerm terminal to access the Robot hardware and display telemetry data on the screen. At the moment, the robot is on a tether(serial cable), eventually we will upgrade to using a RF transceiver.
But now as the project gets larger I need to move to this type of Interrupt servicing USART method so as to keep the robot running and not sit waiting at the command line with software polling .

So since I'm dealing with strings on the command line, I use some of the standard library to get things done. Such as fgets and strcmp, as shown here below, but it's all software pollling. This works fine as it is, but when working with robots, you need to have the robot run independantly, and not wait for your commands using software polling.

I had initially used the sample code you have in this tutorial and stored each character of the command line into a buffer array. But then I didn't know how to continue using the 'strcmp' library to compare strings with what I have in the buffer array. I had to resort to comparing one character at a time, which becomes self-defeating--and the code becomes larger-- when working with a command line interface.

So I thought maybe there's someway of using Timer1 in combination with this, to simply check the usart few times a sec--without polling, but I'm not sure.
I hope you can suggest something.

//-----------------------------------------------
char cmd[80]; // buffer to construct parsable string terminating with CR

int main(void)
{     
.
.
.
     fgets( cmd, 80, stdin ); '//get command line string
     strip_newline( cmd, 80 ); //remove null terminator
.
.
.
     if ( strcmp ( cmd, "quit" ) == 0 )  //time to quit
		{
		  //do something
		}
}
//-----------------------------------------------
// remove the null terminator from input string
void strip_newline( char *str, int size )
{
    int i;
    for (  i = 0; i < size; ++i )
    {
        if ( str[i] == '\n' )
        {
            str[i] = '\0';
            return;   /* we're done, exit function */
        }
    }
    /* if exit here, must not have been any newline! */
}
//-----------------------------------------------
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good day

I have a problem with interrupt driven USART.
firstly here is my code that does not work:

#include  
#include 
#include 
#include 

#define Buffer_Size 32 
#define USART_BAUDRATE 9600 
#define BAUD_PRESCALE 103

// Define the buffer structure
typedef struct buffer_
{
	char 	data[Buffer_Size];
	uint8_t size;
} buffer;

// Set permanent buffer
	buffer	buf;	
	char 	Command[Buffer_Size];
	
// Global variables
	uint8_t tel;

int main (void) 
{ 
// Initialize Buffer
	buf.size = 0;

// Set RS485 enable pin as output
	DDRD |= (1<<DDD6);
	PORTD &= (0<<PORTD6);

// SETUP of USART 0
	// Turn on the TX RX
   	UCSR0B |= (1 << RXEN0) | (1 << TXEN0);   

	// Use 8-bit char - Asynchronous, no parity, 1 Stop-bit
	UCSR0C |= (1 << UCSZ00) | (1 << UCSZ01); 
        //Baud rate
	// Load lower 8-bits 
	UBRR0L = BAUD_PRESCALE; 
	// Load upper 8-bits 
	UBRR0H = (BAUD_PRESCALE >> 8); 
	
	tel = 0;

     // Enable the handling of USART interrupt vector
	UCSR0B |= (1 << RXCIE0)|(1 << TXCIE0);

      // Enable the Global Interrupts 
   	sei(); 

	for(;;)
	{
		if (tel == 1)
		{
                 //Set end of string      
			buf.data[buf.size] = 0;
                 //Copy string for command line
			strcpy(Command,&buf.data[1]);
                 // Reset buffer
			buf.size = 0;

			tel = 0;
                 //Output Enter
			PORTD |= (1<<PORTD6); 
			UDR0 = '\r';
		}
	}
}

ISR(USART0_RX_vect) 
{ 
	// Code to be executed when the USART receives a byte here
	char ReceivedByte; 

	// Fetch the recieved byte
	ReceivedByte = UDR0; 
	
	buf.size += 1;
	buf.data[buf.size] = ReceivedByte;

	if (ReceivedByte == '\r')
	{
		tel = 1;
	}
	else
	{
	    //Clear previous data
                buf.data[buf.size+1] = 0;

            //Reflect received character
		PORTD |= (1<<PORTD6);
		UDR0 = buf.data[buf.size]; 
	}
}
	
ISR(USART0_TX_vect) 
{ 
	PORTD &= (0<<PORTD6); // Enable RS485 receive
}

The code above works when you replace:

tel = 1; 

(which is in the ISR) with the code within the if statement:

if (tel == 1)
		{
                 //Set end of string      
			buf.data[buf.size] = 0;
                 //Copy string for command line
			strcpy(Command,&buf.data[1]);
                 // Reset buffer
			buf.size = 0;

			tel = 0;
                 //Output Enter
			PORTD |= (1<<PORTD6); 
			UDR0 = '\r';
		}

Why is that? What am I doing wrong when using the first code presented? Is it the way that USART interrupts work?

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

Quote:

Why is that?

FAQ#1

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

WOW thanks clawson.

Great FAQ! They should include it in the webpage background or header or flash it every now and then over the screen.;)

Pages