LCD mit einem PIC16F73 ansteuern
Montag, 21. Mai 2012
 
 

PIC Mikrocontroller Forum  |  PIC Mikrocontroller  |  CCS Compiler  |  LCD (CCS)  |  LCD mit einem PIC16F73 ansteuern « vorheriges nächstes »
Seiten: [1] Nach unten Drucken
Autor Thema: LCD mit einem PIC16F73 ansteuern  (Gelesen 4337 mal)
 
OelC
Newbie
*
Offline Offline

Beiträge: 10


Profil anzeigen
« am: Dezember 07, 2006, 11:49:37 »

Hallo Allerseits,

ich versuche gerade ein LCD Display (2x16, HD44780) mit dem PIC16F73 anzusteuern. Hierbei verwende ich die Sourcen von dieser Page. Leider erscheint auf dem Display nichts außer schwarze Balken in der obersten Zeile.

Ich benutze wie im vorgegeben Beispiel Port B. Habe die RB0-RB7 Pins alle direkt an das LCD angeschlossen.

Ich vermutete schon das ich evtl. die Option NOLVP setzen muss, allerdings sagt der CCS Compiler: Unknown keyword in #FUSES "NOLVP"

Vielleicht kann mir jemand helfen?

Hier ist der Quellcode:

Code:

#include <16F73.h>
#use delay(clock=4096000)
#fuses HS, NOPROTECT, NOLVP   //, NOWDT
//#fuses XT,NOWDT, HS,WDT, PUT  //, hs, wdt, put

#define NOP()  { #asm  nop #endasm  }
#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines

void lcd_send_nibble( byte n );
void lcd_send_byte( byte address, byte n );
void lcd_init();
void lcd_gotoxy( byte x, byte y);
void lcd_putc( char c);

struct port_b_layout
{       
                     short unused;     
                     short rs;         
                     short unused2;   
                     short enable;     
                     int lcddata:4;   
} portb;

#byte portb=6

byte CONST LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};

unsigned char wert;

void main() {
   
   int once = 1;
 
   set_tris_a(0);
   set_tris_b(0);
 
   setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
   
   delay_ms(500);
   lcd_init();                // Initialisierung der LCD-Anzeige
   delay_ms(500); 
   
   lcd_gotoxy(1,1);

   lcd_putc("\fHallo Welt\2"); // Ausgabe des Textes "Hallo Welt" \c löscht die Anzeige \2 springt                         danach zur 2. Zeile
   lcd_putc("Ein Test");
   delay_ms(500);
   wert=0;
 
   while (1)
   {
     printf(lcd_putc,"\fWert: %03u",wert);
     wert++;
     delay_ms(200);
     
     while(once == 1)
     {
       output_high(PIN_A0);  // Zur Kontrolle!
       once = 0;   
     }
 
   }
}

void lcd_send_nibble( byte n ) {
      portb.lcddata = n;
      nop();
      portb.enable = 1;
      delay_us(2);
      portb.enable = 0;
}

void lcd_send_byte( byte address, byte n ) {
      portb.rs = 0;
      delay_ms(2);
      portb.rs = address;
      nop();
      portb.enable = 0;
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0xf);
}

void lcd_init() {
    byte i;

    portb.rs = 0;               // siehe 4-Bit Initialisierung (LCD-Datenblatt)
    portb.enable=0;
    delay_ms(15);  // 15 ms Pause
    for(i=1;i<=3;++i) {
       lcd_send_nibble(3);      // 3-mal 0011 mit mind. 5ms Pause
       delay_ms(5);
    }
    lcd_send_nibble(2);         // 0010 = 4-Bit Interface
    for(i=0;i<=3;++i)
       lcd_send_byte(0,LCD_INIT_STRING[i]);
}

void lcd_gotoxy( byte x, byte y) {
   byte address;

   if (y==1) address=0;
   if (y==2) address=0x40;
   if (y==3) address=0x10;
   if (y==4) address=0x50;
   address+=x-1;
   lcd_send_byte(0,0x80|address);
}

void lcd_putc( char c) {
 switch (c) {
     case '\f'   : lcd_send_byte(0,1);
                   delay_ms(2);
                                           break;
     case '\1'   : lcd_gotoxy(1,1);        break;
     case '\2'   : lcd_gotoxy(1,2);        break;
     case '\3'   : lcd_gotoxy(1,3);        break;
     case '\4'   : lcd_gotoxy(1,4);        break;
     default     : lcd_send_byte(1,c);     break;
 }
}
Gespeichert
Ramazuki
Newbie
*
Offline Offline

Beiträge: 37


Profil anzeigen
« Antworten #1 am: Dezember 07, 2006, 18:31:44 »

Salut !

Also dieser Teil läuft ohne Fehler durch den Compiler ?

Code:
#include <16F73.h>

Vieleicht mit #include <16F673.h>
versuchen, wenn nicht..

Dann, vieleich XT-Mode verwenden..

In den Anhängen ein Schaltungsbeispiel..
(Wie hast du den Port direkt auf das LCD verbunden ? )

Und Quellcode, funzt wenigstens bei mir so..


* 1aaaa1.jpg (167.68 KB, 1570x1180 - angeschaut 515 Mal.)
* lcd_keypad_sample.zip (47.07 KB - runtergeladen 190 Mal.)
Gespeichert
OelC
Newbie
*
Offline Offline

Beiträge: 10


Profil anzeigen
« Antworten #2 am: Dezember 07, 2006, 20:35:53 »

Hi,

danke für deine Mühe. Ja, der Quellcode lässt sich auch bei mir Fehlerfrei kompilieren. Allerdings erscheint nichts auf dem LCD Display. Bin mir eigentlich sicher, dass ich nichts falsch miteinander verbunden habe.

Die Ports des Pic habe ich natürlich nicht direkt an das LCD verbunden sondern mit dem HD44780-Controller! 

Ich dachte, dass ich evtl. irgendwelche Fuses-Bits zusätzlich setzen muss. Der XT-Mode sollte eigentlich nicht in Frage kommen, da mein Quarz über 4MHz taktet (4096000Hz)!
Gespeichert
Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #3 am: Dezember 07, 2006, 22:12:30 »

Zitat
Ich vermutete schon das ich evtl. die Option NOLVP setzen muss, allerdings sagt der CCS Compiler: Unknown keyword in #FUSES "NOLVP"

Das ist so korrekt, denn der 16F73 vefügt nicht über LVP (obwohl im Datenblatt der "PGM" Pin auftaucht). Siehe Data Sheet Errata (Module: Pinout Correction).

In Deinem Code hast Du den Watchdog aktiviert (NOWDT ist auskommentiert), ohne dafür zu sorgen, daß er auch zurückgesetzt wird.


Viele Grüße

Bernd
Gespeichert

Ramazuki
Newbie
*
Offline Offline

Beiträge: 37


Profil anzeigen
« Antworten #4 am: Dezember 07, 2006, 22:17:34 »

Hm...

Vieleicht RW nicht auf GND ?

Also, die Schwarze Zeile ist soweit glaubs mal OK..

Ich muss zugeben, dass ich auch so meine Mühe hatte..
Aber mit beigefügtem Code funzt's.. Mit 16F870 / 16F877..
Und da sind PortB auf der selben Adresse ..

Die einzigen Fuses die ich verwende sind :

#fuses XT,NOWDT,NOLVP ..

Ist schwierig zu sagen ohne das Device-File..

Ausser vieleicht :

Code:


/******* Wird in der Programmvariante 2 mit benötigt, weil der BUSY-Flag nicht abgefragt wird ****/
/*
byte lcd_read_byte()
{
      byte low,high;

      set_tris_b(LCD_READ);
      portb.rw = 1;
      delay_cycles(1);
      portb.enable = 1;
      delay_cycles(1);
      high = portb.lcddata;
      portb.enable = 0;
      delay_cycles(1);
      portb.enable = 1;
      delay_us(2);
      low = portb.lcddata;
      portb.enable = 0;
      set_tris_b(LCD_WRITE);
      return( (high<<4) | low);
}
*/


Dies ist in meinem LCD-Driver enthalten..

Und du verwendest anscheinend RW auch nicht..

Code:
struct port_b_layout
{       
                     short unused;     
                     short rs;         
                     short unused2;   
                     short enable;     
                     int lcddata:4;   
} portb;

Siehe Beispiel hier :

http://www.fernando-heitor.de/projekte/mikrocontroller/lcd-steuerung-109_6.html


Gespeichert
Master Snowman
Sr. Member
****
Offline Offline

Beiträge: 289



Profil anzeigen WWW
« Antworten #5 am: Dezember 07, 2006, 23:59:07 »

sorry, ich hab nicht alles durchgelesen. kannste ja mal angehängte datei in dein projekt einbinden und die funktionen aufrufen. vielleicht gehts ja damit...

edit: irgendwie geht das mit der datei anhängen nicht... also so

Code: (c)


/******************************************************************************/
/*                                                                            */
/*  mc.emi, 9.9.2004                                                          */
/*                                                                            */
/*                                                                            */
/*  geschrieben für PCW PICC C-Compiler                                       */
/*                                                                            */
/*  im Haupt-C-File wie folgt den LCD-Port definieren:                        */
/*                                                                            */
/*  #define Output_LCD     Output_C     // hier LCD-Port an Port C            */
/*  #define set_tris_LCD   set_tris_C                                         */
/*                                                                            */
/*                                                                            */
/*  LCD-Anschluss:                                                            */
/*  PortPin 0..3 = DatenLeitung 4..7                                          */
/*  PortPin 4    = RS                                                         */
/*  PortPin 5    = E                                                          */
/*                                                                            */
/******************************************************************************/


void WriteStringToLCD (char data) {
  char x;
  x = data>>4;
  Output_LCD(x);
  Output_LCD(x | 0x30);
  x = data & 0x0F;
  delay_us(200);
  Output_LCD(x);
  Output_LCD(x | 0x30);
  delay_us(200);
}




void WriteToRegisterOfLCD (char data) {
  char x;
  x = data>>4;
  Output_LCD(x);
  Output_LCD(x | 0x20);
  x = data & 0x0F;
  delay_ms(2);
  Output_LCD(x);
  Output_LCD(x | 0x20);
  delay_ms(2);
  Output_LCD(0);
}





void PositionLCD(char zeile, char position) {
// springt mit dem Schreib-Cursor an die angegebene Postition
// Zeilenanfang = 0, LCD-Anfang = (0,0)

  char x;

// 0x80 = LCD-Adresse
// Zeile 1 -> 0x80-0x01=0x7F
// Zeile 2 -> 0x40+0x80-0x01=0xBF
// Zeile 3 -> 0x14+0x80-0x01=0x93
// Zeile 4 -> 0x40+0x14+0x80-0x01=0xD3

  switch(zeile) {
    case 0: x=0x80+position; break;
    case 1: x=0xC0+position; break;
    case 2: x=0x93+position; break;
    case 3: x=0xD3+position; break;
    default : x=0x80; break;           //Ungültige Position. Neue => 0,0
  }
  WriteToRegisterOfLCD(x);
}






void InitLCD() {
// LCD initialisieren

  set_tris_LCD(0x3F); // LCD-PORT = Eingänge (damit eine Weile dem LCD nichts aufdiktiert wird)
  delay_ms(300);

  set_tris_LCD(0x00); // LCD-PORT = Ausgänge
  Output_LCD(0x00);

// Software-Reset - Definition laut Hersteller
  Output_LCD(0x03);  // Interface auf 8-Bit setzen
  Output_LCD(0x23);
  delay_ms(5);
  Output_LCD(0x03);  // Interface auf 8-Bit setzen
  Output_LCD(0x23);
  delay_ms(1);
  Output_LCD(0x03);  // Interface auf 8-Bit setzen
  Output_LCD(0x23);
  delay_ms(20);

// LCD initialisieren
  Output_LCD(0x02);  // Interface auf 4-Bit setzen
  Output_LCD(0x22);
  delay_ms(20);
  WriteToRegisterOfLCD(0x01);  // Display löschen
  WriteToRegisterOfLCD(0x28);  // 2-zeilig, 5x8-Punkt-Matrix
  WriteToRegisterOfLCD(0x02);  // Kursor nach rechts wandernd, kein Display-Shift
  WriteToRegisterOfLCD(0x0C);  // Display ein
  WriteToRegisterOfLCD(0x01);  // Display löschen
  PositionLCD(0,0);            // Cursor an den Anfang setzen
}

Gespeichert
OelC
Newbie
*
Offline Offline

Beiträge: 10


Profil anzeigen
« Antworten #6 am: Dezember 08, 2006, 16:50:09 »

...nein, - geht immer noch nicht. Leider!

Was genau passiert eigentlich in der folgenden Zeile?

Code:
#byte portb=6

----

Und was ist, wenn man einfach die Strukturelemente vertauscht. Also angenommen, rs würde nicht an RB1 angeschlossen sein sondern an RB0. Würde es reichen, einfach die Strukturelemente zu tauschen.

Code:
struct port_b_layout
{       
                     short unused;      // x      <--> RB0
                     short rs;          // rs     <--> RB1
                     short unused2;     // x      <--> RB2
                     short enable;      // enable <--> RB3
                     int lcddata:4;     // data   <--> RB4-RB7
} portb;

Eigentlich ne sau doofe Frage, aber ich bin gerade etwas verunsichert.

Edit: Bitte Code-Tags verwenden.
Bernd
« Letzte Änderung: Dezember 08, 2006, 19:57:19 von Bernd » Gespeichert
Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #7 am: Dezember 08, 2006, 19:58:30 »

Zitat
Was genau passiert eigentlich in der folgenden Zeile?

#byte portb=6

Dem Identifier "portb" wird die Registeradresse "6" zugeordnet. Damit erfolgt jeder Zugriff auf "portb" auf die RAM-Adresse (SFR) "6", was bei den PIC16 dem Register "PORTB" entspricht (sofern vorhanden). Mit #byte wird also ein direkter Zugriff auf Registeradressen ermöglicht.

Zitat
Und was ist, wenn man einfach die Strukturelemente vertauscht. Also angenommen, rs würde nicht an RB1 angeschlossen sein sondern an RB0. Würde es reichen, einfach die Strukturelemente zu tauschen.

Ja.


Viele Grüße

Bernd
Gespeichert

OelC
Newbie
*
Offline Offline

Beiträge: 10


Profil anzeigen
« Antworten #8 am: Dezember 21, 2006, 16:42:41 »

Kurze Anmerkung!

Ich habe jetzt eine kleine Schaltung mit einem PIC16F84A aufgebaut und damit den Code (siehe erstes Posting) getestet. LCD Display konnte daraufhin fehlerfrei betrieben werden!

Merkwürdig nur, dass ich mit dem Code nicht das LCD am PIC16F73 zum laufen bringe?Huch?

Gespeichert
Seiten: [1] Nach oben Drucken 
« vorheriges nächstes »
Gehe zu:  

Powered by MySQL Powered by PHP Made for Mozilla (Firefox) Made for Internet Explorer
Seite erstellt in 0.039 Sekunden mit 18 Zugriffen.
 
Top! Top!