- LiTime Speicher und Akkus         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 16

Thema: LCD: Hallo Welt mit C

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    23.08.2007
    Ort
    Bielefeld
    Beiträge
    39

    LCD: Hallo Welt mit C

    Anzeige

    Praxistest und DIY Projekte
    Hallo,

    mit meinem Pic (16F84A) möchte ich eine LCD-Anzeige (2*16) ansteuern und "Hallo" ausgeben. Das möchte ich allerdings nicht in Assembler machen, sondern in C (MikroC).

    Dazu habe ich folgenden Code geschrieben. Es wäre nett, wenn jemand mal darüber gucken könnte:
    main.c:
    Code:
    #include <C:\Dokumente und Einstellungen\benutzer\Eigene Dateien\PIC\lcd.h>
    
     void controlachtbit(char byte);
     void inittheLCD ();
     void OutLcdControl(char byte);
     void display_loeschen_cursor();
     void display_on();
     void display_off();
     void cursor_anfang();
     void entry_mode();
     void zwei_zeilig();
     void ausfuehren();
     void busy();
     void schreiben(char byte);
     
     
    void main() {
         TRISB = 0;
         PORTB = 0;
         TRISA = 0;
         PORTA = 0;
         PORTA.F0 = 1;
         inittheLCD();
         PORTA.F0 = 0;
         schreiben('H');
         schreiben('a');
         schreiben('l');
         schreiben('l');
         schreiben('o');
    }
    und die Headerdatei lcd.h:
    Code:
    #define ENABLE PORTB.F0
    #define RS PORTB.F2
    #define RW PORTB.F3
    #define D4 PORTB.F4
    #define D5 PORTB.F5
    #define D6 PORTB.F6
    #define D7 PORTB.F7
    #define T4 TRISB.F4
    #define T5 TRISB.F5
    #define T6 TRISB.F6
    #define T7 TRISB.F7
    
     void controlachtbit(char byte);
     void inittheLCD();
     void OutLcdControl(char byte);
     void display_loeschen_cursor();
     void display_on();
     void display_off();
     void cursor_anfang();
     void entry_mode();
     void zwei_zeilig();
     void ausfuehren();
     void busy();
     void schreiben(char byte);
     
    
    void inittheLCD()
    {
    /*Initialisierung des LCD-Displays*/
        Delay_ms(250);
        //LCD auf 8bit initialisieren (3mal)
        controlachtbit(48);
        Delay_ms(50);
        controlachtbit(48);
        controlachtbit(48);
        controlachtbit(48);
        //LCD auf 4bit initialisieren
        controlachtbit(32);
        //Display loeschen - curser home
        display_loeschen_cursor();
        //2zeilig
        zwei_zeilig();
        //Display: aus
        display_off();
        //Eingabemodus
        entry_mode();
        //Curser Anfang:
        cursor_anfang();
        //Display: an
        display_on();
    }
    void controlachtbit(char byte)
    {
           /*Ein Steuerbyte 8bittig uebertragen*/
           PORTB = 0;
           D4 = byte.F4;
           D5 = byte.F5;
           D6 = byte.F6;
           D7 = byte.F7;
           ausfuehren();
           //Test:
           PORTA.F3 = D7;
           return;
    }
    
    void OutLcdControl(char byte){
    /*Ein Steuerbyte 4-bittig uebertragen*/
           busy();
           PORTB = 0;
           D4 = byte.F4;
           D5 = byte.F5;
           D6 = byte.F6;
           D7 = byte.F7;
           ausfuehren();
           busy();
           PORTB = 0;
           D4 = byte.F0;
           D5 = byte.F1;
           D6 = byte.F2;
           D7 = byte.F3;
           ausfuehren();
           busy();
           
           //Test:
           PORTA.F2 = 1;
           return;
    }
    void display_loeschen_cursor(){
    //Display wird geloescht und Cursor an den Anfang gesetzt
              OutLcdControl(1);
    }
    void display_on(){
    //Display wird eingeschaltet
              OutLcdControl(15);
    }
    void display_off(){
    //Display wird ausgeschaltet
              OutLcdControl(8);
    }
    void cursor_anfang(){
    //Curser wird an den Anfang gesetzt
             OutLcdControl(3);
    }
    void entry_mode(){
    //LCD wird auf eingabemodus geschaltet
          OutLcdControl(6);
    }
    void zwei_zeilig(){
    //LCD wird auf 2 zeilig eingestellt
          OutLcdControl(40);
    }
    void ausfuehren(){
           //ein Befehl wird ausgefuehrt (LCD-ENABLE an und aus)
          ENABLE = 1;
          Delay_ms(10);
          ENABLE = 0;
          Delay_ms(10);
    }
    void busy(){
           /*Diese Fkt. laueft solange bis das Busyflag 0 ist*/
           PORTB = 0;
           //Datenbus auf Eingabe schalten
           T4 = 1;
           T5 = 1;
           T6 = 1;
           T7 = 1;
           RW = 1;
           while(1){
              ENABLE = 1;
              Delay_ms(10);
              if(D7 == 0)//Wenn das Busy-Flag 0 ist - dann wird diese Schleife abgebrochen
                    break;
              ENABLE = 0;
              Delay_ms(10);
              ENABLE = 1;
              Delay_ms(10);
              ENABLE = 0;
              Delay_ms(10);
          }
          ENABLE = 0;
          Delay_ms(10);
          ENABLE = 1;
          Delay_ms(10);
          ENABLE = 0;
          //Datenbus auf Ausgabe schalten
          T4 = 0;
          T5 = 0;
          T6 = 0;
          T7 = 0;
          PORTB = 0;
    }
    void schreiben(char byte){
           PORTB = 0;
           D4 = byte.F4;
           D5 = byte.F5;
           D6 = byte.F6;
           D7 = byte.F7;
           RS = 1;
           ausfuehren();
           busy();
           PORTB = 0;
           D4 = byte.F0;
           D5 = byte.F1;
           D6 = byte.F2;
           D7 = byte.F3;
           RS = 1;
           ausfuehren();
           busy();
    
    }
    Mit freundlichen Grüßen,
    Sebastian

  2. #2
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    20.08.2004
    Ort
    Unterschleissheim
    Beiträge
    321
    Hallo robo-sebi

    ich kann zu seinem Code nur allgemeines sagen:

    - zunächst rein formll: Code gehört nicht in ein h-File. Im h-File stehen nur Definition.
    - zum PIC: Der Pic16F84 ist der Urgross-Vater der Flash-PIC's und gehört ins Museum. Zum Programmieren in C sind eigentlich alle PIC16 nicht so besonders geeignet. Falls du noch nichts gekauft hast, solltest du dir einen PIC18 aussuchen. Die sind erstens "state-of-the-art" was Microcontroller-Technik anbelangt und zweitens aufgrund ihrer besseren Resourcen für die Programmierung unter C beser geeignet. Microchip bietet dafür auch den C18-Compiler in der Studentenversion kostenlos an.


    Gerhard

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    23.08.2007
    Ort
    Bielefeld
    Beiträge
    39

    LCD / PIC

    Hallo,

    also danke erstmal für die Antwort. Ich weiß, dass der PIC16F84A schon uralt ist. Bis auf den 16F628 habe ich emoment noch keinen anderen PIC. Ich bin dabei, einen Roboter zu programmieren. Suche noch nach einem guten PIC. (Roboter muss sich in einem Labyrinth {3,2*3,2m Fläche} zurecht finden. Außerdem will ich wie im RN-Wissensbereich erklärt - eine Schrittmotersteuerung bauen und diese über den PIC ansteueren. 3 Sensoren sollen eingebaut werden: 2* Distanz und 1* Helligkeitssensor). Vielleicht kennt jemand einen guten PIC?

    Zu meiner LCD-Ansteuerung:

    Was ich oben vergessen habe zu sagen: Meine LCD-Ansteuerung gibt entweder nichts auf dem Bildschirm oder irgendwelche seltsamen Zeichen aus. Der Aufbau ist übrigens gleich zu folgendem Lernbeispiel:
    http://www.sprut.de/electronic/pic/programm/lcd.htm

    Noch eins: Also die Testversion von MikroC gibt mir echt Rätsel auf. Wenn ich meine Funktionen für meinen PIC in ein anderes C-file im gleichen Ordner packe und dieses zum Projekt hinzufüge, bekomme ich folgende Fehlermeldung: "Access violation at address 006D38CC in module 'mikroC.exe'. Read of address 00000009" beim übersetzen ins Hex-file.
    Ich wollte das ganze aber irgendwie modular aufbauen.

    Darüber hinaus: Für den C18-Combiler auf www.microchip.com muss man sich anmeldem - als ich das probiert habe, kamen nur irgendwelche Fehlermeldungen. Mein Account wurde nicht gespeichert.

    Mit freundlichen Grüßen,
    Sebastian

  4. #4
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    20.08.2004
    Ort
    Unterschleissheim
    Beiträge
    321
    Hallo Sebastian

    also kurz zu deinem Code, was mir auf die Schnelle aufgefallen ist:

    >
    TRISB = 0;
    TRISA = 0;
    <
    Das funktioniert so in Assembler nicht, da die TRIS-Register auf einer anderen Page des Speichers steht. In Assembler müßtest du vorher auf diese Page schalten. Wie MicroC das macht, weiss ich nicht, du solltest den Code auf jeden fall in MPLAB simulieren (also in dem Fall step für step durchtasten und schauen, on die Register des PIC die Werte auch annehemen). Mit MicroC kenn ich mich nicht aus. Ich selbst arbeite nur noch mit PIC18 und PIC30 und den dazugehörigen C-Compilern von Microchip. Versuch das nochmal die Versionen downzuloaden, es lohnt sich auf jeden Fall. Mit dem MicroC kenn ich mich nicht aus, da kann ich dir auch nicht helfen. Aber wie schon gesagt, schmeiss den 16F84 weg. Du bekommst von Microchip auch kostenlose Muster. Für deinen Roboter brauchst du eh einen vernünftigen PIC. Ich hab mir auch einen selber gebaut (einen Roboter), mit einem dsPIC30F4013. Den kannst du dir auch kostenlos als Muster schicken lassen.

    gerhard

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    20.11.2006
    Alter
    31
    Beiträge
    88
    Hallo,

    ich hab mich erst gestern mit genau dem gleichen thema auseinander gesetzt, und bei mir hats nach ein paar weiteren versuchen, bei dem ich ein paar sachen geändert hatte auch funktioniert. Hast du den E port von deinem Display an GND angeschlossen? bei mir hat es erst nix angezeigt, weil e nicht an GND lag. Du kannst es auch an einen Poti anschliessen und dann regeln. (E ist der Kontrast) Einfachmal ausprobieren...

    gruß toni

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    23.08.2007
    Ort
    Bielefeld
    Beiträge
    39
    Hallo,

    danke erstmal für die Nachrichten. Beim 2.Anlauf war die Registrierung bei Microchip erfolgreich. Ich werde das Programm erstmal ausprobieren.

    Apropos: Mein Skript ist in C nicht in Assembler!!! Es läuft auch - das habe ich mit einem Logikprüfer getestet - doch auf dem Display wird nichts angezeigt. Meine Frage ist, ob ich dort irgend etwas in der Initialisierung falsch mache?

    Außerdem das Assembler-Skript von sprut.de läuft bestens. Also mit den Helligkeitseinstellungen passt das - meine Erfahrung: 10 kO zwischen E und GND.

    Microchip versendet kostenlose Muster - wie kommt den das? Ich dachte sie wollten die verkaufen. Wo geht den das?

    Mit freundlichen Grüßen,
    Sebastian

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    23.08.2007
    Ort
    Bielefeld
    Beiträge
    39
    Hallo,

    mal eine dumme Frage: Wie bekomme ich den C18 gestartet?
    Also ich habe erst folgendes Programm installiert:
    http://www.microchip.com/stellent/id...&part=SW007002
    und dann habe ich Folgendes installiert: http://www.microchip.com/stellent/id...cName=en010014

    Es ist allerdings nicht so, wie es unter sprut.de erklärt wird. Da kann man unter dem Projekt Wizard nicht C18 auswählen.

    Mit freundlichen Grüßen,
    Sebastian

  8. #8
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    20.08.2004
    Ort
    Unterschleissheim
    Beiträge
    321
    Hallo

    ich arbeite derzeit mot MPLAB 7.61. Und da wird unter Project\Select Language Toolsuite.. die Sprache bzw der Compiler eingestellt.


    zu den Mustern: "ist so". Das gibts bei mehr Firmen. Bestellen kannst Du die Online auf Microchip.com. Die wollen halt Angaben haben, wie dein Project heisst, und wann du wieviele zu kaufen gedenkst. Also nicht überreizen sonst gints wahrscheinlich mal nix mehr.


    Gerhard

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    23.08.2007
    Ort
    Bielefeld
    Beiträge
    39
    Hallo,

    ich habe immer noch nicht den Fehler in meinem Skript gefunden. Witzigerweise taucht manchmal Hallo ganz schwach im Display auf. Manchmal aber auch nicht. Das C-Programm arbeitet offensichtlich nicht richtig. Ich habe schon in die main eine Endlosschleife eingebaut.
    Aber wenn ich das Assemblerskript von Sprut nehme funktioniert das ganze immer Einwand frei. Da sieht man das Wort Hallo gut. Also kann es nicht am Kontrast liegen.

    Hier noch mal mein Code [Ich weiss, dass man C-files nicht in eine header-file auslagert - aber anders versteht MikroC das nicht - oder ich müsste alles in eine Datei schreiben]:
    Code:
    #include <lcd.h>
    void inittheLCD ();
     void schreiben(char byte);
    
     
    void main() {
         TRISB = 0;
         PORTB = 0;
         TRISA = 0;
         PORTA = 0;
         PORTA.F0 = 1;
         inittheLCD();
         PORTA.F0 = 0;
         schreiben('H');
         schreiben('a');
         schreiben('l');
         schreiben('l');
         schreiben('o');
         Delay_ms(10);
         while(1);
    }
    und die lcd.h:
    Code:
    #define ENABLE PORTB.F0
    #define RS PORTB.F2
    #define RW PORTB.F3
    #define D4 PORTB.F4
    #define D5 PORTB.F5
    #define D6 PORTB.F6
    #define D7 PORTB.F7
    #define T4 TRISB.F4
    #define T5 TRISB.F5
    #define T6 TRISB.F6
    #define T7 TRISB.F7
    
    void controlachtbit(char byte);
     void inittheLCD();
     void OutLcdControl(char byte);
     void display_loeschen_cursor();
     void display_on();
     void display_off();
     void cursor_anfang();
     void entry_mode();
     void zwei_zeilig();
     void ausfuehren();
     void busy();
     void schreiben(char byte);
    
    
    void inittheLCD()
    {
    /*Initialisierung des LCD-Displays*/
        Delay_ms(250);
        //LCD auf 8bit initialisieren (3mal)
        controlachtbit(0b00110000);
        Delay_ms(50);
        controlachtbit(0b00110000);
        Delay_ms(50);
        controlachtbit(0b00110000);
        Delay_ms(50);
        controlachtbit(0b00110000);
        Delay_ms(50);
        controlachtbit(0b00110000);
        Delay_ms(50);
        //LCD auf 4bit initialisieren
        controlachtbit(0b00100000);
        //LCD auf 4bit initialisieren
        controlachtbit(0b00100000);
        //2zeilig
        zwei_zeilig();
        //Display: aus
        display_off();
        //Display loeschen - curser home
        display_loeschen_cursor();
        //Eingabemodus
        entry_mode();
        //Curser Anfang:
        cursor_anfang();
        //Display: an
        display_on();
    }
    void controlachtbit(char byte)
    {
           /*Ein Steuerbyte 8bittig uebertragen*/
           PORTB = 0;
           D4 = byte.F4;
           D5 = byte.F5;
           D6 = byte.F6;
           D7 = byte.F7;
           ausfuehren();
           //Test:
           PORTA.F3 = D7;
           return;
    }
    
    void OutLcdControl(char byte){
    /*Ein Steuerbyte 4-bittig uebertragen*/
           busy();
           PORTB = 0;
           D4 = byte.F4;
           D5 = byte.F5;
           D6 = byte.F6;
           D7 = byte.F7;
           ausfuehren();
           busy();
           PORTB = 0;
           D4 = byte.F0;
           D5 = byte.F1;
           D6 = byte.F2;
           D7 = byte.F3;
           ausfuehren();
           busy();
    
           //Test:
           PORTA.F2 = 1;
           return;
    }
    void display_loeschen_cursor(){
    //Display wird geloescht und Cursor an den Anfang gesetzt
              OutLcdControl(1);
    }
    void display_on(){
    //Display wird eingeschaltet
              OutLcdControl(15);
    }
    void display_off(){
    //Display wird ausgeschaltet
              OutLcdControl(8);
    }
    
    void cursor_anfang(){
    //Curser wird an den Anfang gesetzt
             OutLcdControl(3);
    }
    void entry_mode(){
    //LCD wird auf eingabemodus geschaltet
          OutLcdControl(0b00000110);
    }
    void zwei_zeilig(){
    //LCD wird auf 2 zeilig eingestellt
          OutLcdControl(0b00101000);
    }
    void ausfuehren(){
           //ein Befehl wird ausgefuehrt (LCD-ENABLE an und aus)
          ENABLE = 1;
          Delay_ms(15);
          ENABLE = 0;
          Delay_ms(15);
    }
    void busy(){
           /*Diese Fkt. laueft solange bis das Busyflag 0 ist*/
           PORTB = 0;
           //Datenbus auf Eingabe schalten
           T4 = 1;
           T5 = 1;
           T6 = 1;
           T7 = 1;
           RW = 1;
           while(1){
              ENABLE = 1;
              Delay_ms(10);
              if(D7 == 0)//Wenn das Busy-Flag 0 ist - dann wird diese Schleife abgebrochen
                    break;
              ENABLE = 0;
              Delay_ms(20);
              ENABLE = 1;
              Delay_ms(20);
              ENABLE = 0;
              Delay_ms(20);
          }
          ENABLE = 0;
          Delay_ms(20);
          ENABLE = 1;
          Delay_ms(20);
          ENABLE = 0;
          //Datenbus auf Ausgabe schalten
          T4 = 0;
          T5 = 0;
          T6 = 0;
          T7 = 0;
          PORTB = 0;
    }
    void schreiben(char byte){
           busy();
           PORTB = 0;
           D4 = byte.F4;
           D5 = byte.F5;
           D6 = byte.F6;
           D7 = byte.F7;
           RS = 1;
           ausfuehren();
           busy();
           PORTB = 0;
           D4 = byte.F0;
           D5 = byte.F1;
           D6 = byte.F2;
           D7 = byte.F3;
           RS = 1;
           ausfuehren();
           busy();
    
    }
    Ich möchte - damit endlich mal fertig werden und nicht 4 Tage lang hinter einem blöden Fehler hersuchen.

    Mit freundlichen Grüßen,
    Sebastian

  10. #10
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    20.08.2004
    Ort
    Unterschleissheim
    Beiträge
    321
    Hallo

    manchmal gibts Probleme beim wiederholten Schreiben auf den gleichen Port, wenn man ein IO über PORT anspricht. Ersetze alle PORTs durch LAT, also LATA für PORTA und LATB für PORTB. Vielleicht löst das dein Problem

    Gerhard

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiTime Speicher und Akkus