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?
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.
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.
@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?
Naja, die Funktion wird im Bsp mit Delay(0xFFFFF); aufgerufen, was eine Blinkrate von geschätzt 250ms ausmacht...
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 | }
|
Den auch noch in die main packen:
1 | void SysTick_Handler(void) |
2 | {
|
3 | SysTickCnt++; |
4 | }
|
Gibt es ein gutes tutorial zum stm32 oder eventuell ein Buch.das mir empfohlen werden könnte?
nein, aber wenn du dich gut mit µ-Cs auskennst kann ich dir paar einfache gut dokumentierte Programmierbeispiele schicken, den rest findet man im Referenzmanual
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?
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.
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.
@Abc also IDE programmer geht alles nur mit der stm lib kenn ich mich nicht aus! Erfahrung hab ich einiges mit avr.und 8051
@ 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.
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--; } }
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 );
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; }
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; |
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.