Hallo zusammen, ich habe mal wieder ein interessantes Problem. Der Arduino Treiber für die SSD1306 funktioniert nicht beim MSP, weil er zu verschwenderisch mit dem Speicherplatz umgeht. Auch der Overhead ist relativ groß. Aus diesem Grund decodierte ich die übertragenen Daten bei der Übertragung eines Arduino Uno auf eine SSD1306. Die Initialisierung schicke ich jetzt über ein I2C Terminal Byte für Byte vom PC zur SSD1306. Die Zeichen-Ausgabe funktioniert performant und fehlerfrei!!! Jetzt will ich das nicht immer vom PC aus machen. Deshalb schicke ich die Daten vom MSP430 zur SSD1306. Das mache ich bei diversen Sensoren und Displays genauso. Nur antwortet die SSD1306 nicht!!! 1.Bild: MSP430 nach SSD1306 mit angeschlossenem Display. 2.Bild: I2CTerminal sendet ohne angeschlossenem Display. 3.Bild: I2CTerminal nach SSD1306 (mit angeschlossenem Display). Die Oszi Bilder sehen ähnlich aus. Nun sind Bild1 und Bild2 fast identisch (es waren zwei verschiedene Analyzer). Ich habe die Vermutung dass die SSD1306 irgendwie anders mit den Flanken umgeht als die anderen Sensoren und Komponenten. Konfiguration: - Die Adresse der SSD1306 ist 0x3C. - Die Pullups habe ich mit 12k, 3,3k 1k 470 Ohm betrieben. - Die Frequenz habe ich von 8kHz bis 110kHz betrieben. - Ich habe testweise Kondensatoren an die SDA und SCL gegen GND geschaltet und wieder weggemacht. - Ich habe verschiedene MSP430G2553 verwendet. - Ich habe das Display alleine an den Pullups betrieben. - MSP430 wird über Spy by Wire an 3.5V betrieben. - Das Terminal (USB-to-I2C Bridge) hänge ich bei Bedarf dann auch noch dran. - Das Terminal wird über einen 3.3V Low-Drop-Regler von USB versorgt. - Alternativ habe ich den MSP430 auf dem Launch Pad betrieben und das Display an Port 1.6 und 1.7 angeschlossen. Gnd und Vcc habe ich natürlich auch ans die SSD1306 angerschlossen. - Ich habe die Spannung um 0,5V bis 1,4V durch Vorschaltug von Dioden verringert, da SSD1306 nur Betriebsspannungen von 1,7v bis 3,3V verträgt. Es ist immer das gleiche Ergebnis. Das Terminal bekommt Antwort. Der MSP scheint alleine am I2C bzw. an den Pull-Ups zu hängen. Hat jemand eine Idee warum die nicht Antwortet?
:
Bearbeitet durch User
Ich sehe jetzt in den Bildern keinen Grund, warum es nicht gehen sollte. Also erstmal zur Beschaltung: D7...D3: auf GND gezogen D2+D1: verbunden -> SDA D0: ->SCL E, RW, CS: auf GND gezogen DC: auf GND gezogen -> I2C Adresse 3c RST: Pullup nach VDD (3.3V) BS: 010 für I2C Modus I2C Takt: steht bis 400kHz im Datenblatt, 100kHz sollten also gehen (ausmessen!) Rise und Fall Time: maximal 300ns (per Oszilloskop ausmessen, und zwar beide Flanken (steigend und fallend)! Bei der steigenden Flanke kann es helfen, Pullups verringern. Kabel auf das absolute Minimum reduzieren. Kein Steckbrett verwenden! Das Datenblatt zum SSD1306 hast Du? Gelesen? Verstanden? fchk
:
Bearbeitet durch User
Frank K. schrieb: > Ich sehe jetzt in den Bildern keinen Grund, warum es nicht gehen sollte. > > Also erstmal zur Beschaltung: > > D7...D3: auf GND gezogen > D2+D1: verbunden -> SDA > D0: ->SCL > E, RW, CS: auf GND gezogen > DC: auf GND gezogen -> I2C Adresse 3c > RST: Pullup nach VDD (3.3V) > > BS: 010 für I2C Modus Ich verwende das SSD1306 Modul. Das sollte kein Problem sein. Beim Terminal funktioniert alles bis 400kHz einwandfrei. > I2C Takt: steht bis 400kHz im Datenblatt, 100kHz sollten also gehen > (ausmessen!) Wie gesagt: Das habe ich alles probiert. 8kHz, ..., 83kHz, 100kHz, 110kHz > > Rise und Fall Time: maximal 300ns (ausmessen! Beide Flanken! Pullups > verringern, wenn das kritisch sein sollte) > 470 Ohm, 1K, 3,3K, 12 K habe ich getestet. Das einzige was sich änderte war der Strom. Die Flanken sind so steil, .... Das sollte nicht das Problem sein. > Das Datenblatt zum SSD1306 hast Du? Gelesen? Ja! > Verstanden? Wenn ich das wüsste! ;-) > > fchk
Andreas V. schrieb: >> >> Rise und Fall Time: maximal 300ns (ausmessen! Beide Flanken! Pullups >> verringern, wenn das kritisch sein sollte) >> > > 470 Ohm, 1K, 3,3K, 12 K habe ich getestet. Das einzige was sich änderte > war der Strom. Die Flanken sind so steil, .... Das sollte nicht das > Problem sein. Das Tastverhältnis beim MSP ist 45% zu 55%. Beim Terminal ist das anders: 50% zu 50%.
:
Bearbeitet durch User
Hallo, manche I2C Slaves mögen es absolut nicht wenn es keine sauberen Start- und Stop-Condition gibt. Vor allem wichtig sind vorhergehende Stop-Conditions um dann wieder sauber neu zu beginnen. Ich kann sie auf deinen Bilder nicht wirklich (richtig) erkennen !!! Gruss
Auf deinem ersten Bild oben sieht es aus als passen die Flanken nicht richtig. Scheinen das Timing nicht einzuhalten. Mein Aufbau mit STM32 auf Steckbrett mit 400kHz und 4,7k. Da liegt an der Datenleitung schon Eindeutig der Pegel an, bevor der nächste Takt kommt.
Ich habe da gerade von einem Bekannten gehört, der auch ein I2C SSD1306 Modul zum Laufen bringen will. Er hat mir berichtet, daß die angegebene I2C Adresse vom Hersteller nicht stimmen soll. Er mußte angeblich den Wert multiplizieren um mit dem Teil kommunizieren zu können. Es soll im Internet darüber angeblich einen Hinweis geben. Wie gesagt, dieser Hinweis ist nur anektotisch. Keine Gewähr für Genauigkeit.
:
Bearbeitet durch User
Was du gezeigt hast, sieht OK aus. Schreibe ein minimales(!) Programm, das versucht, ein Byte zu senden, und zeig es hier.
Gerhard O. schrieb: > Er mußte angeblich den Wert multiplizieren um mit dem Teil kommunizieren > zu können. Das ist das ewige Missverständnis zwischen der 7- und 8-Bit-Darstellung von I2C-Adressen. Um auf die 8-Bit-Darstellung zu gelangen, muss die in 7-Bit-Darstellung vorliegende Adresse mit zwei multipliziert werden und zum Ergebnis noch das r/w-Bit (1 = r, 0 = w) addiert werden.
Andreas V. schrieb: > Ich habe die Vermutung dass die SSD1306 irgendwie anders mit > den Flanken umgeht als die anderen Sensoren und Komponenten. Das kann ich mir auch gut vorstellen, leider zeigt dein LA diese nicht an. Dafür bräuchte man ein Oszilloskop. Wenn du keinst hast, würde es zur Not auch ein billiges DSO-138 tun. Jedenfalls darf SDA nicht nur ändern, während SCL auf Low liegt. Und genau das sieht bei Dir sehr knapp aus. Du kannst zur Not meine Arduino Klasse aus http://stefanfrings.de/esp8266/WIFI-Kit-8-OLED.zip verwenden. Die hatte ich ursprünglich für den ESP8266 geschrieben, aber inzwischen so weit angepasst, dass sie theoretisch auf jedem beliebigen Arduino funktionieren müsste. Rufus Τ. F. schrieb: > Das ist das ewige Missverständnis zwischen der 7- und 8-Bit-Darstellung > von I2C-Adressen. Den Teil hat Andreas offensichtlich richtig verstanden.
Nenn mal den genauen Typ des LCDs.
LCDs auf Glas sind sehr hochohmig (bis 1k), da kann es Probleme geben,
den SDA auf low zu ziehen, wenn der Pullup zu klein ist. Probier mal
>=10k Pullups.
An einem MC mit TTL-Pegel ist es kritischer als bei CMOS-Pegel.
Andreas V. schrieb: > Die Initialisierung schicke ich jetzt über ein I2C Terminal Byte für > Byte vom PC zur SSD1306. Die Zeichen-Ausgabe funktioniert performant und > fehlerfrei!!! Wer sendet die Zeichen zur Ausgabe? Hast du schon einmal mit dem PC initialisiert und mit dem uC Daten verschickt? Wenn ich deine Initialisierung vom PC mit der des uC vergleiche, weichen sie in Zeile 42 erheblich ab. ;-)
Peter D. schrieb: > Nenn mal den genauen Typ des LCDs. Die Info, dass es sich um ein Display mit SSD1306 handelt sollte genügen. Diese Chips werden auf das flexible Anschlusskabel montiert. > Probier mal >=10k Pullups. Ich hatte eine Anwendung die mit 12kΩ unzuverlässig lief, dann habe ich 2,2kΩ verwendet und das lief gut.
So Leuts, das war eine schwere Geburt mit trivialem Hintergrund. Danke an alle! Allein hätte ich mich wahrscheinlich verrannt! Jetzt wird wahrscheinlich jeder schreien wie kann man nur so einen Anfängerfehler machen! Es waren nicht die Flanken, die Pull Up's, die Frequenz, das Tastverhältnis, die Start/Stop Conditions, die I2C Adresse... Ich bin es einzeln durchgegangen und das stimmte alles. Ich programmierte mein MSP430 über Spy by Wire neu ohne irgenwelche I2C Funktion und machte das Board stromlos. Ich nahm mein selbst gebautes BreadBoard für MSP430 und versorgte es mit 3.3V. Als Pullups dienten die 10K Widerstände eines angeschlossenen EPROM-Moduls. Danach programmierte ich den MSP430 neu mit einfachen I2C Funktionen und debuggte es mit Spy by Wire. Auf einmal funktionierten die Ausgaben des Buchstaben A, aber die Initialisierung davor brach ab. Das brachte mich auf die Spur... Fazit: Im Prinzip war alles bis auf die Zeile 42 richtig gelaufen. Nach dem Einschalten der Spannungsversorgung wurde die Initialisierung zu früh geschickt und der grottenlahme Display war noch nicht bereit. Der antworte zwar teilweise, aber das Ding war nicht komplett initialisiert bzw. es stürzte komplett ab. Lösung: "__delay_cycles(1000000);" ist momentan meine erste Zeile im Code des Beispielprogramms nach dem Abschalten des WDT! Das dürfte ungefähr 1 Sekunde Verzögerung sein. Dann kommt die Initialisierung des Displays und das Löschen des Displayspeichers (alles Nullen). Des Weiteren brauche ich ein "__delay_cycles(10000);" nach jedem I2cSend. Die Versorgung mit stabilisiertem 3,3V Pegel trug zur Zuverlässigkeit bei. Anmerkung: So viel zum Thema ein anderer Prozesser mit mehr Leistung ist schneller! Beispiel wie es funktioniert:
1 | unsigned char ssd1306_init_sequence [29] = |
2 | { |
3 | 0xAE, 0x20, 0x0, 0xB0, 0xC8, 0x0, 0x10, 0x40, 0x81, 0x3F, 0xA1, 0xA6, 0xA8, 0x3F, 0xA4, 0xD3, 0x0, 0xD5, 0xF0, 0xD9, 0x22, 0xDA, 0x12, 0xDB, 0x20, 0x8D, 0x14, 0xAF, 0x00 |
4 | }; |
5 | unsigned char buchstabeA [7] = {0x40, 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C}; |
6 | unsigned char sendBuffer[34] = { 0x00, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45 , 0x46, 0x47}; |
7 | unsigned char goto00 [6]= {0x00,0xb0,0x21,0,0x7f}; |
8 | unsigned char clr1 [255]= {0x40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
9 | |
10 | unsigned char txAdr = 0x3C; |
11 | |
12 | int main( void ) |
13 | { |
14 | // Stop watchdog timer to prevent time out reset |
15 | WDTCTL = WDTPW + WDTHOLD; // Stop WDT |
16 | _EINT(); |
17 | |
18 | __delay_cycles(1000000); // 1 Sekunde warten |
19 | I2cSend(0x3C, ssd1306_init_sequence, 28); |
20 | __delay_cycles(10000); |
21 | I2cSend(0x3C, goto00, 5); |
22 | |
23 | I2cSend(0x3C, clr1, 255); // 255 Nullen schreiben |
24 | I2cSend(0x3C, clr1, 255); // 255 Nullen schreiben |
25 | I2cSend(0x3C, clr1, 255); // 255 Nullen schreiben |
26 | I2cSend(0x3C, clr1, 255); // 255 Nullen schreiben |
27 | I2cSend(0x3C, goto00, 5); // Adresspointer zur Adresse 0,0 |
28 | int cntChars = 0; |
29 | while(1) |
30 | { |
31 | I2cSend(0x3C, buchstabeA, 7); |
32 | cntChars++; |
33 | if(cntChars>1000) |
34 | { |
35 | WDTCTL = WDTPW + WDTHOLD; // Stop WDT |
36 | _EINT(); |
37 | cntChars = 0; |
38 | __delay_cycles(100000); |
39 | I2cSend(0x3C, goto00, 5); |
40 | I2cSend(0x3C, clr1, 255); |
41 | I2cSend(0x3C, clr1, 255); |
42 | I2cSend(0x3C, clr1, 255); |
43 | I2cSend(0x3C, clr1, 255); |
44 | I2cSend(0x3C, goto00, 5); |
45 | } |
46 | } |
47 | return 0; |
48 | } |
:
Bearbeitet durch User
Da sehe ich eine Menge falsche Pixel am Ende der dritten Reihe und Anfang der vierten Reihe.
Stefanus F. schrieb: > Da sehe ich eine Menge falsche Pixel. Jap! Das sieht aber nur so aus. Da passen die Zeilen Frequenzen der Kamera und des Displays nicht zueinander! Auf die Schnelle habe ich es mit dem neuen IPEVO nicht anders hinbekommen.
Andreas V. schrieb: > Im Prinzip war alles bis auf die Zeile 42 richtig gelaufen. ja, ja, der Andreas und der MSP: zwei Welten treffen aufeinander. ;-) Der MSP ist ein richtig gutes Ding, dass die AVR-Spielzeugprozen verdammt alt aussehen läßt.
tag 4 schrieb: > Andreas V. schrieb: >> Im Prinzip war alles bis auf die Zeile 42 richtig gelaufen. > > ja, ja, der Andreas und der MSP: zwei Welten treffen aufeinander. ;-) > > Der MSP ist ein richtig gutes Ding, dass die AVR-Spielzeugprozen > verdammt alt aussehen läßt. Der Code von Zeile 42 auf dem Terminal sieht dann wie im Bild aus! ;-)
Stefanus F. schrieb: > Du kannst zur Not meine Arduino Klasse aus > http://stefanfrings.de/esp8266/WIFI-Kit-8-OLED.zip verwenden. Die hatte > ich ursprünglich für den ESP8266 geschrieben, aber inzwischen so weit > angepasst, dass sie theoretisch auf jedem beliebigen Arduino > funktionieren müsste. Danke! Ich habe es unter Stefanus abgespeichert. Da sind sehr interessante Aspekte drinnen. Der Stil gefällt mir sehr gut. Allerdings bekomme ich das mit dem MSP430G2553 so nicht hin: - Der Code ist in C++. Ich verwende C beim MSP430G2553. Ich denke C++ ist ein bissl verschwenderischer mit der Speicherverwaltung. C reicht in diesem Fall für meine Zwecke aus. Es ist mal eine Herausforderung mit wenig Ressourcen auszukommen. - Wenn ich das so initialisiere übersteigt das den Speicherplatz des MSP430G2553. Performant ist das allemal. - Ich verwende reduzierten Zeichensatz und initialisiere nur benötigte Zeichen und schreibe nur Zeichen die angezeigt werden sollen. Das ist in der Regel so etwas wie "5,55 V" oder "45,1 %". Ich schreibe dann nur 6 Zeichen anstatt den kompletten Display-Speicher. Eventuell verdopple ich die Zeichengröße noch.
> Der Code ist in C++. Ich verwende C. Es ist genauer gesagt Arduino C++. Du kannst das ganz einfach in C umschreiben. Solange du nur ein Display ansteuern willst, verschiebst du einfach alle Objekt-Daten und Funktionen in den globalen Space. > Wenn ich das so initialisiere übersteigt das den > Speicherplatz des MSP430G2553 Komisch. Beim grössten unterstützten Display sollte der RAM Bedarf "nur" knapp über 1kB sein. Der Zeichensatz liegt ja im Flash.
Stefanus F. schrieb: > Es ist genauer gesagt Arduino C++. > > Du kannst das ganz einfach in C umschreiben. Solange du nur ein Display > ansteuern willst, verschiebst du einfach alle Objekt-Daten und > Funktionen in den globalen Space. > >> Wenn ich das so initialisiere übersteigt das den >> Speicherplatz des MSP430G2553 > > Komisch. Beim grössten unterstützten Display sollte der RAM Bedarf "nur" > knapp über 1kB sein. Der Zeichensatz liegt ja im Flash. Upps! Danke für den Hinweis! Die neue Charge des MSP430G2553 hat wohl mehr als 1 KB Flash! Das hatte ich mal mit einem MSP ausprobiert und war auf den Wert 1 KB gekommen. Da gibts laut Handbuch wohl alles zwischen 1KB und 16KB! Die anderen 10 MSP's haben wohl 16KB Flash. Das ist eine Hausnummer! Super:
1 | 654 bytes CODE memory |
2 | 383 bytes DATA memory |
3 | 15 298 bytes CONST memory |
Anhand der Bezeichnung kann ich es nicht nachvollziehen! Eine Bezeichnung wie IN20 in MSP430G2553IN20 fehlt nämlich. Es steht nur MSP430G2553 darauf. Der Verkäufer gab es jedenfalls nicht an. Anhand des Handbuches ist mir nicht klar wie man die Flashgröße herausfinden kann. Da steht nur es gibt Options. Der Link zu TI ist auch nicht hilfreich. Weiß jemand wie man das herauskriegt ohne zu probieren?
Ich hatte dem Datenblatt entnommen, dass der Chip 16kB haben sollte. Mit nur 1kB RAM wirst du bei solchen Displays nicht glücklich. Prinzipiell ist es zwar auch ohne Puffer möglich Text und rudimentäre Grafik auszugeben, aber das wird dann träge und funktional sehr eingeschränkt. Mit so kleinen Mikrocontrollern würde ich nur reine Text-Displays verwenden - wenn überhaupt.
Ihr habt mich glücklich gemacht! Die Ausgabe funktioniert wider Erwarten richtig fix. Grafikfunktionen dann wie beim Commodore C16/C64 .... Ansonsten schließe ich eine GForce RTX Grafikkarte an. ;-) Der OLED braucht im aktiven Zustand nur 500µA(Bilschirm schwarz) bzw. 6mA (bei komplett gefüllt mit 'A's) + der Strom über die Pullups bei Kommunikation. Das ist OK.
Ich meinte die o. g. Options im Bild mit diversen Flashgrößen. Wie kann ich die herausfinden? Ein Internet-Händler gibt folgende Technische Daten an:
1 | Ultra-Low Power, as low as (@2.2V): |
2 | |
3 | 0.1 µA RAM retention |
4 | 0.4 µA Standby mode (VLO) |
5 | 0.7 µA real-time clock mode |
6 | 220 µA / MIPS active |
7 | Ultra-Fast Wake-Up From Standby Mode in <1 µs |
8 | |
9 | Device Parameters |
10 | |
11 | Flash Options: 0.5 KB - 56 kB |
12 | RAM Options: 128 B - 4 kB |
13 | GPIO Options: 10, 16, 24, 32 pins |
14 | ADC Options: Slope, 10-bit SAR |
15 | Other Integrated peripherals: Analog Comparator |
Kann ich das einstellen: Flash Options: 0.5 KB - 56 kB RAM Options: 128 B - 4 kB
:
Bearbeitet durch User
Andreas V. schrieb: > Lösung: > "__delay_cycles(1000000);" Oder besser: ein I2CSend mit Fehlerbehandlung/Timeout (ist immer sinnvoll), und den ersten Befehl so lange wiederholen, bis es klappt.
Andreas V. schrieb: > Kann ich das einstellen Nein, du kannst nur einen anderen Chip mit einer anderen Nummer kaufen. Der 2553 hat immer 16KB/0,5KB. (Was Suffixe wie "IN20" bedeuten, steht im Datenblatt.)
Andreas V. schrieb: > Die neue Charge des MSP430G2553 hat wohl mehr als 1 KB Flash! Jeder 'G2553 hat 16 kB Flash, und 512 Byte RAM. Das Suffix beschreibt nur die Verpackung, d.h. das Gehäuse. IN20 ist im 20poligen DIP-Gehäuse (und damit von einem seltenen Exoten abgesehen der am besten ausgestattete MSP430 im DIP-Gehäuse). > Ich meinte die o. g. Options im Bild mit diversen Flashgrößen. Wie kann > ich die herausfinden? Das sind unterschiedliche Controller, sieh mal genau hin, die heißen 'G2553, 'G2453 ... in Deiner Tabelle sind es jeweils vier Zeilen für einen Controller, der vollständige Name steht in der Spalte ganz links, und in der Spalte ganz rechts steht die Bauform, d.h. das Gehäuse.
Ich glaube, der Andreas mag den MSP nicht. :-<<<
Clemens L. schrieb: > Andreas V. schrieb: >> Lösung: >> "__delay_cycles(1000000);" > > Oder besser: ein I2CSend mit Fehlerbehandlung/Timeout (ist immer > sinnvoll), und den ersten Befehl so lange wiederholen, bis es klappt. Das macht der MSP430 auch. Das bringt aber nichts wenn der SSD1306 abgestürzt ist.
Clemens L. schrieb: > Andreas V. schrieb: >> Kann ich das einstellen > > Nein, du kannst nur einen anderen Chip mit einer anderen Nummer kaufen. > Der 2553 hat immer 16KB/0,5KB. > (Was Suffixe wie "IN20" bedeuten, steht im Datenblatt.) Dann weiss ich nichr was ich da damals gemessen hatte :-( Alzheimer?
Rufus Τ. F. schrieb: > Das sind unterschiedliche Controller, sieh mal genau hin, die heißen > 'G2553, 'G2453 ... in Deiner Tabelle sind es jeweils vier Zeilen für > einen Controller, der vollständige Name steht in der Spalte ganz links, > und in der Spalte ganz rechts steht die Bauform, d.h. das Gehäuse. Oh nein! Im Ernst: Ich muss mir eine neue Brille kaufen!
tag 4 schrieb: > Ich glaube, der Andreas mag den MSP nicht. :-<<< Das stimmt! Ich liebe den MSP430!!!!!!!!! Er macht genau das was er soll mit minmalen Ressourcen.
Testbild mit MSP430G2553. Die Renderung der Großschrift ist noch nicht optimal.
Andreas V. schrieb: > Die Renderung der Großschrift ist noch nicht > optimal. Sieht doch gut aus, die Displays sind so winzig, dass die Pixeligkeit dabei noch erträglich ist. Wenn du das optimieren wolltest, müsstest du nochmal das 4-Fache and Flash Speicher für den Font opfern.
Wen es interessiert; meine schnelle Lösunng zur Verdopplung der Zeichengröße:
1 | void GotoXY(unsigned char x, unsigned char y) |
2 | { |
3 | unsigned char gotoXySeq[] = {0x00,0xb0,0x21,0,0x7f}; |
4 | gotoXySeq[1] = 0xb0 + y; |
5 | gotoXySeq[3] = x; |
6 | I2cSend(0x3C, gotoXySeq, 5); |
7 | } |
8 | |
9 | unsigned char EnLargeLB(unsigned char column) |
10 | { |
11 | unsigned char returnValue; |
12 | returnValue = (column & 1) + (column & 1)*2 + |
13 | (column & 2)*2 + (column & 2)*4 + |
14 | (column & 4)*4 + (column & 4)*8 + |
15 | (column & 8)*8 + (column & 8)*16 ; |
16 | return returnValue; |
17 | } |
18 | |
19 | unsigned char EnLargeHB(unsigned char column) |
20 | { |
21 | unsigned char returnValue; |
22 | returnValue = (column & 16) /16 + (column & 16) /8 + |
23 | (column & 32) /8 + (column & 32) /4 + |
24 | (column & 64) /4 + (column & 64) /2 + |
25 | (column & 128)/2 + (column & 128)/1 ; |
26 | return returnValue; |
27 | } |
28 | |
29 | void SendCharDouble(unsigned char character, unsigned char x, unsigned char y) |
30 | { |
31 | unsigned char obenlinks [7] = {0x40, 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C}; |
32 | unsigned char obenrechts [7] = {0x40, 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C}; |
33 | unsigned char untenlinks [7] = {0x40, 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C}; |
34 | unsigned char umtenrechts [7] = {0x40, 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C}; |
35 | unsigned char _x = x; |
36 | unsigned char _y = y; |
37 | int offset = 0; |
38 | |
39 | offset = character - 32; |
40 | |
41 | switch(character) |
42 | { |
43 | case '°': offset = 101; |
44 | break; |
45 | } |
46 | |
47 | obenlinks[0] = 0x40; // schreibe Daten |
48 | obenlinks[1] = EnLargeLB(oled_font6x8[offset*7+1]); |
49 | obenlinks[2] = obenlinks[1]; |
50 | obenlinks[3] = EnLargeLB(oled_font6x8[offset*7+2]); |
51 | obenlinks[4] = obenlinks[3]; |
52 | obenlinks[5] = EnLargeLB(oled_font6x8[offset*7+3]); |
53 | obenlinks[6] = obenlinks[5]; |
54 | |
55 | obenrechts[0] = 0x40; // schreibe Daten |
56 | obenrechts[1] = EnLargeLB(oled_font6x8[offset*7+4]); |
57 | obenrechts[2] = obenrechts[1]; |
58 | obenrechts[3] = EnLargeLB(oled_font6x8[offset*7+5]); |
59 | obenrechts[4] = obenrechts[3]; |
60 | obenrechts[5] = EnLargeLB(oled_font6x8[offset*7+6]); |
61 | obenrechts[6] = obenrechts[5]; |
62 | |
63 | untenlinks[0] = 0x40; // schreibe Daten |
64 | untenlinks[1] = EnLargeHB(oled_font6x8[offset*7+1]); |
65 | untenlinks[2] = untenlinks[1]; |
66 | untenlinks[3] = EnLargeHB(oled_font6x8[offset*7+2]); |
67 | untenlinks[4] = untenlinks[3]; |
68 | untenlinks[5] = EnLargeHB(oled_font6x8[offset*7+3]); |
69 | untenlinks[6] = untenlinks[5]; |
70 | |
71 | umtenrechts[0] = 0x40; // schreibe Daten |
72 | umtenrechts[1] = EnLargeHB(oled_font6x8[offset*7+4]); |
73 | umtenrechts[2] = umtenrechts[1]; |
74 | umtenrechts[3] = EnLargeHB(oled_font6x8[offset*7+5]); |
75 | umtenrechts[4] = umtenrechts[3]; |
76 | umtenrechts[5] = EnLargeHB(oled_font6x8[offset*7+6]); |
77 | umtenrechts[6] = umtenrechts[5]; |
78 | |
79 | GotoXY (_x, _y); |
80 | I2cSend(0x3C, (unsigned char*)obenlinks, 7); |
81 | I2cSend(0x3C, (unsigned char*)obenrechts, 7); |
82 | GotoXY (_x, (_y+1)); |
83 | I2cSend(0x3C, (unsigned char*)untenlinks, 7); |
84 | I2cSend(0x3C, (unsigned char*)umtenrechts, 7); |
85 | } |
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.