Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Some info on AVRs

Status
Not open for further replies.

Mike - K8LH

Well-Known Member
Gentlemen,

Can you tell me about AVR microcontrollers? Are they any good? Features? Packages? Samples? Programmers? Software examples / user groups / forums?

TIA. Regards, Mike
 
The most outstanding feature of the AVR is that it is a code hog.
 
Papabravo said:
The most outstanding feature of the AVR is that it is a code hog.
Thanks for the reply.

There are a couple Ham Radio Ops out there that seem to like them and that's why I asked.

I'm familiar with Motorola 68HC11 and 'HC12 series and the Microchip PIC series and was wondering if I should broaden my horizons?

Regards, Mike
 
Broaden your horizon? Certainly. In fact look into the AVR and confirm or refute my position. I've never actually finished an AVR design, but I've started a few and tried to port an existing application. When the code size blew through the 2K limit for the compilers available to me at the time I decided to go another way.

As I've stated on several occasions, you may decide that you like some feature of the design like a peripheral, and are willing to compromize somewhere else.
 
Last edited:
Mike said:
Can you tell me about AVR microcontrollers? Are they any good? Features?

With the mention of code hog, I just want to give my findings.

I ventured into AVR land because I want to generate sinewave of 1Hz-200KHz.

One can do that by increasing a 24-bit counter with a fix value and use the highest 8-bit as index to look up a sine table of 256 values. The value is the output to the port with a D/A converter.

The lookup table is in Flash program memory and it takes a total of 6 AVR instructions to do all that with a loop time of just 9 clock cycles. This is just a tiny bit more than the time where the PIC can execute a single GOTO instruction.

Code:
LOOP1:
		add	r28,r24		; 1
		adc	r29,r25		; 1 (with carry)
		adc	r30,r26		; 1 (with carry)
		lpm			; 3
		out	PORTB,r0	; 1
		rjmp	LOOP1		; 2 => 9 cycles

You can try to do the same routine with PIC and count the instructions required and the total number of clock cycles for a loop. Faster loop gives higher frequencies.

No comment on other features of AVR as I am just started.
 
I see you writing r0 to PORTB, but how does r0 ever get a value? Never mind the lpm does it.
Also what frequency is the crystal you are working with? It is elapsed time not clock cycles that is important.
 
Last edited:
The "lpm" instruction defaults to placing the value into register r0. The destination register of "lpm" can be changed if required.

20MHz on a Tiny2313. If hard pressed for higher frequency, it is possible to do the same routine in only 8 cycles by moving the whole lookup table into the SRAM space of the Mega88 AVR instead.

Edited: Credits for the above code belongs to Jesper, his site, **broken link removed**
 
Last edited:
Papabravo said:
It is elapsed time not clock cycles that is important.

Yes, but more clock cycles means longer elapsed time and this limits how high the output frequency can go.
 
eblc1388 said:
With the mention of code hog, I just want to give my findings.

I ventured into AVR land because I want to generate sinewave of 1Hz-200KHz.

One can do that by increasing a 24-bit counter with a fix value and use the highest 8-bit as index to look up a sine table of 256 values. The value is the output to the port with a D/A converter.

The lookup table is in Flash program memory and it takes a total of 6 AVR instructions to do all that with a loop time of just 9 clock cycles. This is just a tiny bit more than the time where the PIC can execute a single GOTO instruction.

Code:
LOOP1:
        add    r28,r24        ; 1
        adc    r29,r25        ; 1 (with carry)
        adc    r30,r26        ; 1 (with carry)
        lpm            ; 3
        out    PORTB,r0    ; 1
        rjmp    LOOP1        ; 2 => 9 cycles
You can try to do the same routine with PIC and count the instructions required and the total number of clock cycles for a loop. Faster loop gives higher frequencies.

No comment on other features of AVR as I am just started.

I love a challenge (grin), but, I'm afraid I'm not familiar with those instructions.

May I impose and ask you to describe the process in just a bit more detail please? I'd love to compare it to PIC code.

Kind regards, Mike
 
Mike said:
May I impose and ask you to describe the process in just a bit more detail please? I'd love to compare it to PIC code.

The rxx in the code above refers to a 8-bit register/file and there are 32 of them in AVR. The numbers in the comment field marks the number of crystal clocks required to carry out the instructions.

Basically one is doing a 24-bit addition with carry to r28/r29/r30, the constant to be added is stored in r24/r25/26. A higher value results in higher frequency output.

"add" is the addition instruction and "adc" is "add with carry" instruction which performs between these 32 registers.

r30,r31 form the index for the base address of the lookup table anywhere inside the flash memory. r31 does not change in the routine but is only preloaded with a certain memory page address and so can point to the starting address of different waveshape lookup tables.

With the index calculated, the value of the lookup table is retrieved via the "lpm" instruction which moves the table data into register r0. This is outputed to port B and the loop repeats. I've also attached the comment I put inside the ASM file I'm using.

Code:
;====================================================================
; main loop
;
;       r31,r30 use as pointer to Flash table. r31 value don't change 
;       inside loop1. Carry from r30 is ignored
;
;	r28,r29,r30 is the phase accumulator
;  	r24,r25,r26 is the adder value determining output frequency
;
;       larger value in r24,r25 & r26 cause r30 to change at a faster
;       rate thus results in higher frequency output
;
; 	add value to phase accumulator
;
;         R31   R30  R29  R28
;       +       R26  R25  R24 
;    ---------------------------------   
;        (R31   R30) used as index to lookup table
;
;	load byte from current table in Memory Flash ROM using LPM
;       instruction
;
;	output byte to port
;	repeat 
;=====================================================================
 
Thanks. From your description it seems that's very tight and efficient code compared to PIC16/PIC18. I'm not sure where the result of the ADD or ADC goes but I'll attempt to download something with a description of the processor and instruction set.

Is Tosc = Tcyc on this microcontroller?

Regards, Mike
 
Mike said:
Thanks. From your description it seems that's very tight and efficient code compared to PIC16/PIC18. I'm not sure where the result of the ADD or ADC goes but I'll attempt to download something with a description of the processor and instruction set.

Is Tosc = Tcyc on this microcontroller?

Regards, Mike

The addition result is left inside the first register of the instruction. e.g. add r28,r24 the result is in r28 along with carry flag set if there is a carry.

Most AVR instructions take one CPU clock while some take two or three clocks. For some AVRs there is also a clock-prescalar register inside with where the CPU clock can be set to a factor(1/1 ~ 1/256) of the ext crystal osc frequency, even in real time via the user program, like shifting gears on a car.
 
<added> I apologize as I realize I/we have hijacked the thread and will move <added>

Thanks for the additional info'.

So if you're using a 20-MHz clock with Tosc of 50-nsecs and Tosc is the same as Tcyc, then you should be able to generate sine, saw, triangle, or square waves with full 256 step resolution up to a frequency of 8680-Hz, is that correct?

Do you generate signals above 8680-Hz at lower resolution? If so, does the output waveshape suffer?

I'm impressed. It seems the Amtel code has a significant speed advantage over the PIC in this application. A comparable 10-instruction PIC18 code loop (below) uses a whopping 1.2-usecs when using a 40-MHz clock compared to your 450-nsec code loop using a 20-MHz clock. So the PIC18 can only generate full 256 step waveshapes up to a frequency of 3255-Hz. Hopefully my math is correct (grin).

Thanks again for the great info'. Kind regards, Mike

Code:
;
;  setup for Sine table (or Sawtooth, Triangle, or Square table)
;
        movlw   low SINTBL      ;
        movwf   TBLPTRL         ; setup TBLPTRL
        movlw   high SINTBL     ;
        movwf   TBLPTRH         ; setup TBLPTRH
        clrf    TBLPTRU         ; clear TBLPTRU (assume PIC with < 64k)
        clrf    ACCUML          ; clear accumulator L
        clrf    ACCUMH          ; clear accumulator H
        movlw   low KHZ1        ; use 1-KHz adder value
        movwf   ADDERL          ;
        movlw   high KHZ1       ;
        movwf   ADDERH          ;
        movlw   upper KHZ1      ;
        movwf   ADDERU          ;
;
;  Tcyc = 100-nsecs with 40-MHz Fosc
;
LOOP1
        movf    ADDERL,W        ; adder L  (1) (100-nsecs)
        addwf   ACCUML,f        ; accum L  (1)
        movf    ADDERH,W        ; adder H  (1)
        addwfc  ACCUMH,f        ; accum H  (1)
        movf    ADDERU,W        ; adder U  (1)
        addwfc  TBLPTRL,f       ; accum U  (1)
        tblrd   *               ;          (2)
        movf    TABLAT,W        ;          (1)
        movwf   PORTB           ;          (1)
        bra     LOOP1           ;          (2) (1.2-usec loop)
;
;  256 byte sine table
;
SINTBL
 
Last edited:
Mike said:
TDo you generate signals above 8680-Hz at lower resolution? If so, does the output waveshape suffer?

Your timing calculation is correct. In general, a 10-point waveform is still good enough for practical use and that means a x25 factor to the highest frequency with 256-steps.
 
Very cool...

So, in reference to PapaBravo's comment on code size, is there a code size disadvantage of some sort on the Amtel processors, or with certain Amtel processors? Or, was that comment perhaps based on applications written in a higher level language instead of Assembler?

I apologize for all the questions. I intend to download some Amtel documents soon, I promise (grin).

Mike
 
You're right. If you read his post again you willl notice he use the word "compiler" instead of assembler. In fact, he meant a "C compiler with a 2K code limit available to him" and not referring to the free GCC C compliler or the actual AVR hardware.

AVR comes in different flash memory sizes just like the PICs.

Here is some more information that I have gathered:


AVR Parametric Product Table

AVR 8-Bit RISC - Datasheets

AVR Programming Methods

AVR Freaks Forum Index

**broken link removed**

Edited: Links added
 
Last edited by a moderator:
Mike,

The code I was refering to was written in C and compiles to a small, fast and efficient form on the 8051 architecture using the IAR Compiler. When I tried to port to the AVR, the code size jumped by 50%.

I should explain that the original code was for a 68HC05. It was designed using global variables and functions with no arguments and no return value. On the 68HC05 and the 8051 the results are acceptable for the application. On the AVR they would require parts with more memory which did not exist at the time.
 
My limited understanding:
AVRs have multiple working registers versus the PIC single "W"
but they are specialized and you must use certain ones for certain tasks?
IS that the gist of it?
 
There are 32 registers(r0-r31), with some minor differences. When doing register vs register instructions (like math ops, logic ops, comparisons), they're mostly interchangable, but there are some "gotcha"s

R0, R1 hardcoded in some instructions like LPM (i.e. read from Flash memory), and MUL (a 2 cycle 8x8 multiply), but these are special case instructions with some other limitations

The last 3 pairs of registers (6 total) can be used as 16 bit pointers into memory, so they have some special auto incrementing/decrementing functionality

When doing assembly ops versus hardcoded numbers, the operations are mostly limited to the upper 16 registers. So when loading in constants, or comparing versus constants, the target register needs to be r16-r31

There are also some oddball limitations when using the 16 bit add/subtract functions, but I can't say I use them much anyway.
 
Many would know that LPM instruction puts the result in R0.

However, it can also place the result in R1-R29 when the "LPM Rx, Z" is used in the assembly code.

What is insteresting is that "LPM R0,Z" would assemble to a different code than LPM, while both doing the same job. Both use the same amount of clock cycles to complete.

Anyone knows whether this is a recent addition/improvement or is always like that?

Added: I have checked the datasheet, the LPM Rx,Z instruction only start appearing on Tiny and Mega series.
 
Last edited:
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top