AVR128DB28 Usart Communication

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

Hey everyone,

I am trying to use the usart on an AVR128DB28.

I am seeing garbled data.

 

I suspect that the OSCCFG fuse is not programmed correctly (it is set to factory default, 0x02).

 

 

I am using a 14.7456 MHz crystal. There is no option for this. Anyone?

 

This topic has a solution.
Last Edited: Wed. May 25, 2022 - 11:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


You need to read this part of the data sheet.

 

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

yes i have read the datasheet, but maybe I am missing something. Here is  my code, hopefully someone can spot an error:


.def	temp	 	= r16
.def	temp1		= r17
;
.nolist
.include "AVR128DB28def.inc"
.list
;-----------------------------------------------------
.cseg
.org	0	  
Reset:
	rjmp	Start

Start:
	ldi	temp, HIGH(RAMEND)	;set up stack pointer
	out	CPU_SPH, temp
	ldi	temp, LOW(RAMEND)
	out	CPU_SPL, temp

 	ldi	temp,CPU_CCP_IOREG_gc		;IO Register Protection
	ldi	temp1,0b00000011		;External clock or external crystal
	sts	CPU_CCP,temp		;Disable I/O write protection
	sts	CLKCTRL_MCLKCTRLA,temp1

	ldi	temp1,0b00000000		;No prescale
	sts	CPU_CCP,temp		;Disable I/O write protection
	sts	CLKCTRL_MCLKCTRLB,temp1

	ldi	temp1,0b10000101		;Enable clock always, crystal
	sts	CPU_CCP,temp		;Disable I/O write protection
	sts	CLKCTRL_XOSCHFCTRLA,temp1

	ldi	temp, 1			
	sts	PORTC_OUTSET,temp	;PC0 (TX) = high
	sts	PORTC_DIRSET,temp	;PC0 = output
	ldi	temp, 2			;PC1 (RX) = input
	sts	PORTC_DIRCLR,temp

	call	USART_Init

USART_Loop:
	call	USART_RX		;get a byte into temp1
	call	USART_TX		;send it back out
	jmp	USART_Loop
;-----------------------------------------------------
USART_Init:
	ldi	temp, 0
	sts	USART1_CTRLA, temp

; set frame format async, 8, n, 1
	ldi	temp, (1<<USART_CHSIZE1_bp) | (1<<USART_CHSIZE0_bp)
	sts	USART1_CTRLC, temp

;set baud rate to 115200
	ldi temp, 0x00
    	sts USART1_BAUDL, temp
    	ldi temp, 0x02
    	sts USART1_BAUDH, temp

;enable TX and RX, normal speed mode
	ldi	temp, (1<<USART_TXEN_bp) | (1<<USART_RXEN_bp)
	sts	USART1_CTRLB, temp
	ret
;-----------------------------------------------------
;send a byte to the usart
USART_TX:
	lds	temp,USART1_STATUS
	sbrs	temp,USART_DREIF_bp	;wait for empty TX Buffer
	rjmp	USART_TX

	sts	USART1_TXDATAL, temp1	;send data byte
	ret
;-----------------------------------------------------
;receive a byte from the usart
USART_RX:
	lds	temp,USART1_STATUS
	sbrs	temp,USART_RXCIF_bp	;wait for data to be received
	rjmp	USART_RX

	lds	temp1,USART1_RXDATAL	;get and return received byte
	ret
;-----------------------------------------------------
.exit

 

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

I think you should set XOSCHFCTRLA before MCLKCTRLA. You should probably monitor the EXTS bit in MCLKSTATUS as well between setting those registers.

Last Edited: Sun. May 15, 2022 - 07:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

By the way, unless you need to go thousands away, use rcall (it will give err if you try overreach)

 

use

  ldi  temp, low(1234)  ;low byte

  ldi  temp1, high(1234)   ;let low & high do the work for you

  sts  blah 

 

sbrs	temp,USART_RXCIF_bp

Does this flag need cleared by you, or does it cleared when reading the char?  Something needs to clear it to get ready for next time.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sun. May 15, 2022 - 08:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

 

sbrs temp,USART_RXCIF_bp

Does this flag need cleared by you, or does it cleared when reading the char?  Something needs to clear it to get ready for next time.

this is the only confusing info I could find (looks like a typo in the datasheet?)

The buffer shifts out the data either when RXDATAL or RXDATAL ?? is read, depending on the configuration. The
register which does not lead to data being shifted should be read first to be able to read both bytes before shifting.

 

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

balisong42 wrote:

I think you should set XOSCHFCTRLA before MCLKCTRLA. You should probably monitor the EXTS bit in MCLKSTATUS as well between setting those registers.

 

Actually I was going to try that as I did not follow the Initialization EXACTLY (as in post #2 above)

There is not much information out there, especially for someone who programs in assembly!

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

I found this--you are good

 

Bit 7 – RXCIF USART Receive Complete Interrupt Flag This flag is set when there are unread data in the receive buffer and cleared when the receive buffer is empty

 

Also (for spi, but prob same for usart):

Bit 7 – RXCIF Receive Complete Interrupt Flag This flag is set when there are unread data in the Receive Data Buffer register and cleared when the Receive Data Buffer register is empty (that is, it does not contain any unread data). When interrupt-driven data reception is used, the Receive Complete Interrupt routine must read the received data from the DATA register in order to clear RXCIF. If not, a new interrupt will occur directly after the return from the current interrupt. This flag can also be cleared by writing a ‘1’ to its bit location.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

I think I have figured out how to use the usart in the avr128Dx device.

Where I am confused is how to implement the baud rate formula in assembly.

 

I want to use this formula from the c sample source code in assembly:

#define F_CPU                           (4000000UL)         /* using default clock 4MHz*/
#define USART1_BAUD_RATE(BAUD_RATE)     ((float)(64 * 4000000 / (16 * (float)BAUD_RATE)) + 0.5)

Later the c csource sets the baud rate:

 USART1.BAUD = (uint16_t)(USART1_BAUD_RATE(9600));   /* set the baud rate*/

 

How can I translate this so it assembles without errors?

Any help is greatly appreciated.

Last Edited: Tue. May 24, 2022 - 12:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

newbie123 wrote:
How can I translate this so it assembles without errors?
Which assembler? Certainly if it is avr-as then you can simply use those very same macros you just showed. Just make sure the asm  source file is a .S not .s file and it will be preprocessed by the C preprocessor. I think the situation is the same for Atmel ASm2 - it can do #define's and so on but I believe its implementation is "cut down" compared to a full C preprocessor but it's probably enough to expand those macros.

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


OK so I got this to work using avr-as:

 

 

That is:

/*
 * main.S
 *
 * Created: 24/05/2022 13:17:47
 *  Author: me
 */ 
 #define __SFR_OFFSET 0
 #include <avr/io.h>

#define F_CPU                           (4000000)         /* using default clock 4MHz*/
#define USART1_BAUD_RATE(BAUD_RATE)     ((F_CPU / (16 * BAUD_RATE)) + 1)

    .global main
main:
    ldi r16, lo8(USART1_BAUD_RATE(9600))
    out UBRRL, r16
    ldi r16, hi8(USART1_BAUD_RATE(9600))
    out UBRRH, r16
here:
    rjmp here

The pre-processed code looks like:

 

and the generated code is:

 

 

Only thing is that 0x1B is not the right value for 9600@4MHz so I think there may be an integer overflow going on somewhere - could need more work. The assembler is not going to understand concepts like "UL" and "(float)"!

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

First off.   God gave you the INC file.   I suggest that you use the official macros.   e.g.

 

    ldi    temp, USART_NORMAL_CHSIZE_8BIT_gc //(1<<USART_CHSIZE1_bp) | (1<<USART_CHSIZE0_bp)

 

I suggest that you start with the Internal HF clock.   Then you don't need to worry about XTAL connections.

 

Yes,  your BAUD value is correct for your particular XTAL.  

But there is no advantage in using a baud-friendly xtal when the 128DB chip has a fractional divider.

Personally,  I would always calculate the value for BAUD from the F_CPU and baudrate values.

 

I also suggest that you print a known "sign-on" message.    Just using "loopback" is not a good idea.

 

Otherwise,  it looks ok to me.   I would have to add the appropriate HF clock, BAUD calculation,  sign-on message to test it on real hardware.  (Curiosity-128DB48)

 

David.

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

david.prentice wrote:
Personally,  I would always calculate the value for BAUD from the F_CPU and baudrate values.
I'd add the eye-candy later - just hard code the 103 or whatever the d/s functions/tables suggest the value might be and get something working first. Add the stuff to include varying F_CPU and BAUD later when you have proven the basics.

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

This is part of my AVR 0 and 1 series USART lib for the Atmel assembler.

 

;USART0_INIT - Initialize USART0
USART0_INIT:
	lds	temp, PORTA_DIR
	ori	temp, PIN0_bm	; Set TXD pin for output
	andi	temp, ~ PIN1_bm		; Set RXD pin for input
	sts	PORTA_DIR, temp

	ldi	temp,low ((64*fosc)/(16*baud_0)-1)
	ldi	temp1,high ((64*fosc)/(16*baud_0)-1)

SETBAUD_0:
	sts	USART0_BAUD,temp	;baud register low
	sts	USART0_BAUD + 1, temp1	;baud register high
	ldi	temp, USART_RXEN_bm | USART_TXEN_bm
	sts	USART0_CTRLB, temp	;enable bits
	ret  

 

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

You don't need the -1 in your USART0_BAUD calculations.   (At least not from the datasheet equations)

 

The -1 is not going to be significant anyway.  It is only 1/16 due to the "fractional divisor"

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

I was going to make a sample project but looking into my box of goodies from Atmel/Microchip I don't have any AVR128xxxx sample boards around so I would not be able to run it even when I get it to assemble without errors.

 

...and I'm not just saying that just in case someone from Microchip sees the post and decides sends me one so I can help people with newer chips....... winkcheeky

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:

I was going to make a sample project but looking into my box of goodies from Atmel/Microchip I don't have any AVR128xxxx sample boards around so I would not be able to run it even when I get it to assemble without errors.

 

...and I'm not just saying that just in case someone from Microchip sees the post and decides sends me one so I can help people with newer chips....... winkcheeky

 

I have a couple curiosity kits here I could run the code on…..

 

you just reminded me of something on a semi related topic, thanks John 

 

jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Off to piano lessons shortly, maybe tomorrow. smiley

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

clawson wrote:

 

Which assembler? Certainly if it is avr-as then you can simply use those very same macros you just showed. Just make sure the asm  source file is a .S not .s file and it will be preprocessed by the C preprocessor. I think the situation is the same for Atmel ASm2 - it can do #define's and so on but I believe its implementation is "cut down" compared to a full C preprocessor but it's probably enough to expand those macros.

Thanks to everyone for responding. When I attempt to assemble this code with avrasm2 (from Atmel Studio 7 with the latest updates)

#define F_CPU                           (4000000)         /* using default clock 4MHz*/
#define USART2_BAUD_RATE(BAUD_RATE)     ((F_CPU / (16 * BAUD_RATE)) + 1)

USART_Init:
	ldi	temp, 0
	sts	USART2_CTRLA, temp

; set frame format async, 8, n, 1
	ldi	temp, (1<<USART_CHSIZE1_bp) | (1<<USART_CHSIZE0_bp)
	sts	USART2_CTRLC, temp

	ldi	temp, lo8(USART2_BAUD_RATE(9600))
	sts	USART2_BAUDL, temp
	ldi	temp, hi8(USART2_BAUD_RATE(9600))
	sts	USART2_BAUDH, temp

	ldi	temp, (1<<USART_TXEN_bp) | (1<<USART_RXEN_bp) 	;enable TX and RX, normal speed mode
	sts	USART2_CTRLB, temp
	ret

 

I am seeing this error message:

AVRASM: AVR macro assembler 2.2.8 (build 80 Jan 14 2020
Copyright (C) 1995-2020 ATMEL Corporation

usart2.asm(15): Including file 'AVR128DB28def.inc'
usart2.asm(93): error: syntax error, unexpected '('

Assembly failed, 1 errors, 0 warnings
Press any key to continue . . .

 

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

js wrote:

	ldi	temp,low ((64*fosc)/(16*baud_0)-1)
	ldi	temp1,high ((64*fosc)/(16*baud_0)-1)

SETBAUD_0:
	sts	USART0_BAUD,temp	;baud register low
	sts	USART0_BAUD + 1, temp1	;baud register high
	ldi	temp, USART_RXEN_bm | USART_TXEN_bm
	sts	USART0_CTRLB, temp	;enable bits
	ret  

Thanks JS! I used your formula in my code and it works!

.equ	fosc = 14745600
.equ	baud = 115200

USART_Init:
	ldi	temp, 0
	sts	USART2_CTRLA, temp

; set frame format async, 8, n, 1
	ldi	temp, (1<<USART_CHSIZE1_bp) | (1<<USART_CHSIZE0_bp)
	sts	USART2_CTRLC, temp

	ldi	temp,low ((64*fosc)/(16*baud)-1)
	ldi	temp1,high ((64*fosc)/(16*baud)-1)

SETBAUD_0:
	sts	USART2_BAUD,temp	;baud register low
	sts	USART2_BAUD + 1, temp1	;baud register high

	ldi	temp, (1<<USART_TXEN_bp) | (1<<USART_RXEN_bp) 	;enable TX and RX, normal speed mode
	sts	USART2_CTRLB, temp
	ret

however, I am confused. I thought that formula was only for atmegas not avrdx???

 

david.prentice wrote:

You don't need the -1 in your USART0_BAUD calculations.   (At least not from the datasheet equations)

 

The -1 is not going to be significant anyway.  It is only 1/16 due to the "fractional divisor"

 

when I change the "-1" to  "+ 0.5" I see the following warnings:

usart2.asm(82): warning: float->int cast, truncated
usart2.asm(83): warning: float->int cast, truncated

 

Last Edited: Wed. May 25, 2022 - 01:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I thought that formula was only for atmegas not avrdx???

That code is for the AVR 0 and 1 series, as I don't have one of those new chips I haven't messed around with any code. That and the fact that I'm 90% retired and trying to learn to play piano. wink

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:

I thought that formula was only for atmegas not avrdx???

That and the fact that I'm 90% retired and trying to learn to play piano. wink

 

Me too, I am trying to learn to play the guitar but I don't see it happening at my age!

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


Using formula

((64*fosc)/(16*baud)-1)

gets 511.   i.e. BAUDH=1 and BAUDL=255.

 

 

And if we put 511 back into the datasheet formula we get

(64 * 14745600) / (16 * 511) = 115425.4 baud i.e. +0.02% error

 

compared to using 512

(64 * 14745600) / (16 * 512) = 115200 baud i.e.  0% error

 

Do you get my point?   The -1 makes little practical difference to your comms.

 

Likewise you could use a round number clock like 1MHz and get

BAUD = (64 * 1000000) / (16 * 115200) = 34.7

 

using BAUD=34   (64 * 1000000) / (16 * 34) gives 117647 baud i.e. +2.1% error

using BAUD=35   (64 * 1000000) / (16 * 35) gives 114285 baud i.e. -0.08% error

 

Obviously you would round up 34.7 to 35 but even with 34 you would get satisfactory comms.   (on a hard-wired connection)

 

David.

Last Edited: Wed. May 25, 2022 - 06:55 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Thanks for your response David.

I do have a better understanding of the formula now.

 

Everything is working now.

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

I am trying to learn to play the guitar but I don't see it happening at my age!

I'm 70+ and not giving up. wink

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly