Atmega128 Usart. Problem with receive

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi everyone,

I'm facing trouble in a project of mine.
I'm having trouble in USART communication(9600-8-1-N).
The communication is between 2 atmega128 (one on stk501 and the other in a grifo (+mini) board).
I think the problem is in the atmega128 whixh is placed in the Stk.It gets stuck hear:

rcall usart_transmit

	ldi ta,0x0f
	out PORTC,ta

	rcall usart_receive
	ldi ta,0xff

the initializations and routines are the one's shown below.

usart_receive:
  ; Wait for data to be received
  sbis UCSR0A, RXC0
  rjmp usart_receive
  ; Get and return received data from buffer
  in r16, UDRE0
  ret

usart_transmit:
  ; Wait for empty transmit buffer
  sbis UCSR0A,UDRE0
  rjmp usart_transmit
  ; Put data (r16) into buffer, sends the data
       
  out UDRE0,r16
  ret
;;; Setup USART configuration
;;; BAUD 9600,8-bit data frame,1 stop bits,no parity,synchronous mode
usart_init:
     clr r16
     sts UBRR0H,r16
     ldi r16,6
     out UBRR0L,r16
     ldi r16,(1<<RXEN0)|(1<<TXEN0)
     out UCSR0B,r16
	 ldi temp,(3<<UCSZ00)|(1<<UMSEL0)
	 sts UCSR0C,r16

I can't trace any mistake, or bag. The most frustrating of all is that everything works well when both are programmed in C, but that's out of the question due to constraints of our proffesor(it's about univercity).
Thanx in advance for every response :D[/code]

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

Surely your USART0 data register is called UDR0 and not UDRE0.

You should be able to hand translate the C quite easily.

Personally, I would have a full and frank discussion with your professor. The method is important, not the trivial translation.

David.

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

Quote:
Personally, I would have a full and frank discussion with your professor. The method is important, not the trivial translation.

Couldn't agree more..using C can solve a lot of issues and basically save same time(just my point of view).
But our proffesor is not very open in that one.
I'll see that one with UDREO. Probaply this is a mistake.
But fixing it made no difference..
Thanx,

John

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

Did you fix both of them?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

yea i've fixed them,(UDR0 instead of UDRE0) I transmits fine..but it gets stuck into the receive loop.

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

I can do several of trasmits,with a small delay added between them, but when it comes to transmiting I can't get pass the loop. Since it worked in C I've figured I could "disassembly" the C-transmit code and find my way but that also failed.:S
John

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

Write it in C then run the disassembler.

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

You have initialised the stack pointer before calling
the receive routine haven't you :oops: !?
To demonstrate assembler we teach the following code, but then we wean students from assembler to C asap.

.def	temp	=R16

        .org  	$0 
reset:
	; initialise the stack
        ldi temp,low(RAMEND)
	out spl,temp
	ldi temp,high(RAMEND)
	out sph,temp
        
        ;set your baud rate here or 
        ;use default bootloader settings

main:
        ;echo   serial port for ever
        rcall	Serial_RX	;receive character
	rcall  	Serial_TX	;transmit character
	rjmp	main            ;repeat		
		
Serial_TX:
        ;Wait for Uart TX Empty flag to be set
	sbis 	UCSR0A, UDRE0
	rjmp Serial_TX
	;When flag is set send data to UART
	out UDR0,R16
	ret
Serial_RX:
        ;Wait for Uart RX Complete flag
	sbis UCSR0A,RXC0
	rjmp Serial_RX
	;When flag is set read data from UART
	in R16,UDR0
	ret

When coding in C, you do not have to worry about managing the stack.

Lee

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

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

oh,!thanx for the responses!I;ll be back with responses in a while. Yes, i've initialized the SP..!

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

Here is the final code that...didn't work.
I made some modifications in order to imply a protocol with this settings "9600-8-1-N"(clock 1MHZ). I'm busting my head..Because I transmit correctly but in receive program gets stuck.

.include "m128def.inc"
.def   temp   =R16

        .org     $0
reset:
   ; initialise the stack
        ldi temp,low(RAMEND)
   out spl,temp
   ldi temp,high(RAMEND)
   out sph,temp
       
     ldi r16,0x46
     sts UBRR0H,r16
     clr r16
     out UBRR0L,r16
	 ldi r16,(1<<RXEN0)|(1<<TXEN0)
     out UCSR0B,r16
	 ldi temp,(3<<UCSZ00)|(1<<UMSEL0)
	 sts UCSR0C,r16
	
	ldi temp,0x06
	out DDRE,temp

	ser temp
	out DDRC,temp
	out DDRA,temp
	clr r17

main:
		inc r17
		out PORTA,r17
        ;echo   serial port for ever
		ldi r16,0b00100001
        rcall   Serial_RX   ;receive character
	 //  rcall     Serial_TX   ;transmit character
		out PORTC,R16
   rjmp   main            ;repeat      
      
Serial_TX:
        ;Wait for Uart TX Empty flag to be set
   sbis    UCSR0A, UDRE0
   rjmp Serial_TX
   ;When flag is set send data to UART
   out UDR0,R16
   ret
Serial_RX:
        ;Wait for Uart RX Complete flag
   sbis UCSR0A,RXC0
   rjmp Serial_RX
   ;When flag is set read data from UART
   in R16,UDR0
   ret 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Before I posted the code, I re-assembled it and loaded it into an ATMega128 tarhet & it works flawlessly, so it must be your initialization code
at fault.

I can see three errors in the initialization code.

1. You have the UBBR0L & UBBR0H registers transposed
2. You must write to UBBR0H with "sts" instruction
3. You selected Synchronous transmission instead of
Asynchronous transmission.(A huge incompatability)

It got stuck in receive, because it is waiting for synchronous frame. I doubt whether you actually ever saw your transmitted data (with say Hyperterminal) either.

Try this for the UART initialization

                ldi r16,low(51) 
     		sts UBRR0L,r16 
     		ldi r16,high(51) ; general case
     		sts UBRR0H,r16 
    		ldi r16,(1<<RXEN0)|(1<<TXEN0) 
     		out UCSR0B,r16 
    		ldi temp,(3<<UCSZ00) 
    		sts UCSR0C,r16
                ...

All the code is direct from ATMEL ATMega128 data sheet.

By the way, what University are you at?

Lee

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

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

Me and ichionid are at the Aristotle University of Thessaloniki in Greece. We're working on the same project.

About your 3rd remark, we tried the synchronous mode because the asychronous mode could communicate but errors appeared very very often in the trasmitted data. The thing is that the module where the second atmega128 is mounted and welded onto has a built-in oscillator running at 7.3728 MHz while in the STK501+atmega128 we only have the internal oscillator running at 1Mhz. Apparently configuring for the same baud rate in both atmega128 produced synchronization errors and that's why we had faulty bytes being received most of the times.
Then we tried synchronous mode and transmitting (from STK501 to the other module) is smooth as hell with not even one faulty byte. But the other way around (module to STK501) they both get stuck. We assumed that the "master" device (STK501) keeps giving clock pulses all the time, not only when transmitting. Is that wrong?

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

I also believe that the fault is propably in the initialization code..but how comes it transmits perfectly?
So it is Aristoteleio University we are studying to.I'll be back with news from the lab,where I'll test it,in a few hours from now.
Thanx again!

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

Hi Ichionid & EntropicBehaviour,
My estimation looking at your code was that f_osc=8 Mhz. My controller runs at 16Mhz. so you need to allow for that. See table 82-85 in the AVR data sheet
for the correct UBBR value.
Good luck with your studies!
Lee

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

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

We finally solved the issue.

There was a lack of synchronization in the communication. I don't understand why, but the problem disappeared when we added a delay of a few hundreds of milliseconds...quite unorthological but it made it work

Thanx all for the responses,

John

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

Hi Guys,

It seems to me that you have not really solved the real issue.

Quote:
but the problem disappeared when we added a delay of a few hundreds of milliseconds.

You still have a problem of one sort or another,
which as an educational exercise you should get to the bottom of. If you do not, you will never get beyond you current knowledge.

Your code currently only has a throughput of some 2000
baud if you are adding delay between sending characters. The UARTS should be capabble of error proof data throughput in excess of 100,000 baud.
It is a big mistake to rely upon "patches" to make your code work and leads to "buggy" code.
You may well have a hardware problem and you should not attempt to fix hardware problems with software.
Post your final code, along with
- the patch to make it work
- details on how you are actually testing
- the xtal frequencies being used.
Also have you tried it on different hardware?
Have you tested the xtal for correct frequency with a freq counter?
Are you using internal resonators?

As men of science, you need to get to the bottom of this problem! Would Aristotle, the namesake of your University have given up so easy? The answer is out there, it just needs to be found!

Lee

Good, better, best,
Never let it rest,
Until the good is better,
and the better best!

Australian poem

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

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

Hey lee!

I to agree that a "patch" isn't the best solution.
But, through testing the USART everything seemed to wark really well.
Details:
Hardware-A)Atmega128(Stk500+501),
B)2 Modules of Grifo(GMB-HR168 &&GMM AM128)
Which provides you with Inputs/Outputs and several other pins of AtMega128.
"A)" was running at 1Mhz Internal and "B" is "locked" at 7.389 Mhz.

Software that has to do with initializtion and simple Usart tasks doesn't face any problems(tested).

The reason we added a delay is that microcontroller "B" receives 1 byte from "A" and then returns an answer or not according to what was sent.
Basically "A" asks from "B" either to set one of it's outputs to 1 or to return the value of one of it's inputs(1/0). "B" needs some time to decompose the message he received.
When B is at the procedure of decomposing the RX and A sends another byte B goes to "self-destructing!" mode...it does nothing form the things we asked him to ... nothing but a kind of reset, that shouldn't be done.

So we kind of changed the procedure a bit.By adding a delay of 250 ms and also returning a Byte indicating ACK or NACK from B to A.
If I haven't explained things in a good way..maybe the following will help :P

(A sends I.a)write outpout to 0/1 I.b) Return ACK/NACK(B->A ,1 Byte)
II.a)read input x(0..15) II.b) Return Input's Value(B->A ,1 Byte)
)
John