Hämta data från USART med funktion

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
ankan
Inlägg: 1091
Blev medlem: 12 november 2004, 01:50:35

Hämta data från USART med funktion

Inlägg av ankan »

Vill sätta PICen i lyssningsläge för att vänta på ett meddelande.

Snyggast och bäst vore att anropa en funktion som samlar in tecken till den stöter på en pause och skickar vidare strängen till där funktionen anropades.

Problemet är att det kan dyka upp 0x00 vilket skulle klippa retursträngen. Hur löser man detta smartast och snyggast?
Användarvisningsbild
Micke_s
EF Sponsor
Inlägg: 6741
Blev medlem: 15 december 2005, 21:31:34
Ort: Malmö

Inlägg av Micke_s »

typ:

Kod: Markera allt

if( data != 0x00){
   //hantera valida tecken
}
ankan
Inlägg: 1091
Blev medlem: 12 november 2004, 01:50:35

Inlägg av ankan »

Jag skulle alltså vilja behålla 0x00 i strängen men även tecknen efter 0x00. Dvs jag kan antagligen inte skicka returen som en sträng utan en pointer och sedan info om längd på strängen. Men ska man stoppa in pointern vid anropet av funktionen och sedan få längden som retur eller ska man köra ihop det som en array som man returnerar?

Eller kanske lägga till en byte i slutet/början som säger hur lång strängen är.
ankan
Inlägg: 1091
Blev medlem: 12 november 2004, 01:50:35

Inlägg av ankan »

Sedan är frågan hur jag kan kolla datat jag får in om det stämmer överrens med en sträng som också kan innehålla 0x00.

Man skulle kunna omvandla all trafik till ASCII annars men då blir det 2 byte för varje byte. Dvs dubbelt så mycket data att skicka vilket inte känns så bra i och med att jag måste dra ner på förbrukningen så mycket som möjligt.
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Du vill alltså buffra inkommande data till det kommer en viss paus mellan inkommande data eller hur?

Alltså måste du ha en time-out-grej, detta kan lösas på många sätt, helt beroende på hur lång time-out du behöver. Att det kommer data 0x00 är FORTFARANDE data och då är det bara att köra ändå.
ankan
Inlägg: 1091
Blev medlem: 12 november 2004, 01:50:35

Inlägg av ankan »

Men om jag låter en funktion ligga och lyssna och skicka den strängen den får så spelar 0x00 roll eftersom den som anropar funktionen inte ver hur många byte datat som finns i strängen som returneras.
ankan
Inlägg: 1091
Blev medlem: 12 november 2004, 01:50:35

Inlägg av ankan »

Kom på att Easy-RAdio modulen som jag ska ta emot data från har ju en flagga som säger till när det finns datat att plocka in. Ska kolla vilken pinne det är bara.
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Vad vill du egentligen uppnå?
Vilken sorts data ska den ta emot?
0x00 är data på samma nivå som 0xFF eller vad som helst annat.

Antalet inkommande bytes sparar du såklart i en räknare och returnerar sedan eller hur?

Har meddelandet fast format?
Hur lång tid är det mellan meddelanden?
ankan
Inlägg: 1091
Blev medlem: 12 november 2004, 01:50:35

Inlägg av ankan »

Datat är 1-WIRE ID för sändare och mottagare samt datat så det kan vara alla möjliga värden.
Men som du säger och som jag tog upp så kanske man ska skicka en pointer till funktionen där strängen sparas och sedan returnerar strängens längd.

Eftersom Easy-Radio modulen jag använder har egen buffert på 180 byte tänkte jag att den kanske skulle ha en pinne som man kan kolla om det har kommit in någon datat men jag vet inte hur RTS och CTS fungerar.

Det verkar mer vara en pinne som säger till när kretsen är upptagen vilket skulle kunna räcka.
ankan
Inlägg: 1091
Blev medlem: 12 november 2004, 01:50:35

Inlägg av ankan »

Så här ser funktionen ut nu:

Kod: Markera allt

unsigned short Usart_Read_Data(unsigned short * data) {
  unsigned long counter = 0;
  const unsigned long MAXCOUNT = 10000;
  const unsigned short MAXLENGTH = 180;

  unsigned short s_count = 0;

  while(!Usart_data_ready()) {
    counter ++;                  // data not received, increment timeout counter
    if (counter>MAXCOUNT) {      // timeout reached
      *(data+s_count) = 0x00;    // s_count has been incremented in the function, set the end of string
        return s_count;
    }

    counter = 0;                      // data received before timeout occurred
    data[s_count++] = Usart_read(); // read the character and place in the buffer
    if (s_count==MAXLENGTH-1) {       // buffer overflow check
      *(data+s_count) = 0x00;        // in this case, terminate the string and exit
      return s_count;
    }
  }
}
...som anropas med:


unsigned short *data;
unsigned short length;
length=Usart_Read_Data(&data)


men får suspicious pointer conversion.
Användarvisningsbild
Micke_s
EF Sponsor
Inlägg: 6741
Blev medlem: 15 december 2005, 21:31:34
Ort: Malmö

Inlägg av Micke_s »

Du får ha MAXLENGTH global
och göra

Kod: Markera allt

unsigned short data[MAXLENGTH];
unsigned short length;
length=Usart_Read_Data(&data)
Du allokerar en pekare på stacken och sedan skriver du utanför stacken.
:ajabaja:
ankan
Inlägg: 1091
Blev medlem: 12 november 2004, 01:50:35

Inlägg av ankan »

Jag allokerar och får visserligen bort felmeddelandet men jag har fortfarande problem att lyssna av porten.
Eftersom PICen kommer kopplas till en Easy-Radio så är det alltså tänkt att den ska ligga och lyssna en bestämd tid och om det kommer in någon datat ska den tolka datat och svara på det.

Men som sagt, hur ska jag bygga upp denna funktion som jag vill anropa och sedan ligger den där och väntar en viss tid efter data och returnerar det hela. Jag får det inte att fungera med koden jag skrev ovan.

Jag provade att bara allokera 10 byte men det spelar ingen roll. Interruptet verkar balla ur så jag hamnar fel.
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Förklara en sak för mig: Hur kan du göra en sträng när alla värden från och med 0x00 till 0xFF är legala värden?

Sen har du ett problem med att förstå vissa saker tror jag: ER-mottagaren skickar ut de inkomna data när de kommer. När det är 2 eller fler teckens paus i sändningen till sändaren skickas datan iväg, detta ger dig tydliga blockar räknat i tid.

Men du har inte svarat på om du har en tydlig blockstruktur eller inte. Har du ett fast format eller skyfflar du bara iväg lite hur som helst?
ankan
Inlägg: 1091
Blev medlem: 12 november 2004, 01:50:35

Inlägg av ankan »

Jag har tänkt ha en blockstruktur som kommer variera i längd men jag kommer placera fasta delarna först så att det blir lättare att filtrera ut dem.

Ett block kommer typ se ut då här:

Mottagare_ID Sändare_ID Typ_av_data Data

Det är bara data som antagligen kommer variera i längd.

Mastern skickar ut ett kommando att få datat från en klient som sedan svarar mastern med datat i samma struktur som ovan.


Jag antar att jag har använt ordet sträng fel. En array kanske skulle låta bättre eftersom då spelar det ingen roll vilket värde byten har.

Som du säger så skickar ju ER-sändaren i block med tydlig pause så att spara ner datat i en array är inga problem.

Problemet är att jag vill kunna anropa denna lyssna funktion som en funktion och få datat som svar. Men eftersom det inte går att returnera datat som en sträng i och med att det inte bara är vanliga bokstäver och siffror precis så måste jag lösa returen från funktionen på något annat sätt genom att skicka en pointer och längd på arrayen.

Alla USART funktioner hade jag tänkt ha i en egen fil för att få en tydlig ordning på koden.
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Mitt förslag är att du fixar så att du får en interrupt vid mottagning och om du kan avsätta en timer vore det bra.

Då ser du till att fixa att data sparas i en buffer och att det markeras tydligt när en block har kommit.

Jag har gjort ett projekt där jag hade 3 buffrar som jag tog emot i, när en av ifylld bytte jag till nästa och markerade den första som "klar att jobba med", sedan hade jag en "vanlig" rutin i main-loopen som tog hand om datan och avmarkerade buffrarna allt eftersom.
Skriv svar