Datum:
Hallo Leute, Ich versuche ein LCD-Display im 8-Bit Modus am STM32 zum laufen zum Bringen. Initialisierungsroutine:
#include "stm32f10x.h" #include <stdio.h> extern int32_t SysTickCnt; volatile unsigned long TimeTick; /*------------------------------------------------------------------------------ Delay function delays number of tick Systicks (happens every 10 ms) *------------------------------------------------------------------------------*/ static void Delay (unsigned long tick) { unsigned long timetick; timetick = TimeTick; while ((TimeTick - timetick) < tick); } static void LCD_RS(uint8_t val) // RS ... register select { if(val) GPIO_SetBits (GPIOB, GPIO_Pin_0); else GPIO_ResetBits(GPIOB, GPIO_Pin_0); } static void LCD_RW(uint8_t val) // RW ... read/write { if(val) GPIO_SetBits (GPIOC, GPIO_Pin_5); else GPIO_ResetBits(GPIOC, GPIO_Pin_5); } static void LCD_E(uint8_t val) // E ... enable { if(val) GPIO_SetBits (GPIOC, GPIO_Pin_4); else GPIO_ResetBits(GPIOC, GPIO_Pin_4); } static void LCD_Data(uint8_t val) // E ... enable { GPIOA->BSRR=0xFFFFFF; if(val) GPIOA->BSRR=val; } void LCD_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; int32_t SysTickCntHold; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; // Konfig. LED an PC8 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5; // Konfig. LED an PC8 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_All; // Datenports Display GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_ResetBits(GPIOB, GPIO_Pin_0); GPIO_ResetBits(GPIOC, GPIO_Pin_4 | GPIO_Pin_5); GPIO_ResetBits(GPIOA, GPIO_Pin_All); LCD_RW(0); SysTickCntHold = SysTickCnt; while((SysTickCnt - SysTickCntHold ) < 16 ); // wait ca. 15ms GPIO_SetBits (GPIOA, GPIO_Pin_4|GPIO_Pin_5); //Delay(1); LCD_E(1); Delay(1); //SET_TO 8-Bit (1/3) LCD_E(0); SysTickCntHold = SysTickCnt; while((SysTickCnt - SysTickCntHold ) < 5 ); // wait ca. 4.2ms LCD_E(1); Delay(1); //SET_TO 8-Bit (2/3) LCD_E(0); SysTickCntHold = SysTickCnt; while((SysTickCnt - SysTickCntHold ) < 2 ); // wait ca. 110us LCD_E(1); Delay(1); //SET_TO 8-Bit (3/3) LCD_E(0); Delay(1); LCD_E(1); Delay(1); //SET_TO 8-Bit (4/3) LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5); //2-Line Display LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_3); //Display off LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_0); //Delete Display LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_1|GPIO_Pin_2); //Cursor Right LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_2|GPIO_Pin_3); //Display On LCD_E(1); Delay(1); LCD_E(0); //beginn Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_0); //Delete Display LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_0|GPIO_Pin_3); //Blink Cursor LCD_E(1); Delay(1); LCD_E(0); } |
Delay(1) ist ein Delay von ca 10ms, nur zum Testen. Display D0 = PortA0 - D7=PortA7 Leider macht das Display garnichts, außer dass der Hintergrund ist und die Rechtecke in einer Zeile angezeigt werden (Industriestandart). Vielleicht habt ihr eine Idee.
Datum:
Das Problem wurde nun etwas eingeschränkt, anscheinend funtkioniert der Systick Timer nicht richtig.
#include "stm32f10x.h" #include <stdio.h> #include "lcd.h" volatile int32_t SysTickCnt=0; int32_t SysTickCntHold; void SysTick_Handler(void) { SysTickCnt++; } int main(void) { RCC_ClocksTypeDef Clocks; GPIO_InitTypeDef GPIO_InitStruct; RCC_GetClocksFreq(&Clocks); SysTick_Config( Clocks.HCLK_Frequency/1000 - 1 ); // 1000 Hz ( T=1ms) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; // Konfig. LED an PC8 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_SetBits(GPIOC, GPIO_Pin_8); SysTickCntHold = SysTickCnt; while((SysTickCnt - SysTickCntHold ) < 16 ); // wait ca. 15ms GPIO_ResetBits(GPIOC, GPIO_Pin_8); LCD_Init(); while(1) { } } |
Hier im Main Funktioniert der Systick-Timer ohne Probleme.
In der Datei lcd.c (code oben)
extern int32_t SysTickCnt;
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
int32_t SysTickCntHold;
GPIO_ResetBits(GPIOC, GPIO_Pin_8);
SysTickCntHold = SysTickCnt;
while((SysTickCnt - SysTickCntHold ) < 16 ); // wait ca. 15ms
GPIO_SetBits(GPIOC, GPIO_Pin_9);
...
Hängt sich der Prozessor anscheiend bei der While Schleife auf.
Datum:
Wenn ich die Funktionen alle in die Mainpacke, funktioniert das mit dem Systik aufjedenfall, alles wird bis zum ende durchgelaufen, nur am Display tut sich gar nichts.
Datum:
Angehängte Dateien:Hier die Beschaltung des Displays.
Datum:
Hier nun der aktuelle Code in der main.c
#include "stm32f10x.h" #include <stdio.h> //#include "lcd.h" void Delay (unsigned long tick); void LCD_Init(void); void LCD_SetPrintPosition(unsigned int ln, unsigned int col); // line 0...1 column 0...15 volatile int32_t SysTickCnt=0; int32_t SysTickCntHold; void SysTick_Handler(void) { SysTickCnt++; } int main(void) { RCC_ClocksTypeDef Clocks; GPIO_InitTypeDef GPIO_InitStruct; RCC_GetClocksFreq(&Clocks); SysTick_Config( Clocks.HCLK_Frequency/1000 - 1 ); // 1000 Hz ( T=1ms) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; // TESTLEDS GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_SetBits(GPIOC, GPIO_Pin_8); Delay(10); GPIO_ResetBits(GPIOC, GPIO_Pin_8); LCD_Init(); while(1) { } } void Delay (unsigned long tick) { // unsigned long timetick; // timetick = TimeTick; // while ((TimeTick - timetick) < tick); int32_t SysTickCntHold; SysTickCntHold = SysTickCnt; while((SysTickCnt - SysTickCntHold ) < tick ); // wait ca. 110us } static void LCD_RS(uint8_t val) // RS ... register select { if(val) GPIO_SetBits (GPIOB, GPIO_Pin_0); else GPIO_ResetBits(GPIOB, GPIO_Pin_0); } static void LCD_RW(uint8_t val) // RW ... read/write { if(val) GPIO_SetBits (GPIOC, GPIO_Pin_5); else GPIO_ResetBits(GPIOC, GPIO_Pin_5); } static void LCD_E(uint8_t val) // E ... enable { if(val) GPIO_SetBits (GPIOC, GPIO_Pin_4); else GPIO_ResetBits(GPIOC, GPIO_Pin_4); } static void LCD_Data(uint8_t val) // E ... enable { GPIOA->BSRR=0xFFFFFF; if(val) GPIOA->BSRR=val; } void LCD_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; int32_t SysTickCntHold; GPIO_SetBits(GPIOC, GPIO_Pin_9); Delay(15); GPIO_ResetBits(GPIOC, GPIO_Pin_9); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; // RS GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5; //En and R/W GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_All; // Datenports Display GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_ResetBits(GPIOB, GPIO_Pin_0); GPIO_ResetBits(GPIOC, GPIO_Pin_4 | GPIO_Pin_5); GPIO_ResetBits(GPIOA, GPIO_Pin_All); LCD_RW(0); GPIO_SetBits(GPIOC, GPIO_Pin_9); SysTickCntHold = SysTickCnt; while((SysTickCnt - SysTickCntHold ) < 16 ); // wait ca. 15ms GPIO_ResetBits(GPIOC, GPIO_Pin_8); GPIO_SetBits (GPIOA, GPIO_Pin_4|GPIO_Pin_5); //Delay(1); LCD_E(1); Delay(1); //SET_TO 8-Bit (1/3) LCD_E(0); SysTickCntHold = SysTickCnt; while((SysTickCnt - SysTickCntHold ) < 5 ); // wait ca. 4.2ms LCD_E(1); Delay(1); //SET_TO 8-Bit (2/3) LCD_E(0); SysTickCntHold = SysTickCnt; while((SysTickCnt - SysTickCntHold ) < 2 ); // wait ca. 110us LCD_E(1); Delay(1); //SET_TO 8-Bit (3/3) LCD_E(0); Delay(1); LCD_E(1); Delay(1); //SET_TO 8-Bit (4/3) LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5); //2-Line Display LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_3); //Display off LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_0); //Delete Display LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_1|GPIO_Pin_2); //Cursor Right LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_2|GPIO_Pin_3); //Display On LCD_E(1); Delay(1); LCD_E(0); //beginn Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_0); //Delete Display LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_0|GPIO_Pin_3); //Blink Cursor LCD_E(1); Delay(1); LCD_E(0); GPIO_ResetBits(GPIOC, GPIO_Pin_9); } |
Und das Display macht wie gesagt gar nichts, außer der Hintergrund und die erste Zeile bei der alle Punkte leuchten.
Datum:
niemand eine Idee?
Datum:
Hab die Ausgänge jetzt auf Push-Pull gestellt, das Display initialisiert wohl nun erfolgreich, aber angezeigt bekomm ich noch nichts.
//beginn Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_7); //DD-Ram LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_0); //Delete Display LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_0|GPIO_Pin_3); //Blink Cursor LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_3); //Blink Cursor LCD_E(1); Delay(1); LCD_E(0); Delay(1); GPIO_ResetBits (GPIOA, GPIO_Pin_All); GPIO_SetBits (GPIOA, GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3); //W GPIO_SetBits (GPIOA, GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); LCD_RS(1); LCD_E(1); Delay(1); LCD_E(0); |
Will nur einen Buchstaben anzeigen lassen.
Datum:
Habs geschafft ;).
Datum:
Falls es jemand interessiert, hier ist der Funktionierende Code:
#include "stm32f10x.h" #include <stdio.h> //#include "lcd.h" void Delay (unsigned long tick); void LCD_Init(void); static void LCD_Data(uint8_t val); static void lcd_string( const char *data ); void lcd_setcursor( uint8_t x, uint8_t y ); //void LCD_SetPrintPosition(unsigned int ln, unsigned int col); // line 0...1 column 0...15 volatile int32_t SysTickCnt=0; int32_t SysTickCntHold; void SysTick_Handler(void) { SysTickCnt++; } int main(void) { RCC_ClocksTypeDef Clocks; GPIO_InitTypeDef GPIO_InitStruct; RCC_GetClocksFreq(&Clocks); SysTick_Config( Clocks.HCLK_Frequency/1000 - 1 ); // 1000 Hz ( T=1ms) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; // TESTLEDS GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStruct); LCD_Init(); LCD_Data('H'); LCD_Data('A'); LCD_Data('L'); LCD_Data('L'); LCD_Data('O'); lcd_string(" POOL 38°C"); lcd_setcursor(5,2); lcd_string(" TEST"); while(1) { } } /******************************************************************************* * Function Name : EXTI9_5_IRQHandler * Description : This function handles External lines 9 to 5 interrupt request. * Input : None * Output : None * Return : None *******************************************************************************/ void EXTI0_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line0) != RESET) //EXTI_Line 0 hat ausgeloest? { EXTI_ClearITPendingBit(EXTI_Line0); } } void TIM3_IRQHandler (void) { TIM_ClearFlag(TIM3, TIM_FLAG_Update); } void Delay (unsigned long tick) { int32_t SysTickCntHold; SysTickCntHold = SysTickCnt; while((SysTickCnt - SysTickCntHold ) <= tick ); // wait ca. 110us } static void LCD_RS(uint8_t val) // RS ... register select { if(val) GPIO_SetBits (GPIOB, GPIO_Pin_0); else GPIO_ResetBits(GPIOB, GPIO_Pin_0); } static void LCD_RW(uint8_t val) // RW ... read/write { if(val) GPIO_SetBits (GPIOC, GPIO_Pin_5); else GPIO_ResetBits(GPIOC, GPIO_Pin_5); } static void LCD_E(uint8_t val) // E ... enable { if(val){ GPIO_SetBits (GPIOC, GPIO_Pin_4); Delay(1); //SET_TO 8-Bit (1/3) GPIO_ResetBits(GPIOC, GPIO_Pin_4); } else GPIO_ResetBits(GPIOC, GPIO_Pin_4); } static void LCD_Data(uint8_t val) // E ... enable { GPIO_ResetBits (GPIOA, GPIO_Pin_All); if(val) GPIOA->BSRR=val; LCD_E(1); } // Schreibt einen String auf das LCD static void lcd_string( const char *data ) { while( *data != '\0' ) LCD_Data( *data++ ); } // Setzt den Cursor in Spalte x (0..15) Zeile y (1..2) void lcd_setcursor( uint8_t x, uint8_t y ) { uint8_t data; switch (y) { case 1: // 1. Zeile data = 0x80 + 0x00 + x; break; case 2: // 2. Zeile data = 0x80 + 0x40 + x; break; default: return; // für den Fall einer falschen Zeile } LCD_RS(0); LCD_Data( data ); LCD_RS(1); } void LCD_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; // RS GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5; //En and R/W GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_All; // Datenports Display GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_ResetBits(GPIOB, GPIO_Pin_0); GPIO_ResetBits(GPIOC, GPIO_Pin_4 | GPIO_Pin_5); GPIO_ResetBits(GPIOA, GPIO_Pin_All); /* DISPLAY INITIALISATION */ LCD_RW(0); Delay(15); //wait ca 15ms LCD_Data(0x30); //SET_TO 8-Bit (1/4) Delay(5); //wait more than 4,2ms LCD_Data(0x30); //SET_TO 8-Bit (2/4) Delay(1); //wait more than 110us LCD_Data(0x30); //SET_TO 8-Bit (3/4) LCD_Data(0x30); //SET_TO 8-Bit (4/4) LCD_Data(0x38); //2-Line Display LCD_Data(0x08); //Display Off LCD_Data(0x01); //Delete Display LCD_Data(0x03); //Cursor Right LCD_Data(0x06); //Display On lcd_setcursor(0,0); //Cursor 0/0 LCD_Data(0x0C); //Display On LCD_RS(1); } |
Datum:
Hallo, ich arbeite auch mit dem STM32 Board und dem 1602 LCD Modul. Ich bekomm bei deinem Code allerdings den Fehler: ".\Debug\GPIOToggle.axf: Error: L6200E: Symbol SysTick_Handler multiply defined (by stm32f10x_it.o and main.o)." Wenn ich die Funktion SysTick_Handler in der stm32f10x_it.c ausklammer (in der im Übrigen auch nichts gemacht wird), gibts kein Fehler, allerdings kommt beim Display nichts raus (nur der Standardbalken...)!? Fehlt bei deinem geposteten Code noch was?
Datum:
Ich hab den Fehler gefunden: wenn ich mein LCD Modul der Reihe nach anstecke ist DB0 PA7 zugeordnet. Das ist genau umgekehrt, wie bei dir... ich hab alle "LCD_Data" Befehle beim Aufruf geswapt, dann gehts auch. Kennt jmd einen Befehl bei stm32 mit dem man die nibbels eines bytes tauschen kann?
Datum:
Ivan, den code hier nicht nehmen, sondern den vom anderen Thread.
Datum:
kremsy schrieb: > Ivan, den code hier nicht nehmen, sondern den vom anderen Thread. danke, für alle: Beitrag "Delay Funktion für STM32 Board?"
