Spørsmål:
Forsikre deg om at \ n er det siste tegnet i seriell streng
ATE-ENGE
2017-05-05 18:39:18 UTC
view on stackexchange narkive permalink

Jeg har en Arduino som jeg har satt mellom en datamaskin og en RS485-enhet. Arduino-jobben er nå bare å overføre data, men vil til slutt gjøre datalogging og ha et lite brukergrensesnitt etter hvert som tiden går.

Så langt har denne serielle lesekoden fungert for meg å kommunisere til Arduino fra datamaskinen:

  void serialEvent () {while (Serial.available ()) {// get new byte char inChar = (char) Serial.read (); hvis (inChar == '\ n') {stringComplete = true; } annet {inputstring + = inChar; }}}  

Ulempen her er at jeg ikke kan sende '\ n' char til RS485-enheten min. Er det en måte jeg kan avgrense koden på, slik at jeg kan sende en vilkårlig streng med tegn mens jeg fremdeles har en avslutning [ting] for å slå på stringComplete-flagget?

EDIT For å avklare prosessen ved hvordan meldingen min er streng blir opprettet:

  Input: U16 Address, U16 Data, U8 Function CodeU16 Address -> U8 Address Split High, U8 Address Split LowU16 Data -> U8 Data Split High, U8 Data Split LowU8 Array of [U8 Address Split High, U8 Address Split Low, U8 Data Split High, U8 Data Split Low, U8 Function Code] U8 Array -> Message StringOutput: Skriv Message Streng  
Er det bare strenger med ASCII-tegn (kodene 32 til 127 + `\ n`) du vil sende?
Nei, jeg sender n antall u8 ints (ord?) Som er representert som \ code-tegn satt sammen for å danne en streng.
Men selve strenginnholdet som sendes over ledningen består bare av utskrivbare tegn? Du sender slike ting som \ \ 024 \ 075 \ 216 \ 030 \ 777 \ 000 \ 123` etc?
Eller sender du de faktiske 8-bitersverdiene du har lagt inn i strengen ved hjelp av 'hva som helst'?
Akkurat nå sender og mottar jeg de faktiske 8bit-verdiene, hele prosessen er som følger: Datamaskininngang: U16-adresse, U16-data, U8-funksjonskodeU16-adresse -> U8-adresse delt høy, U8-adresse delt lav High, U8 Data Split Low U8 Array of [U8 Address Split High, U8 Address Split Low, U8 Data Split High, U8 Data Split Low, U8 Function Code] U8 Array -> Message StringOutput: Message Streng
Tre svar:
Majenko
2017-05-05 22:21:52 UTC
view on stackexchange narkive permalink

Siden du bruker alle de 8 bitene av seriedataene for dataene dine, er det ingenting "i bånd" som du kan bruke til en avgrenser.

I stedet må du tenke litt utenfor boksen og lage en eller annen form for "ut av bånd" -data som kan signalisere slutten på en pakke.

Ett alternativ (sannsynligvis det enkleste ) ville være å inkludere begrepet tid i protokollen din. Hvis du går mer enn X millisekunder (X skal bestemmes av deg) uten å motta en byte, er du på slutten av pakken. Dette har den ulempen at det reduserer den maksimale pakkefrekvensen, siden hver pakke må ha en passende forsinkelse mellom seg.

Et annet alternativ kan være å bruke et serielt break tegn mellom pakker. Dette er en spesiell hendelse der UART-utgangen holdes lav i minst 10 symbollengder, noe som resulterer i en innrammingsfeil (STOP-biten er feil) og et flagg blir satt. Det vil imidlertid bety at du må implementere all UART-koden selv, siden Arduinos UART-kode ikke støtter pauser.

Et tredje alternativ, som også krever at du skriver din egen UART-kode, eller endrer Arduino UART-koden, ville være å betjene UART i 9-biters modus. Du har da 0-511 i stedet for 0-255, så du kan sende 8-bits dataene dine som normalt (med 9. bit satt til 0) og eventuelle kontroll- og protokolltegn med 9. bit sett, så mellom 256 og 511 .

Til slutt kan du halvere den totale overføringshastigheten ved å sende dataene som ASCII-kodede HEX-sifre. Det vil være to tegn (0-9, A-F) for hver byte som sendes, slik at alle de andre tegnene (inkludert \ n ) er tilgjengelige for deg å bruke som du ønsker.

Michel Keijzers
2017-05-05 19:12:37 UTC
view on stackexchange narkive permalink

Strenger slutter normalt med et '/ 0' element ... enn / n er en del av strengen og kan håndteres som normalt.

Så du må endre sjekken til

  if (inchar == '\ 0')  

Vurder også å ikke legge til et tegn hver gang i strengen, siden det vil føre til at strengen blir erstattet / kopiert hver gang, noe som ikke er bra for både ytelse og minnehull som resulterer.

Lag i stedet en forhåndsdefinert buffer hvis mulig (hvis du vet maksimal strenglengde, ikke glem å legge til +1 for slutten ' 0 'karakter). I så fall kan du legge til '\ 0' selv eller enda bedre:

  char inputString [101]; uint8_t inputStringLength = 0; while (Serial.available ()) {// get new byte char inChar = (char) Serial.read (); inputString [inputStringLength ++] = inChar; stringComplete = (inChar == '\ 0')}  
Mazaryk
2017-05-05 21:22:25 UTC
view on stackexchange narkive permalink

Serial.avilable () returnerer antall byte som er tilgjengelige i bufferen. En løsning kan være å prøve å lese så mange byte om gangen. Dette forutsetter at bufferen bare inneholder hele strenger.

Merk: Hvis RS485-enheten din sender flere, ikke-avgrensede strenger mellom bufferlesninger, kan det hende at dette ikke fungerer som ønsket.

  ugyldig serialEvent () {int bytes = Serial.available (); hvis (byte == 0) // tom buffer, kausjon tilbake; for (; bytes > 0; bytes--) {// få ny byte char inChar = (char) Serial.read (); inputstring + = inChar; } stringComplete = true;}  


Denne spørsmålet ble automatisk oversatt fra engelsk.Det opprinnelige innholdet er tilgjengelig på stackexchange, som vi takker for cc by-sa 3.0-lisensen den distribueres under.
Loading...