Spørgsmål:
Sørg for \ n er det sidste tegn i seriel streng
ATE-ENGE
2017-05-05 18:39:18 UTC
view on stackexchange narkive permalink

Jeg har en Arduino, som jeg har sat mellem en computer og en RS485-enhed. Arduino's job er nu bare at overføre data, men vil til sidst foretage datalogning og have en lille brugergrænseflade, når tiden går.

Indtil videre har denne serielle læsekode fungeret for mig til at kommunikere til Arduino fra computeren:

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

Ulempen her er, at jeg ikke kan sende '\ n' char til min RS485-enhed. Er der en måde, hvorpå jeg kan forfine koden, så jeg kan sende en vilkårlig streng af tegn, mens jeg stadig har en afslutning [ting] for at slå strengComplete-flag til?

REDIGER For at afklare denne proces ved, hvordan min besked streng oprettes:

  Input: U16-adresse, U16-data, U8-funktionskodeU16-adresse -> U8-adresse Opdel høj, U8-adresse Opdel lav U16 Data -> U8 Data opdel høj, U8-data opdeling lav 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: Skriv meddelelsesstreng  
Er det bare strenge af ASCII-tegn (koder 32 til 127 + `\ n`), som du vil sende?
Nej, jeg sender et antal u8 ints (ord?), Der er repræsenteret som \ code-tegn sammensat til at danne en streng.
Men det faktiske strengindhold, der sendes over ledningen, består kun af tegn, der kan udskrives? Du sender ting som '\ 024 \ 075 \ 216 \ 030 \ 777 \ 000 \ 123` osv.?
Eller sender du de faktiske 8-bit-værdier, som du har lagt i strengen ved hjælp af '\ whatever "?
Lige nu sender og modtager jeg de faktiske 8bit-værdier, hele processen er som følger: Computerinput: U16-adresse, U16-data, U8-funktionskodeU16-adresse -> U8-adresseopdeling høj, U8-adresseopdeling 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 String
Tre svar:
Majenko
2017-05-05 22:21:52 UTC
view on stackexchange narkive permalink

Da du bruger alle 8 bit af serielle data til dine data, er der intet "i bånd", som du kan bruge til en afgrænser.

I stedet bliver du nødt til at tænke lidt uden for boksen og oprette en eller anden form for "ud af bånd" -data, der kan signalere slutningen af ​​en pakke.

En mulighed (sandsynligvis den enkleste ) ville være at medtage begrebet tid i din protokol. Hvis du går mere end X millisekunder (X skal bestemmes af dig) uden at modtage en byte, er du i slutningen af ​​din pakke. Dette har den ulempe, at det sænker din maksimale pakkehastighed, da hver pakke skal have en passende forsinkelse imellem.

En anden mulighed kan være at bruge et serielt pause tegn mellem pakker. Dette er en speciel begivenhed, hvor UART-output holdes lavt i mindst 10 symbollængder, hvilket resulterer i en indramningsfejl (STOP-bit er forkert) og et flag er sat. Det vil dog betyde, at du selv skal implementere al UART-koden, da Arduinos UART-kode ikke understøtter pauser.

En tredje mulighed, som også kræver, at du skriver din egen UART-kode eller ændrer Arduino UART-koden ville være at betjene UART i 9-bit-tilstand. Du har så 0-511 i stedet for 0-255, så du kan sende dine 8-bit data som normalt (med 9. bit sat til 0) og eventuelle kontrol- og protokoltegn med 9. bit sæt, så mellem 256 og 511 .

Endelig kan du halvere din samlede transmissionshastighed ved at sende dataene som ASCII-kodede HEX-cifre. Det vil være to tegn (0-9, A-F) for hver sendte byte, så alle de andre tegn (inklusive \ n ) er tilgængelige, som du kan bruge, som du ønsker.

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

Normalt slutter strenge med et '/ 0' element ... end / n er en del af strengen og kan håndteres som normalt.

Så du skal ændre flueben til

  if (inchar == '\ 0')  

Overvej også ikke at tilføje et tegn hver gang til strengen, da det vil medføre, at strengen erstattes / kopieres hver gang, hvilket ikke er godt for både resultat og hukommelseshuller, der resulterer.

Lav i stedet en foruddefineret buffer, hvis det er muligt (hvis du kender den maksimale strenglængde, glem ikke at tilføje +1 til slutningen ' 0 'tegn). I så fald kan du tilføje '\ 0' selv eller endnu 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 antallet af tilgængelige byte i bufferen. En løsning kan være at prøve at læse så mange byte ad gangen. Dette forudsætter, at bufferen kun indeholder hele strenge.

Bemærk: Hvis din RS485-enhed sender flere, ikke-afgrænsede strenge mellem bufferlæsninger, fungerer dette muligvis ikke som ønsket.

  ugyldigt serialEvent () {int bytes = Serial.available (); hvis (bytes == 0) // tom buffer, kaution returneres; for (; bytes > 0; bytes--) {// get new byte char inChar = (char) Serial.read (); inputstreng + = inChar; } stringComplete = true;}  


Denne spørgsmål og svar blev automatisk oversat fra det engelske sprog.Det originale indhold er tilgængeligt på stackexchange, som vi takker for den cc by-sa 3.0-licens, den distribueres under.
Loading...