STM32 - Mit USART String-Input den CCR (PWM-Timer) setzen

OP #5432739
Lesenswert?

Hallo zusammen,

Board: STM32F4-Discovery
Bib: STM32
IDE: Atolic Truestudio

Aufgabe:
möchte durch USART-Schnittstelle vom PC an STM32 die Parameter für 
PWM-Signal (Servo-Motoren) senden. Der STM32 soll string auslesen evtl. 
in int umwandeln und CCR1, CCR2, CCRn.. Wert verändern/stellen.

Aktueller Stand:

USART Interrupt
1
void USART2_IRQHandler() {
2
  if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET) {
3
    USART_ClearITPendingBit(USART2, USART_IT_RXNE);
4
    static int cnt = 0;
5
    char input = USART2->DR;
6

7
    if ((input != '\n') && (cnt < MAX_WORDLEN)) {
8
      received_str[cnt++] = input;
9
    } else {
10
      received_str[cnt] = '\0';
11
      cnt = 0;
12
      USART2_Send(USART2, received_str);
13
//      if(received_str){
14
//
15
//      }
16
    }
17
  }
18

19
}

USART string senden
1
void USART2_Send(USART_TypeDef *USARTx, volatile char *str) {
2
  while (*str) {
3
    while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
4
    USART_SendData(USARTx, *str);
5
    *str++;
6
  }
7
}

Frage:
Wie kann ich "received_str" zerlegen? z.B. ich sende vom Computer 
MP11500
dies soll interpretiert werden als: CCP1 auf Wert 1500 setzen oder 
MP31000: CCP3 auf Wert 1000 setzen.
Wie kann ein Beispielcode dafür aussehen?

Vielen Dank!
Grüß, Nik
Gast #5432769
Lesenswert?

Du kannst erstmal gucken, ob der String mit "MP" beginnt. Dann machst Du 
einen switch-case auf das nächste Zeichen, das '1', '2', '3' oder so 
sein kann. Aufgepaßt, '1' ist nicht der integer 1.

Die Zahlenumwandlung kannst Du mit atoi() machen, was einen String 
erwartet. Der Wert kommt ab Positon 3, also value = 
atoi(received_str+3).

Das als Anregungen.
Gast #5432878
Lesenswert?

Nop1 schrieb:
> sscanf

Den finde ich auch gut. ;)
1
#include "stdio.h"
2
#include "string.h"
3
#include "stdint.h"
4

5
uint8_t Zeichenkette [] = {"MP12345"};
6
void main()
7
{
8
  printf("\nZerlegung von: %s \n",Zeichenkette);
9
  uint8_t Laenge = strlen(Zeichenkette);
10
  printf("Laenge der Zeichenkette: %i\n",Laenge);
11

12

13
  if (Zeichenkette[0]=='M' & Zeichenkette[1]=='P'){
14
    printf("MP Stimmt\n");
15

16
    uint8_t  Kanal = Zeichenkette[2]-'0';
17
    printf("Kanal: %d\n",Kanal);
18

19
    uint8_t buffer[10];
20
    int PWM_Wert;
21

22
    for(int i=3,j=0;i<Laenge;i++,j++) {
23
      buffer[j]=Zeichenkette[i];
24
    }
25

26
    sscanf(buffer,"%d",&PWM_Wert);
27
    //printf("buffer: %s\n",buffer);
28

29
    printf("PWM_Wert: %d\n",PWM_Wert);
30
  }
31
}
#5432880
Lesenswert?

Diese ganze string Bearbeitung auf einem uC ist doch murks. Sende per 
uart doch gleich die hex Werte der Zahlen. Größere Werte kannst du doch 
zerlegen und zusammen führen.
Will dir damit nur sagen, daß du Dir erstmal grundlegende Gedanken über 
das protokol machen solltest.
Ein Byte als qualifier und dann payload plus am Ende ein Trennzeichen.
Gast #5433110
Lesenswert?

Nikita J. schrieb:
> Aktueller Stand:
>
> USART Interruptvoid USART2_IRQHandler() {
> ...
>     if ((input != '\n') && (cnt < MAX_WORDLEN)) {
>       received_str[cnt++] = input;

Du schreibst Murks.

Trenne doch die logschen Ebenen voneinander, sonst verhedderst du dich 
noch viel mehr.

Wie man sowas richtig macht, kannst du in der Lernbetty nachlesen, 
alternativ in diversen geposteten Quellen von mir.

Sene- und Empfangs-Verfahren:
- der Interrupthandler behandelt die Hardware: er sendet Zeichen aus dem 
Sende-Ringpuffer und empfängt Zeichen, die er in den Empfangs-Ringpuffer 
schreibt. Er bewertet die Inhalte NICHT.

- die von außen sichtbaren Funktionen des seiellen Treibers nehmen zu 
sendende Zeichen entgegen und stopfn sie in den Sende-Ringpuffer und sie 
geben empfangene Zeichen aus dem Empfangs-Ringpuffer an die aufrufenden 
Programmteile. Sie befassen sich NICHT mit der Hardware und sie bewerten 
auch die Inhalte NICHT.

Kommando-Verfahren:
Variante A:
Es gibt ein Kommandoprogramm, das eine Funktion enthält, welche aus der 
Grundschleife zyklisch aufgerufen wird. Diese Funktion fragt den 
seriellen Treiber ab, ob Empfangszeichen vorliegen, sortiert diese in 
einen Kommandopuffer und sendet ein Echo der Zeichen zurück. Sie kann 
auch diverse Editierfunktionen haben. Ist der Puffer voll oder ist ein 
Enter (CR oder LF oder was auch immer) erkannt, dann ruft sie die 
eigentliche Kommandofunktion auf, welche die Kommandozeile analysiert 
und entsprechend ausführt.

Variante B:
Es gibt ein Kommandoprogramm, das eine Funktion enthält, welche aus der 
Grundschleife zyklisch aufgerufen wird. Diese Funktion fragt den 
seriellen Treiber ab, ob Empfangszeichen vorliegen, wertet das aktuelle 
Zeichen aus und führt die zugehörigen Funktionen aus.

Diese Variante B ist nicht für HMI geeignet, aber für schnelle 
Maschinenkommunikation. Mal ein Beispiel für nen Plotter:
120.5X92.0YD200X20YU
macht nen Strich von x=120.5, y=92 nach x=200, y=20

W.S.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren