ik wil een serieël data signaal demultiplexen om vervolgends verder te gebruiken in het programma. ik gebruik een atmel at90s2313. het seriële signaal is 5v TTL, heeft 8 bit's, een start en een stop bit. de baudrate is 9600Bps.

nu heb ik dit stuk gevonden om de uart te initialiseren
-------------------------------------------------------------------------------------------
.include "2313def.inc"
.device at90s2313

.equ fck = 4000000 ;kristalfrequentie 4MHz
.equ baudrate = 9600 ;baudrate 9600bps

.equ baudkonst = (fck/(16*baudrate))-1 ;UBRR-waarde berekenen

uart_init: ldi w,baudkonst ;baudrate laden
out UBRR,w
ldi w,0b00011000 ;8 bits ontvangen
out UCR,w
sbi UCR,RXCIE ;ontvangstinterrupt vrijgeven
-------------------------------------------------------------------------------------------

maar is hiermee de uart volledig geinitialiseert en klaar voor gebruik? of moet er nog wat veranderd worden.

en in welk register word nu de ondvangen waarde gezet? in UBBR of in UDR?

Op 3 december 2003 17:13:59 schreef megawat:
maar is hiermee de uart volledig geinitialiseert en klaar voor gebruik? of moet er nog wat veranderd worden.

en in welk register word nu de ondvangen waarde gezet? in UBBR of in UDR?

Wel eens gehoord van een datasheet?

ontvangen is btw met een t en geen d

ja, uit het datasheet haal ik dat het in het UDR register komt te staan.

maar het stukje software in mijn vraag hierboven, is dat volledig, gaat dat werken zo?

kijk ff bij http://www.avrbeginners.net/
Daar staat veel info voor avr newbies. Met voorbeelden. Ook van de uart.

.include "2313def.inc"
.device at90s2313

rjmp uart_init

.equ fck = 4000000 ;kristalfrequentie 4MHz
.equ baudrate = 9600 ;baudrate 9600bps
.equ baudkonst = (fck/(16*baudrate))-1 ;UBRR-waarde berekenen
.def w = r16

uart_init:
sbi UCR,RXEN ;enable UART
ldi w,baudkonst ;baudrate laden
out UBRR,w

Zo kan het ook, scheelt een regel minder, formule verwerken in de code:

sbi UCR, RXEN ;enable UART
ldi w, fck/(baudrate*16)-1 ;set baud rate
out UBRR, w

Nu staat de RX UART aan en ingesteld.
Weet niet of je UART interrupt wilt gebruiken.
Word ontvangen in UDR. Zo inlezen.

serIn: sbis USR, RXC ;if UART RX complete bit is clear
rjmp serIn ; loop back
in w, UDR ;else get received byte in w

En dan verwerken in de vervolg code(s).

[Bericht gewijzigd door RES op ]

Op 3 december 2003 19:27:06 schreef megawat:
ja, uit het datasheet haal ik dat het in het UDR register komt te staan.

Ok perfect. Ik wil je best helpen met info maar aangezien er ook veel mensen zijn die niet eens in de datasheet kijken vroeg ik het ff om te checken ;)

Je hebt het juist gevonden/gelezen in de datasheet: Voor de inkomende (en uitgaande) is het UDR bedoelt. Ontvang je iets dan hoef je alleen maar het UDR uit te lezen. Extra opmerking hierover: dit moet zelfs wil je nieuwe data kunnen ontvangen, dus ook al doe je niks met de waarde. Als je iets ontvangt en het in het UDR staat moet je die uitlezen.

maar het stukje software in mijn vraag hierboven, is dat volledig, gaat dat werken zo?

Super, klopt helemaal.

Ik heb nog een tip voor je die je (eventueel) kunt toepassen.
Je definieert de equivalent baudkonst en gaat vervolgens via W het UBRR ermee vullen. Je kunt ook direct W laden met de gewenste waarde zonder dat eerst via baudkonst te doen.

Haal hiervoor je .equ regel weg en vervang je uart_ini regel door de volgende:


uart_init: ldi w, (fck/(16*baudrate))-1 ;baudrate laden

Hoeft niet, maar is wel mooier ;)

Heb je btw voordat je de AVR gebruikte ook met PIC's gewerkt? Omdat je namelijk w gebruikt als naam voor je register, iets wat bij de PIC niet anders kan.

Op 3 december 2003 20:57:05 schreef RES:
sbi UCR, RXEN ;enable UART
Nu staat de RX UART aan en ingesteld.

In zijn voorbeeld heeft hij de RX en TX aangezet. In dat geval kan hij beter de volgende code gebruiken (vooral met het oog op toekomstige aanpassingen):


ldi w, (1<<rxen|1<<txen)
out ucr, w

ik had inderdaad UDR uit de datasheet gehaald, maar op school sprak iemand me tegen. hij zij dat dat het UBBR register moest zijn. vandaar mijn verwarring.

ik heb tot nu toe alleen nog maar met atmel gewerkt. ik gebruikte w omdat dat in het avr boek stond, maar ik geloof dat het werkregister meestal 'temp' word genoemd. niet dat het iets uitmaakt.

ik ga aan de slag, mochten er problemen voordoen dan meld ik me weer.

bedankt voor alle hulp

Op 4 december 2003 00:47:34 schreef megawat:
ik had inderdaad UDR uit de datasheet gehaald, maar op school sprak iemand me tegen. hij zij dat dat het UBBR register moest zijn. vandaar mijn verwarring.

Begrijpelijk, echter datasheets hebben het zelden mis ;)

ik heb tot nu toe alleen nog maar met atmel gewerkt. ik gebruikte w omdat dat in het avr boek stond, maar ik geloof dat het werkregister meestal 'temp' word genoemd. niet dat het iets uitmaakt.

Maakt idd totaal niks uit. Alleen bij PIC heb je maar 1 register en dat kun je alleen met de synoniem W aanspreken, dus vandaar dacht ik dat je van PIC -> AVR was gegaan.

ldi w, (1<<rxen|1<<txen)
out ucr, w

Ik heb hier nog niet mee gewerkt, maar wat betekend het precies ? Dit -> 1<<rxen|1<<txen

Als RX en/of TX kleiner dan 1 is of zoiets ?

Op 4 december 2003 13:45:23 schreef RES:
ldi w, (1<<rxen|1<<txen)
out ucr, w

Ik heb hier nog niet mee gewerkt, maar wat betekend het precies ? Dit -> 1<<rxen|1<<txen

Als RX en/of TX kleiner dan 1 is of zoiets ?

Nee, het betekend hetzelfde als het bij C/C++ zou betekenen. En dat is als volgt.
Ter voorbeeld:


62<<4

betekend, shift getal 62 4x naar links toe.

Wat gebeurt er nu als je doet:


1<<rxen

dan wordt dus het getal 1 dus "rxen"x geshift. In de include file staat gedefineerd dmv een .equ dat welk bitnummer het rxen bitje heeft. Wat dus als uitwerking heet dat het getal 1 (dus eigenlijk gewoon 1 bitje) opzij wordt geschoven naar de plek van het rxen bit. Op die manier zet je dus de rxen aan.

Gebruik je de code:


67|98

dan wordt het getal 67 ge-OR-ed met 98. Als we dat toepassen op:


1<<rxen|1<<txen

dan heeft dat als effect dat dus de het bitje om de rxen aan te zetten wordt ge-OR-ed met het txen bitje. Op die manier heb je de juiste combinatie die je kan wegschrijven in het UCR register.

Deze "truc" kan je voor alle registers in de AVR toepassen. Het grootste voordeel is dat je synoniemen gebruikt die in de include file staan. Zou je dus een andere AVR nemen met dezelfde code dan gaat dat gewoon goed, want dan staat in de include file vanzelf het juiste bitnummer gedefineerd.
Daarnaast is deze "truc" ideaal voor het geval je laten je code wilt wijzigen. Wil je bijvoorbeeld ook nog later een receive interrupt aanzetten dan hoeft je enkel neer te zetten:


ldi w, (1<<rxen|1<<txen|1<<rxcie)
out ucr, w

en dan staat je interrupt ook aan voor de receiver zonder dat je de rest van de code hoeft te controleren op geldigheid na deze edit.

Kijk trouwens voor meer van dat soort "functies" naar de assembler reference guide die te downloaden is bij Atmel.

Hm, het staat gewoon in mijn AVR Help.

Shift left
Symbol: <<
Description: Binary operator which returns the left expression shifted left a number of
times given by the right expression
Precedence: 11
Example: ldi r17,1<<bitmask ;Load r17 with 1 shifted
;left bitmask times

The following operators are defined:

Symbol Description
! Logical Not
~ Bitwise Not
- Unary Minus
* Multiplication
/ Division
+ Addition
- Subtraction
<< Shift left
>> Shift right
< Less Than
<= Less Than or Equal
> Greater Than
>= Greater Than or Equal
= Equal
!= Not Equal
& Bitwise And
^ Bitwise Xor
| Bitwise Or
&& Logical And
|| Logical Or

Ok, ik snap dit ook weer, thanks!

ik heb het programma af, maar om de een of andere reden krijg ik een foutmelding.
'error: Relative branch out of reach'
het lijkt niks met de uart te maken te hebben. maar heb geen idee waar ik moet zoeken.
is er iemand die mijn programma eens zou wilen bekijken, via de mail/msn wat hulp wil bieden?

willemhs@hotmail.com

bij voorbaad dank

Op 6 december 2003 17:34:16 schreef megawat:
ik heb het programma af, maar om de een of andere reden krijg ik een foutmelding.
'error: Relative branch out of reach'

Dit betekend dat je een branch instructie gebruikt die moet springen naar een adres wat te verweg ligt.

Met branch instructies kun je maar een beperkte "sprong" maken. Gebruik in zo'n geval een rjmp (relative jump). Kun je niet anders dan een branch gebruiken, laat dan de branch naar een regel springen die in de buurt ligt en je daar dan weer de rjmp neerzet.

assembly complete with no errors.
dat was inderdaad het probleem
thnx!