Forum: Mikrocontroller und Digitale Elektronik stm32f4 Probleme mit Sinus funktion


von Oliver F. (ollif)


Lesenswert?

Hallo Forum,

ich versuche gerade eine Lookuptable mit Sinuswerten zu füllen.

Benutze System Workbench un ein STM 32F4 Discovery board.

Wenn ich den Folgenden Code aufrufe
...
1
int sinustable_init(){
2
3
  int  i = 0;
4
  for ( i = 0; i < 255; ++i) {
5
    sinustable[i] = sin(i);   //geht nicht
6
    
7
      }
8
return i;
9
}
bricht das Programm ab.

Zum Test habe ich einmal
1
int sinustable_init(){
2
3
  int  i = 0;
4
  for ( i = 0; i < 255; ++i) {
5
    sinustable[i] = sin(i);   //geht nicht
6
    //sinustable[i] = sin(10);      //funktioniert  
7
      }
8
return i;
9
}
probiert und dann wurde das Array mit -0.54402111088936977 gefüllt.


Was mach ich denn hierbei falsch bzw. wie kann ich hier ermitteln an was 
es liegt.
Dies sin(Double) Funktion scheint ja zu funktionieren und alle libs sind 
dann wohl richtig.



Hier nochmal der komplette Code:
1
#include "stm32f4xx.h"
2
3
#include "stm32f4_discovery.h"
4
5
#include "stm32f4xx_gpio.h"
6
#include "stm32f4xx_rcc.h"
7
8
#include <stdio.h>
9
#include <stdlib.h>
10
#include <math.h>
11
#include <float.h>
12
13
int sinustable_init();
14
15
double sinustable[256];
16
17
void Delay(volatile uint32_t nCount)
18
{
19
  while(nCount--)
20
  {
21
  }
22
}
23
24
int sinustable_init(){
25
26
  int  i = 0;
27
  for ( i = 0; i < 255; ++i) {
28
    sinustable[i] = sin(i);   //geht nicht
29
    //sinustable[i] = sin(10);      //funktioniert -0.54402111088936977
30
      }
31
return i;
32
}
33
34
void init(void) {
35
  GPIO_InitTypeDef  GPIO_InitStructure;
36
37
38
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
39
40
41
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
42
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
43
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
44
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
45
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
46
  GPIO_Init(GPIOD, &GPIO_InitStructure);
47
}
48
49
int main(void)
50
{
51
  SystemInit();
52
  init();
53
  sinustable_init();
54
  while(1) {
55
    Delay(500000);
56
    GPIOD->ODR ^= GPIO_Pin_12;
57
  }
58
}


Vielen Dank im Voraus.

Gruß

Oliver

von Pd G. (pdg)


Lesenswert?

Du denkst schon dran, dass du hier mit Radian rechnest?
Die Sinustabelle hätte also bei 0...255 ca 40.5 Perioden (eine Periode = 
2*Pi).
Eigentlich berechnet man auch nur eine halbe Periode oder sogar nur eine 
viertel Periode und spiegelt diese Teil-Tabellen per Pointer, um 
Speicherplatz zu sparen.

Dann noch das Pre-Increment ++i, das man gelegentlich in Java nimmt. 
Hier hast du es aber mit einer for-Loop in C zu tun und da wird i.d.R. 
Post-Increment i++ verwendet (mach mal eine Grenzwertbetrachtung mit 
i={0|254|255}).

von Embedder (Gast)


Lesenswert?

Hi,

wegen dem ++i, mach dir mal keinen Stress. Ganz im Gegenteil soweit ich 
wieß bringt das sogar Performance Vorteile (den genauen Hintergrund 
bekomme ich jetzt nicht mehr hin ohne selbst zu googeln). Grob hat es 
etwas damit zu tun, dass ein Postinkrement den Wert länger vorhalten 
muss als der Präinkrement. Auf keinen Fall entsteht dadurch in diesem 
Kontext aber ein nachteiliges Verhalten.

Ansonsten hat PdG natürlich recht, was möchtest Du denn mit sin(255) 
ausdrücken? Das gäbe ja noch nichtmal als Gradwert einen Sinn...

Rechne mit 2 * PI bzw. wie vorgeschlagen sogar mit Spiegelungen (ich 
denke aber 2 * PI ist in diesem Fall zielführender...).

Viele Grüße!

von Dr. Sommer (Gast)


Lesenswert?

Pd G. schrieb:
> Hier hast du es aber mit einer for-Loop in C zu tun und da wird i.d.R.
> Post-Increment i++ verwendet

In C++ ist pre de/in-krement etwas sinnvoller, da uU. effizienter falls 
es kein einfacher Integer Typ ist.

Oliver F. schrieb:
> bricht das Programm ab.

Spezifiziere das mal genauer. Hast du vielleicht einfach nur die FPU 
nicht aktiviert, Code für die falsche FPU generiert (Compiler Optionen), 
oder die falsche C Library gelinkt?

von Dr. Sommer (Gast)


Lesenswert?


von Oliver F. (ollif)


Lesenswert?

Hallo,

Inhaltlich habt ihr recht dass die Berechnung über diesen Wertebereich 
keinen Sinn macht. Der Tipp mit
1
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */

war gold richtig.

Vielen Dank.

Gruß

Oliver

von Optimiert schlechter als gar nicht (Gast)


Lesenswert?

Bei billigen Integern und Floats sind selbst bei -O0 die Binarys absolut 
identisch, egal ob Post- oder Preinkrement.(getestet mit gcc 5.3.0 x86 
und ARM)
Mit diesen Pseudooptimierungen verschwendet ihr nur eure Zeit

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.