C Adresse vom Array?!

Janiiix3

Aktives Mitglied
28. Sep. 2013
1.333
10
38
Hannover
Sprachen
  1. ANSI C
  2. C#
Mooin ;)

ich habe mal wieder ein Problemchen.. :(
Versuche gerade was mit einem "HC06" Bluetooth Modul auf zu bauen.
Empfangen und alles klappt soweit.

Nun benutze ich die UART Bibliothek von "Peter Flury".
Dort ist das Empfangen mit einem Buffer realisiert.



CodeBox C
static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];


Wenn ich was auf dem Puffer auslesen möchte, gibt es die Funktion..


CodeBox C
unsigned int uart_getc(void)
{  


unsigned char tmptail;
unsigned char data;

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

}

/* calculate /store buffer index */

tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
UART_RxTail = tmptail;



/* get data from receive buffer */

data = UART_RxBuf[tmptail];

data = (UART_LastRxError << 8) + data;
UART_LastRxError = 0;
return data;

}/* uart_getc */


Wenn ich diese Funktion nutze und den Speicherinhalt von diesem Puffer in einen anderen kopiere, klappt es.

Schreibe ich in den Puffer, den String statisch rein, den ich eigentlich erwarte, klappt es auch.


CodeBox C
while(1)
{

[I]strcpy[/I]((char*)UART_RxBuf,"LEDon");
getState((char*)UART_RxBuf);
}


Laut Terminal empfange ich auch genau diesen String, also diese Zeichen empfange ich richtig und ohne Sonderzeichen.

Hat jemand eine Idee?
 
Hallo Jan,

du schreibst eigentlich, dass mehrere Sachen "klappen". Was funktioniert denn nun nicht, wo liegt dein Problem?

Und du möchtest wissen, wie man an die Adresse eines Arrays heran kommt?

Dirk :ciao:
 
Ich weiß nicht wie ich das beschreiben soll, so das es jeder versteht :D
Also, immer wenn ich ein Zeichen empfange, wird dieses in diesen Buffer geschrieben, diesen Buffer möchte ich jetzt einfach mal ausgeben ohne die Funktion "uart_getc()" zu nutzen.



CodeBox C
ISR (UART0_RECEIVE_INTERRUPT)


/*************************************************************************

Function: UART Receive Complete interrupt

Purpose: called when the UART has received a character

**************************************************************************/

{

unsigned char tmphead;

unsigned char data;

unsigned char usr;

unsigned char lastRxError;





/* read UART status register and UART data register */


usr = UART0_STATUS;

data = UART0_DATA;



/* */


#if defined( AT90_UART )

lastRxError = (usr & (_BV(FE)|_BV(DOR)) );

#elif defined( ATMEGA_USART )

lastRxError = (usr & (_BV(FE)|_BV(DOR)) );

#elif defined( ATMEGA_USART0 )

lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) );

#elif defined ( ATMEGA_UART )

lastRxError = (usr & (_BV(FE)|_BV(DOR)) );

#elif defined( AT90USB_USART )

lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) );

#endif



/* calculate buffer index */


tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK;



if ( tmphead == UART_RxTail ) {

/* error: receive buffer overflow */


lastRxError = UART_BUFFER_OVERFLOW >> 8;

}else{

/* store new index */


UART_RxHead = tmphead;

/* store received data in buffer */


UART_RxBuf[tmphead] = data;

}

UART_LastRxError |= lastRxError;


}



Hier wird der Buffer beschrieben, diesen möchte ich einfach mal Ausgeben lassen. Wenn ich was Empfangen habe und diesen Ausgeben will, erscheint aber nichts?!
 
Ich vermute, dass die Uart-Funktionen einen FiFo Buffer realisieren, dann kannst du nicht einfach ab Index 0 des Buffers einen String ausgeben.

Du müsstest ab dem letzten Lese-Index auslesen, bzw. diese Adresse verwenden.

Ich habe jetzt leider nicht so die Zeit, mir die Lib anzusehen.

Im Prinzip gehts so:

&MeinRingBuffer[LeseIndex]

Dies ist die Adresse des ersten zu lesenden Zeichens im Buffer.
Vorher sollte man ggf. noch prüfen, ob etwas zu lesen ist und wenn wieviele Daten. Da müsstest du dir die Funktionen in der Lib anschauen.

Dirk :ciao:
 
Das leuchtet mir ein, habe ich schon Probiert.


CodeBox C
unsigned int uart_getc(void)
{    

unsigned char tmptail;
unsigned char data;




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

}

/* calculate /store buffer index */

tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
[B]UART_RxTail = tmptail;[/B]

/* get data from receive buffer */

data = UART_RxBuf[tmptail];

data = (UART_LastRxError << 8) + data;
UART_LastRxError = 0;
return data;

}/* uart_getc */


Ich habe den Index mal FETT markiert. Ab da lese ich auch aus, das klappt jedoch nicht.



CodeBox C
uart_puts("LiveMessage\r\n");
uart_puts((char*)&UART_RxBuf[UART_RxTail]);
 
Probiere mal vorher den Index um 1 zu erhöhen ...



CodeBox C
uart_puts((char*)&UART_RxBuf[UART_RxTail+1]);


Siehe auch Zeile 17 und 18 in der ersten Codebox.
 
Leider nach wie vor das gleiche Ergebnis..
 
Dann habe ich im Moment auch keine weitere Idee mehr. Ich müsste mal in die Lib reinschauen ... nur fehlt mir die Zeit dafür :(

Vielleicht hat ja sonst noch jemand eine Idee.
 


CodeBox C
while(1)

{


unsigned char tmpBuff[UART_RX_BUFFER_SIZE];
unsigned char *tmpBuffPtr = &tmpBuff[0];

uart_puts("LiveMessage\r\n");

/* So werden die Bytes nacheinander verschickt. Das haut hin. */

//uart_putc(uart_getc());

/* Warum werden hier nicht die empfangenen Daten rüber kopiert? */

while(*tmpBuffPtr != '\0')
{
*tmpBuffPtr++ = uart_getc();
}
uart_puts((char*)tmpBuffPtr);
uart_puts("\r\n");
[I]_delay_ms[/I](250);
}
 
Wenn du deinen Buffer füllst und danach mit _puts einen String ausgeben möchtest, zeigt dein Pointer auf den Index nach dem String, bzw. nach dem letzten empfanenen Zeichen.

Noch ein Hinweis:
uart_getc gibt uint16_t zurück, das solltest du ggf. noch berücksichtigen (Fehlerbehandlung o. ä)
 
Achja..! Stimmt ja!

Das heißt würde ich es mit dem Pointer machen, müsste ich die Länge ermitteln und das später von der aktuellen Adresse abziehen..
Was geht schneller bzw. ist Effektiver..

Mit for arbeiten oder eher mit einem Pointer?
 
Du hast es hier mit einem Ringbuffer zu tun. Um diesen Ringbuffer auszulesen, empfiehlt es sich, die gleiche Funktionalität zu benutzen, wie die Funktion uart_getc().

Warum also nicht gleich diese schon vorhandene Funktion benutzen?
 
Habe ich jetzt so gemacht. Da ich nicht jedes Byte einzeln testen möchte, habe ich mich für einen ganzen String entschieden.



CodeBox C
unsigned char tmpBuff[UART_RX_BUFFER_SIZE];


for([I]uint8_t[/I] x = 0 ; x < UART_RX_BUFFER_SIZE ; x++)
{
tmpBuff[x] = uart_getc();
}

uart_puts((char*)tmpBuff);
int8_t indexOfCmd = 0x00;
indexOfCmd = readCmd((char*)tmpBuff,"LEDoff",allowedCmd);


Ich habe gehofft das ich den vorhandenen Puffer schon nehmen hätte können.
So muss ich das ganze um kopieren und verschwende doppelten Speicher..
 
Müssen nicht sowieso irgendwann alle Daten mit (einer) der bibliothekseigenen Lesemethode(n) aus dem Puffer gelesen werden (eine eventuelle Buffer-Clear-Methode zählt dazu), um einen früher oder später auftretenden Bufferoverrun zu verhindern?
Ob man die gelesenen Daten zur Weiterverwendung speichert, oder verwirft ist ja egal...

P.S.: Wie sehen denn die zu sendenden/zu empfangenen Telegramme aus?
Möglicherweise wäre es für Dich besser, eben keine vorhandene Ringpuffer-Bilbiothek zu verwenden, sondern eigene "lineare Puffer" mit, auf die Telegrammstruktur angepaßten Schreib-/Leseroutinen zu implementieren...
 
Zuletzt bearbeitet:
Hmmm...wuerde mich in den teil der empfangsroutine einklinken, wo das empf. Byte aus dem hardware teil gelesen wird. Den vorhandenen ringbuffer auf 1 byte setzen. Dafür einen eigenen buffer aufmachen und das receive byte dort ablegen.vor dem ablegen auf ein endezeichen testen und damit die routine aufrufen, die dir den buffer leert.
Addi
 
Ich hatte schon einmal erwähnt, dass uart_getc() uint16_t zurück gibt.

Dies geht so eigentlich nicht ...


CodeBox C
for(uint8_t x = 0 ; x < UART_RX_BUFFER_SIZE ; x++)
{
   tmpBuff[x] = uart_getc();
}


... da uart_getc() gundsätzlich etwas zurück gibt, auch wenn der Buffer leer ist, nichts empfangen oder ein Fehler erkannt wurde.
tmpBuff ist also ganz schnell voll, aber nicht unbedingt mit den empfangenen Daten.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)