Delay Funktion für STM32 Board?

OP #2697438
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?
Gast #2697445
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.
Gast #2697566
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
}
#2697586
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?
#2697691
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.
Gast #2697750
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.
#2698281
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--;
  }
}
OP #2698877
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;
#3034826
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...

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