Forum: Compiler & IDEs receive und Transmit via dem UART (ATmega16)


von Marie (Gast)


Lesenswert?

Hallo Leute
ich versuche seit einige zeit eine receive und transmit Programm mit 
buffer zu schreiben aber es geht nicht. die Daten sollen von der 
tastatur eingegeben und  werden im HyperTerminal erscheinen. ich habe 
ein klein Programm ihne buffer geschrieben und es funtionniert aber wenn 
ich das Programm mit benutzen von buffer schreibt es functionniert nicht 
ich weiss nicht was falsch in meinem programm ist. kann jemand mir 
helfen dieser Programm mit benutzung von buffer zu schreiben?
hier unten ist das quelle code meines unfunctioniertes Programms.

Merci
MFG
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>


  /* ATmega with one USART */
 #define ATMEGA_USART
 #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
 #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
 #define UART0_STATUS   UCSRA
 #define UART0_CONTROL  UCSRB
 #define UART0_DATA     UDR
 #define UART0_UDRIE    UDRIE

 /*Size of the circular receive buffer, must be power of 2*/
 #ifndef UART_RX_BUFFER_SIZE
 #define UART_RX_BUFFER_SIZE 32
 #endif

/*Size of the circular Transmit buffer, must be power of 2*/
 #ifndef UART_TX_BUFFER_SIZE
 #define UART_TX_BUFFER_SIZE 32
 #endif

 /*high byte error return code of uart_getc()*/
 #define UART_NO_DATA     0x0100

// CHECK F_CPU WITH HARDWARE OSZILLATOR SETTING !!!!
#define F_CPU 1000000UL
#define UART_BAUD 9600

/*
 *  module global variables
 */
static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
static volatile unsigned char UART_TxHead;
static volatile unsigned char UART_TxTail;
static volatile unsigned char UART_RxHead;
static volatile unsigned char UART_RxTail;
static volatile unsigned char UART_LastRxError;

void uart_init(void);
unsigned int uart_getc(void);
//unsigned char uart_getc(void);
void uart_putc(unsigned char c);
//int uart_putc(unsigned char c);
void uart_puts (char *s);

int main(void)
{
   unsigned char c;

   uart_init();

   uart_puts("hello world!\r\n\r\n");

   while(1)
   {
      // Poll
      c = uart_getc();

      // Funny conversion

     /************************************************************
     This converion ist only use to convert the alphabetic letter
     and they will be return als echo to the screen
     ************************************************************/

      //if (c >= 'a' && c <= 'z')
       //  c += 'A' - 'a';
      //else if (c >= 'A' && c <= 'Z')
        // c += 'a' - 'A';

      // Echo
      uart_putc(c);
   }

   return 0;
}

void uart_init(void)

/******************************************************************
 Function: Uart_init()
 Purpose: Initialise UART and set baudrate
 Input: baudrate
 Returns: none
 ******************************************************************/

{
    unsigned char UART_TXHead;
  unsigned char UART_TXTail;
  unsigned char UART_RXHead;
  unsigned char UART_RXTail;
  UART_TXHead = 0;
  UART_TXTail = 0;
  UART_RXHead = 0;
  UART_RXTail = 0;

  UCSRB |= (1<<TXEN) |(1<<RXEN);  // tx/rx enable
    UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron 8N1

#if F_CPU < 2000000UL && defined(U2X)
    UCSRA |= (1<<U2X);   /* improve baud rate error by using 2x clk */
    UBRRL = (F_CPU / (8UL * UART_BAUD)) - 1;
#else
    UBRRL = (F_CPU / (16UL * UART_BAUD)) - 1;
#endif
}



void uart_putc(unsigned char c)
{
    unsigned char tmphead;


    tmphead  = UART_TxHead + 1;

    while ( tmphead == UART_TxTail ){
        ;/* wait for free space in buffer */
    }


  UART_TxBuf[tmphead] = c;

    UART_TxHead = tmphead;

    /* enable UDRE interrupt */
    UART0_CONTROL    |= _BV(UART0_UDRIE);

}



void uart_puts (char *s)


/**********************************************************************
 Function: Uart_puts()
 Purpose: Transmit string to UART
 Input: String to be transmitted
 Returns: none
 **********************************************************************/

{
    while (*s)
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
        uart_putc(*s);
        s++;
    }
}



unsigned int uart_getc(void)
{
    unsigned char tmptail;
    unsigned char c;
  //unsigned char data;


    if ( UART_RxHead == UART_RxTail ) {
        return UART_NO_DATA;   /* no data available */
    }

    /* calculate /store buffer index */
    tmptail = UART_RxTail + 1;
    UART_RxTail = tmptail;

    /* get data from receive buffer */
    c = UART_RxBuf[tmptail];


    return (UART_LastRxError << 8) + c;

}

von Karl H. (kbuchegg)


Lesenswert?

In deinem Programm ist ziemlich viel falsch.

Fangen wir mal damit an:
1
unsigned int uart_getc(void)
2
{
3
    unsigned char tmptail;
4
    unsigned char c;
5
  //unsigned char data;
6
7
8
    if ( UART_RxHead == UART_RxTail ) {
9
        return UART_NO_DATA;   /* no data available */
10
    }
11
12
    /* calculate /store buffer index */
13
    tmptail = UART_RxTail + 1;
14
    UART_RxTail = tmptail;
15
16
    /* get data from receive buffer */
17
    c = UART_RxBuf[tmptail];
18
19
20
    return (UART_LastRxError << 8) + c;
21
22
}

Wenn du abfrägst
  if ( UART_RxHead == UART_RxTail )

musst du dich auch mal fragen, wie denn UART_RxHead bzw.
UART_RxTail jemals seinen Wert ändern kann. Da die Variable
das nicht von alleine tun wird, wirst du wahl einen Interrupt
brauchen, der von der UART Hardware ausgelöst wird wenn ein
Zeichen empfangen wird.

Beschäftige dich mal mit einer Vorstufe zu deinem Buffer:
Empfang von Zeichen, wobei beim Empfang eine Interrupt
Funktion aufgerufen werden soll. Im einfachsten Fall
gibt die Interrupt Funktion das Zeichen einfach wieder aus
(das ist dein erstes zu erreichendes Ziel). Dann gehts weiter:
Die Interrupt Funktion speichert das Zeichen in einem Buffer.


von Marie (Gast)


Lesenswert?

 Hallo herr Karl heinz Buchegger,
du hast recht mit diener aussage. ich versuche zu schreiben wie du 
gesagt hast aber es klap immer nicht. ich glaube es hängt von meine 
fähigkeit zu programmiert ich bin eine anfängerin in diesem themas ich 
hatte vorher noch nicht eine controller programmiert. und jetzt brauche 
ich dieses programm um weiter zu kommen mit meiner Arbeit. die 
microcontroller ist nur eine zwischen fall in meiner Arbeit. Bitte wenn 
du schon eine solche programm mit Interrupt geschieben hat kannst du mir 
das senden? es wurde mir sehr helfen

Merci vorraus
MFG
Marie

von Karl H. (kbuchegg)


Lesenswert?

In dem Fall empfehle ich dir das Rad nicht
noch mal neu zu erfinden, sondern dir eine
fertige UART Library zu benutzen.

zb. bei Peter Fleury findest du sowas
http://jump.to/fleury

Unter AVR-Software die 'Uart Library'.

von Marie (Gast)


Lesenswert?

ich habe auch dem library von peter fleury geschaut und herlich gesagt 
ich weiß nict wie ich mit den anfangen kann. weil dort gibt es 3 coden: 
die Test_uart, die uart.c, und die uart.h
soll ich die drei code combienieren? wenn du in meine code schaust du 
kann sehen das meine function getc() und putc() sind nur eine copie die 
von peter fleury.
ich bitte dich noch mal wenn du eine solche programm schreiben kannst 
bitte helfe mir
danke
MFG
Marie

von Karl H. (kbuchegg)


Lesenswert?

Es hilft alles nichts.
Du musst dich damit auseinandersetzen, wie man in C
eine Interruptfunktion macht.

Im Moment versuchst du zu laufen, bevor du gehen
kannst. Du musst mit den Grundlagen anfangen.

> soll ich die drei code combienieren?

Nein. uart.c und uart.h werden zu deinem Projekt
hinzugefügt. Die test_uart zeigt nur, wie man
die Bibliothek verwendet, welche Aufrufe es gibt.
Anstatt test_uart.c kommt dann deine Applikation
zum Einsatz.

Hast du denn schon mal versucht, dieses Testprogramm
so wie es ist zum laufen zu bringen?

von Marie (Gast)


Lesenswert?

nein ich habe es noch nicht. es ist ja klar das ich muss mit den 
Grundlagen anfangen. ich habe dieses library mehr mal gelesen und 
versucht wie ich kann mit den anfangen aber bis jetzt hat es nicht 
geklappt. ich weiss das die lösung steht da drin aber ich weiss nicht 
wie ich die kriegen kann. deeswegen braucht das Hilfe eines Expert. 
bitte Karl wie kann ich das machen? glaube mir ich habe schon mit meines 
verständnis alles versucht.

von Karl H. (kbuchegg)


Lesenswert?

> nein ich habe es noch nicht.

Also das erste was ich immer mache, wenn ich mir von irgendwo
eine Bibliothek hole: Ich schaue nach ob es ein Testprogramm
gibt. Wenn ja (und in dem Fall gibt es eines), dann probiere
ich das mal aus!

Anchliessend fange ich meistens an mit dem Testprogramm ein
bischen rumzuspielen um zu sehen wie denn die Aufrufe funktionieren.

Also: Warum probierst du nicht einfach mal aus ob die
uart.c / uart.h  überhaupt auf deinem System funktionieren.
Anschliessend kannst du immer noch anfangen in test_uart.c
mal ein paar Veränderungen zu machen. Und dann kannst du immer
noch anfangen dich in uart.c einzulesen und zu versuchen zu
verstehen, wie denn das überhaupt funktioniert.

Und nein: Ich werde da jetzt nichts programmieren.

von Karl H. (kbuchegg)


Lesenswert?

Lies dir das hier
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmieren_mit_Interrupts
mal durch

Und danach schaust du ins Datenblatt deines Prozessors und
liest im UART Abschnitt nach, welche Interrupts es gibt,
und wann sie ausgelöst werden.

Danach schreibst du ein Programm, dass eine ISR aufsetzt,
die genau dann aufgerufen wird, wenn die UART ein Zeichen
empfangen hat. Die ISR kann zb. eine LED einschalten wenn
das der Fall ist.

Wenn du soweit bist, hast du auch mehr Verständnis davon,
wie die Sache mit den Interrupts funktioniert und kannst
ja mal Nachschauen was den Peter Fleury in seinem Interrupt-
handler (der bei ihm noch SIGNAL und nicht ISR heist) so alles
treibt.

von Marie (Gast)


Lesenswert?

danke karl ich versuche es mal.
und ich schaue ob es klapp
MFG
Marie

von Marie (Gast)


Lesenswert?

Hallo Karl,
ich probiere mal mit dem Test programm von Peter Fleury aber bei der 
kompilierung krieg ich einigen fehler meldung. ich zeigt dir die code 
und die meldungen und sagt mir bitte wie ich dieser fehler korrigieren 
kann
danke



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

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

#define UART_FRAME_ERROR      0x0800              /* Framing Error by 
UART       */
#define UART_OVERRUN_ERROR    0x0400              /* Overrun condition 
by UART   */
#define UART_BUFFER_OVERFLOW  0x0200              /* receive ringbuffer 
overflow */
#define UART_NO_DATA          0x0100              /* no receive data 
available   */


/* define CPU frequency in Mhz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 4000000UL
#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();

    /*
     *  Transmit string to UART
     *  The string is buffered by the uart library in a circular buffer
     *  and one character at a time is transmitted to the UART using 
interrupts.
     *  uart_puts() blocks if it can not write the whole string to the 
circular
     *  buffer
     */
    uart_puts("String stored in SRAM\n");

    /*
     * Transmit string from program memory to UART
     */
    uart_puts_P("String stored in FLASH\n");


    /*
     * Use standard avr-libc functions to convert numbers into string
     * before transmitting via UART
     */
    itoa( num, buffer, 10);   // convert interger into string (decimal 
format)
    uart_puts(buffer);        // and transmit string to UART


    /*
     * Transmit single character to UART
     */
    uart_putc('\r');

    for(;;)
    {
        /*
         * Get received character from ringbuffer
         * uart_getc() returns in the lower byte the received character 
and
         * in the higher byte (bitmask) the last receive error
         * UART_NO_DATA is returned when no data is available.
         *
         */
        c = uart_getc();
        if ( c & UART_NO_DATA )
        {
            /*
             * no data available from UART
             */
        }
        else
        {
            /*
             * new data available from UART
             * check for Frame or Overrun error
             */
            if ( c & UART_FRAME_ERROR )
            {
                /* Framing Error detected, i.e no stop bit detected */
                uart_puts_P("UART Frame Error: ");
            }
            if ( c & UART_OVERRUN_ERROR )
            {
                /*
                 * Overrun, a character already present in the UART UDR 
register was
                 * not read by the interrupt handler before the next 
character arrived,
                 * one or more received characters have been dropped
                 */
                uart_puts_P("UART Overrun Error: ");
            }
            if ( c & UART_BUFFER_OVERFLOW )
            {
                /*
                 * We are not reading the receive buffer fast enough,
                 * one or more received character have been dropped
                 */
                uart_puts_P("Buffer overflow error: ");
            }
            /*
             * send received character back
             */
            uart_putc( (unsigned char)c );
        }
    }

}


fehler meldungen:


Linking: uart1.elf
avr-gcc -mmcu=atmega16 -I. -gstabs -DF_CPU=8000000UL -Os -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -Wall 
-Wstrict-prototypes -Wa,-adhlns=uart1.o  -std=gnu99 -Wundef -MMD -MP -MF 
.dep/uart1.elf.d uart1.o --output uart1.elf -Wl,-Map=uart1.map,--cref 
-lm
uart1.o: In function `main':
uart1.c:39: undefined reference to `UART_BAUD_SELECT'
uart1.c:39: undefined reference to `uart_init'
uart1.c:53: undefined reference to `uart_puts'
uart1.c:58: undefined reference to `uart_puts_P'
uart1.c:66: undefined reference to `uart_puts'
uart1.c:72: undefined reference to `uart_putc'
uart1.c:83: undefined reference to `uart_getc'
uart1.c:99: undefined reference to `uart_puts_P'
uart1.c:108: undefined reference to `uart_puts_P'
uart1.c:116: undefined reference to `uart_puts_P'
make.exe: *** [uart1.elf] Error 1

> Process Exit Code: 2
> Time Taken: 00:01

von Johannes M. (johnny-m)


Lesenswert?

> //#include "uart.h"
> //#include <avr/uart.h>
Ich kenne zwar die Fleury-Lib nicht, aber für eine Version musste Dich 
schon entscheiden, je nachdem, wo Du die Bibliothek hinkopiert hast. 
Wenn Du keine der Headerdateien einbindest, kennt er natürlich die 
ganzen Funktionen nicht, und dann gibts für jede eine Fehlermeldung...

Also wie Karl Heinz schon angedeutet hat: Die uart.h mit #include 
einbinden und die uart.c zu den Source-Dateien hinzufügen (entweder im 
Makefile oder im AVRStudio im "Projektbaum").

von Patrick K. (kaplan)


Lesenswert?

du muss die uart.h auf jedenfall "includen". also nicht auskommentieren.

eine moeglichkeit:

kopier die uart.h und uart.c vom Fleury in dein projektordner deines 
programmes und sag im AVR Studio (falls du das benutzt) add source file 
(und waehl die uart.c aus)
und anschliessend auf "add existing header files" und waehl die uart.h.

in deinem hauptprogramm musst dann uart.h einbezogen werden:


folgende Zeilen muessen in deinem (test)programm sein:
1
#include "uart.h"
2
#define UART_BAUD_RATE 57600

1
int main(){
2
      
3
  sei();   //now enable interrupt, since UART library is interrupt controlled
4
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
5
        uart_putc(0xAA);       // 'AA' vesenden als Char
6
        uart_puts("Hello World!");         //ein String verschicken usw

ps: parlez vous francais?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.