PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : UART zwischen mega16 und mega48



JeyBee
09.04.2009, 21:33
Nabend,

Ich bin's mal wieder.... Ich bin echt am verzweifeln. Ich versuche nun schon seit Tagen, eine UART Kommunikation zwischen einem ATmega16 und einem ATmega48 zum Laufen zu kriegen....

Zur Hardware:
Ich habe die RxD und TxD der jeweiligen Kontrollern über Kreuz miteinander verbunden. Soweit sollte das stimmen.
Der ATmega16 läuft mit einem externen 16MHz Quarz, der ATmega48 mit einem internen 8MHz Quarz.


Zur Software:
Ich verwende die Peter Fleury Libary. Jedoch funtzt garnix. Ich nutze das AVRStudio 4. Die .c und .h sind im selben ordner der jeweiligen Programme, MCU und Freq. sind richtig eingestellt.

Hier mal die Programme:

ATmega16 (sender)


#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "uart.h"

#ifndef F_CPU
#define F_CPU 16000000UL
#endif

#define UART_BAUD_RATE 9600


uint16_t readADC(uint8_t channel)
{
uint16_t result;

ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1); // ADC einschalten, prescal /64
ADMUX = channel; // Kanal wählen
ADMUX |= (1<<REFS1) | (1<<REFS0); // + interne 2,56V-Referenz
ADCSRA |= (1<<ADSC); // Konvertierung starten
while(ADCSRA & (1<<ADSC)); // warten bis Wandlung abgeschlossen

result= ADC; // Ergebnis zwischspeichern

ADCSRA &= ~(1<<ADEN); // ADC ausschalten

return(result); // Ergebnis abliefern
}



int main(void)
{
unsigned int c;
char buffer[7];
int num=134;

DDRC = 0x00;
uint16_t result0 = 0;
uint16_t result1 = 0;
/*
* Initialize UART library, pass baudrate and AVR cpu clock
* with the macro
* UART_BAUD_SELECT() (normal speed mode )
* or
* UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode)
*/
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

/*
* now enable interrupt, since UART library is interrupt controlled
*/
sei();


itoa( num, buffer, 10); // convert interger into string (decimal format)
uart_puts(buffer); // and transmit string to UART

while(1)
{

uart_putc('A');

}
}




ATmega48(empfänger)


#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

#include "uart.h"


/* define CPU frequency in Mhz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 8000000UL
#endif

/* 9600 baud */
#define UART_BAUD_RATE 9600


int main(void)
{
unsigned int c;
char buffer[7];
int num=134;


/*
* Initialize UART library, pass baudrate and AVR cpu clock
* with the macro
* UART_BAUD_SELECT() (normal speed mode )
* or
* UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode)
*/
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

/*
* now enable interrupt, since UART library is interrupt controlled
*/
sei();



while(1)
{

c = uart_getc();
if (c =='A')
{
PORTB |= (1<<PB4);
}
else
{
PORTB &=~ (1<<PB4);
}
}
}



Die ADC Initialisierung könnte man auch weglassen, ich habe sie einfach mal da gelassen, weil ich später mit Sharp Sensoren arbeiten möchte.... sollte ja soweit nicht stören.


Danke im Voraus!

Mfg JeyBee

Besserwessi
09.04.2009, 22:15
Soweit ich weiss gibt es keine µCs mit internem Quarz. Die AVRs haben einen internen RC oszillator. Die Genauigkeit reicht aber nicht immer für eine zuverlässige UART aus. Gerade bei den neueren µCs ist die Frequenztolleranz größer geworden, bei den alten wie AT90S2313 hats noch fast immer funktioniert.

Laufen die µCs denn wirklich mit der Gewünschten Frequenz ?

Ein Test wäre einen Pegelwandler zu nutzen um mit einer bekannt funktionierenden RS232 einen Test durchzuführen um zu sehen welche Seite nicht geht.

TomEdl
09.04.2009, 22:40
Fahr mal mit der Baudrate runter auf 2400Baud. Vielleicht hilft das was.

Grüße
Thomas

JeyBee
09.04.2009, 23:05
Nabend,

@Besserwessi: Sry, ich meinte auch einen Internen RC-Oszi ;)
ist ein externer Quarz nötig?


@TomEdl: Ich habe die Baud nun auf 2400 runtergeschraubt... aber selbes Ergebnis.


Ich habe die Hardwareverbingungen nochmal ausgemessen, da stimmt alles. Auch GND wurde zusammengelegt.

Ich habe nun beide Kontroller (einzeln) eine LED im 1sec. Takt blinken lassen, um zu testen, ob die Taktraten stimmen. -> Die LEDs blinkten im 1Sekunden Takt -> alles I.O.

Ich weiss echt nicht mehr weiter....


Mgf JeyBee

Besserwessi
10.04.2009, 00:33
Es wird einfacher wenn man weiss welche Hälfte nicht geht. Deshalb der Tip mit dem Pegelwandler und PC.

Es kann sein das der interne RC Oszillator zu weit daneben ist für eine UART. Kommt eher selten vor, ist aber bei den tolleranzen möglich. Ein externer Quarz wäre eventuell sinnvoll, vor allem wenn die Temperatur oder Versorgungsspannung nicht stabil sind.

sternst
10.04.2009, 02:07
Von der Oszillator-Problematik mal abgesehen, produziert der Code im Empfänger auch nur ein sehr kurzes Aufblitzen der LED, denn uart_getc wartet nicht auf ein Zeichen. Zusammen mit dem dauernden Senden des 'A' ergibt sich somit nur ein ganz schwaches Glimmen der LED, was vermutlich nur im Dunkeln zu sehen sein wird (wenn überhaupt).

PS: Ich bin jetzt einfach mal von einer LED an PB4 ausgegangen.

JeyBee
10.04.2009, 11:12
Hallo sternst,

Wie kann ich denn das ändern? Mit einem Delay beim Sender/Empfänger?

Ich werde heute mal dem ATMega48 auch ein 16MHz Quarz, oder einen RC-Oszillator schenken.

Mfg JeyBee

sternst
10.04.2009, 14:46
Wie kann ich denn das ändern? Mit einem Delay beim Sender/Empfänger?
Zunächst einmal würde ich den Code im Empfänger ändern. Zum Beispiel:

while(1) {

while ((c = uart_getc()) & UART_NO_DATA); // warte auf ein Zeichen

switch (c) {

case 'A':
PORTB |= (1<<PB4);
break;

case 'B':
PORTB &= ~(1<<PB4);
break;
}
}


So kannst du die LED mit A ein und mit B ausschalten (oder umgekehrt, je nach dem, wie die LED angeschlossen ist).
Wenn du jetzt im Sender abwechselnd A und B sendest, blinkt die LED bei 2400 Baud mit 120 Hz. Das sollte dir als halbe Helligkeit erscheinen. Wenn du das Blinken sehen willst, musst du dann noch ein Delay beim Sender einbauen.

JeyBee
10.04.2009, 16:06
Nabend,

Also jetzt funktionierts!

Vielen Dank an alle!

Und noch frohe Ostern


Mfg JeyBee