Toon posts:

[BCB] Met DLPortIO een lcd aansturen *

Pagina: 1
Acties:

Verwijderd

Topicstarter
Dag mensen,

Ik heb nu een experimenteerbordje met een 2x16 displaytje. Nu zou ik graag met BCB5 en DLPortIO hier karakters op willen schrijven om zo de werking van het LCD een beetje te snappen.

Ik zou nu graag het display willen initialiseren, het is een standaard 2x16 display met een HD44780 compatible controller. In BCB kan ik waarden naar de parallelle poort schrijven, dmv: DlPortWritePortUshort(0x379,0x00)

Ondertussen ben ik ook zo ver dat de DB0 t/m DB7 op het adres 0x379 zit en de controll pinnen op 0x37A

Ik weet ook (denk ik) welke codes ik moet sturen om het display te initialiseren, alleen doet hij dit niet :( Tussen elke regel heb ik een sleep van 5ms om er zeker van te zijn dat de busyflag weer laag is.

Wie kan mij helpen om in BCB5 en DLPortIO een 2x16 display op een HD44780 controller te initialiseren?

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18-08 21:00

Creepy

Tactical Espionage Splatterer

Verwijderd schreef op 01 October 2003 @ 19:59:
Dag mensen,

Ik heb nu een experimenteerbordje met een 2x16 displaytje. Nu zou ik graag met BCB5 en DLPortIO hier karakters op willen schrijven om zo de werking van het LCD een beetje te snappen.

Ik zou nu graag het display willen initialiseren, het is een standaard 2x16 display met een HD44780 compatible controller. In BCB kan ik waarden naar de parallelle poort schrijven, dmv: DlPortWritePortUshort(0x379,0x00)

Ondertussen ben ik ook zo ver dat de DB0 t/m DB7 op het adres 0x379 zit en de controll pinnen op 0x37A

Ik weet ook (denk ik) welke codes ik moet sturen om het display te initialiseren, alleen doet hij dit niet :( Tussen elke regel heb ik een sleep van 5ms om er zeker van te zijn dat de busyflag weer laag is.

Wie kan mij helpen om in BCB5 en DLPortIO een 2x16 display op een HD44780 controller te initialiseren?
Je bent niet de eerste op GoT die het wil proberen ;)

Anyway, je moet dus zowel de base port als de control port aansturen. Op het moment dat je de pinnen goed hebt staan voor het juiste commando zul je hierna de enable (E, is pin 1 van de control port) hoog moeten maken en weer laag maken. Hiermee signal je het LCD dat hij wat moet gaan doen. Hierna zul je een bepaalde tijd moeten wachten. Hoelang dat is, is afhankelij van het commando dat je gestuurd hebt.

(en je weet ook dat sommige control port pinnen inverted zijn? Dan moet je dus een 0 sturen om die ping hoog te maken en een 1 om de pin laag te maken!)

[ Voor 7% gewijzigd door Creepy op 01-10-2003 21:27 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

^ Wat Creepy hierboven al zegt, nog even de adressen van de lijnen:

PortAdres (Decimaal)Adres (Hex)
Data Lines888378h
Control Lines89037Ah
Status Lines889379h

En voor de geinverteerde pinnen: Wat is de pinout van de poort?

Verwijderd

Topicstarter
Goed, ik ben nog eens bezig geweest met programmeren... maar toch kom ik er niet helemaal uit. Zal het één en ander even uitleggen:

Het display heb ik aangesloten op de parallelle poort volgens dit schema:

Afbeeldingslocatie: http://backupteam.gamepoint.net/smartie/LCDconnect.jpg

dit werkt allemaal (dwz, met smarty ed. krijg ik gewoon tekst)

Allereerst heb ik de datasheet voor mijn specifieke lcd bekeken, daar heb ik in opgezocht hoe ik het display moet initialiseren. Daarvoor moet ik volgens mij dit doen:

code:
1
2
3
4
5
RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

00001110XX
0000001110
0000000110


Wat ik vervolgens moet doen (volgens mij dan :) ) is eerst zorgen dat RS en RW laag worden, aangezien pin 14 geinverteerd is moet ik 0x02 naar 0x380 schrijven.
Als deze laag zijn kan ik 001110XX naar de 8 data pinnen sturen dmv 0x38 naar 0x378. Daarna 0x0e naar 0x378 en 0x06 naar 0x378. Dan stuur ik 0x06 naar 0x380 en als laaste 0x43 naar 0x378.

Als ik dit allemaal verzonden heb blijft mijn lcd een zwarte balk weergeven, wie kan mij vertellen wat ik verkeerd doe.

Ik stuur mijn codes naar het lcd dmv DLPortIO op de volgende manier: DlPortWritePortUshort(0x378,0x43)

Na elke instructie heb ik een pauze van 5ms om er zeker van te zijn dat de BF laag is.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18-08 21:00

Creepy

Tactical Espionage Splatterer

Heb je dat stuk gelezen over de enable pin op je LCD? Die moet je hoog/laag maken op het moment dat je de pinnen goed hebt gezet, en dat mis ik in je beschrijving.
Mocht je wel de enable pin aansturen, post dan anders eens de code die je gebruikt om 1 commando te verzenden, inclusief gebruik van de enable en je pauze.

Edit: ow, en uit m'n hoofd is 5 ms tussen de eerste 3 init commando's te weinig, maar daar moet je maar ff de timing specs van de hd44780 op naslaan.

[ Voor 20% gewijzigd door Creepy op 02-10-2003 12:07 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Knutselsmurf
  • Registratie: December 2000
  • Laatst online: 20-08 20:03

Knutselsmurf

LED's make things better

Ik heb In Delphi een ander LCD-display goed werkend, ook via DLPortIO. Ik kan er nu niet bij, maar vanavond als ik thuis ben, zal ik die code wel posten. De instructies zulen niet exact gelijk zijn, maar als je een basisidee hebt, kun je de rest vast wel zelf aanpassen.

- This line is intentionally left blank -


Verwijderd

Topicstarter
Goed, ik ben nu zover dat ik al wat tekst kan schrijven.. alleen heb ik nog een paar functies nodig omdat het anders wel een erg grote lap code is :)

'K was vergeten dat de Enable pin ook geinverteerd was. Mja, Knutselsmurf: als je dat zou willen doen, heel graag :)

  • Knutselsmurf
  • Registratie: December 2000
  • Laatst online: 20-08 20:03

Knutselsmurf

LED's make things better

OK, Hier komtie dan. Ik zal de code afwisselen met commentaar. Dat moet een idee geven van de code. De code is oorspronkelijk bedoeld voor een KS0108-controller voor een Grafische LCD.

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
const dataport=$0378;
const controlport=$037A;
const
  LCD_Enable=1;
  LCD_CS2=0;
  LCD_CS1=6;
  LCD_Inst=8;
const
  DISPLAY_ON=$3f;
  DISPLAY_OFF=$3e;
  DISPLAY_STARTLINE=$c0;
  DISPLAY_PAGE_SET=$b8;
  DISPLAY_COLUMN_SET=$40;

Dit zijn de hex-codes van een aantal signalen en commando's. Deze kun je uit je eigen datasheet halen. De DISPLAY_* commando's worden uiteindelijk allemaal naar de data-poort gestuurd. De LCD_* constanten worden gecombineerd naar de controlpoort gestuurd. Een aantal van de lijnen op de controlport zijn geinverteerd. Dat is in deze constanten reeds meegenomen.

Delphi:
1
2
3
4
5
6
7
8
9
procedure delay;
var start,finish,req:int64;
begin
Queryperformancecounter(start);
req:=start+delaycounts;
repeat
  Queryperformancecounter(finish);
until finish>req;
end;

Met het gebruik van de API-functie QueryPerformanceCounter kun je een delay krijgen die beter instelbaar is dan de standaard sleep. sleep heeft een minimum van 1ms, terwijl in de specs veel kortere tijden besproken worden. Een delay van 1 microseconde is vaak al voldoende.

Delphi:
1
2
3
4
5
6
7
8
9
10
11
procedure SendLCDCommand(value,CS:byte);
begin
  if ProcLoaded then
  begin
    writeIO(controlport,(LCD_ENABLE or CS or LCD_Inst));
    writeIO(dataport,value);
    writeIO(controlport,(CS or LCD_inst));
    writeIO(controlport,(LCD_ENABLE or CS OR LCD_inst));
    writeIO(dataport,0);
  end;
end;

Bovenstaande procedure stuurt een commando naar de LCD. De procedure writeIO die aangeroepen wordt, is de procedure uit DLPORTIO.
Let op de waarde die meegegeven wordt. CS is bij mijn LCD een select tussen twee controllers en zul jij dus waarschijnlijk niet hoeven te gebruiken.
In regel 5 wordt de enable-flag hoog gezet, samen met het instructie-bit en de controller-selectie. Daarna wordt de instructie naar de datapoort gestuurd.
regel 7 en 8 doen niets anders dan de enable-flag laag en weer hoog maken, terwijl de rest van de bits gelijk blijft.

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
procedure SendLCDData(values:array of byte);
var i:integer;
    CS:byte;
begin
  if ProcLoaded then
  begin
    for i:=low(values) to high(values) do
    begin
      if CurrentColumn>63 then CS:=LCD_CS2 else CS:=LCD_CS1;
      writeIO(controlport,(LCD_ENABLE or CS));
      delay;
      writeIO(dataport,values[i]);
      delay;
      writeIO(controlport,CS);
      delay;
      writeIO(controlport,(LCD_ENABLE or CS));
      inc(currentColumn);
    end;
  end;
end;

Bovenstaande procedure is vergelijkbaar met de SendLCDCommand-procedure, behalve dan dat deze de data stuurt. Let weer op regel 10,12,14,16. Enable hoog, data sturen, enable laag, enable hoog.

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
procedure SetColumn(y:byte);
begin
  CurrentColumn:=y;
  if y<64 then
  begin
    SendLCDCommand(DISPLAY_COLUMN_SET or (y and 63),LCD_CS1);
    SendLCDCommand(DISPLAY_COLUMN_SET or 0,LCD_CS2);
  end
  else
  begin
    SendLCDCommand(DiSPLAY_COLUMN_SET or 63,LCD_CS1);
    SendLCDCommand(DISPLAY_COLUMN_SET or ((y-64) and 63),LCD_CS2);
  end;
end;
procedure setpage(x:byte);
begin
  SendLCDCommand (DISPLAY_PAGE_SET or x,LCD_CS1);
  SendLCDCommand (DISPLAY_PAGE_SET or x,LCD_CS2);
end;
procedure setStartLine(line:byte);
begin
  SendLCDCommand (DISPLAY_STARTLINE or (line and 63),LCD_CS1);
  SendLCDCommand (DISPLAY_STARTLINE or (line and 63),LCD_CS2);
end;

Bovenstaande procedures zijn in feite niets meer dan wrappers om LCD-instructies heen. Alle LCD-instructies kan je uit je datasheet halen.

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
procedure TForm1.FormCreate(Sender: TObject);
var Q:int64;
begin
 MyHandle:=LoadLibrary('DLPortio.dll');
  If MyHandle<>0 then
  begin
    @WriteIO:=GetProcAddress(MyHandle,'DlPortWritePortUchar');
    ProcLoaded:=(@writeIO<>nil);
  end;
  QueryPerformanceFrequency(Q);
  delaycounts:=Q div 1000000;
end;

Als laatste een stukje uit mn Create-procedure. Als eerste wordt hier gepoogd om de juiste DLL te laden en de procedure writeIO te koppelen aan de DLL-functie DLPortWriteUChar. Als dat niet lukt is procloaded false, zodat er in dat geval nooit een writeIO wordt aangeroepen, hetgeen tot ongewenste resultaten zal leiden.
Als laatste wordt via QueryPerformanceFrequency de delay bepaald. Die Frequency is in mijn geval ongeveer 3.5 miljoen. Door te delen door 1 miljoen zal dit uiteindelijk een delay van ongeveer 1 microseconde opleveren. In eerste instantie had ik geen enkele delay ingebouwd, wat tot gevolg had dat enkele pixels niet getoond werden. Mocht zoiets dus het geval zijn, dan moetde delay iets langer.

Delphi:
1
2
3
4
procedure TForm1.FormDestroy(Sender: TObject);
begin
If Myhandle<>0 then FreeLibrary(MyHandle);
end;

Bijna vergeten, achteraf de DLL natuurlijk weer vrijgeven :)

- This line is intentionally left blank -

Pagina: 1