Sida 1 av 1
Problem med Atmega88 UART
Postat: 24 november 2005, 21:46:18
av JJ
Funktionen nedan är avsedd att spruta ut tecknet 'E' på serieporten. Det blir bara skräptecken om jag inte lägger in en fördröjningen.
Någon som vet varför?
Kod: Markera allt
#include <avr/io.h>
void writeE()
{
volatile int i;
cli(); // Disable global interrupts
// Initiate UART
PRR = ~_BV(PRUSART0); // Enable USART
UBRR0 = 12; // cf p. 192
UCSR0A = _BV(U2X0); // Double speed
UCSR0B = _BV(TXEN0); // Enable Tx
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); // 8N1
// Write 'E' repeatedly:
while(1) {
while(!(UCSR0A & _BV(UDRE0))); // Wait for txbuf
// ready.
// for(i = 0; i<100;i++); //<--- workaround...
UDR0 = 'E';
}
}
Postat: 25 november 2005, 10:23:17
av gille
UDRE0 är hur mycket du ska shifta en etta för att hitta rätt i registret.
Ändra alltså: while(!(UCSR0A & _BV(UDRE0))); // Wait for txbuf
till: while(!(UCSR0A & _BV(1<<UDRE0))); // Wait for txbuf
Så bör det nog fungera.
Postat: 25 november 2005, 22:56:43
av JJ
Nja, det är den skiftningen som makrot _BV() gör.
Ingen annan som har tittat har sett något fel i koden så då är den nog riktig...
Jag testade att köra med två stoppbitar för att ge rx-sidan lite andrum. Då fungerade det som det skall!
Kanske var det att serieporten på min PC ställde till det.
Postat: 25 november 2005, 23:02:51
av cykze
> PRR = ~_BV(PRUSART0); // Enable USART
Du vill nog att det ska stå &= istället för =. Annars sätter du ju de andra bitarna i PRR. och det vill du nog inte.
Varför kör du med "double speed"? Vanligtvis brukar man ju kör med "normal" hastighet.
Postat: 25 november 2005, 23:26:28
av JJ
a) Du har rätt, normalt sett. (Fast i just dethär fallet skall uarten bara rapportera fel, interrupten disablas och funktionen returnar inte, funktionen är helt hänsyslös och gör alltså värre saker än PRR-disablar andra moduler!)
b) Tja, man får ett litet fel på 9600bps och standardinställd klocka (p. 192 i manualen).
Postat: 26 november 2005, 00:03:24
av cykze
Kör du på den interna klockan? I så fall är ju den inte särskilt exakt, speciellt inte om man inte har kalibrerat den. Kanske är det det som gör det.
Postat: 30 november 2005, 20:31:18
av Nimzo
Kalibrering är nog rätt väg att gå. Eller om du kör en separat asynkron timer. Hursom behöver du initiera någon räknare mot en kristall. Om du får till det vill jag gärna veta hur du gjort, sitter själv med en atmega88 och vill få till en real time clock. (Se tråden bredvid)
/Jonas
Postat: 2 december 2005, 20:42:04
av JJ
Jag nöjer mig nog med den interna klockan för tillfället. Jag får väl sänka baudraten om jag får problem.
Jag är också nyfiken på hur man gör för att kalibrera och hur bra det blir...men det är inget jag tar tag i nu.