mikrocontroller.net

Forum: Compiler & IDEs falsche Zuweisung


Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich fange an mit gcc und habe ein Problem mit meine Serielle 
Kommunikation.
Hier unten ein Teil des Kodes.
#define UART_TX_BUFFER_SIZE 32
...
static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
....
unsigned char tmptail;
....
UDR = UART_TxBuf[tmptail];
....


Beim Debuggen merkt ich das der Wert  UART_TxBuf[tmptail] ganz gut die 
richtige Werte kriegt (s. unten), aber UDR nicht.
Es sieht als ob die Zuweisung "UDR = UART_TxBuf[tmptail]" ungültig wäre.
und UDR bleibt leer.

Weiß jemand warum?
Danke

UART_TxBuf[...]
[0]   0
[1]   21
[2]   33
[3]   0
[4]   0
[5]   0
[6]   0
[7]   1
[8]   0
[9]   0
[10]  5
[11]  2
[12]  0
[...] ...
[32]  2

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Irgendwie faellt mir zunehmend auf, dass gerade die, die es am 
Noetigsten haben nur dann in's Forum gucken, wenn sie Hilfe brauchen. 
Sonst wuessten sie, dass sie

a) uebersetzbaren Code
b) verwendete Hardware
c) verwendete Tools
d) eine nachvollziehbare Fehlerbeschreibung

posten sollen.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok
Projekt: Befehlt an einem Gerät senden.

Hardware: STK 500 mit Atmega8 externe Quarz 4 Mhz, Fuses richtig 
eingestellt.

Tool AVR Studio 4, WinAVR-20090313
Kommunikation: format -> 8data, 1stop bit Baud 9600 auch beim Empfamger.

Probleme: Es erscheint am Terminal PC gar nichst am Bildschirm.
Beim Debuggen habe bemerkt das UDR  keinen Wert kriegt.

vielen Dank für eure Hilfe
#ifndef F_CPU
#warning "F_CPU was not defined yet, now make up with 4000000"
#define F_CPU 4000000L   // Systemtakt in Hz 
#endif


#define BAUD 9600L
#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)     //clever round
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //real baud rate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)     //Error per thousand


#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
#error Systematic error in the baud rate more than 1% and thus too high!
#endif


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

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

/* size of TX buffers */
#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)

#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
#error TX buffer size is not a power of 2
#endif


/*
 *  module global variables
 */
static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART_TxHead;
static volatile unsigned char UART_TxTail;

SIGNAL(SIG_UART_DATA)
{
    unsigned char tmptail;
  unsigned char wert;

    
    if ( UART_TxHead != UART_TxTail)
  {
        /* calculate and store new buffer index */
        tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
        UART_TxTail = tmptail;
        /* get one byte from buffer and write it to UART */    
        UDR = UART_TxBuf[tmptail];  /* start transmission */
    }
  else
  {
        /* tx buffer empty, disable UDRE interrupt */
        UCSRB &= ~_BV(UDRIE);
    }
}

void USART_Init() 
{
  UART_TxHead = 0;
  UART_TxTail = 0;
    
  UBRRH = (unsigned char)(UBRR_VAL>>8);  // Set baud rate
  UBRRL = (unsigned char)UBRR_VAL;
  
  // Enable transmitter and Interrupt
  UCSRB |= (1<<TXCIE)|(1<<RXEN)|(1<<TXEN);
  
  UCSRC = (1<<URSEL) | (1<<UCSZ1)|(1<<UCSZ0); //format:8data, 1stop b      
}


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

    
    tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
    
    while ( tmphead == UART_TxTail ){
        ;/* wait for free space in buffer */
    }
    
    UART_TxBuf[tmphead] = c;
    UART_TxHead = tmphead;
  
    /* enable UDRE interrupt */
   UCSRB    |= _BV(UDRIE);  
  
}//end USART_Putc()

// command sequences im EEPROM (first program Flash, then EEPROM)
unsigned char eeMenue[] EEMEM = { 0x02, 0x21, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x9D, 0x2A };
unsigned char eeExit[] EEMEM  = { 0x02, 0x21, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5C, 0x2A };

unsigned char cSend;

// Sends a 19 character command found in EEPROM
void SendCommand(unsigned int iNo)
{
  unsigned int i;  
  for  (i = (18 * iNo); i <= ((18 * iNo) + 18); i++ )
  {
  cSend = eeprom_read_byte(&eeMenue[i]);
  USART_Putc(cSend);
  }
}

int main(void)
{

  PORTD = 0x0C;    // pull ups for key inputs  PortD2 and portD3
 
  
   USART_Init();
   sei();
  iState = 0;
  for(;;)
    {  
  if (iState != PIND)  // Key state changed ?
  {
    _delay_ms(50);
  if ((PIND & 0x08) == 0x00)
    SendCommand(0);
  else
  {
   if ((PIND & 0x04) == 0x00)
      SendCommand(1);
  }
        _delay_ms(1000);// dirty "debounce"
    }
}
 

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum am PC nichts ankommt, steht auf einem anderen Blatt, aber
daß du aus UDR nicht das auslesen kannst, was du vorher reinschreibst,
ist normal.
UDR ist nämlich ein Register, sondern zwei.
In das eine schreibt man rein (das, was gesendet werden soll), aus
dem anderen liest man empfangene Zeichen aus.
Die beiden heißen nur zufällig gleich...

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Warum am PC nichts ankommt, steht auf einem anderen Blatt, aber
>daß du aus UDR nicht das auslesen kannst, was du vorher reinschreibst,
>ist normal.

Was meinst du damit?

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gast schrieb:

> Was meinst du damit?

Wenn du aus UDR liest, liest du das, was du auf der seriellen 
Schnittstelle empfaengst. Guck mal in deine eigene Empfangsroutine.

Wenn du wissen willst, ob du etwas sendest, mach entweder den 
Loopbacktest aus dem Tutorial oder nimm ein Oszi/Logicanalyzer.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mein UDR kriegt nicht und bis jetzt weiss ich nicht warum!!!
Also bitte ich um Hilfe falls jemand einen Fehler in meinem Kode sieht.

Autor: Random ... (thorstendb) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

a) wäre es schön, wenn du etwas lesbarer schreiben könntest. Je 
fehlerfreier ein Beitrag geschrieben ist, desto mehr Leute werden diesen 
lesen & ev. beantworten.

b) fehlt noch eine ganze Menge zu deinem Code. Was du beim Posten 
weggelassen hast, kann man hier logischerweise nicht erahnen, und meine 
Glaskugel ist gerade zur Reparatur.

Eine sendString sieht z.B. so aus:
void SendString(char *string)
{
  while(*string)
  {
    while(UART->SR & TX_BUSY);   // Uart Status Register
    UART->DATA = *string++;      // Uart Data Register
  }
}

Damit wartet man darauf, dass der Sendebuffer bereit ist, und schickt 
jeweils das nächste Zeichen eines Strings.

Genaugenommen schreibt man sich eigentlich eine
void sendchar(char c);
die dieses Low-Level-Handling übernimmt, und füttert die mit Daten (z.B. 
aus fputc, einer SendString, o.ä.


VG,
/th.

Autor: Random ... (thorstendb) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gast schrieb:
> mein UDR kriegt nicht
Dann wohl UART kaaaputtt...

> und bis jetzt weiss ich nicht warum!!!
auch nix wisse, warum.

> Also bitte ich um Hilfe falls jemand einen Fehler in meinem Kode sieht.
Glaskugel putt.

Poste bitte mal den ganzen Code.

VG,
/th.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gast schrieb:

> Probleme: Es erscheint am Terminal PC gar nichst am Bildschirm.

Womit siehst du dir das Übertragene an?

Mit einem Terminalprogramm im ASCII Modus?
Da wunderst es mich dann wenig, dass du nichts siehst, du überträgst ja 
praktisch nur ASCII Zeichen, die keine visuelle Repräsentierung haben 
(mit Ausnahme von 0x21, 0x32, 0x2A, 0x5C und 0x9D. Wobei der Himmel 
alleine weiß, welches Zeichen dein Terminal für 0x9D anzeigen wird)

PS: Die Berechnungen in SendCommand solltest du nochmal durchschauen. 
Insbesondere dann, wenn iNo gleich 1 ist.

PS2: Wenn in einer for-Schleife die sich mit Arrays beschäftigt im 
Bedingungsteil ein <= vorkommt, kann man in 90% aller Fälle davon 
ausgehen, dass da was faul ist. Du hast dir mit der komplizierten 
Formulierung ganz einfach selber ein Eigentor geschossen. Solange du das 
nicht überblicken kannst, quetche nicht alles in eine Berechnung 
zusammen
void SendCommand( unsigned char iNo )
{
  unsigned char i;

#define BYTES_IN_COMMAND 19

  // jeweils 19 Bytes sind 1 Kommando
  iNo = BYTES_IN_COMMAND * iNo;
 
  for  (i = 0; i < BYTES_IN_COMMAND; i++ )
  {
    cSend = eeprom_read_byte(&eeMenue[ i + iNo ]);
    USART_Putc( cSend );
  }
}

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe einen Test gemacht.
Der Kode läuft ganz gut und es erscheint am Terminal PC:  Kommunikation 
Test.

Aber der Fehler in den anderen Kode finde ich nicht!
#ifndef F_CPU
#warning "F_CPU was not defined yet, now make up with 4000000"
#define F_CPU 4000000L 
#endif


#define BAUD 9600L
#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)     //clever round
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //real baud rate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)     //Error per thousand


#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
#error Systematic error in the baud rate more than 1% and thus too high!
#endif


#include <avr/io.h>
#include <stdlib.h>
#include <inttypes.h>
#include <util/delay.h>



void USART_Init(void) 
{
  
  UBRRH = (unsigned char)(UBRR_VAL>>8);  // Set baud rate
  UBRRL = (unsigned char)UBRR_VAL;
  
  UCSRB |= (1<<RXEN)|(1<<TXEN);    // Enable receiver and transmitter
  
  UCSRC = (1<<URSEL) | (1<<UCSZ0)|(1<<UCSZ1);  // Set frame format: 8data, 1stop bit        

}//end USART_Init()


void USART_Putc(unsigned char c)
{
    while (!(UCSRA & (1<<UDRE))); // Do nothing until data have been transmited 
    
  UDR = c;                 // Put data into Buffer, sends the data
  _delay_ms(10);   
}//end USART_Putc()

void USART_Puts (char *string)
{
    while( *string != '\0' )  //as long as *string != '\0' so unlike the "stringer end-character"
    {  
        USART_Putc(*string);
        string++;
    }
}//end USART_Puts()

int main(void) 
{
    USART_Init();
  
    USART_Puts("Kommunikation Test");
   return 0;                     
} //end main()


Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Womit siehst du dir das Übertragene an?

Zuerst danke für deinen HIlfe

ja mit einem Terminalprogramm im ASCII Modus.
Ich habe gerade noch etwas getestet. (S. erste Kode)

anstatt
/* get one byte from buffer and write it to UART */    
        UDR = UART_TxBuf[tmptail];  /* start transmission */
/* get one byte from buffer and write it to UART */    
        UDR = 0;  /* start transmission */

Am Terminalprogramm kriege ich 
<0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0>

Das heisst mein Terminalprogramm kann meine Zeichen ganz gut übertragen 
oder!!!

>PS: Die Berechnungen in SendCommand solltest du nochmal durchschauen.
>Insbesondere dann, wenn iNo gleich 1 ist.

bin ich dabei

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gast schrieb:

> Am Terminalprogramm kriege ich
> <0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0>
>
> Das heisst mein Terminalprogramm kann meine Zeichen ganz gut übertragen
> oder!!!

Anzeigen, nicht übertragen.
Und du siehst nur, dass es für 0x00 eine Anzeige hat.
Ob und was es aus den restlichen Bytes macht, welche keine anzeigbare 
Darstellung haben, steht in den Sternen.

Aber da du anscheinend sowieso nur daran interessiert bist, welche Bytes 
aus dem EEPROM gelesen werden, warum machst du dir nicht einfach eine 
SendFunktion die ein Byte in seiner HexForm anzeigen kann. Ist doch 
simpel.
void USART_Puts( const char * text )
{
  while( *text )
    USART_Putc( *text++ );
}

void USART_PutNibble( unsigned char nibble )
{
  if( nibble < 0x0A )
    USART_Putc( nibble + '0' );
  else
    USART_Putc( nibble - 10 + 'A' );
}

void USART_PutHex( unsigned char byte )
{
  USART_Puts( "0x" );
  USART_PutNibble( byte >> 4 );
  USART_PutNibble( byte & 0x0F );
}

void SendCommand( unsigned char iNo )
{
  unsigned char i;
  unsigned char cSend;

#define BYTES_IN_COMMAND 19

  // jeweils 19 Bytes sind 1 Kommando
  iNo = BYTES_IN_COMMAND * iNo;
 
  for  (i = 0; i < BYTES_IN_COMMAND; i++ )
  {
    cSend = eeprom_read_byte(&eeMenue[ i + iNo ]);
    USART_PutHex( cSend );
  }
}

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke an alle für die schnelle Antworten.

>Poste bitte mal den ganzen Code.
habe ich als zweite Post

>fehlt noch eine ganze Menge zu deinem Code. Was du beim Posten
>weggelassen hast, kann man hier logischerweise nicht erahnen, und meine
>Glaskugel ist gerade zur Reparatur.

Für mih wäre alles!!!
dann vielleich liegt meinem Fehler

>void SendString(char *string)
>{
  >while(*string)
  >{
   > while(UART->SR & TX_BUSY);   // Uart Status Register
   > UART->DATA = *string++;      // Uart Data Register
  >}
>}

meinst du, dass ich die Funktion brauche !?!
Ich sende keine String!! sondern nur ASCII Zeichen !!
Ich bin neu bitte sagen Sie mir ob ich mir irre

danke

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Anzeigen, nicht übertragen.
>Und du siehst nur, dass es für 0x00 eine Anzeige hat.
>Ob und was es aus den restlichen Bytes macht, welche keine anzeigbare
>Darstellung haben, steht in den Sternen.

Danke für die Antwort

eingentlcih möchte ich Am Terminalprogramm das Angezeigt kriegen
<2><33><1><0><0><0><0><0><0><0><0><0><0><0><0><0><3><157><42>

Weil übertragen will ich an meinem Gerät Den Befehlt senden.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gast schrieb:

>>void SendString(char *string)
>>{
>   >while(*string)
>   >{
>    > while(UART->SR & TX_BUSY);   // Uart Status Register
>    > UART->DATA = *string++;      // Uart Data Register
>   >}
>>}
>
> meinst du, dass ich die Funktion brauche !?!

Eine String-Funktion kann man immer brauchen.
Aber die hier passt nicht zu deinen restlichen USART-Funktionen (*).
Am einfachsten und am wenigsten fehlerträchtig ist es normalerweise, 
wenn man die String-Funktion so aufbaut, dass sie die 
Einzelzeichen-Funktion in einer Schleife mit den einzelnen Zeichen 
füttert. Dann sind die Details, wie ein Zeichen versendet wird, nur in 
einer Funktion beisammen und man bekommt keinen Wickel, wenn 
Einzelzeichen-Senden und String-Senden abwechselnd benutzt wird.

> Ich sende keine String!! sondern nur ASCII Zeichen !!

Ein String ist eine Folge von ASCII Zeichen.

Was ist dir lieber
  USART_Putc( 'H' );
  USART_Putc( 'a' );
  USART_Putc( 'l' );
  USART_Putc( 'l' );
  USART_Putc( 'o' );

oder
  USART_Puts( "Hallo" );

Wenn man eine USART hat, braucht man praktisch immer eine Stringausgabe 
in irgendeiner Form. Und sei es nur, dass man Zahlen ausgeben möchte
void USART_putInt( int number )
{
  char Buffer[10];
  itoa( number, Buffer, 10 );
  USART_Puts( Buffer );
}

Sieh diese Funktionen als Baukasten an, die du bei Bedarf benutzt, und 
wo sich eine Funktion auf die anderen stützt. Ganz unten steht die 
Einzelzeichenausgabe. Alle anderen Ausgaben landen letztendlich dort.

Ausserdem sind die Ausgabefunktionen normalerweise nicht sehr lang, 
sodass man davon ausgehen kann, diesen Flash-Speicher praktisch immer 
zur Verfügung zu haben.


(*) Edit:
Ich habe noch nicht mitbekommen, dass du zwischendurch den Ringbuffer 
über Bord geschmissen hast.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gast schrieb:
>>Anzeigen, nicht übertragen.
>>Und du siehst nur, dass es für 0x00 eine Anzeige hat.
>>Ob und was es aus den restlichen Bytes macht, welche keine anzeigbare
>>Darstellung haben, steht in den Sternen.
>
> Danke für die Antwort
>
> eingentlcih möchte ich Am Terminalprogramm das Angezeigt kriegen
> <2><33><1><0><0><0><0><0><0><0><0><0><0><0><0><0><3><157><42>

Na dann mach das doch!

Alledings musst du dir im klaren sein, dass DU dafür verantworltich 
bist, dass die Zahlen richtig kommen, dass die '<' und '>' richtig 
ausgegeben werden.

PS: Ob das so sinnvoll ist, die Anzeige mit Dezimalzahlen zu machen, 
wenn du in deinem C-Programm dieselben Zahlen in Hex-Form eingibst, 
solltest du nochmal überprüfen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mann, einige dich jetzt mit dir selber bitte mal, welche Form der 
UART-Routinen du benutzen willst.
Mit Ringbuffer oder ohne.

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vergiss es, es handelt sich offensichtlich um den droeflhundertsten der 
meint man koennte programmieren indem man ein paar Beispielsourcen 
zusammenklebt und die Trottel im Forum den Rest machen laesst. :-/

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke an alle
ich schaue noch heute nachmittag what is the matter

danke nochmals

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.