Forum: Compiler & IDEs falsche Zuweisung


von gast (Gast)


Lesenswert?

ich fange an mit gcc und habe ein Problem mit meine Serielle 
Kommunikation.
Hier unten ein Teil des Kodes.
1
#define UART_TX_BUFFER_SIZE 32
2
...
3
static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
4
....
5
unsigned char tmptail;
6
....
7
UDR = UART_TxBuf[tmptail];
8
....

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

von P. S. (Gast)


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.

von gast (Gast)


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
1
#ifndef F_CPU
2
#warning "F_CPU was not defined yet, now make up with 4000000"
3
#define F_CPU 4000000L   // Systemtakt in Hz 
4
#endif
5
6
7
#define BAUD 9600L
8
#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)     //clever round
9
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //real baud rate
10
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)     //Error per thousand
11
12
13
#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
14
#error Systematic error in the baud rate more than 1% and thus too high!
15
#endif
16
17
18
#include <avr/io.h>
19
#include <avr/interrupt.h>
20
#include <stdlib.h>
21
#include <inttypes.h>
22
#include <util/delay.h>
23
24
/** Size of the circular transmit buffer, must be power of 2 */
25
#ifndef UART_TX_BUFFER_SIZE
26
#define UART_TX_BUFFER_SIZE 32
27
#endif
28
29
/* size of TX buffers */
30
#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
31
32
#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
33
#error TX buffer size is not a power of 2
34
#endif
35
36
37
/*
38
 *  module global variables
39
 */
40
static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
41
static volatile unsigned char UART_TxHead;
42
static volatile unsigned char UART_TxTail;
43
44
SIGNAL(SIG_UART_DATA)
45
{
46
    unsigned char tmptail;
47
  unsigned char wert;
48
49
    
50
    if ( UART_TxHead != UART_TxTail)
51
  {
52
        /* calculate and store new buffer index */
53
        tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
54
        UART_TxTail = tmptail;
55
        /* get one byte from buffer and write it to UART */    
56
        UDR = UART_TxBuf[tmptail];  /* start transmission */
57
    }
58
  else
59
  {
60
        /* tx buffer empty, disable UDRE interrupt */
61
        UCSRB &= ~_BV(UDRIE);
62
    }
63
}
64
65
void USART_Init() 
66
{
67
  UART_TxHead = 0;
68
  UART_TxTail = 0;
69
    
70
  UBRRH = (unsigned char)(UBRR_VAL>>8);  // Set baud rate
71
  UBRRL = (unsigned char)UBRR_VAL;
72
  
73
  // Enable transmitter and Interrupt
74
  UCSRB |= (1<<TXCIE)|(1<<RXEN)|(1<<TXEN);
75
  
76
  UCSRC = (1<<URSEL) | (1<<UCSZ1)|(1<<UCSZ0); //format:8data, 1stop b      
77
}
78
79
80
void USART_Putc(unsigned char c)
81
{
82
    unsigned char tmphead;
83
84
    
85
    tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
86
    
87
    while ( tmphead == UART_TxTail ){
88
        ;/* wait for free space in buffer */
89
    }
90
    
91
    UART_TxBuf[tmphead] = c;
92
    UART_TxHead = tmphead;
93
  
94
    /* enable UDRE interrupt */
95
   UCSRB    |= _BV(UDRIE);  
96
  
97
}//end USART_Putc()
98
99
// command sequences im EEPROM (first program Flash, then EEPROM)
100
unsigned char eeMenue[] EEMEM = { 0x02, 0x21, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x9D, 0x2A };
101
unsigned char eeExit[] EEMEM  = { 0x02, 0x21, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5C, 0x2A };
102
103
unsigned char cSend;
104
105
// Sends a 19 character command found in EEPROM
106
void SendCommand(unsigned int iNo)
107
{
108
  unsigned int i;  
109
  for  (i = (18 * iNo); i <= ((18 * iNo) + 18); i++ )
110
  {
111
  cSend = eeprom_read_byte(&eeMenue[i]);
112
  USART_Putc(cSend);
113
  }
114
}
115
116
int main(void)
117
{
118
119
  PORTD = 0x0C;    // pull ups for key inputs  PortD2 and portD3
120
 
121
  
122
   USART_Init();
123
   sei();
124
  iState = 0;
125
  for(;;)
126
    {  
127
  if (iState != PIND)  // Key state changed ?
128
  {
129
    _delay_ms(50);
130
  if ((PIND & 0x08) == 0x00)
131
    SendCommand(0);
132
  else
133
  {
134
   if ((PIND & 0x04) == 0x00)
135
      SendCommand(1);
136
  }
137
        _delay_ms(1000);// dirty "debounce"
138
    }
139
}

von Klaus W. (mfgkw)


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...

von gast (Gast)


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?

von P. S. (Gast)


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.

von gast (Gast)


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.

von Random .. (thorstendb) Benutzerseite


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:
1
void SendString(char *string)
2
{
3
  while(*string)
4
  {
5
    while(UART->SR & TX_BUSY);   // Uart Status Register
6
    UART->DATA = *string++;      // Uart Data Register
7
  }
8
}

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

Genaugenommen schreibt man sich eigentlich eine
1
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.

von Random .. (thorstendb) Benutzerseite


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.

von Karl H. (kbuchegg)


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
1
void SendCommand( unsigned char iNo )
2
{
3
  unsigned char i;
4
5
#define BYTES_IN_COMMAND 19
6
7
  // jeweils 19 Bytes sind 1 Kommando
8
  iNo = BYTES_IN_COMMAND * iNo;
9
 
10
  for  (i = 0; i < BYTES_IN_COMMAND; i++ )
11
  {
12
    cSend = eeprom_read_byte(&eeMenue[ i + iNo ]);
13
    USART_Putc( cSend );
14
  }
15
}

von gast (Gast)


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!
1
#ifndef F_CPU
2
#warning "F_CPU was not defined yet, now make up with 4000000"
3
#define F_CPU 4000000L 
4
#endif
5
6
7
#define BAUD 9600L
8
#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)     //clever round
9
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //real baud rate
10
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)     //Error per thousand
11
12
13
#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
14
#error Systematic error in the baud rate more than 1% and thus too high!
15
#endif
16
17
18
#include <avr/io.h>
19
#include <stdlib.h>
20
#include <inttypes.h>
21
#include <util/delay.h>
22
23
24
25
void USART_Init(void) 
26
{
27
  
28
  UBRRH = (unsigned char)(UBRR_VAL>>8);  // Set baud rate
29
  UBRRL = (unsigned char)UBRR_VAL;
30
  
31
  UCSRB |= (1<<RXEN)|(1<<TXEN);    // Enable receiver and transmitter
32
  
33
  UCSRC = (1<<URSEL) | (1<<UCSZ0)|(1<<UCSZ1);  // Set frame format: 8data, 1stop bit        
34
35
}//end USART_Init()
36
37
38
void USART_Putc(unsigned char c)
39
{
40
    while (!(UCSRA & (1<<UDRE))); // Do nothing until data have been transmited 
41
    
42
  UDR = c;                 // Put data into Buffer, sends the data
43
  _delay_ms(10);   
44
}//end USART_Putc()
45
46
void USART_Puts (char *string)
47
{
48
    while( *string != '\0' )  //as long as *string != '\0' so unlike the "stringer end-character"
49
    {  
50
        USART_Putc(*string);
51
        string++;
52
    }
53
}//end USART_Puts()
54
55
int main(void) 
56
{
57
    USART_Init();
58
  
59
    USART_Puts("Kommunikation Test");
60
   return 0;                     
61
} //end main()

von gast (Gast)


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
1
/* get one byte from buffer and write it to UART */    
2
        UDR = UART_TxBuf[tmptail];  /* start transmission */
1
/* get one byte from buffer and write it to UART */    
2
        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

von Karl H. (kbuchegg)


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.
1
void USART_Puts( const char * text )
2
{
3
  while( *text )
4
    USART_Putc( *text++ );
5
}
6
7
void USART_PutNibble( unsigned char nibble )
8
{
9
  if( nibble < 0x0A )
10
    USART_Putc( nibble + '0' );
11
  else
12
    USART_Putc( nibble - 10 + 'A' );
13
}
14
15
void USART_PutHex( unsigned char byte )
16
{
17
  USART_Puts( "0x" );
18
  USART_PutNibble( byte >> 4 );
19
  USART_PutNibble( byte & 0x0F );
20
}
21
22
void SendCommand( unsigned char iNo )
23
{
24
  unsigned char i;
25
  unsigned char cSend;
26
27
#define BYTES_IN_COMMAND 19
28
29
  // jeweils 19 Bytes sind 1 Kommando
30
  iNo = BYTES_IN_COMMAND * iNo;
31
 
32
  for  (i = 0; i < BYTES_IN_COMMAND; i++ )
33
  {
34
    cSend = eeprom_read_byte(&eeMenue[ i + iNo ]);
35
    USART_PutHex( cSend );
36
  }
37
}

von gast (Gast)


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

von gast (Gast)


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.

von Karl H. (kbuchegg)


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
1
  USART_Putc( 'H' );
2
  USART_Putc( 'a' );
3
  USART_Putc( 'l' );
4
  USART_Putc( 'l' );
5
  USART_Putc( 'o' );

oder
1
  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
1
void USART_putInt( int number )
2
{
3
  char Buffer[10];
4
  itoa( number, Buffer, 10 );
5
  USART_Puts( Buffer );
6
}

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.

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


Lesenswert?

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

von P. S. (Gast)


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. :-/

von gast (Gast)


Lesenswert?

Danke an alle
ich schaue noch heute nachmittag what is the matter

danke nochmals

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.