[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

After I wrote my UART transmit by interrupt, I found this library by Pascal Stang:
http://www.mil.ufl.edu/~chrisarn...

I repeat the link here, because I think every AVR freak should know about it. There are many good functions there.

Actually, this link is the documentation:
http://www.mil.ufl.edu/~chrisarn...

Why choose? Be there *and* be square!

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

Note to self and others, GCC doesn't produce an error for a misspelled interrupt handle, it just gives you a warning.

Don't learn the hard way....

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

I'd suggest *always* using the -Werror command line switch. That indicates to GCC that all warnings should be treated like errors, preventing successful compilation.

I'm a firm believer that correct code should produce no warnings, and no errors. If code which triggers a warning is desired, then it should either be reworked or the warning suppressed through other means.

- Dean :twisted:

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

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

michael_R wrote:
Note to self and others, GCC doesn't produce an error for a misspelled interrupt handle, it just gives you a warning.

The implication of that is that you just ignore the warnings? If there's a lesson to be learned it is never ignore the warnings. In fact strive to get code compiling with no warnings at all and even so that it is split/lint-able. As Dean says -Werror is a good idea.

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

Thanks a ton for the guides on USART, I'm now able to successfully talk to myself through my microcontroller, a new low! :D

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

Good morning

It seems my interrupt is firing on its own (after about 20 seconds from MCU start up) without any data being sent to it (there physically are no wires connecting to the Rx pin!)

ISR(USART0_RX_vect) {
// code
} // ISR USART0

Is there a timeout or some other function that would fire the interrupt even if there is no data being sent to it?

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

I am using modem in my project to send an sms depending of some conditions. The sending of sms is not urgent ie. sms is not supposed to be fired instantly. Now my question is which way is good one to use - polled or interrupt for interfacing modem.

Moreover, is there any limitation on number of interrupts that we can use.

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

If it's not urgent, don't use interrupts (which should be used for time-critical events). There's no code limitation on the number of interrupts, but keep in mind that each one requires cycles to process -- to many happening simultaneously and you'll start to miss some or have them severely delayed.

- Dean :twisted:

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

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

Trying the (excellent!) tutorial here I see something I don't understand. I modified the final code slightly:

//includes...

static void uart_putchar(char c) {
    loop_until_bit_is_set(UCSRA, UDRE);
    UDR = c;
}

int main(void) {
    //...init usart for the corresponding avr

    UCSRB |= (1 << RXCIE);
    sei();
    
    uart_putchar('p'); //so I just print a character here

    for (;;); // Loop forever

    return 0;
}

ISR(USART_RX_vect) {
    char ReceivedByte;
    ReceivedByte = UDR;
    UDR = ReceivedByte;
}

I load the binary to my attiny2313, go to my terminal program and surely see a

p

sitting there (I just printed it there, right). I press the comma (',') key of my keyboard and as expected the avr starts bouncing commas back to me. But the whole output actually looks like this:

p,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,p,,,,,,,
,,,,p,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,p,,,
,,,,,,,,,,,,,,,,,,,,,p,,,,,,,,,,,,,,p,,,
,,,,p,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

which tells me that somehow the main routine gets re-executed or reset or something... And seems to be pretty undeterministic too - I could have any number of commas between the 'p's. I read wathcdog timers can reset your avr (so the main() starts over), but I don't have that fuse set. As far as I know in C, the main() can be executed only once (unless you do some sort of recursion may be?). Tried putting something more meaningful in the for loop (in my case flipping a pin between 0 and 1) but that didn't change things much. The only other possibility is that the interrupt causes the main program reset but haven't seen that mentioned as an option either (and frankly it would be a bit disturbing). So what am I missing?

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

Hi Dean,

Nice tutorial. I'm new to AVRs and serial programming but it's a lot of fun ;-)

I went through this tutorial and the basic one about serial communications. I have changed the code just to test and to make sure the that it is really the AVR talking to me through the serial port. Basically I wanted it to send back a 'x' with echoed character I send to the AVR.

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
   while ((UCSRA & (1 << UDRE)) == 0) {}; 
      UDR = 'x'; 
}

What I get back is very weird though. At times it works fine and sometimes I get an 'a' back when I send an 'A' and sometimes I will get an '|' back instead of a 'x'. For example every second 'A' I send will return as 'a|' instead of 'Ax'. What's even stranger is that only 'A's will return in lower case. All other characters are echoed in the same case. Sometimes it works fine so results are very spontaneous and I can't pick up a pattern.

I use a Atmega8 and Minicom in linux (i've even tested it with my own C code on linux and with Bray's Terminal in windows, same result). I hooked up and external crystal clocking at 7.3728MHz

Is it caused by the extra code I have added? Like I said, that code is not needed, I'm just using for testing purposes.

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

pepper_bg:

That's very odd behavior. Is that the only code running in your system? Does it appear to reset by itself (when you don't try to send characters) or only after you're sending data to it?

kakasi:

Spinloops in ISRs are usually a very bad idea - you run the risk of delaying too far and missing other interrupts. That said, if that's your only ISR you should be fine with low data rates.

I'd suspect that its either an issue with noise on the line or (more likely) a slight baud mismatch. What are you using for your AVR's clock source? If it's the default internal RC oscillator, you'll have problems as it's too low tolerance for reliable communications.

- Dean :twisted:

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

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

I'm using the external crystal as the clock source. Both the PC's port and the AVR is set up for 9600 bps...is it possible that crystal is unstable?

Thanks for the info...there is a possibility of noise, coz i built the circuit on a breadboard, right?

:roll:

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

Noise is *always* a possibility ;).

How certain are you that the external crystal is being used? Plenty of people attach the crystal and blindly assume it's the AVR's clock source, but never change the AVRs fuses. My apologies if I'm going over things you already know, but it's a common trip-point for newbies.

The crystal might be unstable if the breadboard is giving it too much capacitance. However that voodoo-electronics is not my area, and you'd really need an oscilloscope to check it easily.

I'd rule out the cable first, as bad (or too long) cables can garble data more easily than you'd think.

- Dean :twisted:

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

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

hehe, no problem. it's definitely using the external clock...I had a flashing LED app running on the mega8, and right after connecting the crystal and burning the fuses, it started to flash much faster. That was easily fixed by specifying the new clock speed (#define F_CPU 7372800UL) ;-)

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

OK, i have taken out the code that send the 'x', so I obviously don't get the random '|' back from the AVR anymore. But, I still have a problem with the 'A'...sometimes it echoes 'A' back and sometimes 'a' when you send 'A'.

I went through all the keys on my keyboard, and it gets even weirder. When I send a 'P' or 'p' it returns a 'X' or 'x' and sometimes it returns the correct results.

I doubt if it is noise, because it ONLY happens to these characters.

Is this happening to anyone else?

I don't know why it only happens to these chars but this is interesting:
P - 101 0000
X - 101 1000

p - 111 0000
x - 111 1000

A - 100 0001
a - 110 0001
...there's only one bit chat changes between the pairs.

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

It seem to be working now...I have changed the baud rate to 19200 and no more funny results echoed back the the PC :D

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

..just some feedback...
I have moved all the components to my "production" pc board, and I also used another crystal (same specs as the one I used on my breadboard). I changed the baud rate back to the original 9600bps and everything is working as it should.

I think that either the crystal I used was faulty, or there is less noise or less capacitance on the pcboard. Unfortunately I am not a guru in electronics so I'm not sure exactly what caused the strange behavior on the breadboard. ;-)

Thanks for the assistance Dean!

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

good tutoril!

i'm planning to implement rs485 network for my application,where i may have a PC and several mcu units and i think one more tutorial on multi-processor communication would be helpful to some me and someone out there!

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

Did anyone solve that 'USART_RXC_vect' problem? I'm using the latest WinAVR with ATmega640 and getting the same error . . . Does it have anything to do with the fact I have four UARTs?

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 . . .

Interestingly, all of them give me the 'misspelled' error except this one:
USART1_RX_vect

Which gives me this error:
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

How do YOU make a robot?
http://www.societyofrobots.com

Last Edited: Mon. Aug 4, 2008 - 04:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looking at the part header files, "USARTn_RX_vect" is the correct vector name, where "n" is 0 to 3 inclusive.

That error indicates other build problems (as the binaries weren't produced). Run a "make clean" and then a "make all", and post the compiler output.

- Dean :twisted:

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

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

You could always simply give in on the "guessing game" and read the manual:

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

The mega640 is listed (for RX vectors) against:

USART0_RX_vect
USART1_RX_vect
USART2_RX_vect
USART3_RX_vect

So it's no surprise that USART1_RX_vect "half worked" for you. As to the rest of the error, it's probably a link error in the build so switch back to the build tab to see what that was.

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

Does anyone have any code for receiving a string of characters (15 bytes in specific). Each string begins with 0x41 and ends with 0x0A. I am using interrupt driven receive. I have my code working where I can get the first character stored in my receive[0] array, but I cannot seem to figure out how to collect the other 14 bytes in the transmission and put them in receive[1]-receive[14]. Any help would be great. Also thanks for the tutorials and the informative posts; very helpful to people who are new and stuck!

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

I am using USART_RXC interrupt, when when an '1' arrives to the UDR it's saves in a register and then return to the cycle loop where It's compared where if its 0, sending zeros to the port c, if it's 1, go will to the label start and starts the adc, when the conversion ends interrupt and go to ISR end_conversion, and returns to where the flag ADIF is polls so if the UDR comes a new date of information it receives in the ISR of RXC is executed but fails to return to the cycle of comparison but again the cycle of poll flag ADIF, Which I can do to solve this?

This is a my code

.cseg
.include "m8535def.inc"

.EQU fq=4000000 ; Xtal frequency
.EQU baud=9600 ; Baudrate
.EQU bdpresc=(fq/(16*baud))-1 ; Baud-Divider

.DEF c=R30 ; char.

;VECTOR DE INTERRUPCIONES****************************************************

.ORG 0x0000
rjmp RESET
rjmp EXT_INT0
rjmp EXT_INT1
rjmp TIM2_COMP
rjmp TIM2_OVF
rjmp TIM1_CAPT
rjmp TIM1_COMPA
rjmp TIM1_COMPB
rjmp TIM1_OVF
rjmp TIM0_OVF
rjmp SPI_STC
rjmp UART_RXC
rjmp UART_UDRE
rjmp UART_TXC
rjmp fin_de_conv; interrupt end of conversion
rjmp EE_RDY
rjmp ANA_COMP

EXT_INT0: reti
EXT_INT1: reti
TIM2_COMP: reti
TIM2_OVF: reti
TIM1_CAPT: reti
TIM1_COMPA: reti
TIM1_COMPB: reti
TIM1_OVF: reti
TIM0_OVF: reti
SPI_STC: reti
UART_UDRE: reti
UART_TXC: reti
EE_RDY : reti
ANA_COMP: reti

UART_RXC:

in c, udr

OUT UDR, c

reti

fin_de_conv:

cbi adcsra, adie

in r18, adch

out portc, r18

reti

Reset:

ldi r26, low (RAMEND)
out spl, r26
ldi r26, high (RAMEND)
out sph, r26

ldi r26, 0xff ; port c outputs
Out ddrc, r26

ldi r26, 0x00 ; Port a inputs
out ddra, r26

;Configuración USART *****************************************************

ldi r20, HIGH (bdpresc)
out UBRRH, r20
ldi r21, LOW (bdpresc)
out UBRRL, R21

ldi r16, 0b10011000 ; RXCIE, RX y Tx
out UCSRB, r16

ldi r16, 0b10000110 ;
out UCSRC, r16

;Configuración ADC *******************************************************

ldi r26, 0b01111100 ; Aref = vcc, adlar=1, adc4+, adc2-
out admux, r26

ldi r26, 0b10100101 ; prescaler = 32
out adcsra, r26

sei

loop:

Ldi r22, '1'
cpse c, r22
rjmp stop
rjmp start

stop:
cbi adcsra, adie
clr r17
out portc, r17
rjmp loop

start:

sbi adcsra, adsc

sbi adcsra, adie
fincon:

sbis adcsra, adif
rjmp fincon

rjmp loop

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

how i can avoid buffer overrun?? i try to send data full duplex (continues both from AVR to PC), but after 3-4 minutes my avr stop communication, because data overrun? any suggestion about using timeout when receive data (interrupt AVR - UART RX)?

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

Well you either have to consume the data at a faster rate than it arrives or slow the rate at which it is arriving.

If you are currently polling the received data then implenting an Rx-interrupt may help things.

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

Dean,

So, now lets say we've gotten advanced and have our UART code working nicely. How does one go about making a clean interface for handiling the transmission of multiple data streams?

Quote:

communication ISRs are generally made short by receiving in characters via an ISR, and placing them into a buffer which the main code may read at its leisure. This ensures that received data will not be missed, while giving the main program time to complete what it is currently doing before having to process the input. Similarly, long transmissions may be made by placing the data to be sent into a buffer, and have an interrupt send the data as the hardware is ready while the main program performs other tasks.

From what I understand, we create a transmission buffer in which the main loop will place data in. Then, when it is ready, the program sends the data in the transmit buffer by successively printing each character.

When I try to do this, I have issues, such as one transmission being overwritten by another, etc. Could you point out some ways to fix this problem? Would it be wise to use flags? Perhaps some kind of flag to prevent the UART from printing more data until the latest data has finished being sent? Your help is much appreciated.

Diode Dan

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

You need two ring buffers - one for reception and one for transmission. When transmitting, before adding the next byte to the buffer you need to spinloop until space is available. The TX USART interrupt then fetches the next byte out of the buffer when it is available and puts it into the UDR register to send it.

You need to trigger the start of the transmission - otherwise, the TX USART interrupt will not fire for the first time and nothing will happen.

I suggest you download my MyUSB project (http://www.fourwalledcubicle.com...) and take a look at the "USBtoSerial" demo in the demos folder; you can ignore all the USB code and just focus on the buffering and serial transmission/reception. It implements the proper way to make buffered USART communications.

- Dean :twisted:

PS: Please excuse any incoherency in the above due to my slight inebriation. If something is unclear ask again - in an hour or two.

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

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

Personally I've often found it sufficient to just use interrupts and a ring buffer for Rx then do the Tx sychronously

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

Great tutorial, thanks! I implemented in the 90S8515, cannot wait to program it into STK500, I need to get a USB to RS232, first,

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

the code in the begining of this tutorial without the interruptions worked on my atmega16, but the one with the interruptions seems to be sending random numbers.
I dont know why...

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

I can not complie the simple code that is placed in this tutorials.

can anyone tell me what is wrong.

#include  
#include  

#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 << 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) //SIG_USART_RECV
{ //linie 25
   char ReceivedByte; 
   ReceivedByte = UDR; // Fetch the recieved byte value into the variable "ByteReceived" 
   UDR = ReceivedByte; // Echo back the received byte back to the computer 


}

warnings in studio 4

../interupt6.c:25: warning: return type defaults to `int'
../interupt6.c: In function `ISR':
../interupt6.c:25: warning: type of "USART_RXC_vect" defaults to "int"
../interupt6.c:31: warning: control reaches end of non-void function

[/b][b]

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

Looks like your version of avr-libc is out of date. What version of WinAVR do you have installed? If it's not the latest version from the WinAVR website, you need to update.

- Dean :twisted:

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

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

I have version AVR Studio 4.14.589, but I really dont know about the avr-libc.
Will it not be updated when the studio is updated???

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

Quote:

Will it not be updated when the studio is updated???

No. AVR Studio is something separate from the avr-gcc/avrlibc toolchain. The latter is easily updated on a Windows system by installing/upgrading WinAVR.

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:
but I really dont know about the avr-libc.
Will it not be updated when the studio is updated???

No, it gets updated when you manually download and install the latest WinAVR (which is 20080610 at present):

http://sourceforge.net/projects/...

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

yeeeeeeeeees......your guys are the best...thanks

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

now I allmost got it.

I cant figure out what to do with the

void check_RS232(void)

I know the name should not be Buffer_GetElement. but what should it be. see my code below. and what is the error releated to.??

compiler errors and warnings
Build started 5.11.2008 at 15:49:54
../ring1.c: In function 'check_RS232':
../ring1.c:112: warning: implicit declaration of function 'Buffer_GetElement'
../ring1.c:115: error: expected ';' before 'if'
make: *** [ring1.o] Error 1
Build failed with 1 errors and 1 warnings...

/*
                  Simple Ringbuffer Library
                  -------------------------
						  (c) Dean Camera, 2005
						-------------------------
						 dean_camera@hotmail.com

          
 This library allows you to implement a ringbuffer into your code
 (useful for buffering FIFO data while the processor is busy)
 via easy-to-use functions.
 
 By changing the typedefs in RingBuff.h, you can change both the
 datatype stored and the size of the buffer.
 
 An error variable is exposed via extern to your program; if the
 buffer is full when you try to store data bit 1 of the error
 variable is set, and if you try to read an empty buffer bit 0 is
 set. Both bits are cleared after a sucessful data store or read.
 The error masks are avaliable via the defines BUFF_ERR_OVERFLOW
 and BUFF_ERR_EMPTY.

 Before it can be used, you must execute the "InitialiseBuffer"
 routine. To store data, use the "StoreBuffByte" routine and for
 reading data you use the "StoreBuffByte" routine.
 
 The extern BuffElements variable holds the number of elements
 in the buffer. This can be polled to check if the buffer is
 empty or not.
 
 The macro "ClearBuffError()" is defined in the RingBuff.h file
 so you can clear the error variable manually if you wish.
 
                [{ Feedback Appreciated }]
*/

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


// Includes:
#include 
#include "RingBuff.h"
#include 

// Global Variables:
volatile BuffType       *StoreLoc;
volatile BuffType       *RetrieveLoc;
volatile BuffType       RingBuffer[BuffLen];
volatile ElemType       BuffElements;
volatile unsigned char BuffError;


volatile uint8_t TotalRecLines; 


int main (void) 
{ 

  BUFF_InitialiseBuffer();


   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) //SIG_USART_RECV
{ 
   char c;
    
   c = UDR; // Fetch the recieved byte value into the variable "ByteReceived" 
   //UDR = c; // Echo back the received byte back to the computer 
	
	if (c != '\r')    // Ignore the \r in the standard \r\n sequence 
      return; 

   if (c == '\n')    // Reached the \n in the \r\n sequence 
   { 
      TotalRecLines++; // Indicate that an entire line is ready 
      c = '\0'; // Null terminate 
    } 
	
	if (c>1)
	{
	BUFF_StoreBuffByte(c);
	}
}


void check_RS232(void) 
{ 
   char LineBuffer[100]; // Max line length is 100 bytes 
    
    if (TotalRecLines) // Wait for a whole line to be buffered before reading it out 
   { 
      char c; 
      uint8_t LineSize = 0; 
    
      do 
         LineBuffer[LineSize++] = Buffer_GetElement(&RingBuffer); 
      while ((c != '\0') && (LineSize != sizeof(LineBuffer))) 
       
      if (LineSize == LineBuffer) // Line too long//linie 115 for buffer 
         LineBuffer[sizeof(LineBuffer) - 1] = '\0'; // Terminate string 
       
      TotalRecLines--; 

      // LineBuffer now contains the next line from the USART - process it here 
   } 
} 




// Routines:
void BUFF_InitialiseBuffer(void)
{
	StoreLoc    = (BuffType*)&RingBuffer; // Set up the IN pointer to the start of the buffer
	RetrieveLoc = (BuffType*)&RingBuffer; // Set up the OUT pointer to the start of the buffer

	BuffElements = 0;           // Reset the buffer elements counter
}





void BUFF_StoreBuffByte(BuffType DataToStore)
{
	if(BuffElements == BuffLen) // Buffer full
	{
		BuffError |= BUFF_ERR_OVERFLOW;   // Set the "buffer full" error flag
		return;
	}
	else                       // Sucessfull operation
	{
		BuffError = 0;          // Clear the error variable
	}
		
	*StoreLoc = DataToStore;   // Store the data

	StoreLoc++;                // Increment the IN pointer to the next element
	BuffElements++;            // Increment the total elements variable

	if (StoreLoc == (BuffType*)&RingBuffer[BuffLen])
		StoreLoc = (BuffType*)&RingBuffer; // Wrap pointer if end of array reached
}	



BuffType BUFF_GetBuffByte(uint8_t Pop)
{
	if(!(BuffElements))        // No elements in the buffer
	{
		BuffError |=  BUFF_ERR_EMPTY;       // Set the "buffer empty" error flag
		return 0;
	}
	else                      // Sucessfull operation
	{
		BuffError = 0;         // Clear the error variable
	}

	BuffType RetrievedData = *RetrieveLoc; // Grab the stored byte into a temp variable

	if (Pop)
	{
		RetrieveLoc++;   // Increment the OUT pointer to the next element if flag set
		BuffElements--;  // Decrement the total elements variable
	}
	
	if (RetrieveLoc == (BuffType*)&RingBuffer[BuffLen])
		RetrieveLoc = (BuffType*)&RingBuffer; // Wrap pointer if end of array reached
		
	return RetrievedData;    // Return the retrieved data
}
[/code:1][code:1]
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I mean how do I read out from

BuffType BUFF_GetBuffByte(uint8_t Pop)

rutine......I dont get it

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

hallo all

where to finde

#include 

to use for the adv ring buffer???

BR

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

Try:

#include 

as described in the user manual:

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

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

Hi, I'm just a noob using AVR.. From what i know ISR do not allow any argument to be pass and do not return anything. How do you normally pass data receive by USART interrupt to be read by another function? I tried using structure but no luck.. Thanks in advance.

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

Well here's a mad, wild, whacky, off-the-wall idea - why not try reading this thread?

Did the "ReceivedByte" Dean uses not ring any bells as a mechanism for returning a value from an ISR (basically write something 'global' in the ISR, read it in the main() loop)?

The extension of this is then a ring buffer where rather than just ReceiveByte you keep a whole array and separate Write and Read pointers to it.

Cliff

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

Quote:

I tried using structure but no luck..

Did you declare the struct volatile? If not then read FAQ#1 in Cliff's footer above, and then move on to the avr-libc FAQ proper to read the explanation (also item #1).

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:

and then move on to the avr-libc FAQ proper to read the explanation (also item #1).

The quick route there is to click on my signature.

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

Hallo there. This was a great tutorial, and I had a great use of it.
But now I've made a communication, which behaves really strange. This is what I mean:
I have Atmega32 with 16MHz external crystal(I have set the fuse on the bottom of the list, i can't remember its name). I want to communicate with 9600bps and it should be interrupt driven.
I use a simple way of communication. I send a character from PC, use the Rx ISR to handle it, and send back a character('!' in my case) by Tx ISR.
I use MATLAB in my PC to connect to the MCU. There I have a loop which is waiting for the '!' and when it receives it I send another character.
This is a breaf description of my idea.
Now the problem. The communication starts, but after I send some characters (1,2,3 different all the time) the communication hangs up. Matlab says 'A Timeout occured...'. The MCU goes on working properly though.

Can the problem be caused by the errors in the baud rates? I placed the code on an ATMEGA16 board with 7.3728MHz and it is working perfect, no timeouts.

This is the code, but the comments are not written in an english language:):

#include "avr/io.h"
#include "avr/interrupt.h"
#include "avr/eeprom.h"

//1. Inicializaciq na EEPROM
#define EEMEM __attribute__((section(".eeprom")))

unsigned char symbols[159][5] EEMEM=
{0x00,0x00,0x00,0x00,0x00, // sp sh indeks 0
0x00,0x30,0x7d,0x30,0x00, // ! sh 1
0x00,0x70,0x00,0x70,0x00, // " sh 2
0x14,0x7f,0x14,0x7f,0x14, // # sh 3
0x12,0x2a,0x7f,0x2a,0x24, // $ sh 4
0x62,0x64,0x08,0x13,0x23, // % sh 5
0x36,0x49,0x55,0x22,0x05, // & sh 6
0x00,0x50,0x60,0x00,0x00, // ' sh 7
0x00,0x1c,0x22,0x41,0x00, // ( sh 8
0x00,0x41,0x22,0x1c,0x00, // ) sh 9
0x14,0x08,0x3e,0x08,0x14, // * sh 10
0x08,0x08,0x3e,0x08,0x08, // + sh 11
0x00,0x05,0x06,0x00,0x00, // , sh 12
0x04,0x04,0x04,0x04,0x04, // - sh 13
0x00,0x00,0x03,0x00,0x00, // . sh 14
0x02,0x04,0x08,0x10,0x20, // / sh 15
0x3e,0x45,0x49,0x51,0x3e, // 0 sh 16
0x00,0x21,0x7f,0x01,0x00, // 1 sh 17
0x21,0x43,0x45,0x49,0x31, // 2 sh 18
0x42,0x42,0x51,0x69,0x46, // 3 sh 19
0x0c,0x14,0x24,0x7f,0x04, // 4 sh 20
0x72,0x51,0x51,0x51,0x4e, // 5 sh 21
0x1e,0x29,0x49,0x49,0x06, // 6 sh 22
0x40,0x47,0x48,0x50,0x60, // 7 sh 23
0x36,0x49,0x49,0x49,0x36, // 8 sh 24
0x30,0x49,0x49,0x4a,0x3c, // 9 sh 25
0x00,0x36,0x36,0x00,0x00, // : sh 26
0x00,0x35,0x36,0x00,0x00, // ; sh 27
0x08,0x14,0x22,0x41,0x00, // < sh 28
0x14,0x14,0x14,0x14,0x14, // = sh 29
0x00,0x41,0x22,0x14,0x08, // > sh 30
0x20,0x40,0x45,0x48,0x30, // ? sh 31
0x26,0x49,0x4f,0x41,0x3e, // @ sh 32
0x3f,0x44,0x44,0x44,0x3f, // A sh 33
0x7f,0x49,0x49,0x49,0x36, // B sh 34
0x3e,0x41,0x41,0x41,0x22, // C sh 35
0x7f,0x41,0x41,0x22,0x1c, // D sh 36
0x7f,0x49,0x49,0x49,0x41, // E sh 37
0x7f,0x48,0x48,0x48,0x40, // F sh 38
0x3e,0x41,0x49,0x49,0x2f, // G sh 39
0x7f,0x08,0x08,0x08,0x7f, // H sh 40
0x00,0x41,0x7f,0x41,0x00, // I sh 41
0x02,0x01,0x41,0x7e,0x40, // J sh 42
0x7f,0x08,0x14,0x22,0x41, // K sh 43
0x7f,0x01,0x01,0x01,0x01, // L sh 44
0x7f,0x20,0x18,0x20,0x7f, // M sh 45
0x7f,0x10,0x08,0x04,0x7f, // N sh 46
0x3e,0x41,0x41,0x41,0x3e, // O sh 47
0x7f,0x48,0x48,0x48,0x30, // P sh 48
0x3e,0x41,0x45,0x41,0x3e, // Q sh 49
0x7f,0x48,0x4c,0x4a,0x31, // R sh 50
0x31,0x49,0x49,0x49,0x46, // S sh 51
0x40,0x40,0x7f,0x40,0x40, // T sh 52
0x7f,0x01,0x01,0x01,0x7f, // U sh 53
0x7c,0x02,0x01,0x02,0x7c, // V sh 54
0x7f,0x01,0x0e,0x01,0x7f, // W sh 55
0x63,0x14,0x08,0x14,0x63, // X sh 56
0x70,0x08,0x70,0x08,0x70, // Y sh 57
0x43,0x45,0x49,0x51,0x61, // Z sh 58
0x00,0x7f,0x41,0x41,0x00, // [ ok 59
0x20,0x10,0x08,0x04,0x02, // \ ok 60
0x00,0x41,0x41,0x7f,0x00, // ] sh 61
0x10,0x20,0x40,0x20,0x10, // ` sh 62
0x01,0x01,0x01,0x01,0x01, // _ sh 63
0x00,0x40,0x20,0x10,0x00, // ` sh 64
0x02,0x15,0x15,0x15,0x0f, // a sh 65
0x7f,0x09,0x11,0x11,0x0e, // b sh 66
0x0e,0x11,0x11,0x11,0x02, // c sh 67
0x0e,0x11,0x11,0x09,0x7f, // d sh 68
0x0e,0x15,0x15,0x15,0x0c, // e sh 69
0x08,0x3f,0x48,0x40,0x20, // f sh 70
0x18,0x25,0x25,0x25,0x3e, // g sh 71
0x7f,0x08,0x10,0x10,0x0f, // h sh 72
0x00,0x11,0x5f,0x01,0x00, // i sh 73
0x02,0x01,0x11,0x5e,0x00, // j sh 74
0x7f,0x04,0x0a,0x11,0x00, // k sh 75
0x00,0x41,0x7f,0x01,0x00, // l sh 76
0x1f,0x10,0x0C,0x10,0x0f, // m sh 77
0x1f,0x08,0x10,0x10,0x0f, // n sh 78
0x0e,0x11,0x11,0x11,0x0e, // o sh 79
0x1f,0x14,0x14,0x14,0x08, // p sh 80
0x08,0x14,0x14,0x0c,0x1f, // q sh 81
0x1f,0x08,0x10,0x10,0x08, // r sh 82
0x09,0x15,0x15,0x15,0x02, // s sh 83
0x10,0x7f,0x11,0x01,0x02, // t sh 84
0x1e,0x01,0x01,0x02,0x1f, // u sh 85
0x1c,0x02,0x01,0x02,0x1c, // v sh 86
0x1e,0x01,0x06,0x01,0x1e, // w sh 87
0x11,0x0a,0x04,0x0a,0x11, // x sh 88
0x18,0x05,0x05,0x05,0x1e, // y sh 89
0x11,0x13,0x15,0x19,0x11, // z sh 90
0x00,0x08,0x36,0x41,0x00, // { sh 91
0x00,0x00,0x7f,0x00,0x00, // | sh 92
0x00,0x41,0x36,0x08,0x00, // } sh 93
0x20,0x40,0x20,0x10,0x20, // ~ sh index 94
//Kirilica Glavni
0x3f,0x44,0x44,0x44,0x3f,// A sh index 95
0x7f,0x49,0x49,0x49,0x06,// Á sh 96
0x7f,0x49,0x49,0x49,0x36,// Â sh 97
0x7f,0x40,0x40,0x40,0x40,// Ã sh 98
0x03,0x7f,0x42,0x42,0x7f,// Ä sh 99
0x7f,0x49,0x49,0x49,0x41,// E sh 100
0x63,0x14,0x7f,0x14,0x63,// Æ sh 101
0x42,0x41,0x51,0x69,0x46,// Ç sh 102
0x7f,0x04,0x08,0x10,0x7f,// È sh 103
0x7f,0x04,0x48,0x10,0x7f,// É sh 104
0x7f,0x08,0x14,0x22,0x41,// Ê sh 105
0x1f,0x20,0x40,0x20,0x1f,// Ë sh 106
0x7f,0x20,0x18,0x20,0x7f,// M sh 107
0x7f,0x08,0x08,0x08,0x7f,// H sh 108
0x3e,0x41,0x41,0x41,0x3e,// O sh 109
0x7f,0x40,0x40,0x40,0x7f,// Ï sh 110
0x7f,0x48,0x48,0x48,0x30,// Ð sh 111
0x3e,0x41,0x41,0x41,0x22,// Ñ sh 112
0x40,0x40,0x7f,0x40,0x40,// T sh 113
0x7f,0x09,0x09,0x09,0x7f,// Ó sh 114
0x1c,0x14,0x7f,0x14,0x1c,// Ô sh 115
0x63,0x14,0x08,0x14,0x63,// X sh 116
0x7f,0x02,0x02,0x7f,0x03,// Ö sh 117
0x78,0x08,0x08,0x08,0x7f,// × sh 118
0x7f,0x01,0x7f,0x01,0x7f,// Ø sh 119
0x7e,0x02,0x7e,0x02,0x7f,// Ù sh 120
0x40,0x7f,0x11,0x11,0x0e,// Ú sh 121
0x7f,0x11,0x11,0x0e,0x7f,// û sh 122
0x7f,0x11,0x11,0x11,0x0e,// Ü sh 123
0x22,0x41,0x49,0x49,0x3e,// Ý sh 124
0x7f,0x08,0x3e,0x41,0x3e,// Þ sh 125
0x39,0x46,0x44,0x44,0x7f,// ß sh 126

//Kirilica malki
0x02,0x15,0x15,0x15,0x0f,// a sh 127
0x66,0x59,0x49,0x49,0x46,// á sh 128
0x3e,0x49,0x49,0x39,0x06,// â sh 129
0x02,0x15,0x15,0x15,0x09,// ã sh 130
0x26,0x49,0x49,0x49,0x3e,// ä sh 131
0x0e,0x15,0x15,0x15,0x0c,// å sh 132
0x1b,0x04,0x1f,0x04,0x1b,// æ sh 133
0x11,0x15,0x15,0x15,0x0a,// ç sh 134
0x1e,0x01,0x01,0x02,0x1f,// è sh 135
0x1e,0x41,0x21,0x41,0x1f,// é sh 136
0x1f,0x04,0x0a,0x11,0x00,// ê sh 137
0x01,0x1e,0x10,0x10,0x1f,// ë sh 138
0x0f,0x10,0x0c,0x10,0x0f,// ì sh 139
0x1f,0x04,0x04,0x04,0x1f,// í sh 140
0x0e,0x11,0x11,0x11,0x0e,// î sh 141
0x1f,0x08,0x10,0x10,0x0f,// ï sh 142
0x1f,0x14,0x14,0x14,0x08,// ð sh 143
0x0e,0x11,0x11,0x11,0x02,// ñ sh 144
0x10,0x10,0x1f,0x10,0x10,// ò sh 145
0x18,0x05,0x05,0x05,0x1e,// ó sh 146
0x0c,0x12,0x7f,0x12,0x0c,// ô sh 147
0x11,0x0a,0x04,0x0a,0x11,// õ sh 148
0x1c,0x02,0x02,0x1c,0x03,// ö sh 149
0x1c,0x02,0x02,0x04,0x1f,// ÷ sh 150
0x1e,0x01,0x1f,0x01,0x1f,// ø sh 151
0x1c,0x02,0x1e,0x02,0x1f,// ù sh 152
0x10,0x1f,0x05,0x05,0x02,// ú sh 153
0x1f,0x05,0x05,0x02,0x1f,// û sh 154
0x1f,0x05,0x05,0x02,0x00,// ü sh 155
0x02,0x11,0x15,0x15,0x0e,// ý sh 156
0x1f,0x04,0x0e,0x11,0x0e,// þ sh 157
0x09,0x16,0x14,0x1f,0x00// ÿ sh index 158
};

#define CLOCK 0x35//zadavam clock kam hc595
#define SERIAL 0x05//zadavam vreme za podavane na serien signal kam hc595
#define PWM 0x05//tazi stoinost otgovarq na vremeto v koeto 6te sveti 1 led.
#define SPEED 0x0000a000//opredelq skorostta na dvigenie. Za iz4islqvane na velocity
#define STAND 0x00100000//opredelq vremeto na nepodvigno sastoqnie na nadpisa

#define ROWS_passed 0x30//tova e broqt na redovete, koito trbva da se sledi a da se obnovi ekrana s nepodvigno saob6tenie

//RAZMERI NA SAOB6TENIETO KOETO SAHRANQVAM V MCU
#define ROW 0x0a//saob6tenie ot 10 reda
#define COL 0x19//25 bukvi na red

//Upravlenie na 74hc595 i portovete
unsigned char clocks=0x00;//broi kolko clock-a sa pusnati kam clock vhodovete na hc595
unsigned char write=0x00;//sledi dvigenieto na impulsa podaden kam hc595, koito obhogda kolonite na ekrana
unsigned char next595=0x00;//pokazva koga nastapva prehoda megdu dva sasedni hc595
unsigned char light_on=0x00;//pokazva koga trqbva da pusnem funkciqta PORT_ctrl

//SAOB6TENIE
unsigned char message[ROW][COL];//tova e saob6tenieto sahraneno kato char stoinosti
unsigned char mess_y=0x00;
unsigned char mess_x=0x00;
unsigned char mess_ind_x=0x00;//pokazva poziciqta do koqto sme stignali pri zapisvaneto v message po horizontala
unsigned char mess_ind_y=0x00;//pokazva poziciqta do koqto sme stignali pri zapisvaneto v message po vretikala

long int repeat=0x00000000;//pokazva kolko pati 6te se izpi6e vseki ot ekranite display_1/2 predi da se prehvarlim kam drugiq
unsigned char mode=0x01;//tazi promenliva opredelq regima na rabota (dvigenie mode=0x00 nagore, mode=0x01 nadolu, mode=0x02 nalqvo i mode=0x00 nadqsno)

unsigned char disp=0x01;//kogato disp=1, zna4i display_1 e popalnen
//kogato disp=2, zna4i display_2 e popalnen
unsigned char display_1[0x06][0x7d];//tova sa dvata masiva koito sadargat obraza na ekrana
unsigned char display_2[0x06][0x7d];

unsigned char ctrl=0x00;//pokazva dali po serijniq port sledva da se podade komanda za upravlenie na displeq
unsigned char brightness=0x00;//pokazva kakva e qrkostta na izobragenieto

//promenlivi za kontrol na skorostta na dvigenie i za zadargane na obraza
//unsigned int velosity=SPEED;//pokazva kakva e skorostta na dvigenie na izobragenieto po ekrana
long int still=0x00;//pokazva kolko vreme nadpisat 6te stoi nepodvigen kogato se izpolzva regimat za zadargane na obraza
long int velosity=SPEED;
long int stat=STAND;
unsigned char to_go=0x00;//broi kolko reda sme preminali pri dvigenieto po vertikala predi za zadargim obraza

void init(void)
{
unsigned char i;
unsigned char j;

for(i=0x00;i {
for(j=0x00;j {
message[i][j]=0x00;
//message[i][j]=0x00;
}
}

//inicializiram display_1 i display_2
for(i=0x00;i<0x06;i++)
{
for(j=0x00;j<0x7d;j++)
{
//display_1[i][j]=0b01010101;
//display_2[i][j]=0b01010101;
display_1[i][j]=0x00;
display_2[i][j]=0x00;
}
}

//izhodni portove
DDRB=0xff;
PORTB=0x00;
DDRD=0xff;
PORTD=0b00100000;
DDRA=0xff;
PORTA=0x00;
//DDRC=0xff;
//PORTC=0x00;

//puskam taimer 0 na prescaler /8. Izpolzva se za 6IM na didoite.
TCCR0=0b00000010;
//nastroivam taimer 2 za funkciqta delay
TCCR2=0b00000010; //8
//Taimer 1 se nastroiva da dava clock kam 595ta i data send kam 595.
//Nastroivam TIMER1 v regim NORMAL
TCCR1A=0x00;
TCCR1B=0b00000010;//x8 prescaler
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x01;
OCR1AL=CLOCK;
//tozi registyr e ob6t za trite taimera
TIMSK=0b00010000;

//razre6avam zapis v EEPROM
EECR=0b00000011;

//RS232 setting
//1. nastroivame boad rate 9600 pri 16MHz
UBRRL=0x67;
//2.
UCSRA=0x00;
//3. nastroivame recieve, i interrupt pri receive, transmit disable i ne razre6avame prekasvane pri izprazvane na UDR
UCSRB=0b10010000;
//4. nastroivame 8bit duma, asinhronen regim, 1 stop bit,
UCSRC=0b10000110;

/* //TWI nastroiki
TWBR=0xf2;//4estotata na clock-a za predavbane na danni e CPU_frequency/(16+2*TWBR*4^0)=16*10^6/500=46666Hz
TWSR=0b00000000;//bez prescaler
TWAR=0b00000011;//adresa na MCU. LSB pokazva 4e e pozvolen regima na GENERAL CALL
TWCR=0b00000101;//tova e kontrolniq registar. Dvata setnati bita pokazvat 4e sme
//pozvolili rabotata na interfeisa i sme razre6ili prekasvaneto. Tova e master regim
//TWCR=0b01000101;//tova sa nastroikite za slave regim
*/

sei();
}

//tazi funkciq puska taimer2 za da zadava vremeto, v koeto seriiniqt signal e v 1
void delay(unsigned int time)
{
TCNT2=0x00;
while(TCNT2 {}
TCNT2=0x00;
}

//paramteri za funkciqta sa kolonite ot display_x masivite i led_on_x masivite
void PORT_ctrl(unsigned char b1, unsigned char a1, unsigned char cd1, unsigned char b2, unsigned char a2, unsigned char cd2)
{
unsigned char c=0x00;
unsigned char d=0x00;
unsigned char hold_SREG;

hold_SREG=SREG;//zapazvam status registara
cli();//zabranqvam prekasvaniqta

//c=cd1;
//d=cd1;

//c = cd1 & 0b11111100;
//c = cd1 | c;
//d = cd1 & 0b00000011;
//d = cd1 | d;

PORTB=b1;
PORTA=a1;
//PORTC=c;
//PORTD=d;

SREG=hold_SREG;
sei();
}

void leds_on(unsigned char content[0x06][0x7d])
{
PORT_ctrl(content[0x00][write],content[0x01][write],content[0x02][write],content[0x03][write],content[0x04][write],content[0x05][write]);
light_on=0x00;
if(write==0x40)
{
write=0x00;
}
}

ISR(TIMER1_COMPA_vect)
{
unsigned char hold_SREG;
unsigned char temp=0x00;

hold_SREG=SREG;//zapazvam status registara
cli();//zabranqvam prekasvaniqta

//1. Proverqvam sastoqnieto na PORTD 5
temp=PORTD;
temp=temp & 0b00100000;

if(temp==0x00)//ako do momenta e bil v nisko nivo podavam impuls i go slagam vav visoko nivo
{
clocks++;

if(clocks>=2 && clocks<=65)
{
write++;
//light_on=0x01;
}

if(clocks==66)
{
//vdigam bit na DATA SEND
PORTD = PORTD & 0b11101111;
PORTD = PORTD | 0b00010000;
//4akam
delay(SERIAL);
//vdigam bit na CLOCK
PORTD=PORTD & 0b11011111;
PORTD=PORTD | 0b00100000;
//4akam
delay(SERIAL);
//svalqm bit na DATA SEND
PORTD = PORTD & 0b11101111;
PORTD = PORTD | 0b00000000;

clocks=0x00;
}
else
{
//PORTA=0x00;
//PORTB=0x00;

PORTD=PORTD & 0b11011111;
PORTD=PORTD | 0b00100000;

PORTA=0x00;
PORTB=0x00;

if(disp==0x01)
{
leds_on(display_1);
}
else
{
leds_on(display_2);
}
}
}
else//ako do momenta sam bil vav visoko nivo, minavam v nisko
{
PORTD=PORTD & 0b11011111;
PORTD=PORTD | 0b00000000;
}

TCNT1H=0x00;
TCNT1L=0x00;

SREG=hold_SREG;
sei();
}

unsigned char shift(unsigned char in1, unsigned char in2, unsigned char direction)
{
unsigned char temp=0x00;
unsigned char temp1=0x00;
switch(direction)
{
case 0x00:
//2. poplvam display_1 - obhogdam po koloni, vzimam element i shift nagore
temp=in1;//premestvam sadarganieto na byta
temp=temp<<0x01;//s edna poziciq
temp1=in2;//vzimam sledva6tiq byte
temp1=temp1>>0x07;//shift na MSB na mqstoto na LSB
temp=temp & 0b11111110;//promenqm sadarganieto na LSB ot byta, koito premestvame
temp=temp | temp1;
break;
case 0x01:
//2. poplvam display_1 - obhogdam po koloni, vzimam element i shift nagore
temp=in1;//premestvam sadarganieto na byta
temp=temp>>0x01;//s edna poziciq
temp1=in2;//vzimam sledva6tiq byte
temp1=temp1<<0x07;//shift na LSB na mqstoto na MSB
temp=temp & 0b01111111;//promenqm sadarganieto na MSB ot byta, koito premestvame
temp=temp | temp1;
break;
}
return temp;
}

unsigned char row49(unsigned char addr, unsigned char mask, unsigned char in, unsigned char direction)
{
unsigned char temp,temp1;

switch(direction)
{
case 0x00:
temp=eeprom_read_byte((uint8_t*)addr);//tova e kolonata ot bukvata
temp=temp >> mask;//premestvam sadarganieto na temp bita koito 6te vliza na poziciq 0
temp=temp & 0b00000001;
temp=temp | 0b00000000;
temp1=in;
temp1=temp1 & 0b11111110;//6te promenqm samo bit 0 ot kolonata v display_2
temp1=temp1 | temp;//promenqm bita
break;
case 0x01:
temp=eeprom_read_byte((uint8_t*)addr);//tova e kolonata ot bukvata
temp=temp << mask;//premestvam sadarganieto na temp bita koito 6te vliza na poziciq 7
temp=temp & 0b10000000;
temp=temp | 0b00000000;
temp1=in;
temp1=temp1 & 0b01111111;//6te promenqm samo bit 0 ot kolonata v display_2
temp1=temp1 | temp;//promenqm bita
break;
}
return temp1;
}

//iztrivame saob6tenieto
void clear_mess(void)
{
unsigned char i,j;

for(i=0x00;i {
for(j=0x00;j {
message[i][j]=0x00;
}
}
mess_ind_x=0x00;
mess_ind_y=0x00;
}

//tazi funkciq opredelq dali po RS232 idva komanda ili bukva
void is_ctrl(unsigned char in)
{
if(ctrl!=0x00)
{
switch(ctrl)
{
case 0x06://skorost
velosity=in;
ctrl=0x00;
break;
case 0x07://qrkost
brightness=in;
ctrl=0x00;
break;
case 0x08://zadragane
stat=in;
ctrl=0x00;
break;
}
}
}

//funkciqta se izpolzva za popalvane na bukvite
void get_char(unsigned char in)
{
if(mess_ind_y {
if(mess_ind_x {
if(in>=0x20 || in<=0x7e)//ako podavam bukva na latinica
{
message[mess_ind_y][mess_ind_x]=in-0x20;
}
else//ako podavam bukva na kirilica
{
message[mess_ind_y][mess_ind_x]=in;
}
mess_ind_x++;
}
else//ako reda svar6i
{
mess_ind_y++;
if(in>=0x20 || in<=0x7e)//ako podavam bukva na latinica
{
message[mess_ind_y][0x00]=in-0x20;
}
else//ako podavam bukva na kirilica
{
message[mess_ind_y][0x00]=in;
}
mess_ind_x=0x01;
}
}
else
{
message[0x00][0x00]=in;
mess_ind_x=0x01;
mess_ind_y=0x00;
}
}

//funkciqta se izpolzva za zapisvane na novoto saob6tenie.
void load(unsigned char in)
{
switch(in)
{
case 0x1c://ako e izprateno 28, zna4i sme stignali do kraq na saob6tenieto, prekratqvame komunikaciqta
break;

default:
get_char(in);
break;
}
}

//prekasvaneto za seriniq interfeis
ISR(USART_RXC_vect)
{
unsigned char temp;
unsigned char stat_reg=0x00;

stat_reg=SREG;
cli();

temp=0x00;
temp=UDR;

is_ctrl(temp);//ako ctrl=0x00, ne pravim ni6to. Ina4e promenqm skorostta, qrkostta ili zadarganeto

switch(temp)
{
case 0x01://mode 0x01 - dvigenie nagore
mode=0x01;
break;

case 0x02://mode 0x02 - dvigenie nadolu
mode=0x02;
break;

case 0x03://mode 0x03 - dvigenie nalqvo
mode=0x03;
break;

case 0x04://mode 0x04 - dvigenie nadqsno
mode=0x04;
break;

case 0x05://mode 0x05 - stati4en regim
mode=0x05;
break;

case 0x1b://ako e izprateno 27, zna4i iskame da iztriem saob6tenieto
clear_mess();
ctrl=0x00;
break;

case 0x06://upravlenie na skorostta
ctrl=0x06;
break;

case 0x07://upravlenie na qrkostta
ctrl=0x07;
break;

case 0x08://upravlenie na zadarganeto na teksta v neopdvigno sastoqnie
ctrl=0x08;
break;

default://default se izpolzva kogato podavame bukvi
if(temp!=0x0a)//ako e podaden0 10, zna4i e inicializirana komunikaciqta
{
load(temp);//ako e podadeno ne6to razli4no ot 10, zna4i trbva da zapi6em bukvata
}
break;
}

//razre6avam 'transmit' i 'transmit interrupt', a zabranqvam 'receive' i 'receive interrupt'
UCSRB=0b01001000;
temp=0x21;
UDR=temp;
SREG=stat_reg;
sei();
}

ISR(USART_TXC_vect)
{
unsigned char stat_reg=0x00;

stat_reg=SREG;
cli();
//zabranqvam 'transmit' i 'transmit interrupt', a pozvolqvam 'receive' i 'receive interrupt'
UCSRB=0b10010000;
SREG=stat_reg;
sei();
}

void main(void)
{
unsigned char i;
unsigned char offset=0x00;//tova e promenlivata koqto obhogda elementa ot tablicata v EEPROM PO KOLONI
unsigned char mask=0x07;//tazi promenliva sledi bita koito 6te vliza kam ekrana
unsigned char buffer_ready=0x00;//kogato display_1 ili display_2 se popalnqt, setvame tazi promenliva
unsigned char column=0x00;//tazi promenliva se izpolzva pri popalvane na display_x, za opredelqne na kolonata varhu koqto rabotim

init();

while(1)
{
switch(mode)
{
case 0x01:
PORT_ctrl(0x01,0x01,0x01,0x01,0x01,0x01);
break;
case 0x02:
PORT_ctrl(0x02,0x02,0x02,0x02,0x02,0x02);
break;
case 0x03:
PORT_ctrl(0x04,0x04,0x04,0x04,0x04,0x04);
break;
case 0x04:
PORT_ctrl(0x08,0x08,0x08,0x08,0x08,0x08);
break;
}
}
}

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

i followed ur tutorial and wrote thos code...to switch on a led when i send a from hyperterminal and switch off the led when i send d from hyper terminal but no matter wat i send iam not able to control the led coz it keeps on blinking as given in the default program bfore any serial commands are sent

plzz check my code...iam running my cpu at 8mhz internal oscillator

#include  
#include  
#include 


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

volatile int f=0;

void portinitialize();
void uartinitialize();
void handleleft();
void handleright();
void bytedecision(volatile unsigned char);


void portinitialize()
 {
  DDRD|=(1<<4);
  TCCR1B|=(1<<CS12);
  }

void uartinitialize()
 {
   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 
 }
void handleleft()
 {
  int m=0;
  PORTD&=~(1<<4);
  
  for(m=0;m<=100;m++)
  _delay_ms(10);
 }

void handleright()
 {
  int m=0;
  PORTD|=(1<<4);

  for(m=0;m<=100;m++)
  _delay_ms(10);
  }

void bytedecision(volatile unsigned char a)
 { 
  if(a=='a' || a=='A')
   {
    handleleft();
    }
  if(a=='d' || a=='D')
   {
    handleright();
   }
 }

int main (void) 
{ 
   portinitialize();
   uartinitialize();
   
   for(;;) // Loop forever 
   { 
     if(f==0)
	   
	    
     {
  
    if(TCNT1>=31250)
	 
	 {
	  PORTD^=(1<<4);  // run test program blinking- echoing is handled by the ISR instead of in the main loop 
	  TCNT1=0;
	 }
	 }
 }
       
      
} 

ISR(USART_RXC_vect) 
{ 
   f=1;
   volatile unsigned char ReceivedByte; 
   ReceivedByte = UDR; // Fetch the recieved byte value into the variable "ByteReceived" 
   //UDR = ReceivedByte; // Echo back the received byte back to the computer 
   bytedecision(ReceivedByte);
} 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i followed ur tutorial and wrote thos code...to switch on a led when i send a from hyperterminal and switch off the led when i send d from hyper terminal but no matter wat i send iam not able to control the led coz it keeps on blinking as given in the default program bfore any serial commands are sent

plzz check my code...iam running my cpu at 8mhz internal oscillator

#include  
#include  
#include 


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

volatile int f=0;

void portinitialize();
void uartinitialize();
void handleleft();
void handleright();
void bytedecision(volatile unsigned char);


void portinitialize()
 {
  DDRD|=(1<<4);
  TCCR1B|=(1<<CS12);
  }

void uartinitialize()
 {
   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 
 }
void handleleft()
 {
  int m=0;
  PORTD&=~(1<<4);
  
  for(m=0;m<=100;m++)
  _delay_ms(10);
 }

void handleright()
 {
  int m=0;
  PORTD|=(1<<4);

  for(m=0;m<=100;m++)
  _delay_ms(10);
  }

void bytedecision(volatile unsigned char a)
 { 
  if(a=='a' || a=='A')
   {
    handleleft();
    }
  if(a=='d' || a=='D')
   {
    handleright();
   }
 }

int main (void) 
{ 
   portinitialize();
   uartinitialize();
   
   for(;;) // Loop forever 
   { 
     if(f==0)
	   
	    
     {
  
    if(TCNT1>=31250)
	 
	 {
	  PORTD^=(1<<4);  // run test program blinking- echoing is handled by the ISR instead of in the main loop 
	  TCNT1=0;
	 }
	 }
 }
       
      
} 

ISR(USART_RXC_vect) 
{ 
   f=1;
   volatile unsigned char ReceivedByte; 
   ReceivedByte = UDR; // Fetch the recieved byte value into the variable "ByteReceived" 
   //UDR = ReceivedByte; // Echo back the received byte back to the computer 
   bytedecision(ReceivedByte);
} 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,
I am using an atmega128. I have copied the program to avr but does anybody know how I can use 2 USART's at the same time. I want to connect a compas to UART0 and my pc on UART1. The meaning is that I can read the input on UART0(compas) via UART1(pc).
You can find my program in an attachement.

Attachment(s): 

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

nilswinkelmans,

You need to append the USART number to the end of the register names (before any suffixes):

UCSRB

Becomes:

UCSR0B

For the first USART for example, or:

UCSR1B

For the second. You also need to change the ISR vector name to include the USART you are referencing:

ISR(USART_RXC_vect)

Becomes:

ISR(USART0_RXC_vect)

For the first USART. You need to initialise and control each USART separately in the same way as the tutorial.

- Dean :twisted:

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

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

nice tutorial...
i liked the idead of having 2 buffers for line processing.. if you want to implement help/configure menu...

Pages