Forum: Mikrocontroller und Digitale Elektronik Delay Funktion für STM32 Board?


von Ivan J. (ivan1987)


Lesenswert?

Hallo,

ich übe mich in der c-Programmierung eines STM32 discovery bords.
In den Example Ordner ist ein Bsp GPIO-Toggle mit dem zwei LEDs blicken.
die Blink-Frequenz wird hierbei mit folgender Funktion beeinflusst.

void Delay(__IO uint32_t nCount)
{
  for(; nCount != 0; nCount--);
}

FRAGE:
Kann ich diese Funktion für eine definierte Wartezeit von z.B. 5ms 
verwenden?
Oder gibt es eine andere Möglichkeit eine definierte Warte-Funktion zu 
erstellen?

von abc (Gast)


Lesenswert?

Ich würds mit systic timer machen, so gehts aber auch.

Hab vor kurzem ein Displaytech 162 im 8-Bit mode angesteuert mit dem 
STM32F10x, wennst den selben hast kann ich dir die Lib schicken.

von AVerr (Gast)


Lesenswert?

Soviel ich mich erinnern kann, hing diese Funktion vom Systick Timer ab.
Man übergibt die Anzahl von Systick Takten, die gewartet werden soll,
also wenn der Systick jede ms tickt, würdest du mit Delay(5) 5ms warten.
Am Anfang der main Funktion wurde der Systick Timer eingestellt.

von Ivan J. (ivan1987)


Lesenswert?

@abc: Danke, das Board hab ich auch.
Und ich bin auch dabei ein LCD-Modul im 8-bit mode anzusteuern, bin aber 
schon bei der Initialisierung hängen geblieben.
Kannst du mir das schicken?

von Ivan J. (ivan1987)


Lesenswert?

Naja, die Funktion wird im Bsp mit
Delay(0xFFFFF);
aufgerufen, was eine Blinkrate von geschätzt 250ms ausmacht...

von abc (Gast)


Lesenswert?

main:
1
volatile int32_t SysTickCnt=0;
2
3
int main(void)
4
{
5
  RCC_ClocksTypeDef   Clocks;
6
  SystemInit();
7
8
  RCC_GetClocksFreq(&Clocks);
9
  SysTick_Config( Clocks.HCLK_Frequency/1000 - 1 );  // 1000 Hz ( T=1ms)
10
11
  while(1)
12
  {
13
14
}
15
}
16
17
void Delay (unsigned long tick)
18
{  
19
  int32_t SysTickCntHold;
20
     SysTickCntHold = SysTickCnt;  
21
  while((SysTickCnt - SysTickCntHold ) <= tick );   // wait ca. 110us
22
}

LCD.c:
1
#include "stm32f10x.h"
2
#include <stdio.h>
3
4
extern void Delay (unsigned long tick);
5
6
void LCD_RS(uint8_t val)           // RS ... register select
7
{
8
  if(val)   GPIO_SetBits  (GPIOB, GPIO_Pin_0);
9
  else     GPIO_ResetBits(GPIOB, GPIO_Pin_0);
10
}
11
12
13
static void LCD_RW(uint8_t val)           // RW ... read/write
14
{
15
  if(val)   GPIO_SetBits  (GPIOC, GPIO_Pin_5);
16
  else     GPIO_ResetBits(GPIOC, GPIO_Pin_5);
17
}
18
19
20
static void LCD_E(uint8_t val)             // E ... enable
21
{
22
  if(val){
23
    GPIO_SetBits  (GPIOC, GPIO_Pin_4);
24
    Delay(1);  //SET_TO 8-Bit (1/3)
25
      GPIO_ResetBits(GPIOC, GPIO_Pin_4);
26
  }
27
  else GPIO_ResetBits(GPIOC, GPIO_Pin_4);
28
}
29
30
void LCD_Data(uint8_t val)           
31
{
32
   GPIO_ResetBits (GPIOA, GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
33
  if(val)  GPIOA->ODR |= val;  //GPIOA->BSRR=val;
34
     LCD_E(1);
35
36
}
37
38
// Schreibt einen String auf das LCD
39
 
40
void lcd_string( char *data )
41
{
42
    while( *data != '\0' )
43
        LCD_Data( *data++ );
44
}
45
46
47
// Setzt den Cursor in Spalte x (0..15) Zeile y (1..2) 
48
 
49
void lcd_setcursor( uint8_t x, uint8_t y )
50
{
51
    uint8_t data;
52
 
53
    switch (y)
54
    {
55
        case 1:    // 1. Zeile
56
            data = 0x80 + 0x00 + x;
57
            break;
58
 
59
        case 2:    // 2. Zeile
60
            data = 0x80 + 0x40 + x;
61
            break;
62
        default:
63
            return;                                   // für den Fall einer falschen Zeile
64
    }
65
    LCD_RS(0);
66
    LCD_Data( data );
67
  LCD_RS(1);
68
}
69
70
void LCD_Init(void)
71
{
72
  GPIO_InitTypeDef  GPIO_InitStruct;
73
74
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
75
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
76
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);
77
78
    GPIO_InitStruct.GPIO_Pin    =  GPIO_Pin_0;      // RS
79
  GPIO_InitStruct.GPIO_Speed  =  GPIO_Speed_10MHz;
80
  GPIO_InitStruct.GPIO_Mode    =  GPIO_Mode_Out_PP;
81
  GPIO_Init(GPIOB, &GPIO_InitStruct);
82
83
    GPIO_InitStruct.GPIO_Pin    =  GPIO_Pin_4|GPIO_Pin_5;    //En and R/W
84
  GPIO_InitStruct.GPIO_Speed  =  GPIO_Speed_10MHz;
85
  GPIO_InitStruct.GPIO_Mode    =  GPIO_Mode_Out_PP;
86
  GPIO_Init(GPIOC, &GPIO_InitStruct);
87
88
    GPIO_InitStruct.GPIO_Pin    = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;      // Datenports Display
89
  GPIO_InitStruct.GPIO_Speed  =  GPIO_Speed_10MHz;
90
  GPIO_InitStruct.GPIO_Mode    =  GPIO_Mode_Out_PP;
91
  GPIO_Init(GPIOA, &GPIO_InitStruct);
92
93
  GPIO_ResetBits(GPIOB, GPIO_Pin_0);
94
  GPIO_ResetBits(GPIOC, GPIO_Pin_4 | GPIO_Pin_5);
95
  GPIO_ResetBits(GPIOA, GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
96
     
97
  /* DISPLAY INITIALISATION */
98
  LCD_RW(0);
99
100
  Delay(15);  //wait ca 15ms
101
  LCD_Data(0x30);    //SET_TO 8-Bit (1/4)
102
  Delay(5);  //wait more than 4,2ms
103
  LCD_Data(0x30);    //SET_TO 8-Bit (2/4)
104
  Delay(1);  //wait more than 110us
105
  LCD_Data(0x30);    //SET_TO 8-Bit (3/4)
106
  LCD_Data(0x30);    //SET_TO 8-Bit (4/4)
107
   
108
  LCD_Data(0x38);    //2-Line Display
109
  LCD_Data(0x08);    //Display Off
110
111
  LCD_Data(0x01);    //Delete Display
112
113
  LCD_Data(0x03);    //Cursor Right
114
115
  LCD_Data(0x06);    //Display On
116
117
  lcd_setcursor(0,0);    //Cursor 0/0
118
   
119
   LCD_Data(0x0C);    //Display On
120
121
   LCD_RS(1);
122
     
123
}

von abc (Gast)


Lesenswert?

Den auch noch in die main packen:
1
void SysTick_Handler(void)
2
{
3
  SysTickCnt++;
4
}

von frage (Gast)


Lesenswert?

Gibt es ein gutes tutorial zum stm32 oder eventuell ein Buch.das mir 
empfohlen werden könnte?

von abc (Gast)


Lesenswert?

nein, aber wenn du dich gut mit µ-Cs auskennst kann ich dir paar 
einfache gut dokumentierte Programmierbeispiele schicken, den rest 
findet man im Referenzmanual

von Roland H. (batchman)


Lesenswert?

Ivan Jast schrieb:
> void Delay(__IO uint32_t nCount)
> {
>   for(; nCount != 0; nCount--);
> }

Das ist Pfusch - vor allem auf einem stm32, welcher massig Timer zur 
Verfügung stellt.

abc schrieb:
> main:
> volatile int32_t SysTickCnt=0;

Kann es sein, dass da die ISR fehlt?

> void Delay (unsigned long tick)
> {
>   int32_t SysTickCntHold;
>      SysTickCntHold = SysTickCnt;
>   while((SysTickCnt - SysTickCntHold ) <= tick );   // wait ca. 110us
> }

Wo wird der Zählerüberlauf beachtet? Was bedeutet der Kommentar?

EDIT: Die ISR ist inzwischen eingetrudelt. Aber wo wird der Überlauf des 
Zählers behandelt?

von Ivan J. (ivan1987)


Lesenswert?

Danke für den Code! Ich werd ihn mal für meine Pins anpassen...

abc schrieb:
> Den auch noch in die main packen:
> void SysTick_Handler(void)

die Fkt ist (laut Fehler) schon in stm32f10x_it.c definiert... ohne sie 
gibts auch keinen Fehler.

von Karl H. (kbuchegg)


Lesenswert?

Roland H. schrieb:

>> void Delay (unsigned long tick)
>> {
>>   int32_t SysTickCntHold;
>>      SysTickCntHold = SysTickCnt;
>>   while((SysTickCnt - SysTickCntHold ) <= tick );   // wait ca. 110us
>> }
>
> Wo wird der Zählerüberlauf beachtet? Was bedeutet der Kommentar?
>
> EDIT: Die ISR ist inzwischen eingetrudelt. Aber wo wird der Überlauf des
> Zählers behandelt?

Da hier unsigned gerechnet wird, braucht man sich um 1 Überlauf nicht 
kümmern. Mehrere dürfen es allerdings nicht sein.

von frage (Gast)


Lesenswert?

@Abc also IDE programmer geht alles nur mit der stm lib kenn ich mich 
nicht aus! Erfahrung hab ich einiges mit avr.und 8051

von abc (Gast)


Lesenswert?

@ ivan, in der it datei passt natürlich auch
Wichtig ist dass du die SysTickCnt variable definierst und im IR handler 
erhöhst.

 SysTickCnt++;

Übern überlauf hab ich mir noch wenig gedanken gemachtr.

von Stefan von Bölde (Gast)


Lesenswert?

Ich habe mich an dieses Tutorial mit Beispielen gehalten:
http://en.radzio.dxp.pl/stm32vldiscovery/

von Klaus S. (skibby)


Lesenswert?

Ich habe das so realisiert:

void delay_us(uint32_t time_us)
{
  SysTick->LOAD  = 72 * time_us-1;
  SysTick->VAL   = 0;                                          /* Load 
the SysTick Counter Value */
  SysTick->CTRL  |= SysTick_CTRL_ENABLE_Msk;                   /* Enable 
SysTick Timer */

  do
  {
  } while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG)==0);
  SysTick->CTRL  &= ~SysTick_CTRL_ENABLE_Msk;                  /* 
Disable SysTick Timer */
  SysTick->VAL   = 0;                                          /* Load 
the SysTick Counter Value */
}

void delay_ms(uint16_t time_ms)
{
  while (time_ms>0)
  {
    delay_us(1000);
    time_ms--;
  }
}

von abc (Gast)


Lesenswert?

bei deinem Problem:

  if(val)  GPIOA->ODR |= val;  //GPIOA->BSRR=val;
     LCD_E(1);



Das es verkehrt herum ist, Probier mal:

  val = ( ((uint16_t)val) >> 8 ) | ( val << 8 );

von abc (Gast)


Lesenswert?

Das sollte funktionieren:

int bit_reverse(int in) {
  int rev=0;
  int i;

  for (i = 0; i < BIT_WIDTH; i++) {
   rev = (rev << 1) | (in & 1);
   in >>=1;
  }
  return rev;
}

von Ivan J. (ivan1987)


Lesenswert?

Jawohl :-)
dein Code funktioniert!! Herzlichen Dank!!!

Ich musste nur die Bitreihenfolge der Datenbits ändern, weil ich die 
andersrum angeschlossen hab (DB0 : PA7 usw), das geht mit folgendem 
Algorithmus am Anfang der LCD_Data Funktion:
1
  uint8_t temp1 = 0x00;
2
  uint8_t temp2 = 0x00;
3
  int i;
4
  for (i = 0; i<=7; i++) 
5
  {
6
    temp1 = val << i;
7
    temp1 = temp1 >> 7;
8
    temp1 = temp1 << i;
9
    temp2 = temp1 | temp2;
10
  }
11
  val = temp2;

von kremsy (Gast)


Lesenswert?

schön ;)

von Felix d. (inqui85)


Lesenswert?

abc schrieb:
> Ich würds mit systic timer machen, so gehts aber auch.
>
> Hab vor kurzem ein Displaytech 162 im 8-Bit mode angesteuert mit dem
> STM32F10x, wennst den selben hast kann ich dir die Lib schicken.

Moin Zusammen!

Bin grad am Basteln mit genau dem LCD,
habe auch ungefähr das selbe Problem mit der Initialisierung...

Möchte mir jemand mla einen Beispielcode/Project zur verfügung stellen, 
dann könnte cih vergleiche wie ihr das gemacht habts...

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.