DOGM132 + SPI an Mega16

Gast #964959
Lesenswert?

Hallo,
Ich habe mir vor Kurzem ein DOGM132 Grafik-Display geholt und scheitere 
an der Ansteuerung.
Ich habe schon ein paar Texte hier über das Display gelesen, aber keiner 
hat wirklich etwas gebracht.
Die Kondensatoren in der Schaltung sind 1µF, wie im Datenblatt.
Der ATmega32 arbeitet mit 5V, daher die Spannungsteiler.
CS,MOSI,SCK sind an den SPI-Pins und LCD_reset & RAMSEL sind an PORTD.

Anbei ist der C-Code & ein Bild der Beschaltung (die Jumper sind 
natürlich übergelötet, JTAG ist aus).
Momentan kann ich die nicht genauer nachprüfen. Die Hardware habe ich 
schonmal flüchtig geprüft (auf lötfehler) und die schien i.O. zu sein.
Ich rufe dann im Code einfach nur dogm_init(); auf und erwarte, dass 
alles Kurz an & wieder aus geht - es passiert aber nichts! (Der 
Prozessor macht noch anderes, woran ich merke dass der Prozessor 
funktioniert und die Funktion auch aufgerufen wird...)
Eigentlich habe ich mit Programmieren, Elektronik u.s.w. schon etwas 
Erfahrung, aber momentan komme ich mit dem Display einfach nicht weiter 
und hoffe hier auf Hilfe...
1
HEADER: DOGM.H
2

3

4

5
#ifndef DOGM_H
6
#define DOGM_H
7

8
#include <avr\io.h>
9
#include <util\delay.h>
10

11
#define DOGM_RESET_PORT PORTD 
12
#define DOGM_RESET_DIR DDRD 
13
#define DOGM_RESET_BIT 3 
14

15
#define DOGM_RAMSEL_PORT PORTD 
16
#define DOGM_RAMSEL_DIR DDRD 
17
#define DOGM_RAMSEL_BIT 4 
18

19
#define DOGM_INIT_BYTES 14
20

21
void dogm_init(void);
22

23
void dogm_adress(uint8_t ptr);
24

25
void dogm_writedata(uint8_t data);
26

27
void dogm_page(uint8_t page);
28

29
void dogm_all(uint8_t onoff);
30

31
#endif
32

33

34

35

36
SOURCE: DOGM.C
37

38

39

40

41
#include "dogm.h"
42

43
const uint8_t dogm_init_data[DOGM_INIT_BYTES] = {0x40,0xA1,0xC0,0xA6,0xA2,0x2F,0xF8,0x00,0x23,0x81,0x1F,0xAC,0x00,0xAF};
44

45
inline void dogm_reset_lo(void) {
46
  DOGM_RESET_PORT &= ~(1 << DOGM_RESET_BIT);
47
}
48

49
inline void dogm_reset_hi(void) {
50
  DOGM_RESET_PORT |= (1 << DOGM_RESET_BIT);
51
}
52

53
inline void dogm_ramsel_lo(void) {
54
  DOGM_RAMSEL_PORT &= ~(1 << DOGM_RAMSEL_BIT);
55
}
56

57
inline void dogm_ramsel_hi(void) {
58
  DOGM_RAMSEL_PORT |= (1 << DOGM_RAMSEL_BIT);
59
}
60

61
inline void dogm_cs_hi(void) {
62
  PORTB |= (1 << 4);
63
}
64

65
inline void dogm_cs_lo(void) {
66
  PORTB &= ~(1 << 4);
67
}
68

69
void dogm_spi_init(void) {
70
  DDRB |= (1<<PB4) | (1<<PB5) | (1<<PB7);
71

72
  dogm_cs_hi();
73

74
  SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0);
75

76
    uint8_t dummy = (SPSR); // clear status, nie verkehrt...
77
  dummy=dummy;
78

79
}
80

81
void dogm_spi_transmit(uint8_t cData) {
82
  /* Start transmission */
83
  dogm_cs_lo();
84

85
  SPDR = cData;
86
  /* Wait for transmission complete */
87
  while(!(SPSR & (1<<SPIF)));
88

89
  dogm_cs_hi();
90
}
91

92
void dogm_all(uint8_t onoff) {
93
  dogm_ramsel_lo();
94

95
  dogm_spi_transmit(0b10100100 | onoff);
96
}
97

98
void dogm_init(void) {
99
  DOGM_RESET_DIR |= (1 << DOGM_RESET_BIT);
100
  DOGM_RAMSEL_DIR |= (1 << DOGM_RAMSEL_BIT);
101

102
  dogm_spi_init();
103

104
  dogm_reset_lo();
105

106
    dogm_ramsel_lo();
107

108
    _delay_ms(50);
109
    dogm_cs_lo();
110

111
  dogm_reset_hi();
112

113
  _delay_us(1000);
114

115
  uint8_t i;
116
  for (i=0; i < DOGM_INIT_BYTES; ++i) {
117
    dogm_spi_transmit(dogm_init_data[i]);
118
  }
119
  _delay_us(1000);
120

121
  dogm_all(1);
122

123
  _delay_ms(500);
124

125
  dogm_all(0);
126

127
  _delay_ms(500);
128
/*
129
  dogm_page(0);
130
  dogm_adress(0);
131
  for(i=0;i<132;++i) {
132
    dogm_writedata(170);
133
  }
134
*/
135
}
136

137

138

139
void dogm_adress(uint8_t ptr) {
140
  dogm_ramsel_lo();
141

142
  dogm_spi_transmit(0b0001 | ((ptr >> 4) & 0b00001111));
143
  dogm_spi_transmit(0b0000 | (ptr & 0b00001111));
144
}
145

146
void dogm_page(uint8_t page) {
147
  dogm_ramsel_lo();
148

149
  dogm_spi_transmit(0b1011 | (page & 0b00001111));
150
}
151

152
void dogm_writedata(uint8_t data) {
153
  dogm_ramsel_hi();
154

155
  dogm_spi_transmit(data);
156
}

MfG Alex
Angehängte Dateien:
Gast #965242
Lesenswert?

Ich habe gerade gesehen, dass einer der Spannungsteiler-Widerstände 
nicht richtig gelötet war. Kann das Display davon schaden genommen 
haben?
Das Display hat vom Mega16 die 5V vom Pin über 10kOhm auf Reset oder A0 
bekommen :-/.

MfG Alex
Gast #965744
Lesenswert?

Das Problem habe ich jetzt gelöst. Die Buchse in die ich das Display 
gesteckt  hatte, hielt nicht richtig und hat nicht alle Kontakte korrekt 
hergestellt.
Jetzt scheint das Display zu laufen :-).
MfG Alex
#965800
Lesenswert?

Ich spiele gerade mit einem DOGM128 herum.
Das müsste ähnlich genug sein.
Das Display habe ich auf einer Adapter-Platine sitzen die auf meinem 
Controller-Board steckt.

Spannungsteiler an Reset und Select sind nicht so geschickt weil die ja 
low-aktiv sind und somit aktiviert werden, wenn der Controller durch den 
Reset läuft, etwa beim Programmieren.
Das habe ich mit einem digital-Transistor und einem Pullup-Widerstand 
gelöst, dann ist zwar die Polarität für die Software anders herum, macht 
aber nichts.

Ein Teiler 10k/10k macht auch etwas knappe Pegel.
Ich benutze 4k7/6k8, betreibe das Display aber auch "nur" mit 3,0V.

In meinem Aufbau dauert ein Flankenwechsel mit diesen Spannungs-Teilern 
etwa 15 ns mit einem FET als Level-Shifter kam ich nur auf 12 ns runter.

Die wichtigste Erkenntnis bisher war aber, dass der SPI-Takt während der 
Initialisierung maximal 500 kHz betragen darf.
Bei 16 MHz Takt meines AT90CAN32 setze ich vor dem Display-Init SPR1 und 
kann nach dem Init das wieder löschen und somit den SPI mit 4 MHz laufen 
lassen.

Ausserdem setze ich in SPCR noch CPHA und CPOL.
Angehängte Dateien:
Gast #966328
Lesenswert?

@Rudolph R.
Ich erkenne den Nachteil der Spannungsteiler nicht so richtig...
Sobald das Display benutzt wird, Resete ich es ja und beim Schreiben 
nutzte ich CS. Vorher kann an den Pins also passieren was will...
Die Spannungsteiler teilen das Signal auf ca. 2,3V runter... 
funktionieren tut es. Wenn ich mehrere von den Dingern baue, dann nehme 
ich wirklich andere Spannungsteiler, aber für meinen Erstversuch reicht 
es mir ersteinmal.
Mein Prozessor hat einen 16 Mhz Quarz. Zum Testen habe ich SPI mal auf 8 
Mhz gestellt und es funktioniert (auch beim Init).
Wie kommst du darauf, dass man nur 500kHz nutzen sollte?
Das ist mein erstes Projekt wo ich SPI nutze und beim Durchlesen dachte 
ich mir auch ich müsste CPOL & CPHA nutzen, da es hier aber alle ohne 
machen, dachte ich es wäre ohne richtig... Ich habs jetzt wieder rein 
getan :-).

MfG Alex
#966595
Lesenswert?

Alex wrote:
> @Rudolph R.
> Ich erkenne den Nachteil der Spannungsteiler nicht so richtig...

Wie gesagt, das trifft nur Select und Reset und ist eher theoretisch.
Zumal die Daten ja nur in Richtung Display gehen.

> Die Spannungsteiler teilen das Signal auf ca. 2,3V runter...

Dann ist Deine Versorgung nicht stabil auf 5V?
Und das meinte ich damit, dass die Pegel etwas schlapp wären.

> funktionieren tut es.

Das habe ich auch nicht bestritten.
Gerade die Kombination mit Reset ist eigentlich wieder gut.

Man kann auf diese Art ja auch andere Komponenten wie SD-Karten 
anschliessen.
Mit einem Spannungs-Teiler auf dem Select sollte man dann aber besser 
keine Karte im Sockel haben, wenn man den Controller programmieren 
möchte.

> Mein Prozessor hat einen 16 Mhz Quarz. Zum Testen habe ich SPI mal auf 8
> Mhz gestellt und es funktioniert (auch beim Init).
> Wie kommst du darauf, dass man nur 500kHz nutzen sollte?

Weil das eben genau die Erfahrung ist die wir mit dem DOGM128S-6 gemacht 
haben.
Hmm, ich habe die Takt-Reduzierung während der Initialisierung gerade 
mal aus meinem Code rausgenommen - läuft doch.
Gleiche Plattform wie vorher allerdings anderer Code, da werde ich dem 
Arbeitskollegen der das zuerst in Betrieb genommen hat wohl mal eine 
EMail schicken müssen, dass er doch nochmal sein Programm prüfen sollte. 
:-)

> Das ist mein erstes Projekt wo ich SPI nutze und beim Durchlesen dachte
> ich mir auch ich müsste CPOL & CPHA nutzen, da es hier aber alle ohne
> machen, dachte ich es wäre ohne richtig... Ich habs jetzt wieder rein
> getan :-).

Mir kommt dieses Setup vor allem entgegen weil der 8-Kanal DAC den ich 
auf dem Board noch drauf habe das auch braucht. :-)
#966661
Lesenswert?

Okay, ob das Initialisieren bei 4 MHz klappte oder nicht,
war jetzt in meinem Code von der Optimierungs-Stufe abhängig.

Die Zeit zwischen Reset-loslassen und dem Übertragen der Daten war wohl 
zu knapp, ich verwende im ganzen Code kein einziges delay().
Die Zeile für den Reset habe ich jetzt einfach aus der display_init() 
genommen und in main() vor can_init() gesetzt, das gibt dem Display auch 
ohne delay() genug Zeit aus dem Reset zu kommen.
Gast #966717
Lesenswert?

Im Datenblatt steht, dass es ein bisschen Zeit braucht bis man schreiben 
kan (<1ms stand da Wimre). Ich hab jetzt ein 1000µs Delay nach dem Reset 
drinnen. Alle anderen Delays habe ich raus genommen und es läuft noch 
mit 8 Mhz. :)
CS nutze ich weiterhin.


MfG Alex
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren