Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
farshad4017
PostPosted: Mar 22, 2011 - 04:07 PM
Newbie


Joined: Jun 11, 2010
Posts: 4


Hi
I now how to send a character?
The program that you've written, any changes I will not care.
Code:
#include <avr/io.h>
#include <avr/interrupt.h>

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

int main (void)
{
   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 << RCXIE); // 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"
   UDR = ReceivedByte; // Echo back the received byte back to the computer
}

I want to send a number to the micro and micro to the number dialed then I have a job.
But I do not know inside how do I put variable! Please let s a clearer example of the program?
thnx
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Mar 23, 2011 - 09:31 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62944
Location: (using avr-gcc in) Finchingfield, Essex, England

To send/receive variable contents it's often easiest (because humans can read these things) to convert to and from ASCII digits. Use sprintf()/itoa() to convert a variable into a human readable string of characters - send this across the UART link then use atoi() at the receiving end to convert the ASCII back to binary if you need it in that form.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
AxelAxis
PostPosted: Mar 24, 2011 - 05:07 AM
Newbie


Joined: Mar 20, 2011
Posts: 2


sagenepal wrote:
Hello,

I want to share this code in order to help out Stefan and anyone else who wants to to UART transmit using interrupts. This code uses the TXC interrupt, not UDRE. I don't know much about the latter. Maybe it would be better? But this code works, and it has a nice wrap-around buffer for very efficient use of processor time.

- Sage Radachowsky
Boston, USA


Code:
// SendWithInterrupt - main.c
//
// by Sage Radachowsky, Feb-Mar 2008 ("sager" at "mit" dot "edu")
//
//
// Program to test sending data to the serial output (UART / RS232) using interrupts
// instead of actively polling to check if the last byte was written.
//
// This has two advantages -- the CPU is using its built-in hardware signals rather than
// burning CPU instructions so it consumes less power, and (2) the CPU is freed
// to do other things rather than wait for some 9600 baud output or even 57k baud output,
// which is a heck of a long time in a multi-MHz world.
//
// This is written for the AT90CAN128 microcontroller, which has 2 UART lines. To rewrite
// it for any Atmel AVR micro that has just one serial line, you would have to change the
// names of all the UART registers to remove the "0".
//
// Note that interrupts must be globally enabled for this stuff to work - of course!
//
// This code sets up the interrupts to interface with stdout, so that "printf()" sends
// by interrupt! Easy and Sweet!
//
// NOTE: Be sure to change your CPU speed if it's not 1.8432 MHz !
//




//**********************************************
//                DEFINITIONS
//**********************************************



// CPU frequency
#define F_CPU 1843200L   // 1.8432 MHz

// UART baud rate
#define UART_BAUD  9600

// UART buffer size
#define UART_BUFFER_SIZE 256


//**********************************************
//               HEADER FILES
//**********************************************


#include <ctype.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#include <util/delay.h>




//**********************************************
//            FUNCTION DECLARATIONS
//**********************************************

void         USART0_Init(void);
static int   UART0_Putchar(char c, FILE *stream);
void         DelayAwhile(void);


//**********************************************
//               GLOBAL VARIABLES
//**********************************************

char UartBuffer[UART_BUFFER_SIZE]; // this is a wrap-around buffer
int  UartBufferNextByteToSend; // position of next byte to be sent
int  UartBufferNextFree; // position of next free byte of buffer
int  UartSendingInProgress; // 1 = sending is in progress


/* This is the pointer to the serial interface */
/* Defines the stream interface for write only */

FILE uart_str = FDEV_SETUP_STREAM (UART0_Putchar, NULL, _FDEV_SETUP_WRITE);




// ################## here we GO! ####################

int main()

{

   // initialize the UART and enable interrupts
   USART0_Init(); sei();

   printf ("Hello from SendWithInterrupt.\n");
   DelayAwhile();


   // loop forever
   while (1)
   {

      printf ("This is test output. How's the weather?\n");
      DelayAwhile();

   }


}


//===============================================================================
  void DelayAwhile()

//
// Delays a while, to slow down to a human level.
//


{
   _delay_ms(200);
   _delay_ms(200);
   _delay_ms(200);
}





//****************************************************
//                 UART functions
//****************************************************




//===============================================================================
  void USART0_Init()

// This routine initializes the UART0 port of the AT90CAN128 and clears the
// write buffer.
//
// This routine does NOT enable the transmit-complete interrupt (TXCIE0).
// That is left up to the UART0_PutChar() routine, after it puts something in
// the buffer for the first time.
//
// This routine also does NOT enable general interrupts. That is left to the
// main() initializing code, and it MUST be done for this stuff to work.
//
// Also sets standard out to the uart interface, so printf() works sweetly.
//

{

   // init buffer data structures
   UartBuffer[0] = '\0'; // clear the first byte of buffer
   UartBufferNextByteToSend = 0; // set "next byte to send" to beginning
   UartBufferNextFree = 0; // next free byte is also beginning of buffer
   UartSendingInProgress = 0; // clear "sending in progress" flag

   // set baud rate
   UBRR0H = (unsigned char) (((F_CPU/(16L*UART_BAUD))-1) >> 8);
   UBRR0L = (unsigned char) ((F_CPU/(16L*UART_BAUD))-1);

   // Set frame format: 8data, no parity & 1 stop bits
   UCSR0C = (0<<UMSEL0) | (0<<UPM0) | (0<<USBS0) | (3<<UCSZ00);


   // Enable transmit
   UCSR0B = (1<<TXEN0); //Enable the transmitter only

    // set standard output stream to our UART interface
   stdout = &uart_str;

}


//===============================================================================
  static int UART0_Putchar(char c, FILE *stream)

// If transmit is in progress, adds a character to the UART output buffer.
// If transmit is not in progress, kicks off a transmit.
//
// The send buffer is a wrap-around buffer.
//
// If the buffer is full, then this routine returns EOF.
// A successful completion returns 0.
//
// This routine disables the UART Tx interrupt temporarily, because
// things would get funky if the interrupt signal routine were called during
// execution of this routione.
//
// If the buffer was empty to start with, then this routine "primes the pump"
// sending the character directly to the UART.
//
// This routine also adds carriage returns to newlines.
//

{
   register int ReturnStatus = 0; // return 0 for success
   register int UartBufferNextFree_last; // space to save last UartBufferNextFree

   // if character is a "newline" then add a "carriage return" before it.
   if (c == '\n')
      UART0_Putchar('\r', stream);


   // if no send is already in progress, then "prime the pump" by sending directly to UART
   if (UartSendingInProgress == 0)
   {
      // set "sending in progress" flag
      UartSendingInProgress = 1;
      // send the first byte!
      UDR0 = c;
   }
   else
   {
      // disable the Tx Complete interrupt
      UCSR0B &= ~( 1 << TXCIE0 );

      UartBuffer[UartBufferNextFree] = c;

      // increment the next free byte index, while saving last value
      UartBufferNextFree_last = UartBufferNextFree++;

       // check for wrap-around
      if (UartBufferNextFree == UART_BUFFER_SIZE) // if we reached the end of the buffer -
           UartBufferNextFree = 0; // start back at the beginning

      if (UartBufferNextFree == UartBufferNextByteToSend) // if buffer is full -
      {
         // bump back the index so transmit routine doesn't think buffer's empty
         UartBufferNextFree = UartBufferNextFree_last;
         // return with error code   
         ReturnStatus = EOF;
      }
      
      // enable the Tx Complete interrupt
      UCSR0B |= ( 1 << TXCIE0 );
   }


   // return with status code
   return ReturnStatus;
}









//********************************
//       INTERRUPT HANDLERS
//********************************


//===============================================================================
   ISR (USART0_TX_vect)


// This interrupt service routine is called when a byte has been sent through the
// UART0 port, and it's ready to receive the next byte for transmission.
//
// If there are more bytes to send, then send the next one and increment the index.
// If the index reached the end of the buffer, then wrap around to the beginning.
//
// If there is not another byte to write, then clear the "UartSendingInProgress"
// flag, otherwise set it if a byte has just been sent.
//

{
   if (UartBufferNextByteToSend == UartBufferNextFree)  // if nothing to send -
   {
        UartSendingInProgress = 0;   // clear "sending in progress" flag
       return; // then we have nothing to do, so return
   }

   // set "sending in progress" flag
   UartSendingInProgress = 1;

   // send the next byte on UART0 port
   UDR0 = UartBuffer[UartBufferNextByteToSend];

   // increment index and check for wrap-around
   UartBufferNextByteToSend++;
   if (UartBufferNextByteToSend == UART_BUFFER_SIZE) // if we reached the end of the buffer -
      UartBufferNextByteToSend = 0; // then start back at the beginning

}


Have fun!


Can this method of using streams and stdout etc be used in a similar way to read in strings? Ie stdin, an Rx interrupt, buffer and then reading with say scanf?

Im half way through doing so and wanted to make sure Im not on a futile path. Im aiming towards a simple way to have interrupt powered functions that easily send and capture complete strings from the UARTs. Thanks guys!
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Mar 24, 2011 - 09:18 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62944
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

Can this method of using streams and stdout etc be used in a similar way to read in strings? Ie stdin, an Rx interrupt, buffer and then reading with say scanf?

See the user manual:

http://www.nongnu.org/avr-libc/user-man ... odemo.html

As you'll see that implements two output streams (LCD and UART) and one input stream (UART)

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
hobbss
PostPosted: Apr 05, 2011 - 03:32 PM
Resident


Joined: Oct 06, 2010
Posts: 527
Location: Chicago

Preface: I have not read all 13 pages of comments -- just the original tutorial, and pages 11 - 13 of comments (i.e., "recent" comments).

After reading the tutorial, I have written my ISR as:

Code:

ISR(USART1_RX_vect) {
   uint8_t rxByte;
   uint8_t dummyByte;

   if(!rxFlag1) {   //Buffer has been read by decode function
      while(!(UCSR1A & (1 << RXC1)))
      {}
      rxByte = UDR1;
      if(rxByte == 10 || rxByte == 13) {   //NL or CR
         rxFlag1 = 1;
      }
      else {
         if(bufcnt1 > (RXBUFSZ-1))
            bufcnt1 = (RXBUFSZ - 1);
         rx_buffer[bufcnt1] = rxByte;
         bufcnt1++;
      }
   }
   else {
      while(!(UCSR1A & (1 << RXC1)))
      {}
      dummyByte = UDR1;   //throw away bytes received before ready
   }
}


If I am understanding a comment several pages earlier (by Dean?) correctly, the while(!...) loops are not necessary, because the bit will definitely be set if the ISR is called. Is this correct? Does this change if the incoming messages are extremely rapid, i.e., faster than the ISR can handle them?
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Apr 05, 2011 - 05:56 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62944
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

Is this correct?

Yes, there are two ways to use a bit such as RXC or UDRE. One is to simply have a "polled" receive or transmit routine which is called synchronously and does not return until the action has completed. In this case you "block" on the specified bit in a while() loop that repeats until the desired state is achieved. The other way to use the flags is to make use of interrupts and do things asychronously so the main() code can get on and do other things and when triggered the ISR fires and receives/sends the character. The main() code *may* block in this case but it will be on a volatile flag set by the ISR to say something of relevance has happened (perhaps an entire string has been received to the buffer or similar).

What you should not do is mix asychronous use of the flags together with synchronous polling loops. In fact, unless it's guaranteed to happen in microseconds, no ISR should ever block on an asychronous event flag because it could be seconds or minutes before the event occurs (during which time the entire interrupt/main system is blocked from doing anything). Of course you can "block" on a flag even that you KNOW is already set without any problem (which is what your code does) but why would you do this. Even if the while() is done only once it's one time more than you need.

You are on dodgy ground if you start writing ISRs that take longer to process than the period of the event they are reacting too as you may never "get out". But with circular ISR buffering as long as the buffer is large enough to cope with a "sudden burst of activity" (assuming there's then an interval allowing for the buffer to be processed/flushed) then you'll be OK.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
hobbss
PostPosted: Apr 05, 2011 - 06:02 PM
Resident


Joined: Oct 06, 2010
Posts: 527
Location: Chicago

Clawson: thanks for the reply. As you may have noted, I am also involved in a ... heated... discussion about serial comms over in the other forum. This was an attempt to not get this thread offtrack (not an attempt at cross posting).

I will remove the while loops from my code. That said, is your warning about lengthy ISRs directed explicitly at this piece of code? I am unsure how to make it leaner. My handling routine (that deals with the actual message) may be slow, in which case I am fine throwing away incoming data -- which is what I think happens with the whole rxFlag1 variable (reset by the handling function when it is done).
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Apr 05, 2011 - 06:12 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62944
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

That said, is your warning about lengthy ISRs directed explicitly at this piece of code? I am unsure how to make it leaner

No, by a fluke (perhaps by design) there's no problem with the while() loops you have because they check for a bit that's known to be set so don't (hardly!) delay the action. But more generally you should always be asking yourself if you are really doing the right thing if you ever put ANY kind of iterative loop in an ISR. The goal is that through whatever code path they always complete in a time measured in microseconds (on 1MHz..20MHz processors). With Serial Rx your ISR is almost always going to be identical. You pick up UDR and you put it into a circular buffer at the write pointer position that is then incremented and if it wraps then reset it to the beginning (hence "ring" or "circular"). This action is the only work that HAS to be in the ISR, any "data processing" should be handled outside the ISR with I enabled again so nothing else is being blocked from happening. Having said that some people might put a special check for '\n' in a RXC ISR if they need quick/special notification of the "end of sentence".

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
hobbss
PostPosted: Apr 05, 2011 - 06:22 PM
Resident


Joined: Oct 06, 2010
Posts: 527
Location: Chicago

Noted. Thanks for the info. I will refrain from using possibly infinite loops in ISRs in the future.
 
 View user's profile Send private message  
Reply with quote Back to top
anil85
PostPosted: Apr 20, 2011 - 05:02 PM
Rookie


Joined: Apr 11, 2011
Posts: 21


Well explained...thanks...
 
 View user's profile Send private message  
Reply with quote Back to top
ucupzzz
PostPosted: Jul 25, 2011 - 03:48 AM
Newbie


Joined: May 18, 2009
Posts: 14


Hii... i`ve simple code that make me so confused...
i want to turn on the led from the keyboard via usart...

this is the code:
Code:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>

#define LED PORTA

uint8_t data;

ISR(USART_RXC_vect)
{
data=UDR;
[b]LED=data;[/b]
}

void USARTinit(uint16_t ubrr_value)
{
set baudrate
UBRRL=ubrr_value;
UBRRH=(ubrr_value>>8);


UCSRC=(1<<URSEL)|(3<<UCSZ0);

//ENABLE THE RECEIVER AND TRANSMITTER
UCSRB=(1<<RXEN)|(1<<TXEN)|(1<<RXCIE); //REGISTER RXCIE YANG MENGAKTIFKAN INTERUPT NYA...
sei();
}

int main(void)
{
DDRA=0XFF;
USARTinit(71);

while(1)
{
   
};

}


The program work well...

but if i want to make something different.. like this code :

Code:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>

#define LED PORTA

uint8_t data;

ISR(USART_RXC_vect)
{
data=UDR;

}

void USARTinit(uint16_t ubrr_value)
{
// set baudrate
UBRRL=ubrr_value;
//UBRRH=(ubrr_value>>8);

//   Asynchronous mode
//   No Parity
//   1 Stop Bit
//   Char size 8

UCSRC=(1<<URSEL)|(3<<UCSZ0);

//ENABLE THE RECEIVER AND TRANSMITTER
UCSRB=(1<<RXEN)|(1<<TXEN)|(1<<RXCIE); //REGISTER RXCIE YANG MENGAKTIFKAN INTERUPT NYA...
sei();
}




int main(void)
{

DDRA=0XFF;


USARTinit(71);

while(1)
{
   
[b]LED=data;
[/b]};
}

The program cannot work like the previous program...
how to make its work in while(1){};....?
 
 View user's profile Send private message  
Reply with quote Back to top
larryvc
PostPosted: Jul 25, 2011 - 04:29 AM
Raving lunatic


Joined: Dec 06, 2007
Posts: 2512
Location: Redmond, WA USA

Code:
uint8_t data;

The variable "data" is shared between the ISR and the code in main(), it must be declared volatile.
Code:
volatile uint8_t data;

Also Bold characters
Code:
[b] test [/b]

do not work in code blocks.

_________________
Larry

Those afraid to embrace the future will quickly fade into the past. - larryvc
 
 View user's profile Send private message  
Reply with quote Back to top
ucupzzz
PostPosted: Jul 25, 2011 - 04:38 AM
Newbie


Joined: May 18, 2009
Posts: 14


great.. thank you very much...
"volatile"......
 
 View user's profile Send private message  
Reply with quote Back to top
Daniel_sky
PostPosted: Sep 17, 2011 - 12:19 PM
Newbie


Joined: Sep 17, 2011
Posts: 4


Hi,

Great tutorial Dean!!!

But here is my problem. I'm using Peter's Fluery lib. And after compilation it returns very known warning: uart.c:322: multiple definition of `__vector_11'. I checked (in case) list of vectors in iom16.h (for my MEGA16), and they are correct but conflict is in file uart.c where there is a function:
Code:

ISR(UART0_RECEIVE_INTERRUPT)
/*************************************************************************
Function: UART Receive Complete interrupt
Purpose:  called when the UART has received a character
**************************************************************************/
{
    unsigned char tmphead;
    unsigned char data;
    unsigned char usr;
    unsigned char lastRxError;
 
 
    /* read UART status register and UART data register */
    usr  = UART0_STATUS;
    data = UART0_DATA;
   
    /* */
#if defined( AT90_UART )
    lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
#elif defined( ATMEGA_USART )
    lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
#elif defined( ATMEGA_USART0 )
    lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) );
#elif defined ( ATMEGA_UART )
    lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
#endif
       
    /* calculate buffer index */
    tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK;
   
    if ( tmphead == UART_RxTail ) {
        /* error: receive buffer overflow */
        lastRxError = UART_BUFFER_OVERFLOW >> 8;
    }else{
        /* store new index */
        UART_RxHead = tmphead;
        /* store received data in buffer */
        UART_RxBuf[tmphead] = data;
    }
    UART_LastRxError = lastRxError;   
}

which is collides with ISR(USART_RXC_vect) in my code. Is there way to accord this problematic dependence?

Thanks in advance for your help.
Daniel
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Sep 17, 2011 - 01:01 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62944
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

which is collides with ISR(USART_RXC_vect) in my code. Is there way to accord this problematic depen

Well you can't have two handlers for the same vector so you have to decide if you are going to handle it or are you going to let Fleury handle it - it cannot be both. The fact that you are using Fleury rather suggests that it's your own code that is pointless.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Daniel_sky
PostPosted: Sep 17, 2011 - 01:43 PM
Newbie


Joined: Sep 17, 2011
Posts: 4


Quote:

The fact that you are using Fleury rather suggests that it's your own code that is pointless.

That's so true. This is my first steps in uC's programming so I'm still learning and searching for answers and confirmations of my uncertainty in writing. It's actually not writing yet. It's boils down to googling and searching parts of code and trying it and that from where my problems comes. Sorry if that question was frustrating for You, but it will helps me choose what solution should I seek to.

Greetings
Daniel
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Sep 17, 2011 - 01:57 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18757
Location: Lund, Sweden

Quote:

Sorry if that question was frustrating for You

Most noob questions are frustrating for us Wink, but we try to answer (perhaps with a twist) each time after grinding our teeth for a few minutes.

Welcome to AVRfreaks Daniel!
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Daniel_sky
PostPosted: Sep 17, 2011 - 02:17 PM
Newbie


Joined: Sep 17, 2011
Posts: 4


Quote:
grinding our teeth for a few minutes

What can I say? You should have a good dentist Razz.
Ok, seriously thank You guys for Your patient, selflessness and so kind welcome in forum Smile. Big Bravo for AVRfreaks Team for the great job They are doing for us to make our lives easier Very Happy!!!

Greetings
Daniel
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Sep 17, 2011 - 06:22 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18757
Location: Lund, Sweden

Quote:
Big Bravo for AVRfreaks Team for the great job They are doing

Stay around for a possible re-evaluation, or the final crash of the site. (Not that the guys behind the site aren't ambitious. Just no money.)
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
clawson
PostPosted: Sep 19, 2011 - 09:50 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62944
Location: (using avr-gcc in) Finchingfield, Essex, England

Discussion about implementing CTS/CTS split from this thread to AVR Forum here:

http://www.avrfreaks.net/index.php?name ... highlight=

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits