Forum: Mikrocontroller und Digitale Elektronik Datenstrom auf Zeichenkette untersuchen


von Paul (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich bau gerade ein Diagnoseinterface für alte Eberspächer Standheizungen 
(Modell D3WZ). Die Standheizung schickt zyklisch einen Datenstrom 
variabler Länge.

Die ersten drei Byte sind statisch immer die Zeichenfolge "ZHE" bzw. 
0x5A 0x45 0x48.
Danach kommt ein Byte mit dem aktuellen Fehlercode (0 wenn alles OK 
ist). Das 5te Byte ist die Anzahl der Fehlercodes im Fehlerspeicher (0-5 
sind möglich), gefolgt von maximal 5 Bytes (Fehler 1 - 5). Danach kommen 
viele Termperaturdaten, Statusbits etc (da fehlt mir leider die 
Umrechnung, bleibt daher vorerst unbeachtet).

Das Bild zeigt einen normalen Datenstrom, Fehlerspeicher mit 5 Fehlern 
gefüllt.

Jetzt möchte ich quasi permanent empfangen (aktuell ist mein Buffer 100 
Byte groß) und dann in dem Buffer den String ZHE suchen. So stelle ich 
sicher das ich den Start-Punkt kenne und kann dann die Bytes 4-10 
auswerten.

Wie suche ich einen String in einem größerem String?

von Wolfgang (Gast)


Lesenswert?

Paul schrieb:
> Jetzt möchte ich quasi permanent empfangen (aktuell ist mein Buffer 100
> Byte groß) und dann in dem Buffer den String ZHE suchen.

Warum so kompliziert. Gucke dir direkt die Zeichen an, die rein kommen. 
Per FSM prüfst du, ob "ZHE" kommt und damit setzt du deinen 
Schreibpointer auf den Pufferanfang. Dann hast du deine relevanten Daten 
auf festen Positionen im Puffer stehen.

von Parser (Gast)


Lesenswert?

Das Ende scheint doch auch eindeutig definiert 00 00 00 05
Damit packst Du immer ein komplettes Telegramm in deinen String Buffer 
und verwurstest den dann….

von Norbert (Gast)


Lesenswert?

1
s = "12345ZHE6789"
2
print(s.find('ZHE'))
3
  5
4
print(s.find('XXX'))
5
 -1

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Paul schrieb:
> Die ersten drei Byte sind statisch immer die Zeichenfolge "ZHE" bzw.
> 0x5A 0x45 0x48.
Es ist immer ungünstig, auf etwas in der Zukunft zu warten. Es könnte 
durchaus sein, dass es nicht kommt oder korrumpiert wird.

Ich würde da den Spieß umdrehen und mir die bereits empfangenen Zeichen 
vor dem ZHE anschauen. Oder eben wie gesagt das Ende der 
Zeichenkette abwarten, wenn dies tatsächlich immer 00 00 00 05 ist.

Paul schrieb:
> Wie suche ich einen String in einem größerem String?
Da gibt es mehrere Ansätze:
A) Mit welcher Programmiersprache?
B) Du suchst gar nicht, sondern du nimmst jedes einzelne empfangene Byte 
in die Hände und schaust, ob es ein Z ist. Wenn ja, dann setzt du einen 
Zähler auf 1, wenn nein, dann setzt du den Zähler auf 0. Wenn der Zähler 
auf 1 ist, dann schaust du, ob das Zeichen ein H ist. Falls ja, dann 
setzt du den Zähler auf 2, wenn nicht, dann auf 0. Und wenn der Zähler 
auf 2 ist, dann schaust du, ob das empfangene Zeichen ein E ist. Falls 
ja, dann setzt du den Zähler auf 3, wenn nicht, dann auf 0. Wenn der 
Zähler 0 und das empfangene Zeichen ein Z ist, dann setzt du den Zähler 
auf 1, sonst auf 0.
Dieser Zähler ist der oben erwähnte Zustandsautomat (FSM).

Und du siehst: wenn der Zähler irgendwann 3 ist, dann hast du gerade 
eben das E von ZHE empfangen. Du kannst das ganze Telegramm davor 
auswerten.

> (aktuell ist mein Buffer 100 Byte groß)
Mein Tipp: wenn du den Ringpuffer für die SIO 128 oder 256 Bytes machst, 
dann ist die Pufferverwaltung einfach, weil nichts verglichen, sondern 
nur maskiert werden muss. Denn auch wenn dir als Zehnfingermensch das 
Zehnersystem und seine Potenzen (10, 100, 1000, 10000,...) reinläuft wie 
Butter: so ein binärer Rechner tut sich mit dem Zweiersystem (2, 4, 8, 
16, 32, ...) viel leichter.

Und dann wird so ein Ringpuffer auch recht kompakt: 
http://www.lothar-miller.de/s9y/categories/51-Fifo

von Paul (Gast)


Lesenswert?

Lothar M. schrieb:
> Es ist immer ungünstig, auf etwas in der Zukunft zu warten. Es könnte
> durchaus sein, dass es nicht kommt oder korrumpiert wird.

OK, leider ist der Anfang der einzig statische Teil. Der Endstring kann 
variieren, sonst wäre die Welt schön einfach. In einem anderen Projekt 
empfange ich so lange die Daten, bis ein <CR> kommt. Das ist schön 
einfach.

Lothar M. schrieb:
> A) Mit welcher Programmiersprache?

Ich verwende C auf einem STM32.

Lothar M. schrieb:
> Dieser Zähler ist der oben erwähnte Zustandsautomat (FSM).

OK, ich habe hier schon mal die FSM gebaut. Ich frage quasi live ab 
welche Zeichen reinkommen. Ich komme auch beim Counter = 3 an, 
allerdings empgange ich dann so viel bis mein Buffer überläuft. Der 
Buffer habe ich auf 128 angepasst. Wenn ich eine for Schleife drüber 
setzte läuft diese so schnell, dass ich das akutell anligende Zeichen 
den Buffer füllt. Wie löse ich das elegant?

Das mit dem FIFO Buffer von deiner Website muss ich erst mal 
verinnerlichen :D
1
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
2
{
3
  if(huart->Instance==USART1)
4
   {
5
6
     if(rx_data==90)
7
        {
8
       ZHE_counter=1;
9
        }
10
     if(rx_data==72 && ZHE_counter==1)
11
         {
12
       ZHE_counter=2;
13
         }
14
     if(rx_data==69 && ZHE_counter==2)
15
         {
16
       ZHE_counter=3;
17
         }
18
19
     if(ZHE_counter == 3)
20
     {
21
22
       usart1_buffer[usart1_rx_index++]=rx_data;
23
       //ZHE_counter = 0;
24
       //rx_data = 0;
25
       //HAL_UART_Receive_IT(&huart1,&rx_data,1);// 
26
     }
27
28
29
     HAL_UART_Receive_IT(&huart1,&rx_data,1);
30
31
   }
32
}

von Olaf (Gast)


Lesenswert?

> Wie suche ich einen String in einem größerem String?

Garnicht. Mach in deiner Empfangsroutine eine Statemachine:

Wenn State=Anfang: If Zeichen=Z State=State2

Wenn State=State: If Zeichen=H State=State3 else State=Anfang

[..]

Wenn State=Am_Ende: If LetzesZeichenEmpfangen Copy Daten, 
Flagready=true, State=Anfang

So arbeitest du dich durch die ganzen reinkommenden Daten.

Wichtig ist:

1. Immer nur kurz fuer ein Byte in der STatemachine bleiben, egal wie 
lang
der Source im IRQ auch wird. Also schnell wieder raus aus dem IRQ.

2. Im Zweifel immer auf Anfang zurueck damit dein Code immer frisch 
syncronisiert wenn was schief laeuft.

Olaf

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Olaf schrieb:
> Wichtig ist:
> 1. Immer nur kurz fuer ein Byte in der STatemachine bleiben, egal wie
> lang der Source im IRQ auch wird. Also schnell wieder raus aus dem IRQ.
Kurz: die FSM ist nicht in der ISR. In der ISR wird nur 1 Zeichen 
abgeholt und in den Puffer geschrieben.

Wolfgang schrieb:
> Gucke dir direkt die Zeichen an, die rein kommen.
Das passt nicht so einfach mit der aufwendigen HAL zusammen. Was im 
normalen Leben ein besserer Dreizeiler ist, wächst sich mit dem Ding zu 
einem internationalen Raumfahrtprogramm aus...

Besonders beim UART-Handling hat sich da bei ST augenscheinlich ein 
frischer Absolvent in bisher unerreichte Höhen verstiegen (siehe 
Screenshot). Da braucht man dann schon mal einen halben Tag, bis man das 
Ding zurechtgeknechtet hat und 1 Interrupt für 1 Zeichen bekommt, wo man 
dann genau dieses 1 Zeichen einlesen kann. Genug gelästert.

Also: zuerst mal mit dem CubeMX den ganzen µC konfigurieren (das ist der 
Teil, den man tatsächlich nutzen kann). Und dann via HAL noch den 
Interrupt mit der HAL_UART_Receive_IT() aktivieren:
1
static void MX_USART2_UART_Init(void)
2
{
3
  /* USER CODE BEGIN USART2_Init 0 */
4
  /* USER CODE END USART2_Init 0 */
5
6
  /* USER CODE BEGIN USART2_Init 1 */
7
  /* USER CODE END USART2_Init 1 */
8
9
  huart2.Instance = USART2;
10
  :
11
  :
12
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
13
  if (HAL_UART_Init(&huart2) != HAL_OK)
14
  {
15
    Error_Handler();
16
  }
17
18
  /* USER CODE BEGIN USART2_Init 2 */
19
   // via HAL den Interrupt aktivieren.
20
   // Wichtig: Pointer!=0 und Anzahl!=0
21
  HAL_UART_Receive_IT(&huart2, (void*)1, 1);
22
  /* USER CODE END USART2_Init 2 */
23
}

Jetzt wird nach dem Empfang eines Zeichens vom Framework der 
USART2_IRQHandler() aufgerufen, der wiederum den unheimlichen Klimbim im 
HAL_UART_IRQHandler() aufruft, wo wieder alles Mögliche aufgerufen wird. 
Und das alles in der ISR... Schluck!

Aber Rettung naht: dort im USART2_IRQHandler() wird jetzt eingegriffen. 
Vor der ganze Klimbim losläuft, wird das Zeichen abgeholt und in den 
oben mal genannten Ringpuffer namens geschrieben:
1
:
2
void USART2_IRQHandler(void)
3
{
4
  /* USER CODE BEGIN USART2_IRQn 0 */
5
  if ((USART2->SR & USART_SR_RXNE) == USART_SR_RXNE)
6
  {
7
    rxbuf[++rxw%bufsize] = (uint8_t)(USART2->DR); // Read data, clear flag
8
  }
9
  if (0) // nachfolgende CubeMX HAL_IRQHandler Routine ignorieren
10
  /* USER CODE END USART2_IRQn 0 */
11
  HAL_UART_IRQHandler(&huart2);
12
  /* USER CODE BEGIN USART2_IRQn 1 */
13
  /* USER CODE END USART2_IRQn 1 */
14
}
15
:
Das if(0) dient zum hinterlistigen Deaktivieren des HAL_Aufrufs, der ja 
vom CubeMX verwaltet wird. Vielleicht gibts auch noch weniger fiese 
Methoden, aber Hauptsache läuft.

Paul schrieb:
> Die Standheizung schickt zyklisch einen Datenstrom variabler Länge.
Hoppla, übersehen. Dann ist es tatsächlich einfacher, auf die Zukunft zu 
hoffen... ;-)

Also geht es weiter mit der Verwaltung des Ringpuffers in der 
Hauptschleife:
1
:
2
#define bufsize 128 /* Zweierpotenz!!! */
3
char rxbuf[bufsize];
4
volatile uint32_t rxw=0, rxr=0; // Pointer für USART Empfang
5
:
6
char chrx, cnt = 0;
7
char errcnt, error[5];
8
:
9
:
10
    // UART Empfang abhandeln
11
if (rxw!=rxr)                    // Zeichen gekommen?
12
{
13
  chrx = rxbuf[++rxr%bufsize]; // Zeichen einlesen
14
  switch (cnt) {    
15
    case 0 : if (chrx =='Z') cnt++; // Z erkannt? Zähler hochzählen
16
             break;
17
    case 1 : if (chrx =='H') cnt++; // H erkannt? Zähler hochzählen
18
             else            cnt=0; // Fehlstart
19
             break;
20
    case 2 : if (chrx =='E') cnt++; // E erkannt? Zähler hochzählen
21
             else            cnt=0; // Fehlstart
22
             break;
23
    case 3 : errcnt   = chrx;
24
             cnt++;
25
             break;
26
    case 4 : error[0] = chrx;
27
             cnt++;
28
             break;
29
    case 5 : error[1] = chrx;
30
             cnt++;
31
             break;
32
    case 6 : error[2] = chrx;
33
             cnt++;
34
             break;
35
    case 7 : error[3] = chrx;
36
             cnt++;
37
             break;
38
    case 8 : error[4] = chrx;
39
             cnt=0;                  // Finito -> Neustart der FSM
40
             break;
41
  }
42
}
43
:
44
:
Das wars.

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

Die Liste der Funktionen für einen simplen UART ist echt eindrucksvoll. 
Läster

von Stefan F. (Gast)


Lesenswert?

Abdul K. schrieb:
> Die Liste der Funktionen für einen simplen UART ist echt eindrucksvoll.

Das ist der Preis der HAL. Für einfache kleine Aufgaben unnötig komplex 
und für komplexe Aufgaben manchmal unzureichend. Dafür kann man relativ 
leicht auf andere STM32 wechseln.

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

Mag sein, aber nix für mich. Auf einem 8051 hab ich in Hex-Code in ca. 
300 Byte einen kompletten seriell auf parallel Ringbuffer inkl. Xon/off 
für meinen damaligen Parallelinterface-Drucker geschrieben. Die 
Druckdaten kamen seriell vom Mac an. Assembler hatte ich keinen, also 
direkt in Hex gecodet. Damit wurden dann Platinenlayouts gedruckt. 
Höllenlärm eines NEC P2200 :-)

von Olaf (Gast)


Lesenswert?

> Kurz: die FSM ist nicht in der ISR. In der ISR wird nur 1 Zeichen
> abgeholt und in den Puffer geschrieben.

Nein, ich habe kein Problem damit eine einfache Ueberpruefung bereits im
IRQ zu machen. Wir programmieren hier ja nicht in Python und koennen es 
uns daher erlauben. .-)
Das hat dann den Vorteil das man sofort wieder syncronbereit ist wenn es 
zu einem Uebertragungsfehler kam. Zuletzt hab ich sowas z.B bei einer 
Empfangsroutine einer IR-FB genutzt die sehr zuverlaessig arbeitet, auch 
wenn sie kurz vorher etwas falsches empfangen hat, was dort ja haeufig 
vorkommt.
Ich weiss z.B das das dritte Byte immer 0xa0 sein muss und breche sofort
ab wenn das nicht stimmt.

> Das ist der Preis der HAL. Für einfache kleine Aufgaben unnötig komplex
> und für komplexe Aufgaben manchmal unzureichend.

Daran erkennt man das man besser die Finger davon laesst. Ja, auch ich 
hab das schon mal genutzt wenn ich faul sein wollte, aber ich hab dann 
auch mal geschaut was ich da aufrufe, das dann direkt in meinen Source 
kopiert und dann nochmal vereinfacht. Damit kannst du praktisch sofort 
die Ausfuehrungszeit halbieren und das ist ja gerade bei IRQ-Routinen 
echt nett.

> Dafür kann man relativ leicht auf andere STM32 wechseln.

Die sind dann aber auch nicht verfuegbar. Wir wechseln gerade deshalb 
zwischen komplett andere CPUs (ARM, !ARM). Was glaubst du wie kacke das 
ist wenn dann alles auf proprietaeren Murks basiert. .-)

Olaf

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Olaf schrieb:
> Das hat dann den Vorteil das man sofort wieder syncronbereit ist wenn es
> zu einem Uebertragungsfehler kam.
Da sehe ich noch keinen Vorteil, das kann ich ja genauso in der mainloop 
abarbeiten. Der Ringpuffer verliert ja auch kein Zeichen und die FSM 
läuft in der Mainloop gleich gut wie in der ISR.

Aber hier gilt wie üblich: jeder so wie ihm beliebt, denn genau dafür 
hat er sich ja den µC gekauft.

von Wattislos? (Gast)


Lesenswert?

Das schreit ja schon nach einem kleinen Atmega/Tiny "Coprozessor" der 
sich darum kümmert.
Das ist ja der Hammer, solch ein Atomkratftwerk dafür aufzubauen.

Also Hobbyprogrammierer würde ich mir sowas nie antun.
Wäre das mein Job würde ich mir selbst in die Klöten beißen;-)

von Rainer V. (a_zip)


Lesenswert?

Wattislos? schrieb:
> Wäre das mein Job würde ich mir selbst in die Klöten beißen;-)

Also ich würde beten, dass es nie jemand bemerkt...
Gruß Rainer

von Parser (Gast)


Lesenswert?

Rainer V. schrieb:
> Wattislos? schrieb:
>> Wäre das mein Job würde ich mir selbst in die Klöten beißen;-)
>
> Also ich würde beten, dass es nie jemand bemerkt...
> Gruß Rainer

Und ich würde wetten, dass Du es nie schaffst.
Nicht weil Du zu unbeweglich bist..

von Sebastian (Gast)


Lesenswert?

Vielleicht solltest du auch noch die Pause zwischen den Telegrammen als 
Startsignal behandeln. Also, falls 0x5A 0x45 0x48 auch in den Daten 
vorkommen kann ...

LG, Sebastian

von Paul (Gast)


Lesenswert?

Lothar M. schrieb:
> Was im
> normalen Leben ein besserer Dreizeiler ist, wächst sich mit dem Ding zu
> einem internationalen Raumfahrtprogramm aus...

OK, ich verstehe, die HAL ist ziemlich aufgebläht. Da hab ich bis jetzt 
noch nie drüber nachgedacht/bin da noch nie an Grenzen gestoßen.

Lothar M. schrieb:
> den
> Interrupt mit der HAL_UART_Receive_IT() aktivieren:

OK, so weit klar. Aber was genau macht:
Lothar M. schrieb:
> HAL_UART_Receive_IT(&huart2, (void*)1, 1);

Es startet den Empfang für UART2, zeigt auf eine Empfangsvariable und 
bekommt noch die Byte Anzahl mitgegeben, aber worauf zeig denn der 
zweite Parameter? Oder ist das nur ein Dummy, denn sobald was empfangen 
wurde springt er ja eh in die ISR?


Lothar M. schrieb:
> HAL_UART_IRQHandler() aufruft, wo wieder alles Mögliche aufgerufen wird.
> Und das alles in der ISR... Schluck!

Kann ich (interessehalber) in der ISR einen Ausgang setzen und mit dem 
Oszi die Laufzeit messen? nur um mal den Unterschied zwischen HAL und 
Direkt zu vergleichen oder ist das zu ungenau und macht keinen Sinn?

Lothar M. schrieb:
> Also geht es weiter mit der Verwaltung des Ringpuffers in der
> Hauptschleife:

Ok, aber das klappt doch nur wenn meine Hauptschleife schnell genug ist 
um den Puffer zu leeren? Sonst könnte es ja theoretisch sein, dass der 
128 Byte große Buffer schon drei mal überschrieben wurde und bevor ich 
in der Hauptschleife den Buffer auslesen kann?

Lothar M. schrieb:
> Das wars.

Vielen Dank für deine Geduld und deine Muße es so super zu erklären, 
sogar direkt am lebenden Objekt! Der Wahnsinn :).

Stefan ⛄ F. schrieb:
> Das ist der Preis der HAL. Für einfache kleine Aufgaben unnötig komplex
> und für komplexe Aufgaben manchmal unzureichend. Dafür kann man relativ
> leicht auf andere STM32 wechseln.

Gibt es Kriterien nach den man entscheidet das man die HAL lieber links 
liegen lässt und den direkten Weg wählt?

Lothar M. schrieb:
> Der Ringpuffer verliert ja auch kein Zeichen und die FSM
> läuft in der Mainloop gleich gut wie in der ISR.

Aber doch nur, solange es nicht überläuft, oder?

Wattislos? schrieb:
> Das schreit ja schon nach einem kleinen Atmega/Tiny "Coprozessor"
> der
> sich darum kümmert.
> Das ist ja der Hammer, solch ein Atomkratftwerk dafür aufzubauen.

Sicher, dass kann auch ein ATTINY. Ich hab auch mal mit Atmel und Co 
angefangen, aber das Debugging finde ich auf den STM32 deutlich bequemer 
und da ich das als Hobby betreibe und gerne einen "Standard µC" habe, 
auf dem meine Projekte laufen bin ich bis jetzt mit F103 und F303 ganz 
gut gefahren. Ich will ja auch keine Stückzahlen aufbauen, vllt werden 
es mal zwei bis drei für paar Schrauberkumpels (diese Heizungen sind in 
allen VAG Dieseln von Mitte 90 bis 2005 drin und haben oftmals Probleme)

Wattislos? schrieb:
> Also Hobbyprogrammierer würde ich mir sowas nie antun.
> Wäre das mein Job würde ich mir selbst in die Klöten beißen;-)

Was man sich als Hobby antut kann ja zum Glück jeder selbst entscheiden 
;).

von Klaus W. (mfgkw)


Lesenswert?

Paul schrieb:
> OK, so weit klar. Aber was genau macht:
> Lothar M. schrieb:
>> HAL_UART_Receive_IT(&huart2, (void*)1, 1);
>
> Es startet den Empfang für UART2, zeigt auf eine Empfangsvariable und
> bekommt noch die Byte Anzahl mitgegeben, aber worauf zeig denn der
> zweite Parameter? Oder ist das nur ein Dummy, denn sobald was empfangen
> wurde springt er ja eh in die ISR?



Das zweite Argument für HAL_UART_Receive_IT() ist die Adresse, wo 
enmpfangene Zeichen hingeschrieben werden.
Wenn ich das Zeichen nicht an der Adresse 1 haben will, würde ich da 
auch nicht eine 1 hinschreiben.
Entsprechend ist der eigentlich richtige Datentyp für den zweiten 
Parameter auch uint8_t*.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Paul schrieb:
> Aber was genau macht:
>> HAL_UART_Receive_IT(&huart2, (void*)1, 1);
> Es startet den Empfang für UART2, zeigt auf eine Empfangsvariable und
> bekommt noch die Byte Anzahl mitgegeben, aber worauf zeig denn der
> zweite Parameter? Oder ist das nur ein Dummy, denn sobald was empfangen
> wurde springt er ja eh in die ISR?
Markier mal den Funktionsaufruf und geh dann mit der F3-Taste oder über 
Rechtsclick-"Open Declaration" zu der Funktionsimplementierung. Sieh dir 
die Deklaration und den Code der Funktion an und dir wird klar, warum da 
beim pData und bei Size etwas "ungleich 0" stehen muss.
1
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
2
{
3
  /* Check that a Rx process is not already ongoing */
4
  if (huart->RxState == HAL_UART_STATE_READY)
5
  {
6
    if ((pData == NULL) || (Size == 0U))
7
    {
8
      return HAL_ERROR;
9
    }
10
11
    /* Process Locked */
12
    __HAL_LOCK(huart);
13
14
    /* Set Reception type to Standard reception */
15
    huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
16
17
    return(UART_Start_Receive_IT(huart, pData, Size));
18
  }
19
  else
20
  {
21
    return HAL_BUSY;
22
  }
23
}
Mit einem Nullpointer oder einer 0 als Size wird die Funktion gleich 
beendet. Mit passenden Werten wird die zum Freischalten der Interrupts 
nötige UART_Start_Receive_IT() aufgerufen:
1
HAL_StatusTypeDef UART_Start_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
2
{
3
  huart->pRxBuffPtr = pData;
4
  huart->RxXferSize = Size;
5
  huart->RxXferCount = Size;
6
7
  huart->ErrorCode = HAL_UART_ERROR_NONE;
8
  huart->RxState = HAL_UART_STATE_BUSY_RX;
9
10
  /* Process Unlocked */
11
  __HAL_UNLOCK(huart);
12
13
  /* Enable the UART Parity Error Interrupt */
14
  __HAL_UART_ENABLE_IT(huart, UART_IT_PE);
15
16
  /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
17
  __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);
18
19
  /* Enable the UART Data Register not empty Interrupt */
20
  __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
21
22
  return HAL_OK;
23
}
Woring über das Makro __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE) 
letztlich der Interrupt freigegeben wird:
1
#define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__)   ((((__INTERRUPT__) >> 28U) == UART_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 |= ((__INTERRUPT__) & UART_IT_MASK)): \
2
                                                           (((__INTERRUPT__) >> 28U) == UART_CR2_REG_INDEX)? ((__HANDLE__)->Instance->CR2 |= ((__INTERRUPT__) & UART_IT_MASK)): \
3
                                                           ((__HANDLE__)->Instance->CR3 |= ((__INTERRUPT__) & UART_IT_MASK)))

Wie gesagt: die F3 Taste ist dein Freund beim Untersuchen solcher 
Aufrufketten.

von N. M. (mani)


Lesenswert?

Ist zwischen 2 Frames keine Pause?
Die meisten STM haben sich extra HW im UART um auf Pausen auf zu syncen.
Warum also in Software machen?

Zusammen mit einem DMA und 1-2 Empfangspuffer braucht das keine 
Rechenleistung.
Wenn der Pausen Interrupt kommt einfach schauen ob der Anfang stimmt. 
Wenn ja nehmen, ansonsten verwerfen.

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.