HD44780-kompatibel display: Kommer inte över till CGRAM...

Lysdioder, Optiska sensorer, Fiberoptik, Displayer, Lasrar, Optiska kopplare
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 7435
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av Marta »

Kan det vara så enkelt som att displayen inte är redo för kommando när Du skickar CGRAM-adressen?

Det finns några kommandon som är ultralångsamma, bl.a. "clear display'. Det kan ta upp till 64ms vill jag minnas att det står i databladet. Skickas något innan pågående kommando är klart kan allehanda magiska fenomen uppträda...

Efter att Du skrivit till CGRAM måste något kommando ges som återställer till DDRAM för att Du skall kunna skriva tecken

Kan tillägga att jag precis provat att skriva CGRAM i 4-bit mode och det fungerade alldeles utmärkt, men inte förän jag lagt till en stadig fördröjning efter "clear display"... Använde 100ms delay för att vara helt säker på att den räckte.
Användarvisningsbild
JimmyAndersson
Inlägg: 26470
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av JimmyAndersson »

Icecap:
"I databladet är det tydligt angivit att man ska vänta ung. 4,1ms från power-on/Reset till man börjar prata med displayen."

Det är ingen som helst risk (eller ens chans) att jag kommer i närheten av det.
Jag måste sträcka mig lite för att slå på labaggregatet, sedan kollar jag så allt reagerar som det ska
innan jag startar programmet. Det lär gå 8-10 sekunder efter power-on tills jag tar en pratstund med den.


Marta:
"Kan det vara så enkelt som att displayen inte är redo för kommando när Du skickar CGRAM-adressen?"

Om man måste vänta längre än de 3 sekunder som jag provat med så lär den aldrig bli redo. :)
De flesta av testerna är gjorda med en väntetid på 1 sekund innan jag skickar CGRAM-adressen.
Efter varje rad kod så har jag åtminstone 10ms paus, så det tar närmare 100ms
från det att jag t.ex sätter DB-pinnarna tills jag är klar med att ha tänt och släckt E-pinnarna.

Så när jag t.ex skrivit text så har jag sett bokstav för bokstav komma fram,
som om texten kom från ett äldre modem. :)
Samma sak när jag gjort eget tecken och markören har hoppat fram ett steg för varje byte.




Nu gjorde jag ett litet php-program som knåpar ihop alla initierings-rader.
Jag använder samma initierings-data som innan.
(Det blev 35 rader eftersom jag ville vara lite tydlig med upplägget.) Såhär ser det ut:

Kod: Markera allt

<?php
$init_array = array(
"00110000", "00110000", "00110000",
"00100000",
"00100000", "10000000", "00000000", "11110000", "00000000", "00010000", "00000000", "01100000");

$rs = 0;
$e1e2 = "11"; //Binärt i strängform. E1 och E2.
$wait = "0.1"; //antal sekunder. Dvs 100ms.

echo 'bus.write_byte_data(DEVICE, OLATA, 0b0000000', $rs, ') # RS<br>';
echo 'sleep(', $wait, ')<br>';
echo "<br>";

foreach ($init_array as $init_temp)
	{
	$db = substr($init_temp, 0, 4);

	//DB-pinnarna
	$byte_db = substr_replace($init_temp, $rs, 7, 1); //Ersätter RS med rätt för stunden.
	
	//E-pinnarna
	$byte_eon_temp = substr_replace($init_temp, $e1e2, 5, 2); //Ersätter E1 och E2 med rätt för stunden.
	$byte_eon = substr_replace($byte_eon_temp, $rs, 7, 1); //Ersätter RS med rätt för stunden. Till E on.
	$byte_eoff = $byte_db;
	
	echo 'bus.write_byte_data(DEVICE, OLATA, 0b', $byte_db, ') # DB<br>';
	echo 'sleep(', $wait, ')<br>';
	echo 'bus.write_byte_data(DEVICE, OLATA, 0b', $byte_eon, ') # E on<br>';
	echo 'sleep(', $wait, ')<br>';
	echo 'bus.write_byte_data(DEVICE, OLATA, 0b', $byte_eoff, ') # E off<br>';
	echo 'sleep(', $wait, ')<br>';
	echo "#<br>";
	}
?>

När man kör den koden så resulterar det som sagt i en ny och ren initiering:
(Lite lång, men jag ville ta med den för att visa.)

Kod: Markera allt

bus.write_byte_data(DEVICE, OLATA, 0b00000000) # RS
sleep(0.1)

bus.write_byte_data(DEVICE, OLATA, 0b00110000) # DB
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00110110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00110000) # E off
sleep(0.1)
#
bus.write_byte_data(DEVICE, OLATA, 0b00110000) # DB
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00110110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00110000) # E off
sleep(0.1)
#
bus.write_byte_data(DEVICE, OLATA, 0b00110000) # DB
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00110110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00110000) # E off
sleep(0.1)
#
bus.write_byte_data(DEVICE, OLATA, 0b00100000) # DB
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00100110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00100000) # E off
sleep(0.1)
#
bus.write_byte_data(DEVICE, OLATA, 0b00100000) # DB
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00100110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00100000) # E off
sleep(0.1)
#
bus.write_byte_data(DEVICE, OLATA, 0b10000000) # DB
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b10000110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b10000000) # E off
sleep(0.1)
#
bus.write_byte_data(DEVICE, OLATA, 0b00000000) # DB
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00000110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00000000) # E off
sleep(0.1)
#
bus.write_byte_data(DEVICE, OLATA, 0b11110000) # DB
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b11110110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b11110000) # E off
sleep(0.1)
#
bus.write_byte_data(DEVICE, OLATA, 0b00000000) # DB
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00000110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00000000) # E off
sleep(0.1)
#
bus.write_byte_data(DEVICE, OLATA, 0b00010000) # DB
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00010110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00010000) # E off
sleep(0.1)
#
bus.write_byte_data(DEVICE, OLATA, 0b00000000) # DB
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00000110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00000000) # E off
sleep(0.1)
#
bus.write_byte_data(DEVICE, OLATA, 0b01100000) # DB
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b01100110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b01100000) # E off
sleep(0.1)
#

Den initierings-koden lägger jag efter följande:

Kod: Markera allt

import smbus
from time import *
import sys
import getopt

#============================================================
#
#  40 x 4  LCD <-  MCP23017 <- I2C <- Raspberry Pi model B
#
#
#  PORT - LCD
#  -----+----
#  GPA0 - RS
#  GPA1 - E1
#  GPA2 - E2
#  GPA3 - Reserverad for R/W.
#         Tills vidare ar R/W kopplad till GND, dvs Write-lage.
#
#  GPA4 - DB4
#  GPA5 - DB5
#  GPA6 - DB6
#  GPA7 - DB7
#
#=============================================================


# - - - - - -
# Definiera adresser

DEVICE = 0x22 # Adressen till min krets

# A
IODIRA = 0x00 # Register for pin direction. In or Out
OLATA = 0x0A  # Register for outputs (When IOCON.BANK=1)
GPIOA = 0x09  # Register for inputs (When IOCON.BANK=1)

# B
IODIRB = 0x10
OLATB = 0x1A
GPIOB = 0x19

#
IOCON = 0x04
GPPUA = 0x06
GPPUB = 0x16

# - - - - - -


bus = smbus.SMBus(1) # I2C-bussen och vilken kanal.

#Bank 1. No mirror in INT. Sequential operation enabled.
bus.write_byte_data(DEVICE, IOCON, 0b10000000)

# Pull-up disabled for inputs
bus.write_byte_data(DEVICE, GPPUA, 0b00000000)
bus.write_byte_data(DEVICE, GPPUB, 0b00000000)

# Set all GPA and GPB pins as outputs by setting
# all bits of IODIRA and IODIRB register to 0
bus.write_byte_data(DEVICE,IODIRA, 0x00)
bus.write_byte_data(DEVICE,IODIRB, 0x00)

# Set output all 7 output bits to 0 on GPA and GPB
bus.write_byte_data(DEVICE,OLATA, 0)
bus.write_byte_data(DEVICE,OLATA, 0)

# - - - - - -

Det är alltså allt.

Resultatet av detta?

Mjo.. precis som innan.
När jag startat labaggregatet, väntat en stund och kör programmet så går initieringen fel.
När jag då väntar ett par sekunder och kör programmet igen så blir det rätt.

Är det nu man ska sätta sig i ett hörn och prata med tapeterna?

Nä jag sparar det till senare.
Jag funderar istället på att kavla upp ärmarna och göra ett kretskort
så att de enda sladdarna som finns är de för I2C-anslutningen.
(Har tyvärr inte möjlighet att sätta kortet direkt på Raspberryn.)
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 7435
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av Marta »

Här är min initiering som är testad och fungerar. Displayen är en 2x20.
Hoppas det är tydligt nog, kan annars skicka programkoden i morgon.

5ms väntan mellan allt som skickas utom enskilda nibblepar för att forma en hel byte. Där är väntan 100µs.

Detta skickas som enkla nibbles. Hexadecimalt och avser bit 4..7
3
3
3
2

Från och med här skickas data som två niblbes. Hexadecimalt och avser byten i dess helhet.
28
14
0E
06
02
01
Lång väntan 100ms.

Nu sätts CGRAM
40
RS sätts till 1
Teckendata skickas

Tillbaka till DDRAM pos 0
RS sätts till 0
80

----klart----
Användarvisningsbild
JimmyAndersson
Inlägg: 26470
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av JimmyAndersson »

Jag jämförde våra initieringar:
(Från och med rad 7 så är datan uppdelad på två nibble.
Det är alltså bara bit 7-4 som tas om hand från dessa bytes.)

Kod: Markera allt

Martas       Jimmys          Marta                            Jimmy
00110000     00110000        8 bit. (initiering)              Samma
00110000     00110000        8 bit. (initiering)              Samma
00110000     00110000        8 bit. (initiering)              Samma

00100000     00100000        4 bit.                           Samma

00100000     00100000        4 bit. 2 line mode.              Samma
10000000     10000000        5x8 dot format.                  Samma

00010000     00000000        Shift cursor to the right        Display is turned on.
01000000     11110000        AC is increased by 1             Cursor on. Blink on.

00010000     00000000        Shift cursor to the right        Clear display
01000000     00010000        AC is increased by 1

00000000     00000000        Cursor/blin moves to left and    Samma
01100000     01100000        DDRAM adress is increased by 1   Samma

00000000                     Return home
00100000     

00000000                     Clear display
00010000
Du kör "Shift cursor to the right. AC is increased by 1" två gånger.
Jag sätter istället igång displayen med synlig markör och blink.
Jag kör visst aldrig "Return home"...


När jag testade din initiering så blev det först likadant. Dvs:
Startade labaggregatet. Väntade en stund. Körde initieringen. Det blev fel.
Väntade en stund igen och körde initieringen igen. Då blev det rätt.

Men varje gång jag kör din initiering så händer det en massa under tiden som den tar emot varje byte.
T.ex så kan alla pixlar tändas för ett ögonblick, markören hoppar ner till mitten av rad 2 för en stund. osv.
Men när initieringen är klar så är markören där den ska och allt ser ok ut.

Det blev aningen bättre när jag lade till längre fördröjningar (100ms) mellan varje nibble skickades.
Då hoppar bara markören till kolumn 3 på rad 1 och står där tills initieringens slutfas.
Då hoppar markören till kolumn 1 och allt ser ut som det ska.

Det går förmodligen att ordna genom att låta displayen vara avstängd (0b000010xx) under tiden den initieras.



Men resten, att sätta CGRAM, har jag inte lyckats med.
Jag använde din initiering.
Väntade 3 sekunder.
Satte CGRAM.
Väntade 3 sekunder.
RS sätts till 1.
Väntade 3 sekunder.

Så här långt blir allt ok.

Men när jag sedan skickar teckendatan så blir det exakt samma tecken på displayen som under alla mina försök.


Har du möjlighet att visa exakt vad du skickar när du skickar teckendata?
Som du gjorde med initieringen t.ex.



Om jag t.ex vill ha ett tecken som ser ut såhär:
00000001
00000011
00000111
00001111
00000111
00000011
00000001
00000000

Så delar jag upp varje rad till 2 nibble. T.ex så blir rad 3 ovan såhär:
Skickar 0000 0000 (bit 7-4 är för mitt tecken. bit 3-0 är utfyllnad så det blir en byte.)
Skickar 0111 0000 (samma förklaring som ovan.)

I detta har jag ju även bakat in E och RS. RS är bit 0. E-pinnarna är bit 1 och 2.
Så det som skickas ut blir i själva verket såhär:

Skickar 0000 0111 (E1 och E2 = 1. RS = 1.)
Skickar 0000 0001 (E1 och E2 = 0. RS = 1.)
Det var ena nibblen, den höga. Nu nästa, den låga:
Skickar 0111 0111 (E1 och E2 = 1. RS = 1.)
Skickar 0111 0001 (E1 och E2 = 0. RS = 1.)

När jag skickar 0x40, dvs sätter CGRAM så gör jag på samma sätt som ovan,
men med motsvarande nibbles och med RS = 0.


Jag kan inte hitta något fel där.
Men jag skulle bli glad om någon ser något galet.



edit:
Finns det något jag kan testa, rent hårdvarumässigt mellan portexpandern och displayen?
Pull-down, filter, osv. Blybunker?
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 7435
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av Marta »

Kan Du klocka in data i logikanalysatorn från en extern klocka, så den registrerar vad som skickas och visar det i numerisk form istället för kurvor? Det skulle vara bra för att se vad det är som tas emot vid displayen.

Jag skickar inget dubbelt, det är 14 och sedan 0E som skickas. Du har missat 0E.

Gör två rutiner, en för att skicka en nibble och en annan för att skicka en hel byte i form av två nibbles. Verifiera dem så Du vet med absolut säkerhet att de fungerar och använd dem sedan för att hantera displayen. Då blir allt mycket enklare och överskådligare med mindre möjliheter för fel.
Användarvisningsbild
JimmyAndersson
Inlägg: 26470
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av JimmyAndersson »

Oj, jag måste ha missat när jag räknade om till binär visning.

Här är den rättade listan:

Kod: Markera allt

Martas       Jimmys          Marta                            Jimmy
00110000     00110000        8 bit. (initiering)              Samma
00110000     00110000        8 bit. (initiering)              Samma
00110000     00110000        8 bit. (initiering)              Samma

00100000     00100000        4 bit.                           Samma

00100000     00100000        4 bit. 2 line mode.              Samma
10000000     10000000        5x8 dot format.                  Samma

00010000     00000000        Shift cursor to the right        Display is turned on.
01000000     11110000        AC is increased by 1             Cursor on. Blink on.

00000000     00000000        Display is turned on. 			  Clear display
11100000     00010000        Cursor on. Blink off.

00000000     00000000        Cursor/blin moves to left and    Samma
01100000     01100000        DDRAM adress is increased by 1   Samma

00000000                     Return home
00100000     

00000000                     Clear display
00010000
Därmed är det bara detta som min initiering saknar:
Shift cursor to the right.
AC is increased by 1.
Return home.

Inget speciellt som kan göra att displayen förlorar fattningen.
När jag kör den korrigerade initieringen så blir det exakt samma resultat som innan.



Över till ditt senaste inlägg:

"Kan Du klocka in data i logikanalysatorn från en extern klocka, så den registrerar vad som skickas och visar det i numerisk form"

Det kan jag ordna, men jag förstår inte riktigt.
Jag lär ju bara få en lång rad med just 1 0 1 0 1 0 1 osv.
Möjligen en extra etta eller nolla varje gång klockan och logikanalysatorns klocka hamnar i "rätt" läge,
men det är ju helt normalt när man har två saker som går i olika frekvens.

"Det skulle vara bra för att se vad det är som tas emot vid displayen."

Okej... (tänker jag och ser ut som ett frågetecken). :)
Hur ska jag koppla det?
Menar du att jag ska ta en tråd som nu går mellan klockan och portexpandern
och istället koppla klockan i ena änden och logikanalysatorn i andra?

Berätta lite mer om vad du söker så kan jag fixa det.



"Gör två rutiner, en för att skicka en nibble och en annan för att skicka en hel byte i form av två nibbles."

Sådana har jag ju redan. De använde jag fram till mitt 3e inlägg i tråden.
Sedan dess har jag pratat direkt med I2C-bussen, utan rutinerna.
Vill du alltså att jag ska göra om rutinerna och börja använda dem igen?

Inga problem i såfall. :)
(Jag frågar bara för att vara säker, så jag inte sätter mig och gör något som inte alls var det du sökte.)

De rutiner jag har nu fungerar såhär:

Nibble_high = indata AND 0b11110000
Nibble_low = (indata AND 0b00001111) << 4 #dvs shift 4 åt vänster.

Förmodligen det enklaste sättet man kan göra det på.
Jag har testat rutinerna genom att stoppa in alla möjliga tal mellan 0 och 255.
Någonstans i tråden finns utdatan från dessa rutiner.





Jag missade ju förresten att gå tillbaka till en av bilderna jag postade tidigare. Den här:
http://www.varion.se/elektronik/temp3/L ... helhet.gif

Du skrev om en negativ flank:
"På den mellersta bilden från logikanalysatorn har en negativ flank hamnat så den går rakt igenom där pixlarna tar ett språng i sidled. Samma språng syns på databitarna. Det kan ge intrycket att dessa händelser är samtidiga, men jag antar att det inte är så?"

Tänker du på den som kommer strax innan RS blir hög i bilden ovan?
Tyvärr har jag inte kvar resultatet av den loggningen, men jag stoppade in bilden i Photoshop och förstorade:
http://www.varion.se/elektronik/temp3/L ... t_zoom.gif
Där ser man att flanken kommer samtidigt på alla de kanalerna.
(Jag släcker ju E-pinnarna samtidigt som datapinnarna.(I koden är E-pinnarna är höga i 10,01ms.)

När sådana nedförsbackar kommer samtidigt överallt och med jämna mellanrum, så brukar det ju bero på att två klockor
hamnar i just det läge där den ena "slår runt" precis efter den andra.

Dessutom har jag ju zoomat ut för att kunna visa hela initieringen.
Då blir ju sneda streck utan antialiasing lite förändrade.

På första bilden jag postade, dvs:
http://www.varion.se/elektronik/temp3/L ... s_init.gif
så ser man hur flankerna ser ut i riktig inzoomning.
Där ser man även tiderna bättre.

--

Jag håller även på att göra schema till ett kretskort med display och portexpandern.
Så om du eller någon annan tycker att jag ska lägga till filter, pull-down, osv, på datapinnarna
så skulle jag behöva veta det i kväll. :)
Användarvisningsbild
JimmyAndersson
Inlägg: 26470
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av JimmyAndersson »

Jag skulle vilja få en sak bekräftat:

Om jag t.ex vill ha ett tecken som ser ut såhär:
00000001
00000011
00000111
00001111
00000111
00000011
00000001
00000000

Så delar jag upp varje rad till 2 nibble. T.ex så blir rad 3 ovan såhär:
Skickar 0000 0000 (bit 7-4 är för mitt tecken. bit 3-0 är utfyllnad så det blir en byte.)
Skickar 0111 0000 (samma förklaring som ovan.)

I detta har jag ju även bakat in E och RS. E-pinnarna är bit 1 och 2. RS är bit 0.
Så det som skickas ut blir i själva verket såhär:

Skickar 0000 0111 (E1 och E2 = 1. RS = 1.)
Skickar 0000 0001 (E1 och E2 = 0. RS = 1.)
Det var ena nibblen, den höga. Nu nästa, den låga:
Skickar 0111 0111 (E1 och E2 = 1. RS = 1.)
Skickar 0111 0001 (E1 och E2 = 0. RS = 1.)

När jag skickar 0x40, dvs sätter CGRAM så gör jag på samma sätt som ovan,
men med motsvarande nibbles och med RS = 0.


Jag kan inte hitta något fel där.
Men jag skulle bli glad om någon ser något galet.
Användarvisningsbild
Icecap
Inlägg: 26623
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av Icecap »

Det galna är att du skickar data OCH kontrollsignaler samtidig! Det är inte nödvändigtvis själva datan du överför som blir fel men din data kontra handskakningstiming är helt klart fel!

Du måste skriva en byte som följer:
1: Lägg ut MSB.
2: Lyfta Enable.
3: Sänka Enable.
4: Lägg ut LSB.
5: Lyfta Enable.
6: Sänka Enable.

Varje byte ut till displayen blir alltså minst 6 st skrivningar till bus-expandern!
Användarvisningsbild
JimmyAndersson
Inlägg: 26470
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av JimmyAndersson »

Jag förenklade visst lite för mycket i min förklaring där. :)
Det är svårt att få med lagom mycket.
För mycket och det blir oöverskådligt. (Någon som vill se alla 358 rader kod?)
För lite och det fattas något.



Jag backar bandet lite:

Först och främst använder jag Martas initiering av displayen.
Det gör jag på samma sätt som koden nedan, men förstås annorlunda för de första bitar som inte ska delas upp.

Sedan RS = 0.

Tänder bit 6 för att hamna i CGRAM. Det gör jag på samma sätt som koden nedan.

Därefter sätter jag RS = 1.

Och därefter datan som ska till CGRAM.
För att t.ex skicka 00000111 :

#
bus.write_byte_data(DEVICE, OLATA, 0b00000001) # DB (MSB)
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00000111) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00000001) # E off
sleep(0.1)
#
bus.write_byte_data(DEVICE, OLATA, 0b01110001) # DB (LSB)
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b01110111) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b01110001) # E off
sleep(0.1)

osv för de övriga byte som bildar ett tecken.

(E1 och E2 är bit 1 och 2. RS är bit 0.)


Är detta rätt? Det är så jag skickar data till CGRAM.
Men även med Martas initiering och adressering av CGRAM
så hamnar teckendatan på displayen istället för i CGRAM.

Vad 17 gör jag för galet. Allt fungerar utom just att "ställa sig" i CGRAM. :shock:
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 7435
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av Marta »

Här är programkod befunnits fungera. Rutiner för att initiera LCD inklusive laddning av CGRAM med ÅÄÖ samt för att skicka kommandon och tecken till displayen. Tyvärr är det inte samma tabulering här som i min editor så texten blir tilltufsad.

Kod: Markera allt



SWECHR	.EQ @/2
	.RL HS 04,0A,0E,11,1F,11,11,80	Å
	.RL HS 0A,80,0E,11,1F,11,11,80	Ä
	.RL HS 0A,80,0E,11,11,11,0E,80	Ö
	.RL HS 00





***	SEND DATA TO DISPLAY
*
LCDOUT	SEF REGSEL		SELECT DATA REG
.8OUT	LOD LCDPAD,A		SAVE CHAR
	SWN LCDPAD
	JSR .4OUT		PUT FIRST NIBBLE
	SWN LCDPAD		SWAP NIBBLES AND PUT SECOND ONE
.4OUT	JSR DELAY.100
	LOD A,#$F0		CLEAR OUT DATA BITS
	AND PORTC,A
	LOD A,LCDPAD		GET DATA
	AND A,#$0F		MASK OUT DATA BITS
	ORR PORTC,A		 PUT DATA
	NOP
	SEF STROBE		SHAKE STROBE
	NOP
	CLF STROBE
	RTS			DONE

.4BIT	CLF REGSEL		SELECT COMMAND REG
	LOD LCDPAD,A		SAVE CHAR
	JSR .4OUT
	JMP DELAY.5000		LONG WAIT, JUST TO BE SURE

.CMD	CLF REGSEL		SELECT COMMAND REG
	JSR .8OUT
	JMP DELAY.5000		LONG WAIT, JUST TO BE SURE


******	INIT LCD DISPLAY
*
LCDINI	CLF STROBE		INIT LCD STROBE
	CLF REGSEL		SELECT CONTROL REGISTER
	JSR DELAY.5000		WAIT 15000US
	JSR DELAY.5000
	JSR DELAY.5000
	*			DISPLAY RESET
	LOD A,#$03		PUT FUNCTION SET CMD
	JSR LCDOUT.4BIT
	LOD A,#$03		PUT FUNCTION SET CMD ONCE MORE
	JSR LCDOUT.4BIT
	LOD A,#$03		PUT FUNCTION SET CMD A LAST TIME
	JSR LCDOUT.4BIT
	*			DISPLAY CONFIG
	LOD A,#$02		SET 4-BIT MODE
	JSR LCDOUT.4BIT
	LOD A,#$28		SETUP DISPLAY
	JSR LCDOUT.CMD
	LOD A,#$14
	JSR LCDOUT.CMD



	LOD A,#$0E		TURN ON DISPLAY AND CURSOR
	JSR LCDOUT.CMD
	LOD A,#$06		SET ENTRY MODE
	JSR LCDOUT.CMD
	LOD A,#$02
	JSR LCDOUT.CMD


	LOD A,#$01		CLEAR DISPLAY
	JSR LCDOUT.CMD
	LOD A,#20		THIS TAKES TIME...
	LOD PAD2,A
.CLRWT	JSR DELAY.5000
	DSZ PAD2
	JMP .CLRWT

	JSR SETCG		LOAD CGRAM

	LOD A,#$80		BACK TO DDRAM, POS0
	JSR LCDOUT.CMD

	RTS


	*			INIT CGRAM
SETCG	LOD A,#$40		ADDRESS CGRAM
	JSR LCDOUT.CMD
	LOD A,#SWECHR		INIT ADR PNT
	LOD PAD3,A
.CGINIT LOD A,PAD3		GET PNT
	INC PAD3		NXT POS
	JSR TBLRD.0		GET DATA
	ORR A,#0		ZERO = AT END?
	SFC Z
	RTS			YES-ALL DONE  !! EXITPOINT HERE !!
	AND A,#$7F		MASK OFF HIGH BIT = NONZERO FILLER FOR BLANK
	JSR LCDOUT		PUT DATA
	JMP .CGINIT		DO NXT


***	DELAYS
*	.5000 = 5000µs
*	.100 = 100µs
*
DELAY
.5000	STZ PAD0		SETUP DELAY COUNT FOR 5000 US
	LOD A,#12
	LOD PAD1,A
.N5000	DSZ PAD0		COUNT DOWN INNER LOOP
	JMP .N5000		INNER DELAY LOOP
	DSZ PAD1		COUNT DOWN OUTER DELAY LOOP
	JMP .N5000		OUTER DELAY LOOP
	RTS			DELAY DONE


.100	LOD A,#70		COUNT FOR 100 US DELAY
	LOD PAD0,A		SET IT
.N100	DSZ PAD0		COUNT DOWN
	JMP .N100		DELAY LOOP
	RTS			DELAY DONE






Användarvisningsbild
Marta
EF Sponsor
Inlägg: 7435
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av Marta »

När det går troll i ett program brukar jag alltid börja om med att lägga till bit för bit av koden och testa så allt verkligen fungerar som det är tänkt innan nästa bit läggs till. På det sättet brukar felet komma fram så småningom. Det är alltid extra svårt att hitta fel när det finns många bugs som samverkar och påverkar varandra...

Så mitt råd är att göra enkla rutiner från grunden och testa dessa noggrant innan nästa steg tas. Det brukar hjälpa.

Angående logikanalysatorn så var tanken att koppla E som klocka och låta denna klocka in signalerna i analysatorn som om de klockades in i displayen. Är där tidsmarginaler på alla sidor om flankerna så bör den då "se" detsamma som displayen gör och eventuella magiska fenomen på vägen kan upptäckas.

Har Du förresten möjlighet att skicka data som SPI istället för I2C? Förutsatt att det även finns en vanlig portpinne tillgänglig kan Du då använda vanliga skiftregister med latch på utgången och komma ifrån både portexpander och 4-bit mode.
Användarvisningsbild
JimmyAndersson
Inlägg: 26470
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av JimmyAndersson »

Jag börjar med ditt förra inlägg:
Tack för koden! :)
Vad använder du för assembler/kompilerare? Jag tycker instruktionerna skiljer sig lite från Microchip's vanliga.

Det är två saker i koden som jag inte är helt säker på:
1)
I LCD.8OUT så byter du bara plats på de båda nibbles med SWN,
men i LCD.4OUT så använder du tricket med AND för att göra (till synes) samma sak.
Varför två olika sätt?

2)
I SETCG.CGINIT så maskar du bort högsta biten (AND A,#$7F).
Vad jag kan se så förekommer den biten bara i ÅÄÖ-datans sista byte.
Först tänkte jag att det kanske var någon markör för "slut på data",
men direkt efter så verkar du anropa LCDOUT.
Så det verkar vara något jag missar här.



Över till ditt senaste inlägg:

"När det går troll i ett program brukar jag alltid börja om med att lägga till bit för bit av koden"[klipp]

Samma här. Jag är på version 2.C och den här sista versionen har jag rensat totalt många gånger.
Som jag skrivit så har jag inte ens några rutiner kvar.
Allt görs med anrop direkt till I2C-busssen.
Men inte ens det fungerar för att hamna i CGRAM.

Jag kör med din initiering och det fungerar.
Men så fort jag lägger till adresseringen av CGRAM så hamnar datan i DDRAM istället.

I mitt förra inlägg finns koden för hur jag gör för att hamna i CGRAM.
Nu har varken du eller Icecap (eller någon annan) skrivit att den koden varken är rätt eller fel,
så jag antar att den är rätt. Ni brukar ju ha falkögon när det gäller att hitta fel. :)



"Så mitt råd är att göra enkla rutiner från grunden och testa dessa noggrant innan nästa steg tas. Det brukar hjälpa."

Rutiner är ju ett bra sätt att få kod mer kompakt och snygg,
men det är ju även en risk eftersom det är svårare att följa hopp mm.
En "rak" lista med alla instruktioner under varandra är svår att gå vilse i,
så länge det finns kommentarer som "milstenar".

Nackdelen är förstås att en "rak" lista med instruktioner blir lång.
Men eftersom principen är likadan genom hela initieringen
(även anropet till CGRAM görs ju på samma sätt)
så behöver man bara läsa ca 6 rader för att få grepp om exakt hur det är gjort.

Därför har jag alltid sett en rak lista med instruktioner som mer grundläggande
och en bra utgångspunkt för att undvika så många fel som möjligt.

För att få det bästa av båda världar så är dessutom min lista med instruktioner
automatiskt genererad av mitt php-script som använder indata från din initiering.
Om något skulle vara fel med det scriptet så skulle man definitivt få konstig utdata redan från början.


Så jag kan inte komma på hur jag skulle kunna göra det hela mer grundläggande.
Plockar jag bort det enda som inte fungerar (anropet till CGRAM) så plockar jag
ju bort just det som jag försöker få att fungera.
Och att försöka göra det anropet mer grundläggande än att skriva direkt till I2C-bussen finns nog inte.
(Ja om man inte ska stoppa dit tre momentana brytare och knacka in ettor och nollor helt manuellt. :D )

Jag kommer nog inte på något mer att prova när det gäller mjukvaran.





"Angående logikanalysatorn så var tanken att koppla E som klocka och låta denna klocka in signalerna"[klipp]

Nu förstår jag. Intressant idé.
Jag ska testa det.




"Har Du förresten möjlighet att skicka data som SPI istället för I2C? Förutsatt att det även finns en vanlig portpinne tillgänglig kan Du då använda vanliga skiftregister med latch på utgången och komma ifrån både portexpander och 4-bit mode."

SPI istället för I2C är inga problem. Men jag är osäker på om jag har några shiftregister av rätt sort.
Jag vet att jag har 4-bitars med parallell input och det går ju att ordna det med dem (och lite annat),
men det hade varit smidigt med något mer färdigt. Så det inte riskerar att bli en till felkälla.
Jag ska titta runt lite och se vad jag kan ordna. :)


Jo det här med att jag valt köra displayen som 4-bit istället för 8-bit:
Portexpandern har två portar med 8 pinnar i varje.
Till den behöver jag ansluta displayen och 5st knappar.
För att göra det enkelt så tar jag 1st pinne per knapp.
Då får jag över 11st för displayen.
Kör jag displayen i 8-bit så går det åt 12 pinnar. Därav mitt val att köra displayen som 4-bit.

Hm, visst ja...
Det blir lite rörigt om jag kör displayen över SPI och knapparna på en hel portexpander med I2C...
Men som test är det inga problem.
Användarvisningsbild
JimmyAndersson
Inlägg: 26470
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av JimmyAndersson »

Jag är eventuellt något på spåren.
Började mäta på displayens bana för bit 6 och där var det inte helt ren 1a när det skulle.
Det fladdrade lite upp och ner. Så är det inte på de andra datapinnarna.

Förtydligande:
Mäter jag direkt på portexpandern utan displayen inkopplad så finns inte detta fladder.
Misstänkte ett tag labplattan så jag lödde sladden direkt mot IC'ns ben och det tog inte bort felet.
Så det är något med kontakten på displayen eller något som fångas upp av displayens kretskortsbana.

Jag ska fortsätta spåra och se vad det beror på.

edit: Usch, det hade jag inte sett... Flera SMD-komponenter på displayens baksida
(3-4st motstånd och lite avkopplingskondingar) är lite dåligt lödda. Ska löda om dem och se.


edit 2: Det blev bättre. Inget fladder på bit 6, men ingen skillnad i resultat på displayen.
Dvs det som skulle hamna i CGRAM hamnar i DDRAM.
Användarvisningsbild
Icecap
Inlägg: 26623
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Inlägg av Icecap »

Du behöver att systematisera din kontroll! Gör din mjukvara så att den uteslutande skriver ett steg åt gången. Sedan mäter du och noterar alla pinnarna (kan göras med lite LED för enkelhetens skull) och sedan kommer nästa steg. Och jag menar att ett steg UTESLUTANDE är en enda uppdatering av portexpandern! Sedan får du en lång kedja av värden som du sedan kan stycka ihop till ett vettigt flöde.

Jag hoppas även att du vet om att under initieringen tror displayen att det är 8-bit fram till att det får kommandot om att det är 4-bit som gäller, detta betyder att det under initieringen skrivs ett antal "halva" kommandon!
Användarvisningsbild
Icecap
Inlägg: 26623
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Någon som använt MCP23017 med LCD och egna tecken (CGRAM

Inlägg av Icecap »

Datablad

Det viktiga för mig är att du rent faktisk vet exakt vad som händer. Gör en testcase som initierar "som du brukar" men lägg till en knapp och säkra dig att den inte bouncer. Varje skrivning av data till displayen får först ske när du trycker på knappen, det får bara ske en enda skrivning per tryck och du kollar vad som sker.

Skriv för allt i världen ner vad du ser, vilka steg osv. Alltså alla databit, Enable, R/S, R/W osv. Räkna '0' och '1' så länge du inte får tveksamma spänningsvärden.

Så det blir:
- Notera startvärden!
*tryck*
- En nippel data läggs ut på databitten. Notera.
*tryck*
- Enable höjs. Notera - ALLA bit!
*tryck*
- Enable sänks. Notera ALLA bit!
osv osv.

Detta sätt är långsamt, tråkigt - och ger ett stensäkert bild av vad som händer! Den tid det tar att göra såhär är definitivt kortare än det (som jag uppfattar det) hattande och antagande som du har gjort tidigare.

Har du en LSA kan det såklart gå snabbare men den skal klockas av tid eller SCL, inte Enable! Det blir många data att leta igenom men du hittar problemet och när det är känd är resten enkelt.
Skriv svar