Sida 1 av 1

Problem med egna tecken på 2x16-LCD

Postat: 18 augusti 2006, 19:41:36
av JimmyAndersson
Skrev detta först i Optokomponent-delen, men det är ju mer ett programmeringsproblem, så jag raderade den tråden och postade här istället:

LCD'n är en Sharp LM16A211 som är kopplad i "4bitars-läge".
Styrs med en PIC18LF2320. Kod i MikroBasic.


Det som händer är att det blir svarta fyrkanter istället för de tecken som jag gjort. Övriga bokstäver/siffror syns däremot som de ska.

Någon som vet vad som kan vara galet?


Kopplat såhär:
PORTA.0 - D4 (LCD)
PORTA.1 - D5 (LCD)
PORTA.2 - D6 (LCD)
PORTA.3 - D7 (LCD)
PORTA.4 - RS (LCD)
PORTA.5 - E (LCD)



Lite kod där jag gör och visar tecknen. LCD'n är redan initierad:

Kod: Markera allt

symbol RS = PORTA.4 ' Kan därför skriva RS istället för PORTA.4
symbol E = PORTA.5

sub procedure lcd_vanta
  delay_ms(30)
  E = 1
  delay_ms(30)
  E = 0
  delay_ms(30)
end sub

sub procedure lcd_tecken
  'Göra egna tecken.
  LATA = %0100 ' CGRAM och position noll.
  lcd_vanta
  LATA = %0000 ' CGRAM och position noll.
  lcd_vanta
  RS = 1 ' Används här för att kunna skicka pixlar till minnet.
  delay_ms(50)

  'Tecken nr 0 - UT
  LATA = %0000
  lcd_vanta
  LATA = %1010
  lcd_vanta
  LATA = %0000
  lcd_vanta
  LATA = %1010
  lcd_vanta
  LATA = %0000
  lcd_vanta
  LATA = %1110
  lcd_vanta
  LATA = %0000
  lcd_vanta
  LATA = %0000
  lcd_vanta
  LATA = %0000
  lcd_vanta
  LATA = %1110
  lcd_vanta
  LATA = %0000
  lcd_vanta
  LATA = %0100
  lcd_vanta
  LATA = %0000
  lcd_vanta
  LATA = %0100
  lcd_vanta
  LATA = %0000
  lcd_vanta
  LATA = %0000
  lcd_vanta

  'Tillbaka till DDRAM
  RS = 0 ' För att skicka kommandon.
  delay_ms(50)
  LATA = %0000 ' ClearScreen
  lcd_vanta
  LATA = %0001 ' ClearScreen
  lcd_vanta
  LATA = %1000 ' DDRAM adress 0
  lcd_vanta
  LATA = %0000 ' DDRAM adress 0
  lcd_vanta
end sub
Sedan skrivs tecknet ut på displayen. Den delen är ok, men jag kan visa den ändå:

Kod: Markera allt

sub procedure lcd_skriv(dim value, plats as byte)
'---Skicka plats---
RS = 0 ' För att skicka kommandon.
   oversta = 0
   understa = 0
   flytta = 0
   skicka = 0

   oversta = plats >> 4 ' Flyttar de översta (4st) fyra steg åt höger.
   skicka = oversta OR 8 ' Lägger till 1(000)
   LATA = skicka ' Skicka översta delen
   lcd_vanta ' E och vänta

   flytta = plats << 4 ' Flyttar fyra steg åt vänster för att de fyra översta ska försvinna.
   understa = flytta >> 4 'Flytta tillbaka igen och nu har de tidigare översta försvunnit.
   skicka = understa
   LATA = skicka ' Skicka understa delen
   lcd_vanta ' E och vänta

'---Skicka tecken---
' Tar value och delar till varsin variabel.
' T.ex om value = 01000010 så delas det så att oversta = 0100 och understa = 0010.
RS = 1 ' För att skriva text.
   oversta = 0
   understa = 0
   flytta = 0
   skicka = 0
   
   oversta = value >> 4 ' Flyttar de översta (4st) fyra steg åt höger.
   skicka = oversta OR 16 ' Lägg till en RS-bit.
   LATA = skicka ' Skicka översta delen
   lcd_vanta ' E och vänta
   
   flytta = value << 4 ' Flyttar fyra steg åt vänster för att de fyra översta ska försvinna.
   understa = flytta >> 4 'Flytta tillbaka igen och nu har de tidigare översta försvunnit.
   skicka = understa OR 16 ' Lägg till en RS-bit.
   LATA = skicka ' Skicka understa delen
   lcd_vanta ' E och vänta
end sub


sub procedure lcd_mall
  'Övre raden
  lcd_skriv(0, 9) ' UT (Special-tecken nr 0 skrivs ut på LCD'ns kolumn 9.)
end sub

Om någon fortfarande är vaken efter all kod:
Vad är galet?


Jag har gjort likadant tidigare och då fungerade det. Enda skillnaden nu är att jag skickar 4 bitar åt gången istället för 8 på en gång. Men annars är allt likadant.

Postat: 18 augusti 2006, 19:52:47
av sodjan
På flera ställen gör du "LATA = %xxxx".
Notera att du då även kommer att fippla med RS och E
eftersom du alltid skriver *8* bitar till LATA, även om du bara
har anget 4 i kommendot.

Har du full kontroll över vad som händer med RS och E ?

Det är ju i princip samma problem som du hade innan och som du
har löst i "lcd_skriv" så vitt jag förstår...

Postat: 18 augusti 2006, 20:19:00
av JimmyAndersson
> På flera ställen gör du "LATA = %xxxx".
> Notera att du då även kommer att fippla med RS och E

Anledningen att jag skrev till LATA istället för att använda min lcd_skriv-rutin var för att det skulle bli mer överskådligt när jag gjorde tecknen. Eftersom det fungerade att initiera genom att skriva till LATA så tänkte jag inte mer på det. Men nuu ser jag: Vid initieringen så ska ju ändå RS och E vara noll. Men däremot inte när jag gör tecknen! Glasklart, men jag såg det inte förrän du skrev ditt inlägg.

Tack för hjälpen och en snabb lösning! :)

Postat: 18 augusti 2006, 20:27:39
av sodjan
Jag skulle antingen dela "lcd_skriv" i två rutiner "lcd_skriv_data" och
"lcd_skriv_kommando". Eller införa en extra parameter i anropet
till "lcd_skriv" som talar om om det är data eller kommando.

Eller (kanske bättre) dela "lcd_vanta" i "lcd_vanta_data" och "lcd_vanta_kommando".
Och så lägga hanteringen av RS där tillsammans med E.
Fortfarande måste dock "lcd_skriv" veta vilken av "vanta" rutinerna
som ska anropas...

Ditt problem är att delar av "lågnivå" hanteringen (d.v.s hantering av RS pinnen)
görs i kod som ligger "för högt upp", om du förstår hur jag menar.
Det blir lite svåröverskådligt. Hanteringen av RS och E bör ligga
tillsammans (så gått det går).

Postat: 18 augusti 2006, 21:40:59
av JimmyAndersson
Det har du rätt i. Jag väljer varianten att lägga till en extra parameter till "lcd_skriv" och dela upp "lcd_vanta".

Det är nog säkrast att jag förbättrar detta innan jag gör menyhanteringen. Annars lär det bli väldigt jobbigt.

Postat: 23 augusti 2006, 17:02:11
av anlamotte
så här brukar jag göra.
Lcdcmd för kommande (RS = 0) och LcdWr för data
(RS=1)

Kod: Markera allt

Lcdcmd:                                                     ' skriv till display
  RS = 0                                               ' RS
Lcdwr:
  Porta = Char

  E = 1
  Waitms 1
  E = 0

  RS = 1                                               ' RS
Return