Sida 1 av 2
USART, AVR och Mega88
Postat: 7 oktober 2008, 22:54:04
av Snouser
Jag försöker lista ut genom exemplen i databladet hur man tar emot information på min uC. Så här säger bladet.
Kod: Markera allt
USART_Init:
; Set baud rate
out UBRRnH, r17
out UBRRnL, r16
; Enable receiver and transmitter
ldi r16, (1<<RXENn)|(1<<TXENn)
out UCSRnB,r16
; Set frame format: 8data, 2stop bit
ldi r16, (1<<USBSn)|(3<<UCSZn0)
out UCSRnC,r16
ret
USART_Receive:
; Wait for data to be received
sbis UCSRnA, RXCn
rjmp USART_Receive
; Get and return received data from buffer
in r16, UDRn
ret
Jag tror att ja förstår det mesta av koden, eller i alla fall principen av den.
Problemet är bara de att dom skriver UDRn (ett N på slutet). Ja gissar att den sista bokstaven ska bytas ut mot något. Frågan är bara vad, och fram för allt varför.
Skulle någon kunna förklara.
Ja försökte läsa mig till det, men efter 10 sidor gav ja upp...
Postat: 7 oktober 2008, 23:06:36
av johano
Säkert en siffra, 0 eller 1 eller så..
/johan
Postat: 7 oktober 2008, 23:21:35
av Stinrew
Precis somjohanosäger så ska n bytas ut mot 0. Det beror på att i vissa AVR-kretsar finns det 2 st. UART, och då används 0/1 för att välja vilken av dom det gäller. I mega88 finns ju bara en UART, så alla 'n' ska i dessa sammanhang bytas ut mot '0'.
Postat: 8 oktober 2008, 11:01:42
av Snouser
Okej, då är min följdfråga; vad ska man med två stycken ingångar till? Jag menar man kan väll ändå bara ta emot en byte itaget så länge man inte kör multitask, eller?
Jag är bara lite nyfiken på hur det fungerar...
Postat: 8 oktober 2008, 11:04:18
av sodjan
> , eller?
Fel. Varje USART fungerar självständigt.
Postat: 8 oktober 2008, 11:06:34
av Icecap
Tja... kommunikation med en PC på den ena UART och kommunikation med andra enheter på den andra UART... eller GSM-modem eller Mätinsamling eller .... ja, vad man nu behöver.
Och det har INGET med multitask att göra.
Jag har tillverkad enheter som dels kommunicerar med PC samtidig som de insamlar data från en radar via UART och som medelst en 3'dje UART skickade ut debug-meddelanden, inget speciellt konstigt i det.
Postat: 8 oktober 2008, 11:47:34
av Micke_s
lite förtydlignade: Visst, du kan bara ladda och läsa av uart registrerna en i taget. Men hårdvaran kan skicka och ta emot seriella strömmar oberoende av varandra.
Postat: 8 oktober 2008, 21:49:05
av Snouser
Okej, tack för svaret.
Nästa fråga.
Hur ska jag ladda in boudrate värdet i UBRR0H och UBRR0L?
Jag har inte rikigt fattat de där med låga och högra register,
Är det meningen att jag ska ladda in ett värde i ett te.x Z register och sedan ladda in de högsta registerparet i UBRR0H och viseverse?
EDIT:
Enligt en annan bok jag har så räcker det att man laddar in "prescalervärdet" in i UBRR, i bokens fall (3,69Mhz 9600bps) så är det 23 som ska laddas in. Då borde man väll inte behöva ett register par för att ladda in de värdet...eller?
EDIT2:
Detta borde väll fungera?
Kod: Markera allt
ldi ZH, HIGH(129)
ldi ZL, LOW(129)
out UBRR0H, ZH
out UBRR0L, ZL
Jag får följande fel när jag kör koden:
C:\kod\kod.asm(74): error: Operand 1 out of range: 0xc5
Postat: 8 oktober 2008, 22:27:02
av Stinrew
Låga och höga register används när man eventuellt hanterar tal större än 0-255, vilka är dom tal som kan beskrivas med unsigned char. Vi säger att du använder 20MHz kristall och vill ställa in en baudrate på 4800 Baud, vilket innebär att UBRR0 ska ges värdet 259. Det decimala värdet 259 kräver 9 bitar för att beskrivas. 259 -> 0b00000001.00000011 = 256 + 2 + 1 = 259. I det fallet ska UBRR0H laddas med 1 medans UBRR0L laddas med 3.
I ditt fall ska UBRR0H laddas med 0 och UBRR0L laddas med 23. Då dessa register vid power-up initeras till 0 behöver du givetvis inte skriva till UBRR0H, men det är snyggare/bättre/säkrare att skriva till samtliga register när du initierar USARTen. Det bör inte spela någon roll i vilken ordning du skriver till dessa register, då detta bör ske innan USART0 aktiveras.
Vet inte hur det fungerar i assembler, men i C så kan man förenkla och skriva:
i stället för:
EDIT2-SVAR:
Du kan inte ladda in högre siffra än 15 i UBRR0H, kolla i databladet så får du se att dom 4 höga bitarna är reserverade.
Postat: 8 oktober 2008, 22:44:51
av Swech
Ditt problem är inte att UBRR0H endast kan innehålla 0-15
Assemblern håller inte reda på detta och varnar ej
Däremot är adressen till UBRR0H utanför området man kan
nå med OUT instruktionen
Skriv istället
LDI ZH,HIGH(BAUD_NR)
STS UBRR0H,ZH
Swech
Postat: 8 oktober 2008, 22:50:52
av Snouser
Båda förslagen fungerade super!
Nu till nästa del..
Jag får precis samma fel längre ner i koden.
Operand 1 out of range: 0xc0
Kod: Markera allt
USART_Receive:
; Wait for data to be received
sbis UCSR0A, RXC0
rjmp USART_Receive
Vilket är "sbis" raden.
Varför de tro?
Postat: 8 oktober 2008, 22:54:21
av sodjan
Samma orsak kanske ?

Postat: 8 oktober 2008, 22:56:10
av Snouser
Innan så skulle jag väll lagra data.
Nu ska jag väll bara kolla om en bit är satt i SREG.
Jag kan inte se varför något värde skulle vara för stort.
Postat: 8 oktober 2008, 23:01:48
av sodjan
Läste du inte vad Swech skrev ?
> Däremot är adressen till UBRR0H utanför området man kan
> nå med OUT instruktionen
Du kanske ska läsa på om SBIS ?
Postat: 8 oktober 2008, 23:28:51
av Snouser
Jaha, nu fattar jag.
Det går inte att komma åt de specifika registrera, det är därför felmeddelandet kommer upp.
Jag löste problemet så här.
Om någon råkar ut för samma problem så finns det en massa information det här:
http://www.avrfreaks.net/index.php?name ... ic&t=58721