g457 schrieb:>> Das Datasheet ist recht dürftig und erwähnt keine spezielle>> Initialisierungssequenz.>> Einfach Seite 5 nochmal lesen :-)>> HTH
Hey,
habe ich, nur sagt das Tutorial zum einen, dass man erstmal 15 ms warten
soll und dann
1
// Soft-Reset muss 3mal hintereinander gesendet werden zur Initialisierung
2
lcd_out( LCD_SOFT_RESET );
3
_delay_ms( LCD_SOFT_RESET_MS1 );
4
5
lcd_enable();
6
_delay_ms( LCD_SOFT_RESET_MS2 );
7
8
lcd_enable();
9
_delay_ms( LCD_SOFT_RESET_MS3 );
ausführen soll. Davon steht im Datasheet nichts. Mein Test heute schien
zu gehen (gemäß Anleitung), aber wollte sichergehen, dass ich nichts
übersehe.
Namenloser324 schrieb:> Davon steht im Datasheet nichts.
Nein, denn das Display braucht derlei auch an sich nicht für den Init
nach dem Einschalten. Aber stell Dir mal folgendes Szenario vor:
- Du schaltest das System ein
- Du wartest 20ms
- Du konfigurierst das Display (speziell 4/8 bit und so)
- System läuft
- System ist leider instabil, Watchdog macht Reset
- Du fährst wieder hoch
- System ist neu gebootet, aber Display steht immer noch in irgendeinem
abstrusen Konfig-Zustand, der nicht mit Power-on identisch ist
=> und jetzt zahlt es sich aus, das Ding mehrfach zu resetten, damit die
Init-Sequenz geht, egal was man vorher mal konfiguriert hatte.
Nop schrieb:> Namenloser324 schrieb:>> Davon steht im Datasheet nichts.>> Nein, denn das Display braucht derlei auch an sich nicht für den Init> nach dem Einschalten. Aber stell Dir mal folgendes Szenario vor:>> - Du schaltest das System ein> - Du wartest 20ms> - Du konfigurierst das Display (speziell 4/8 bit und so)> - System läuft> - System ist leider instabil, Watchdog macht Reset> - Du fährst wieder hoch> - System ist neu gebootet, aber Display steht immer noch in irgendeinem> abstrusen Konfig-Zustand, der nicht mit Power-on identisch ist>> => und jetzt zahlt es sich aus, das Ding mehrfach zu resetten, damit die> Init-Sequenz geht, egal was man vorher mal konfiguriert hatte.
Okay, danke!
[quote]
Du wartest 20ms
[/quote]
Das ist die Dauer der internen Initialisierung, ja?
Namenloser324 schrieb:> Das ist die Dauer der internen Initialisierung, ja?
Ich empfehle dazu mal diese Seite hier, die hat mir bei Text-LCDs sehr
geholfen:
http://www.sprut.de/electronic/lcd/
Unter dem Punkt "Init" findet sich, daß die interne Reset-Prozedur etwa
15ms dauert. Praktisch hab ich das einfach zu 20ms aufgerundet. Bei den
sonstigen Timings nehme ich übrigens das Doppelte von dem an, was das
jeweilige Datenblatt schreibt, dann ist man auf der sicheren Seite.
Man kann natürlich (außer bei Powerup) auch das busyflag abfragen, aber
einfacher ist es, das wegzulassen und länger zu warten. Insbesondere,
wenn man ein 5V-Display an einen 3.3V-Controller anschließt, spart man
auch noch einen Levelshifter. Wobei das mit Deinem Display kein Thema
ist, weil das sowieso mit 3.3V klarkommt, wenn man es auch an 3.3V
betreibt.
Realistisch gesehen ist das alles eh nicht zeitkritisch, denn schon bei
mehr als 2 Display-Updates pro Sekunde wird es für den ablesenden
Menschen ohnehin unangenehm; ich würde sogar höchstens einmal pro
Sekunde updaten.
Ich pushe nochmal, da es leider immernoch nicht funzt:
Welches Spannungsniveau interpretiert der LCD-Controller als High?
Betreibe das Display mit 3.3..3.4 V und ich bin mir bei der Anleitung
etwas unsicher. Eigentlich sollte sich High und Low auf die
Versorgungsspannung beziehen, d.h. sollte passen.
Namenloser324 schrieb:> Welches Spannungsniveau interpretiert der LCD-Controller als High?
Genau zur Beantwortung solcher Fragen wurde das Datenblatt erfunden.
Dabei ist zu berücksichtigen, dass es nicht den LCD Controller gibt
sondern diverse Hersteller mit u.U. abweichenden Spezifikationen.
Was ist bei "minimal 0.9*VDD" unklar?
Georg G. schrieb:> Was ist bei "minimal 0.9*VDD" unklar?
Das es immernoch nicht geht :( Hatte gehofft, dass irgendwie zwar 3.3V
Versorgungsspannung zum Betrieb, aber doch ein anderes Level für die
Logik erwartet wird :/
Hier mal mein Code:
1
#include <stdbool.h>
2
#include <stdint.h>
3
#include "nrf_delay.h"
4
#include "boards.h"
5
#define PIN_RS 4
6
#define PIN_RW 22
7
#define PIN_EN 23
8
9
#define PIN_DB0 24
10
#define PIN_DB1 25
11
#define PIN_DB2 26
12
#define PIN_DB3 27
13
#define PIN_DB4 28
14
#define PIN_DB5 29
15
#define PIN_DB6 30
16
#define PIN_DB7 31
17
18
#define PIN_DB_OFFSET (PIN_EN+1)
19
20
void led_enable(void)
21
{
22
nrf_gpio_pin_set(PIN_EN);
23
nrf_delay_us(1);
24
nrf_gpio_pin_clear(PIN_EN);
25
}
26
27
void writeData(char instruction)
28
{
29
unsigned int pin = PIN_DB_OFFSET;
30
for(; pin <= PIN_DB7;++pin)
31
{
32
bool p = instruction & (1 << (pin - PIN_DB_OFFSET));
33
if(p == true){
34
nrf_gpio_pin_set(p);
35
}
36
else{
37
nrf_gpio_pin_clear(p);
38
}
39
}
40
41
}
42
43
void WriteIns(char instruction)
44
{
45
nrf_gpio_pin_clear(PIN_RS);
46
nrf_gpio_pin_clear(PIN_RW);
47
writeData(instruction);
48
led_enable();
49
}
50
51
void writeChar(char c)
52
{
53
nrf_gpio_pin_set(PIN_RS);
54
nrf_gpio_pin_set(PIN_RW);
55
writeData(c);
56
led_enable();
57
}
58
59
void setRangeDirOut(unsigned int start, unsigned int end)
60
{
61
int i;
62
for(i = start; i <= end; ++i){
63
nrf_gpio_cfg_output(i);
64
}
65
}
66
67
/**
68
* @brief Function for application main entry.
69
*/
70
int main(void)
71
{
72
setRangeDirOut(4,31);
73
nrf_delay_ms(20);
74
WriteIns(0x30);
75
nrf_delay_ms(5);
76
WriteIns(0x30);
77
nrf_delay_us(200);
78
WriteIns(0x30);
79
80
/* Configure board. */
81
bsp_board_leds_init();
82
WriteIns(0x08); //display off
83
84
WriteIns(0x39); //function set european chararacter set
85
WriteIns(0x06); //entry mode set increment cursor by 1 not shifting display
86
WriteIns(0x17); //Character mode and internel power on
87
WriteIns(0x01); //clear display
88
WriteIns(0x02); //return home
89
WriteIns(0x0C); //display on
90
//WriteIns(0x0F);
91
/* Toggle LEDs. */
92
while (true)
93
{
94
for (int i = 0; i < LEDS_NUMBER; i++)
95
{
96
bsp_board_led_invert(i);
97
nrf_delay_ms(500);
98
//writeChar('H');
99
}
100
}
101
}
Es passiert: nichts. Pins sind alle richtig angeschlossen, wobei ich
auch hier nochmal auf Nummer sicher gehen möchte: Die eine Spalte der
Pins auf dem LED-Display umfasst alle ungeraden Zahlen und die andere
alle geraden, ja? Nicht das es nachher an so etwas dummen liegt.
Die Pegel sind auch alle richtig, habe ich vorhin mit nem Multimeter
gemessen, saubere 3.44V bei 3.45 VDD. Enable springt auch korrekt.
An sich scheint das Display auch zu laufen, manchmal, wenn ich noch
nichts programmiert habe, geht es wenn dir Versorgungsspannung an ist
tatsächlich an und der Cursor blinkt.
Namenloser324 schrieb:> habe eine kurze Frage zur LCD-Ansteuerung:Namenloser324 schrieb:> Das Datasheet ist recht dürftig und erwähnt keine spezielle> Initialisierungssequenz.
OK, die wichtigsten Befehlsfolgen sind auf Seite 5 der Dokumentation in
C geschrieben.
Dabei gibt es offensichtlich immer wieder dieselben "erratischen"
Blöcke,
gegen die man insbesondere als "LCD-Erstkonfrontierter" anrennt:
A:) tatsächliche Portzuweisung der verwendeten MCU
B:) Definition der Steuersignale Enable, RS, RWquer
C:) Zeitschleifen
D:) und für Fortgeschrittene: (I2C Bus), 4-Bit-Modus
Anbei ein (bei mir jedenfalls lauffähiges) Assemblerprogramm für die
LCD-Initialisierung und Ausgabe von Charakters.
In der Hoffnung, dass dies weiterhilft:
(Das Proggi kann leicht auf DOG-Ms umgeschrieben werden, es ist
ursprünglich für ein Displaytech 16x2 geschrieben mit
HD44780-Controller.)
ciao
gustav
P.S:
Namenloser324 schrieb:> Gehe ich recht in der Annahme, dass trotz des Beispiels im Datasheet,> ich genau wie im Tutorial erstmal eine Initialisierungssequenz "senden"> muss?
OK,
insbesondere, wenn MCU und LCD an derselben Versorgungsspannung
angeschlossen sind, kann es sein, dass der "Power On Self Reset" des LCD
noch nicht fertig ist, wenn die MCU bereits Steuersignale sendet.
Deswegen doppelt gemoppelt....
Hallo liebe Leute,
vielen Dank für eure Hilfe :)
ES GEHT HAHAHA
Zwei Ursachen:
- Dummer Programmierfehler in der "writeChar"-Funktion. Natürlich muss
nur im Falle p == 0 der pin gecleared werden und in jedem anderen Fall
der Pin gesetzt werden. Was so alles passiert wenn das C ein wenig
einrostet^^
- Hatte die Textschreibmaske (also das Bitmuster) falsch aus nem anderen
Beispiel kopiert und daher immer den Speicher GELESEN und nicht
geschrieben hahahaha
Jetzt geht alles. Sogar mit 2.8V, hätte ich nicht gedacht, dann könnte
ich sogar mit meiner Knopfzelle alles betreiben.
Namenloser324 schrieb:> - Hatte die Textschreibmaske (also das Bitmuster) falsch aus nem anderen> Beispiel kopiert und daher immer den Speicher GELESEN und nicht> geschrieben hahahaha
Hi,
was auch oft Probs. macht, sind Proggis, die aus Schnipseln oder -
besser gesagt - sog. "include"-Dateien zusammengesetzt sind, bei denen
bestimmte Targets, Asssemblerdirektiven, Deklarationsteile etc.
stillschweigend vorausgesetzt werden.
(Das gilt auch für das vorher einkopierte Beispiel. Es fehlten z.B.
die Zuweisung von "daten" und "licht" etc. Was hiermit nachgeholt werden
soll.)
Progs. lassen sich oft nicht so easy 'mal auf eine andere ATMEL-MCU
portieren.
Auch ist bei bestimmten Targets vieles "memory mapped", so dass mit den
SRAM-typischen Befehlen mit sts und nicht in und out gearbeitet werden
muss.
Hier noch ein kleines Beispiel, das lange Kopfzerbrechen machte, bis
herausgefunden wurde, dass der 32U2 den SRAM-Bereich erst ab Adresse 100
anspricht, und nicht - wie in der Programmvorlage angegeben - bei
Adresse 60.
Habe jedenfalls keine Erfahrung, ob die C-Compiler von vorne herein
diese Probs. immer ausmerzen.
ciao
gustav
P.S.:
Habe beide Varianten einmal ins Studio 4 Version 18 geladen. Assembliert
mit no errors, obwohl der ATTINY2313 garkeinen HIGH-STACK hat.
Karl B. schrieb:> Hier noch ein kleines Beispiel, das lange Kopfzerbrechen machte, bis> herausgefunden wurde, dass der 32U2 den SRAM-Bereich erst ab Adresse 100> anspricht, und nicht - wie in der Programmvorlage angegeben - bei> Adresse 60.
Steht aber in den Appnotes der einzelnen Controller:
m32u2def.inc:
; ***** DATA MEMORY DECLARATIONS
*****************************************
.equ FLASHEND = 0x3fff ; Note: Word address
.equ IOEND = 0x00ff
.equ SRAM_START = 0x0100
.equ SRAM_SIZE = 1024
Karl B. schrieb:> nicht - wie in der Programmvorlage angegeben - bei> Adresse 60.
Hi,
bestätigt, dass man doch lieber nochmal nachchecken sollte.
Da gibt es bestimmt noch ein paar üble Bugs mehr, deren stundenlange
Fehlersuche überflüssig gemacht würde, wenn man sich angewöhnt hätte,
nochmals aktuelle Appnotes zu durchforsten.
TF schrieb:> Steht aber in den Appnotes der einzelnen Controller:
Aber auch hier nicht "blind" vertrauen, denn:
Dann taucht da in den Appnotes gelegentlich noch die Angabe "for
compatibility use" auf.
Was heißt das jetzt konkret, geht's oder nicht?
Beispiel für den ATTINY4313:
Die geremten .equ-Anweisungen "for compatibility" 'mal der Appnote
entnommen:
rs232init:
ldi temp, bdrt ;Baudrate setzen
out UBRR, temp ; .equ UBRR=UBRRL;for compatibility
ldi temp, 0x18 ;(1<<RXEN)+(1<<TXEN)
out UCR, temp ; .equ UCR=UCSRB;for compatibility
ret
senden: ;RS232-Ausgaberoutine
sbis UCSRA, UDRE ; .equ USR=UCSRA;for compatibility
rjmp senden
out UDR, temp
ret
OK,
einfach einmal ausprobieren.
Beim ATTINY2313 meldet der Assembler:
: error: Undefined symbol: UCSRA
beim 4313-er gehts fehlerfrei durch
compatibility gilt also für "Nachfolge"-Typen
ciao
gustav