| Author |
Message |
|
|
Posted: Mar 22, 2011 - 04:07 PM |
|

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 |
|
|
| |
|
|
|
|
|
Posted: Mar 23, 2011 - 09:31 AM |
|


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. |
_________________
|
| |
|
|
|
|
|
Posted: Mar 24, 2011 - 05:07 AM |
|

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! |
|
|
| |
|
|
|
|
|
Posted: Mar 24, 2011 - 09:18 AM |
|


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) |
_________________
|
| |
|
|
|
|
|
Posted: Apr 05, 2011 - 03:32 PM |
|


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? |
|
|
| |
|
|
|
|
|
Posted: Apr 05, 2011 - 05:56 PM |
|


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. |
_________________
|
| |
|
|
|
|
|
Posted: Apr 05, 2011 - 06:02 PM |
|


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). |
|
|
| |
|
|
|
|
|
Posted: Apr 05, 2011 - 06:12 PM |
|


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". |
_________________
|
| |
|
|
|
|
|
Posted: Apr 05, 2011 - 06:22 PM |
|


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. |
|
|
| |
|
|
|
|
|
Posted: Apr 20, 2011 - 05:02 PM |
|

Joined: Apr 11, 2011
Posts: 21
|
|
| Well explained...thanks... |
|
|
| |
|
|
|
|
|
Posted: Jul 25, 2011 - 03:48 AM |
|

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){};....? |
|
|
| |
|
|
|
|
|
Posted: Jul 25, 2011 - 04:29 AM |
|


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
|
| |
|
|
|
|
|
Posted: Jul 25, 2011 - 04:38 AM |
|

Joined: May 18, 2009
Posts: 14
|
|
great.. thank you very much...
"volatile"...... |
|
|
| |
|
|
|
|
|
Posted: Sep 17, 2011 - 12:19 PM |
|

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 |
|
|
| |
|
|
|
|
|
Posted: Sep 17, 2011 - 01:01 PM |
|


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. |
_________________
|
| |
|
|
|
|
|
Posted: Sep 17, 2011 - 01:43 PM |
|

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 |
|
|
| |
|
|
|
|
|
Posted: Sep 17, 2011 - 01:57 PM |
|


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 , but we try to answer (perhaps with a twist) each time after grinding our teeth for a few minutes.
Welcome to AVRfreaks Daniel! |
|
|
| |
|
|
|
|
|
Posted: Sep 17, 2011 - 02:17 PM |
|

Joined: Sep 17, 2011
Posts: 4
|
|
|
Quote:
grinding our teeth for a few minutes
What can I say? You should have a good dentist .
Ok, seriously thank You guys for Your patient, selflessness and so kind welcome in forum . Big Bravo for AVRfreaks Team for the great job They are doing for us to make our lives easier !!!
Greetings
Daniel |
|
|
| |
|
|
|
|
|
Posted: Sep 17, 2011 - 06:22 PM |
|


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.) |
|
|
| |
|
|
|
|
|
Posted: Sep 19, 2011 - 09:50 AM |
|


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