LCD Programmierung Nibble verschwinden
-
Hallo,
ich bin gerade dabei, eine Wetterstation zu bauen. Dazu habe ich dieses Display:
https://www.reichelt.de/lcd-dip-modul-supertwist-4x20-zeichen-blau-ea-dip203b-4-p129612.html?r=1
Das Display wird im 4 Bit Modus angesteuert und die Initialisierung läuft so weit.
Jetzt soll in der- Zeile "Temperatur:"
- Zeile "Luftdruck:"
- Zeile "Feuchtigkeit:"
- Zeile "Helligkeit:"
Nach der Initialisierung werden direkt diese Zeilen auf das Display geschrieben.
Jetzt zu meinem Problem:
Die erste Zeile wird richtig ausgegeben. (Zeile 1 Spalte 0)
Die zweite Zeile wird jedoch in Zeile 2, Spalte 11 ausgegeben.
Die dritte Zeile wird in Zeile 3, Spalte 11 und die
vierte zeile wird in Zeile 4, Spalte 11
ich habe herausgefunden, warum ausgerechnet in Spalte 11 geschrieben wird. Das liegt daran, dass wenn ich die Funktion, um den Cursor in eine bestimmte Zeile und Spalte aufrufe, das erste Nibble irgendwie verloren geht. Das heißt, der Cursor wird mit dem unteren Nibble des 1. Befehls und des oberen Nibbles des 2. Befehls gesetzt.
Ich habe aber keine Ahnung, warum dieses obere Nibble des 1. Befehls "verloren geht?".
Ich hoffe ihr könnt mir da helfen. Ich hoffe das ist soweit alles verständlich.
Danke schonmal im Vorraus.
Hier ist meine main:
#include "defines.h" // ********************************************************* /// \fn int main(void) /// \par Funktion: /// - main Funktion der Wetterstation // ********************************************************* int main(void) { // initialize the device SYSTEM_Initialize(); timer_init(); // init des Timers //temp_hum_init(); //auswertung_sensoren_init(); //Globale Interruptfreigabe INTERRUPT_ENABLE; //Initialisierung_Lichtsensor(); //Initialisierung_LED_Treiber(); initialize_lcd(); setcursor_lcd(LCD_ADRESSE_LINIE3,0); text_LCD("Temperatur:"); delay_display =10000/FAKTOR_US; while(delay_display); setcursor_lcd(LCD_ADRESSE_LINIE1,8); delay_display = LCD_CURSOR_SET_MS / 10; while(delay_display); text_LCD("Luftdruck:"); setcursor_lcd(LCD_ADRESSE_LINIE3,0); delay_display = LCD_CURSOR_SET_MS / 10; while(delay_display); text_LCD("Feuchtigkeit:"); setcursor_lcd(LCD_ADRESSE_LINIE4,0); delay_display = LCD_CURSOR_SET_MS / 10; while(delay_display); text_LCD("Helligkeit:");
Hier ist mein Unterprogramm fürs LCD: (Ich weiß, dass mein LCD_OUT NICHT schön ist)
Zur Erklärung: Die delay_display = xxx/FAKTOR_US ist meine Zeitverzögerung, While delay_display gehört auch dazu.#include "defines.h" //////////////////////////////////////////////////////////////////////////////// // Initialisierung des LCD void initialize_lcd() //Funktioniert { delay_display=50000/FAKTOR_US; while (delay_display); LCD_RS_LOW; delay_display=10000/FAKTOR_US; while (delay_display); LCD_RW_LOW; delay_display=10000/FAKTOR_US; while (delay_display); LCD_EN_HIGH; delay_display=10000/FAKTOR_US; while (delay_display); LCD_OUT(0x03); LCD_EN_PULSE(); delay_display=10000/FAKTOR_US; while (delay_display); LCD_OUT(0x03); LCD_EN_PULSE(); delay_display=10000/FAKTOR_US; while (delay_display); LCD_OUT(0x03); LCD_EN_PULSE(); delay_display=10000/FAKTOR_US; while (delay_display); LCD_OUT(0x02); LCD_EN_PULSE(); delay_display=10000/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(0x24); delay_display=50/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(0x09); delay_display=50/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(0x20); delay_display=50/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(0x02); delay_display=2000/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(0x0F); delay_display=50/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(0x01); delay_display=2000/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(0x24); delay_display=50/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(0x06); delay_display=50/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(0x20); delay_display=50/FAKTOR_US; while (delay_display); } //////////////////////////////////////////////////////////////////////////////// // Aufruf zum senden eines Commands void LCD_COMMAND_OUT(uint8_t Befehl) //Befehl zum aufrufen von Befehlen { BYTE_ZERLEGEN(Befehl); } //////////////////////////////////////////////////////////////////////////////// // Aufruf zum senden eines Textes void LCD_TEXT_OUT(uint8_t byte) //Befehl zur Ausgabe von Texten { BYTE_ZERLEGEN_TEXT(byte); } //////////////////////////////////////////////////////////////////////////////// // Zerlegen eines Bytes in 4 Nibble und senden an LCD (Befehl) void BYTE_ZERLEGEN(uint8_t byte) { uint8_t data4_u = 0; //untere 4 Bit uint8_t data4_o = 0; //obere 4 Bit uint8_t data8 = 0; //Ursprungsbyte data8 = byte; //Übergebenes Byte in Ursprungsbyte schreiben data4_u = data8 & 0x0F; //Ausmaskieren der unteren 4 Bit data4_o = 0xF0 & data8; //Ausmaskieren der oberen 4 Bit mit Hilfe von Shift data4_o = data4_o >> 4; LCD_RS_LOW; //Setzen von RS=0 (Command) LCD_RW_LOW; //setzen von RW=0 (Write) LCD_OUT(data4_o); //Ausgabe an Display oberes Nibble LCD_EN_PULSE(); //Enable Pulse LCD_OUT(data4_u); //Ausgabe an Display unteres Nibble LCD_EN_PULSE(); //Enable Pulse } //////////////////////////////////////////////////////////////////////////////// // Zerlegen eines Bytes in 2 Nibble und senden an LCD (Text) void BYTE_ZERLEGEN_TEXT(uint8_t byte) { uint8_t data4_u = 0; //untere 4 Bit 0101 0010 uint8_t data4_o = 0; //obere 4 Bit uint8_t data8 = 0; //Ursprungsbyte data8 = byte; //Übergebenes Byte in Ursprungsbyte schreiben data4_u = data8 & 0x0F; //Ausmaskieren der unteren 4 Bit data4_o = 0xF0 & data8; //Ausmaskieren der oberen 4 Bit mit Hilfe von Shift data4_o = data4_o >> 4; LCD_RS_HIGH; //Setzen von RS=1 (Text) LCD_RW_LOW; //setzen von RW=0 (Write) LCD_OUT(data4_o); //Ausgabe an Display oberes Nibble LCD_EN_PULSE(); //Enable Pulse LCD_OUT(data4_u); //Ausgabe an Display unteres Nibble LCD_EN_PULSE(); //Enable Pulse } //////////////////////////////////////////////////////////////////////////////// // Senden eines Enable Puls -> Wechsel von high auf low und zurück void LCD_EN_PULSE() { LCD_EN_HIGH; //Setzen von Enable Pin auf High delay_display = 10000 / 10; //Zeitverzögerung while (delay_display); //Zeitverzögerung LCD_EN_LOW; //Setzen von Enable Pin auf Low delay_display = 10000 / 10; //Zeitverzögerung while (delay_display); //Zeitverzögerung LCD_EN_HIGH; //Setzen von Enable Pin auf High delay_display = 10000 / 10; //Zeitverzögerung while (delay_display); //Zeitverzögerung } //void text_LCD(unsigned char *str,uint8_t zeile, uint8_t spalte) void text_LCD(unsigned char *str) { LCD_RS_HIGH; //Setzen von RS=1 (Text) LCD_RW_LOW; //setzen von RW=0 (Write) LCD_OUT(0x00); LCD_EN_PULSE(); while(*str != '\0') { LCD_TEXT_OUT(*str); str++; } LCD_OUT(0x00); } //////////////////////////////////////////////////////////////////////////////// // Cursor an beliebige Position setzen void setcursor_lcd(uint8_t zeile, uint8_t spalte) { LCD_RS_LOW; uint8_t Byte=0; Byte=zeile+spalte; LCD_COMMAND_OUT(Byte); //Befehl mit entsprechendem Hex Wert an Display senden } //////////////////////////////////////////////////////////////////////////////// // Ausgabe von hex Werten an das Display int LCD_OUT(uint8_t data) { switch (data) //je nach Hex Wert werden verschiedene Datenleitungen auf die entsprechenden Pegel gelegt { case 0x00: { LCD_D0_LOW; LCD_D1_LOW; LCD_D2_LOW; LCD_D3_LOW; break; } case 0x01: { LCD_D0_HIGH; LCD_D1_LOW; LCD_D2_LOW; LCD_D3_LOW; break; } case (0x10): { LCD_D0_HIGH; LCD_D1_LOW; LCD_D2_LOW; LCD_D3_LOW; break; } case 0x02: { LCD_D0_LOW; LCD_D1_HIGH; LCD_D2_LOW; LCD_D3_LOW; break; } case 0x20: { LCD_D0_LOW; LCD_D1_HIGH; LCD_D2_LOW; LCD_D3_LOW; break; } case 0x03: { LCD_D0_HIGH; LCD_D1_HIGH; LCD_D2_LOW; LCD_D3_LOW; break; } case 0x30: { LCD_D0_HIGH; LCD_D1_HIGH; LCD_D2_LOW; LCD_D3_LOW; break; } case 0x04: { LCD_D0_LOW; LCD_D1_LOW; LCD_D2_HIGH; LCD_D3_LOW; break; } case 0x40: { LCD_D0_LOW; LCD_D1_LOW; LCD_D2_HIGH; LCD_D3_LOW; break; } case 0x05: { LCD_D0_HIGH; LCD_D1_LOW; LCD_D2_HIGH; LCD_D3_LOW; break; } case 0x50: { LCD_D0_HIGH; LCD_D1_LOW; LCD_D2_HIGH; LCD_D3_LOW; break; } case 0x06: { LCD_D0_LOW; LCD_D1_HIGH; LCD_D2_HIGH; LCD_D3_LOW; break; } case 0x60: { LCD_D0_LOW; LCD_D1_HIGH; LCD_D2_HIGH; LCD_D3_LOW; break; } case 0x07: { LCD_D0_HIGH; LCD_D1_HIGH; LCD_D2_HIGH; LCD_D3_LOW; break; } case 0x70: { LCD_D0_HIGH; LCD_D1_HIGH; LCD_D2_HIGH; LCD_D3_LOW; break; } case 0x08: { LCD_D0_LOW; LCD_D1_LOW; LCD_D2_LOW; LCD_D3_HIGH; break; } case 0x80: { LCD_D0_LOW; LCD_D1_LOW; LCD_D2_LOW; LCD_D3_HIGH; break; } case 0x09: { LCD_D0_HIGH; LCD_D1_LOW; LCD_D2_LOW; LCD_D3_HIGH; break; } case 0x90: { LCD_D0_HIGH; LCD_D1_LOW; LCD_D2_LOW; LCD_D3_HIGH; break; } case 0x0a: { LCD_D0_LOW; LCD_D1_HIGH; LCD_D2_LOW; LCD_D3_HIGH; break; } case 0xa0: { LCD_D0_LOW; LCD_D1_HIGH; LCD_D2_LOW; LCD_D3_HIGH; break; } case 0x0b: { LCD_D0_HIGH; LCD_D1_HIGH; LCD_D2_LOW; LCD_D3_HIGH; break; } case 0xb0: { LCD_D0_HIGH; LCD_D1_HIGH; LCD_D2_LOW; LCD_D3_HIGH; break; } case 0x0c: { LCD_D0_LOW; LCD_D1_LOW; LCD_D2_HIGH; LCD_D3_HIGH; break; } case 0xc0: { LCD_D0_LOW; LCD_D1_LOW; LCD_D2_HIGH; LCD_D3_HIGH; break; } case 0x0d: { LCD_D0_HIGH; LCD_D1_LOW; LCD_D2_HIGH; LCD_D3_HIGH; break; } case 0xd0: { LCD_D0_HIGH; LCD_D1_LOW; LCD_D2_HIGH; LCD_D3_HIGH; break; } case 0x0e: { LCD_D0_LOW; LCD_D1_HIGH; LCD_D2_HIGH; LCD_D3_HIGH; break; } case 0xe0: { LCD_D0_LOW; LCD_D1_HIGH; LCD_D2_HIGH; LCD_D3_HIGH; break; } case 0x0f: { LCD_D0_HIGH; LCD_D1_HIGH; LCD_D2_HIGH; LCD_D3_HIGH; break; } case 0xf0: { LCD_D0_HIGH; LCD_D1_HIGH; LCD_D2_HIGH; LCD_D3_HIGH; break; } default:break; } }
Hier ist noch meine .h Datei:
/* * File: UP_LCD.h * Author: sebas * * Created on 15. Juni 2020, 13:12 */ #ifndef UP_LCD_H #define UP_LCD_H //////////////////////////////////////////////////////////////////////////////// //Pinkonfiguration //RS PIN #define LCD_RS_HIGH IO_RB10_D_RS_SetHigh() //RS High #define LCD_RS_LOW IO_RB10_D_RS_SetLow() //RS Low //RW PIN #define LCD_RW_HIGH IO_RB13_D_RW_SetHigh() //RW High #define LCD_RW_LOW IO_RB13_D_RW_SetLow() //RW Low //EN PIN #define LCD_EN_HIGH IO_RB12_D_EN_SetHigh() //EN High #define LCD_EN_LOW IO_RB12_D_EN_SetLow() //EN Low //Datenleitungen #define LCD_D0_HIGH IO_RB2_D0_SetHigh() //Datenleitung 0 High #define LCD_D0_LOW IO_RB2_D0_SetLow() //Datenleitung 0 Low #define LCD_D1_HIGH IO_RB3_D1_SetHigh() //Datenleitung 1 High #define LCD_D1_LOW IO_RB3_D1_SetLow() //Datenleitung 1 Low #define LCD_D2_HIGH IO_RB4_D2_SetHigh() //Datenleitung 2 High #define LCD_D2_LOW IO_RB4_D2_SetLow() //Datenleitung 2 Low #define LCD_D3_HIGH IO_RB5_D3_SetHigh() //Datenleitung 3 High #define LCD_D3_LOW IO_RB5_D3_SetLow() //Datenleitung 3 Low //////////////////////////////////////////////////////////////////////////////// //Byte in 2 Nibble zerlegen für Befehle void BYTE_ZERLEGEN(uint8_t byte); //////////////////////////////////////////////////////////////////////////////// //Byte in 2 Nibble zerlegen für Text Ausgabe void BYTE_ZERLEGEN_TEXT(uint8_t byte); //////////////////////////////////////////////////////////////////////////////// //Ausgabe eines Bytes int LCD_OUT(uint8_t data); //////////////////////////////////////////////////////////////////////////////// //Ausgabe eines Befehls void LCD_COMMAND_OUT(uint8_t Befehl); void text_LCD(unsigned char *str); //void text_LCD(unsigned char *str, uint8_t zeile, uint8_t spalte); //void text_Druck_LCD(); //void text_Feucht_LCD(); //void text_Hell_LCD(); //void text_Var_LCD(x, y, z) //Variable Textausgabe wenn x=...h-> helligkeit ...t->temperatur ...d-> druck ...f->feuchtigkeit //y=Zeile, z=Spalte //////////////////////////////////////////////////////////////////////////////// //Ausführungszeiten in Mikrosekunden #define LCD_BOOTUP_MS 30000 #define LCD_ENABLE_US 20 #define LCD_COMMAND_US 50 #define LCD_SOFT_RESET_MS1 5000 #define LCD_SOFT_RESET_US2 100 #define LCD_SOFT_RESET_US3 100 #define LCD_SET_4BITMODE_MS 5000 #define LCD_CLEAR_DISPLAY_MS 2000 #define LCD_CURSOR_HOME_MS 2000 #define LCD_CURSOR_SET_MS 2000 //////////////////////////////////////////////////////////////////////////////// //Zeilendefinition #define LCD_ADRESSE_LINIE1 0x80 //Zeile 1 #define LCD_ADRESSE_LINIE2 0xA0 //Zeile 2 #define LCD_ADRESSE_LINIE3 0xC0 //Zeile 3 #define LCD_ADRESSE_LINIE4 0xE0 //Zeile 4 //////////////////////////////////////////////////////////////////////////////// //Enable Impuls //void LCD_EN_PULSE(); //////////////////////////////////////////////////////////////////////////////// //Initialisierung void init_lcd(); void initialize_lcd(); //////////////////////////////////////////////////////////////////////////////// //LCD Zeilen löschen void clear_lcd(void); //////////////////////////////////////////////////////////////////////////////// //Cursor an Zeile 1 Spalte 1 (Home) void home_lcd(void); //////////////////////////////////////////////////////////////////////////////// //Cursor an beliebige Position void setcursor_lcd(uint8_t zeile, uint8_t spalte); //////////////////////////////////////////////////////////////////////////////// //Ausgabe eines Commands an LCD void LCD_COMMAND_OUT(uint8_t Befehl); //////////////////////////////////////////////////////////////////////////////// //Ausgabe eines Textes an LCD void text_lcd(unsigned char data); int CHAR_ASCII(char data); //////////////////////////////////////////////////////////////////////////////// //Kommandos für command_lcd //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //Clear LCD Display 0b00000001 Dauer: 1.53ms EN=*, RS=0,R/W=0 #define LCD_CLEAR 0x01 //////////////////////////////////////////////////////////////////////////////// //Cursor at Home 0b00000010 Dauer: 1.53ms EN=0, ES=0, R/W=0 #define CURSOR_AT_HOME 0x02 //////////////////////////////////////////////////////////////////////////////// //4_Zeilen Display #define FOUR_LINE_DISPLAY 0x28 //////////////////////////////////////////////////////////////////////////////// //Display On/Off 0b00001xxx Dauer: 39µs EN=0, RS=0, R/W=0 #define LCD_DISPLAY_OFF 0x08 #define LCD_DISPLAY_ON 0x0C #define LCD_CURSOR_OFF 0x08 #define LCD_CURSOR_ON 0x0A #define LCD_BLINKING_OFF 0x08 #define LCD_BLINKING_ON 0x09 #define LCD_ALL_ON 0x0F //////////////////////////////////////////////////////////////////////////////// //Entry Mode Set #define LCD_ENTRY_MODE_SET 0x06 //////////////////////////////////////////////////////////////////////////////// //Function Set 0b001xxxxx Dauer: 39µs EN=0, RS=0, R/W=0 #define Function_Set_4Bit_2Line 0x2E #define Function_Set_4Bit 0x28 #define Function_Set_8Bit 0x30 //////////////////////////////////////////////////////////////////////////////// //extendet Function Set #define Extend_Function_Set 0x09 //////////////////////////////////////////////////////////////////////////////// //Display Data Ram Adresse 0b10000000 Dauer:39µs EN=0, RS=0, R/W=0 #define SET_DISPLAY_DATA_RAM 0x80 //////////////////////////////////////////////////////////////////////////////// #endif
-
Ist es hier im Forum möglich, Bilder hochzuladen?
MfG
-
Falls es wichtig ist: Ich verwende ein PIC32MX110F016B-I/SS Controller in Verbindung mit MPLAB und einem X32 Compiler
-
@IchBins sagte in LCD Programmierung Nibble verschwinden:
Ist es hier im Forum möglich, Bilder hochzuladen?
Nein, in dem Fall solltest du einen externen Bildhoster benutzen.
Zu deiner Frage: Uff! Das ist eine Menge Code zu einem sehr speziellen Gebiet. Da musst du viel Glück haben, um jemanden zu finden, der sich damit auskennt. Ich tu's jedenfalls nicht.
-
@IchBins Was für ein Display hast du denn (4x16, 4* 32, ....)?
Und welchen Controller hat das Display?@IchBins sagte in LCD Programmierung Nibble verschwinden:
Hier ist mein Unterprogramm fürs LCD: (Ich weiß, dass mein LCD_OUT NICHT schön ist)
Auch deine Funktionsnamen sind verwirrend und machen eigentlich andere Dinge als sie heißen.
BYTE_ZERLEGEN sendet ein ganzes Byte als Command an das LCD. LCD_send_cmd fände ich passender.
In C werden i.A. Namen von Makros komplett gross geschrieben. Funktionen (größtenteils) klein.
Das Programm sollte, bis auf die Ansteuerung der IO-Pins, auch auf einem PC laufen.
Da kannst du besser Debuggen oder mehr Kontrollausgaben mitprintf
machen. Dann siehst du, ob die Nibble "verschwinden"
-
Danke erstmal für die Antworten.
Das mit den namen werde ich überarbeiten, danke für den Hinweis.
Das Programm habe ich schon gedebugged. Dort hat eigentlich alles gepasst. Ich glaube ich werde jetzt mal mein altes Oszi raus suchen und schauen, wo das Nibble verschwindet.
-
@DirkB Es handelt sich um ein 4x20 Display mit einem SSD1803 Controller.
-
delay_display=50000/FAKTOR_US; while (delay_display);
Sieht merkwürdig aus. Wer dekrementiert die Variable delay_display?
Ein Timer-Interrupt? Wenn ja, läuft dieser auch? Prüfe auch ob die Variable delay_display als volatile definiert wurde, sonst bekommst du Probleme mit Compiler-Optimierungen.
PS:
Gibt es da nicht alternative Funktionen ala __delay_ms()?
-
Wir haben ein eigenes Timer Programm geschrieben.
Hier die c Datei:#include "defines.h" uint16_t volatile timer_sys_intervall; ///< system timer in ms bereich uint16_t volatile delay_display; ///< delay timer display us uint16_t volatile delay_drucksensor; ///< delay timer drucksensor us uint16_t volatile delay_ledtreiber; ///< delay timer led-treiber us uint16_t volatile delay_lichtsensor; ///< timer delay lichtsensor in us uint16_t volatile delay_temp_hum_ms; ///< timer delay temperatur und Luftfeuchtigkeitssensor in ms uint16_t volatile delay_temp_hum; ///< timer delay temperatur und Luftfeuchtigkeitssensor in us uint16_t volatile delay_lichtsensor_ms; ///< timer delay lichtsensor in ms // ********************************************************* /// \fn void TMR1_CallBack(void) /// \par Funktion: /// - interruptroutine fuer Timer 1 /// - wird jede 1 ms aufgerufen /// - erhoehen des Timerintervalls // ********************************************************* void TMR1_CallBack(void) { //TESTPUNKT_1_TOGGEL; timer_sys_intervall++; if(delay_temp_hum_ms) //Timer herunterzaehlen delay temp und hum sensor { delay_temp_hum_ms--; } if(delay_lichtsensor_ms) //Timer herunterzaehlen delay lichtsensor { delay_lichtsensor_ms--; } } // ********************************************************* /// \fnvoid TMR2_CallBack(void) /// \par Funktion: /// - interruptroutine fuer Timer 2 /// - wird jede 1 us aufgerufen /// - veringern der delays // ********************************************************* void TMR2_CallBack(void) { //TESTPUNKT_2_TOGGEL; if(delay_display) //Wenn delay_display gesetzt dann herunterzaehlen { delay_display--; } if(delay_ledtreiber) // Delay fuer den Led-treiber { delay_ledtreiber--; } if(delay_lichtsensor) // Delay fuer den Lichtsensor { delay_lichtsensor--; } if(delay_drucksensor) // Delay fuer den Drucksensor { delay_drucksensor--; } if(delay_temp_hum) //Delay fuer den Temperatur und Luftfeuchtigkeitssensor { delay_temp_hum--; } } // ********************************************************* /// \fn void timer(void) /// \par Funktion: /// - resetet timer_sys_intervall // ********************************************************* void timer() { timer_sys_intervall =0; } // ********************************************************* /// \fn void timer_init( void ) /// \par Funktion : /// - Init der Variablen // ********************************************************* void timer_init() { timer_sys_intervall = 0; delay_display = 0; delay_ledtreiber = 0; delay_lichtsensor = 0; delay_drucksensor = 0; delay_temp_hum_ms = 0; delay_temp_hum = 0; }
und hier die h Datein:
#ifndef HILF_H #define HILF_H #define FAKTOR_US 10 void TMR1_CallBack(void); void TMR2_CallBack(void); void timer_init(); void timer(); extern uint16_t volatile timer_sys_intervall; // timer system intervall extern uint16_t volatile delay_display; // timer delay display in us extern uint16_t volatile delay_drucksensor; ///< delay timer drucksensor us extern uint16_t volatile delay_ledtreiber; // timer delay led-treiber in us extern uint16_t volatile delay_lichtsensor; // timer delay lichtsensor in us extern uint16_t volatile delay_lichtsensor_ms; // timer delay lichtsensor in ms extern uint16_t volatile delay_temp_hum_ms; // timer delay temperatur und Luftfeuchtigkeitssensor in ms extern uint16_t volatile delay_temp_hum; // timer delay temperatur und Luftfeuchtigkeitssensor in us /* Beispiel programm fuer nutzen des delays fuer den display * * Delay setzen mit mindest wartezeit + 1, in us * bsp. bei mindestens 59us delay muss mit 60us gesetzt werden, da dadurch die tatsaechliche zeit zwischen 59 und 60 us variiert * * delay_display = 50; //Delay setzen mit mindest wartezeit + 1, in us * while(delay_display); //warten bis Zeit abgelaufen * * */ #endif
Ja, es gibt alternative Funktionen, wir müssen jedoch eine eigene schreiben.
Der Timer läuft auch so weit, sonst würde die initialisierung nicht funktionieren.
MfG
-
@IchBins
Ok, habe dein Problem erst jetzt verstanden.Deine Ausgabe der Zeilen scheint etwas durcheinandergewürfelt zu sein. Erst schreibst du in Linie 3, dann in Linie 1,... Auch die Wartezeiten (LCD_CURSOR_SET_MS) sind nicht einheitlich. Ich würde folgendes erwarten:
setcursor_lcd(LCD_ADRESSE_LINIE1,0); // Zeile 1 // Warte bis Cursor gesetzt wurde delay_display = LCD_CURSOR_SET_MS / 10; // LCD_CURSOR_SET_MS = Wartezeit bis Cursor gesetzt wurde? while(delay_display); // Gebe Text aus text_LCD("Temperatur:"); // Warte bis Textausgabe fertig ist delay_display =10000/FAKTOR_US; while(delay_display); setcursor_lcd(LCD_ADRESSE_LINIE2,0); // Zeile 2 // Warte bis Cursor gesetzt wurde delay_display = LCD_CURSOR_SET_MS / 10; // LCD_CURSOR_SET_MS = Wartezeit bis Cursor gesetzt wurde? while(delay_display); // Gebe Text aus text_LCD("Luftdruck:"); // Warte bis Textausgabe fertig ist delay_display =10000/FAKTOR_US; while(delay_display); setcursor_lcd(LCD_ADRESSE_LINIE3,0); // Zeile 3 // Warte bis Cursor gesetzt wurde delay_display = LCD_CURSOR_SET_MS / 10; // LCD_CURSOR_SET_MS = Wartezeit bis Cursor gesetzt wurde? while(delay_display); // Gebe Text aus text_LCD("Feuchtigkeit:"); // Warte bis Textausgabe fertig ist delay_display =10000/FAKTOR_US; while(delay_display); setcursor_lcd(LCD_ADRESSE_LINIE4,0); // Zeile 4 // Warte bis Cursor gesetzt wurde delay_display = LCD_CURSOR_SET_MS / 10; // LCD_CURSOR_SET_MS = Wartezeit bis Cursor gesetzt wurde? while(delay_display); // Gebe Text aus text_LCD("Helligkeit:"); // Warte bis Textausgabe fertig ist delay_display =10000/FAKTOR_US; while(delay_display);
-
@Quiche-Lorraine Ja, das ist so richtig. Die durchgetauschten zeilen kommen noch von meiner Fehlersuche. Die sollten eigentlich so aussehen, wie in deinem Code. Trotzdem werden die Texte immernoch in der falschen Spalte ausgegeben. Meine Vermutung ist, dass es an meiner Funktion "BYTE_ZERLEGEN_TEXT"(Zeile 104ff in der c Datei)oder "text_LCD" (Zeile 138) liegt. Vielleicht fehlt irgendwo ein delay oder ein Enable Pulse. Ich finde aber nicht wo.
-
@IchBins Warum machst du denn diese komische Berechnung bei jedem delay_display?
Kannst du die Zeit nicht gleich in µs angeben?Mit wieviel MHz läuft denn dein PIC?
Ich habe etwas von maximal 40 MHz gefunden.
Da bleibt nicht viel Luft bei einem Interrupt von 1 µsEs kann auch sein, dass noch irgendwo etwas anderes gesetzt werden muss.
Denn "Temperatur:" ist ja gerade 11 Zeichen lang.Du solltest dir auch ein paar
#define
für die Magic Numbers von LCD_COMMAND_OUT machen.
Weißt du aus dem Stehgreif was 0x24 oder 0x20 ist?
-
@IchBins
Kann es sein das du LCD_OUT() immer mit 4 Bits aufrufst? (siehe BYTE_ZERLEGEN() und BYTE_ZERLEGEN_TEXT())Warum steht da innerhalb von LCD_OUT() folgendes?
int LCD_OUT(uint8_t data) { switch (data)//je nach Hex Wert werden verschiedene Datenleitungen auf die entsprechenden Pegel gelegt { // ... case 0x20: // Kann dieser Wert überhaupt erreicht werden, da in data immer nur 4 Bit angegeben sind? { LCD_D0_LOW; LCD_D1_HIGH; LCD_D2_LOW; LCD_D3_LOW; break; }
-
@DirkB sagte in LCD Programmierung Nibble verschwinden:
@IchBins Warum machst du denn diese komische Berechnung bei jedem delay_display?
Kannst du die Zeit nicht gleich in µs angeben? -> Das ist ein Gruppenprojetkt und die delay Funktion hat jemand anderes geschrieben. Mir wurde nur die Anweisung gegeben, es so zu machen.Mit wieviel MHz läuft denn dein PIC? mit 25Mhz
Ich habe etwas von maximal 40 MHz gefunden.
Da bleibt nicht viel Luft bei einem Interrupt von 1 µsEs kann auch sein, dass noch irgendwo etwas anderes gesetzt werden muss.
Denn "Temperatur:" ist ja gerade 11 Zeichen lang. -> wie meinst du das? dass die letzten 9 Zeichen mit Leerstellen gefüllt sind?Du solltest dir auch ein paar
#define
für die Magic Numbers von LCD_COMMAND_OUT machen.
Weißt du aus dem Stehgreif was 0x24 oder 0x20 ist? -> da bin ich gerade dabei, die kann ich dann anfügen, wenn ich sie fertig habe
-
@Quiche-Lorraine Ich rufe LCD_OUT() immer mit einem Byte auf, jedoch sind davon entweder die ersten 4 Bit oder die letzen 4 Bit =0
0b00001111 wäre in hex ja 0x0F und
0b11110000 wäre in hex ja 0xF0. Die können beide erreicht werden
-
@IchBins sagte in LCD Programmierung Nibble verschwinden:
wie meinst du das? dass die letzten 9 Zeichen mit Leerstellen gefüllt sind?
Nein.
Nach Ausgabe von "Temperatur:" steht der Cursor in der 11 Spalte.
Der Wert bleibt dann (irgendwie) erhalten.Gib doch einfach nur mal "Temp:" aus und schau, wo dann die Texte in den folgenden Zeilen stehen.
Oder fang mal mit Zeile 4 an.Das "Temperatur:" in der 1. Spalte steht, kann ja auch mit dem LCD_Init zu tun haben.
-
@DirkB Hätte ich vielleicht schreiben sollen. Ich habe die Temperatur schon in Zeile 1 Spalte 0, zeile 1 Spalte 8, Zeile 2 Spalte 0 und Zeile 2 Spalte 8 ausgegeben. Egal in welcher Konstellation ich die Texte ausgebe, auch wenn ich zuerst etwas in Zeile 1 und dann in Zeile 2 ausgebe. Der erste ausgegebene Text ist an der richtigen Position. Der 2. 3. und 4. ausgegebene Text ist immer in der richtigen zeile aber in Spalte 11 der jeweiligen Spalte.
-
Laut Datenblatt mußt du immer jeweils die drei Bits
RE
,RS
undRW
passend setzen (sowie dann die entsprechenden Data-Bits).
Für "Cursor / Display Shift" alsoLCD_RE_LOW; LCD_RS_LOW; LCD_RW_LOW;
Außerdem scheint das nur eine relative Positionierung zu sein (keine absolute). Dafür müßtest du dann selber die aktuelle Position dir merken und die Differenz (x / y) ausrechnen.
-
@Th69 so wie ich das verstanden habe werden Befehle immer dann vom Display eingelesen, wenn der Enable Pin von 1 auf 0 wechselt, also bei fallender Flanke. Wenn ich aber den Enable Pin auf 0 setze, bevor ich den Befehl an die Datenleitungen anlege, werden die Daten in dem Fall dann bei steigender Flanke übertragen?
-
@DirkB
Hier ist nochmal meine überarbeitete init ohne "Magic Numbers"void init_lcd() { delay_display=LCD_BOOTUP/FAKTOR_US; //Warten, bis Display bereit ist while (delay_display); LCD_RS_LOW; //RS Pin auf "low" -> Befehl delay_display=LCD_SET_PIN/FAKTOR_US; while (delay_display); LCD_RW_LOW; //RW Pin auf "low" -> write delay_display=LCD_SET_PIN/FAKTOR_US; while (delay_display); LCD_EN_HIGH; //Enable Pin auf "high" delay_display=LCD_SET_PIN/FAKTOR_US; while (delay_display); LCD_OUT(Function_Set_8Bit); //0x03 8Bit-Modus LCD_EN_PULSE(); delay_display=LCD_8BIT/FAKTOR_US; while (delay_display); LCD_OUT(Function_Set_8Bit); //0x03 8Bit-Modus LCD_EN_PULSE(); delay_display=LCD_8BIT/FAKTOR_US; while (delay_display); LCD_OUT(Function_Set_8Bit); //0x03 8Bit-Modus LCD_EN_PULSE(); delay_display=LCD_8BIT/FAKTOR_US; while (delay_display); LCD_OUT(Function_Set_4Bit); //0x02 4Bit-Modus LCD_EN_PULSE(); delay_display=LCD_4BIT/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(Function_Set_Reg1); //0x24 Function Set extension register = 1 delay_display=50/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(Extend_Function_Set); //0x09 extend Function set 5dot font width, normal cursor,4-line display delay_display=50/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(Function_Set_Reg0); //0x20 Function Set extension register = 0 delay_display=50/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(CURSOR_AT_HOME); //0x02 Cursor At Home delay_display=2000/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(LCD_ALL_ON); //0x0F Display On/Off Control display on, cursor on, cursor blink on delay_display=50/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(LCD_CLEAR); //0x01 Display löschen und Cursor auf Home delay_display=2000/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(LCD_ENTRY_MODE_SET); //0x06 Entry Mode Set Cursor Moving Direction increment, shift enable bit=disable delay_display=50/FAKTOR_US; while (delay_display); LCD_COMMAND_OUT(Function_Set_End); //Function Set: 4bit, 2-line, RE=0,dot scroll,reverse bit normal delay_display=50/FAKTOR_US; while (delay_display); }