PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : AtMega8 und UART-Problem



jimmy0815
06.04.10, 11:48
Hallo Leute,

ich will in die Welt der Microcontroller einsteigen und so habe ich diese Seite gefunden:
http://derjulian.net/mikrocontroller
Ich hab mir also die besagte Schaltung zusammengebaut, inklusive externem Quarz (8Mhz) und der Transistorschaltung zum Invertieren der Pins.

Als Testcode habe ich mir das hier zusammenkopiert:


#include <avr/io.h>
#include <avr/interrupt.h>
#define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1)
#define UART_BAUD_RATE 2400
#define UART_BUFFER 10
uint8_t uart_buffer[UART_BUFFER];
int8_t uart_count = 0 ;
uint8_t uart_getc(void)
{ /* output next char in cache
*/
if (uart_count == 0) return 0;
return uart_buffer[--uart_count];
}
ISR(SIG_UART_RECV)
{ /* INTERRUPT: receive char from UART and save it the buffer
*/
if (uart_count < UART_BUFFER) uart_buffer[uart_count++] = UDR;
}
inline void uart_init(uint8_t tx, uint8_t rx)
{ /* initializes UART communication;
* tx: sending should be activated
* rx: receiving should be activated
*/
uint16_t baudrate;
// Baud-Rate setzen
baudrate = UART_BAUD_RATE/2;
UBRRH = (uint8_t) (UART_UBRR_CALC(baudrate,F_CPU)>>8);
UBRRL = (uint8_t) UART_UBRR_CALC(baudrate,F_CPU);
// Ggf. TX und RX anschalten
UCSRA |= (1<<U2X);
UCSRB |= (1<<RXCIE);
if(tx) UCSRB |= (1<<TXEN);
if(rx) UCSRB |= (1<<RXEN);
sei();
pause(1);
}
void uart_putc(uint8_t c)
{ /* send one char per UART
*/
while (!(UCSRA & (1<<UDRE)));
UDR = c;
}
void uart_puts(uint8_t *data)
{ /* send string per UART
*/
while(*data)
{
uart_putc(*data);
data++;
}
}
void uart_puti(uint16_t data)
{ /* send integer per UART
*/
uint8_t buffer[7];
uart_puts(utoa(data, buffer, 10));
}
void uart_putf(float data)
{ /* send float per UART
BUG: unnötige Leerzeichen am Anfang?
*/
uint8_t buffer[7];
uart_puts(dtostrf(data, 6, 2, buffer));
}
int main(void)
{
DDRB |= (1 << PB1);
PORTB &= ~(1 << PB1);

uart_init(1, 1);
uart_puts("Hello World!\n");
}


Das ganze compiliert er schonmal nicht durch, er hat ein Problem mit pause(1):

undefined reference to 'pause'
Davor noch ein paar Warnings.
Schmeiße ich das pause raus compiliert er durch, wobei die warnings bleiben.

Nun schreibe ich die hex auf den uC, die LED leuchtet auch wie gewollt, allerdings bekomme ich nichts auf der Seriellen Konsole, tail -f /dev/ttyS0 gibt mir nichts aus.
Am Windows-Netbook hab ich einen RS232-USB Converter. Schließe ich es da an und öffne den Hyperterminal, stelle 2400Bauds ein, bei 8 Datenbits, keine Parität, Stoppbits: 1, und Flusssteuerung Hardware, dort bekomme ich auch nichts.

Woran kanns liegen?

grüße
dennis

derRichard
06.04.10, 12:31
Das ganze compiliert er schonmal nicht durch, er hat ein Problem mit pause(1):

Davor noch ein paar Warnings.
Schmeiße ich das pause raus compiliert er durch, wobei die warnings bleiben.


kann es sein, dass du eine zu alte oder andere avrlibc verwendest?

hth,
//richard

jimmy0815
06.04.10, 14:51
zu alt kann eigentlich nicht sein, avrstudio und programmers notepad auf meinem win-netbook wo ich auch programmiere ist ganz frisch. Die Libc Version ist 1.6.7.
Da einige Quelltexte von der Website mit dem Copyright 2006 versehen sind, weiß ich nicht in wiefern der Quellcode noch gepflegt wird.
Aber was kann ich machen?

jimmy0815
06.04.10, 19:15
Ich habe noch was anderes probiert:

main.c:

#include <avr/interrupt.h>
#include "uart.h"

#define BAUDRATE 38400UL //Definition als unsigned long, sonst gibt es Fehler in der Berechnung

void uart_init()
{
uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16*BAUDRATE) - 1);

UBRRH = (uint8_t) (ubrr>>8);
UBRRL = (uint8_t) (ubrr);

// UART Receiver und Transmitter anschalten
// Data mode 8N1, asynchron
UCSRB = (1 << RXEN) | (1 << TXEN);
UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);

// Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte)
do
{
UDR;
}
while (UCSRA & (1 << RXC));
}

// Einen 0-terminierten String übertragen.
void uart_puts (const char *s)
{
do
{
uart_putc (*s);
}
while (*s++);
}

// Ein Zeilenumbruch, abhängig davon, was die Gegenstelle haben will
// Windows: "rn"
// Linux : "n"
// MacOS : "r"
#define CR "\r\n"

char text[] = "Hallo Welt." CR;

int main()
{
uart_init();
sei(); // Wird nur gebraucht bei der Interrupt-Version

uart_puts (text);
uart_puts ("Hallo Welt!" CR);

return 0;
}


uart.h:

#ifndef _UART_H_
#define _UART_H_

#include <avr/io.h>

extern void uart_init();

static inline int
uart_putc (const uint8_t c)
{
// Warten, bis UDR bereit ist für einen neuen Wert
while (!(UCSRA & (1 << UDRE)))
;

// UDR Schreiben startet die Übertragung
UDR = c;

return 1;
}

static inline uint8_t
uart_getc_wait()
{
// Warten, bis etwas empfangen wird
while (!(UCSRA & (1 << RXC)))
;

// Das empfangene Zeichen zurückliefern
return UDR;
}

static inline int
uart_getc_nowait()
{
// Liefer das empfangene Zeichen, falls etwas empfangen wurde; -1 sonst
return (UCSRA & (1 << RXC)) ? (int) UDR : -1;
}

#endif /* _UART_H_ */


Hier compiliert er voll durch, nur ein paar warnings:

In file included from main.c:2:
uart.h:6: warning: function declaration isn't a prototype
uart.h:23: warning: function declaration isn't a prototype
uart.h:34: warning: function declaration isn't a prototype
main.c:7: warning: function declaration isn't a prototype
main.c:45: warning: function declaration isn't a prototype

Auf den externen Quarz (im Makefile definiert) schalte ich per

uisp -dlpt=0x378 -dprog=dapa --wr_fuse_l=0xee
Ich hoffe das ist richtig?

Auf dem Terminal bekomme ich rein gar nichts...

Wenn ich jetz mit dem Multimeter dran gehe bekomme ich auf dem TXD/RXD pin des Controllers etwa 5V (bei beiden).
An den Pins der Transen für die Invertierung bekomme ich beim RXD 6V für den USB-RS232Wandler und etwa 10V für direkte RS232, am TXD, also der wo eigentlich was raus soll, bekomme ich nur 0,02V raus.
Das ist ja nicht ganz richtig, oder?
Demnach würde ich vermuten dass die Transe kaputt ist? Kann das durch vertauschen der Drähte vom PC kommen?

grüße
dennis

edit:
hm...hat sich irgendwie gelöst...das ganze funktioniert jetzt. Ich weiß nicht wieso, aber ich bekomm auf dem Terminal jetzt mein "hallo Welt"

E S
02.05.10, 10:59
Hi,

es heißt übrigens TRANSISTOR, nicht Transvestit!!!

Benutze den MAX232 oder wenn Du keine Lust hast die vielen Kondensatoren verdrahten zu müssen den MAX233 (ist aber schwächer).
Das ist ein Pegelwandler der aus RS232 TTL echte RS232 macht. Die Ladungspumpen für +/-10V sind im Chip eingebaut, die notwendige invertierung der Logikpegel wird auch im Chip erledigt.

Gruß
Elmar