Problem med Atmega88 UART

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
JJ
Inlägg: 366
Blev medlem: 16 maj 2005, 21:33:02

Problem med Atmega88 UART

Inlägg 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';
	}	
}
gille
Inlägg: 69
Blev medlem: 28 november 2004, 18:06:09
Ort: Stockholm
Kontakt:

Inlägg 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.
JJ
Inlägg: 366
Blev medlem: 16 maj 2005, 21:33:02

Inlägg 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.
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg 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.
JJ
Inlägg: 366
Blev medlem: 16 maj 2005, 21:33:02

Inlägg 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).
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg 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.
Nimzo
Inlägg: 6
Blev medlem: 2 augusti 2004, 15:29:09
Ort: Stockholm
Kontakt:

Inlägg 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
JJ
Inlägg: 366
Blev medlem: 16 maj 2005, 21:33:02

Inlägg 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.
Skriv svar