Hallo!
Bei einem älteren Projekt, das noch im AVR Studio 4 erstellt würde,
möchte ich ein TWI-Display (I2C-Display) einbinden.
Welche Lib kann dafür im AVR Studio benutzt werden und wo findet man die
Steuerbefehle für diese Lib, gibt es dafür dann eine Doku oder
Beispielcode?
Das Programm ist in C geschrieben und das Display hat zwei Zeilen mit
jeweils 16 Zeichen.
Vielleicht noch wichtig zu erwähnen, der Controller ist ein M328P und
das Display, das am Controller angeschlossen werden soll, hat vier
Anschlüssen:
+5V, GND, SDA, SCL.
Da es nur einen Typ I2C-Display gibt, wird Dir sicher gleich jemand die
passende LIB posten.
Das AVR-Studio ist keine Arduino IDE, die eine Lib für die eine Hardware
gibt es nicht. Schau Dir die Schaltung des Displays an und sieh nach wie
die Bauteile angesprochen werden. Wenn Du das verstanden hast, ist es
nicht schwer Dir selbst eine passende Lib zu schreiben.
Peter_Michael schrieb:> Der Sketch dort ist sehr übersichtlich:
Weil die ganzen Fähigkeiten in den Libs stecken.
Peter_Michael schrieb:> Würde es dann reichen, die <Wire.h> und die <LiquidCrystal_I2C.h> ins> AVR-Studio-Projekt zu includieren?
Nein.
Du stellst dir das zu einfach vor. Denn die beiden Libs sind
wiederum Klassen die auf dem Arduino-Framework aufbauen. Man
kann sie nicht einfach nehmen und ins eigene Projekt einbinden.
(genau genommen bräuchtest du natürlich <Wire.cpp> und
<LiquidCrystal_I2C.cpp> aus der Arduino Umgebung)
Ich habe mir mal die Mühe gemacht und eine Arduino-Klasse in
normales C zu überführen, aber ich schätze das ist nichts was
du so auf die Schnelle schaffst.
Wen man ein bisschen sucht findet man ganz nette Kleinode.
Für I2C zum Beispiel das hier im Anhang. Das ist so ziemlich
alles was man braucht um über TWI zu kommunizieren.
(für dich relevante Teile im Archiv sind twi.c und twi.h)
Peter_Michael schrieb:> Niemand mehr eine Idee dazu?
google?
LCD-"Libs" in C für AVR gibt es durchaus, und die lassen sich auch
finden.
Hier im Forum links oben die Artikelsammlung wäre ein guter Startpunkt.
Oliver
Da finde ich z.B. das hier:
https://www.mikrocontroller.net/articles/AVR_TWI#Benutzung_des_TWI
Aber nichts mit Display.
Ich kann ja mal kurz sagen, was bei dem Projekt passieren soll.
Es soll im Prinzip nur eine 10bit-Variable auf der ersten Zeile des
Displays angezeigt werden.
Normalerweise mache ich das immer über den UART, aber die RX/TX-Pins
sind belegt.
Mit der üblichen lcd.h geht es auch nicht weiter, weil keine Pins mehr
für die 4bit-Ansteuerung eines HD44780 übrig sind.
I2C/TWI ginge über einen PCF8574T zum LCD. Unter Arduino funktioniert
das auch.
Jetzt müsste man das nur unter AVR Studio angesteuert bekommen.
Vorrausgesetzt, der TWI läuft mit
#include <util/twi.h>
Wie teilt man dann dem PCF8574T-LCD die 10-Bit-Zahl zur Anzeige in
dezimaler Schreibweise mit?
Peter_Michael schrieb:> das Display hat zwei Zeilen mit> jeweils 16 Zeichen
Gibt es davon nur eine Sorte/Ausführung? Hat das Teil auch eine
Bezeichnung? Das kann alles mögliche sein ... entsprechend vielfältig
sind die Möglichkeiten.
Je genauer ein Problem beschrieben ist, desto zielführender sind die
Antworten :-)
Ich sehe gerade:
Peter_Michael schrieb:> Wie teilt man dann dem PCF8574T-LCD
Das gibt es nicht - wenn es aber ein
Peter_Michael schrieb:> HD44780
ist, dann wäre das
Beitrag "I2CLCD Library für HD44780 LCDs"
eine gute Wahl.
Hugo H. schrieb:> Je genauer ein Problem beschrieben ist, desto zielführender sind die> Antworten :-)
Schau mal in den Beitrag direkt über deinem ;)
Beitrag "Re: AVR Studio 4: TWI Display einbinden"
Da sollte alles stehen. Wenn nicht, antworte ich zeitnah auf offene
Fragen.
Das Display ist wie dort gesagt eins mit zwischengeschaltetem PCF8574T.
Peter_Michael schrieb:> Ah, wir haben uns überschnitten.
Ja :-) schau Dir den Link mal an, der passt sicher. Für HD44780 und
Port-Expander (danach googlen) gibt es viele "Librarys" - Falk ist "ein
Guter" :-)
i2c_write(0x70);//dirrectión del modulo I2C = Richtung oder Adresse?
8
lcd_init();
9
#include<util/delay.h>
10
11
12
while(1)
13
{
14
lcd_cmd(0x80);
15
lcd_msg("Welt Hallo");
16
lcd_cmd(0xC3);
17
lcd_msg("1234567890123456");
18
}
19
20
}
Statt
1
lcd_cmd(0xC3);
habe ich auch
1
lcd_cmd(0x27);
probiert, weil das verwendete 16x2 I2C-Display als Adresse 0x27 hat,
aber auch damit funktioniert es nicht.
Die beiden dazugehörenden h-Dateien sind im Anhang. So richtig klar ist
mir nicht, wo man die Adresse des Displays einträgt.
Weiter unten in LCD_I2C.h befindet sich jedenfalls folgende Sequenz:
1
voidlcd_init()
2
{
3
lcd_cmd_hf(0x30);//-----Sequence for initializing LCD
4
lcd_cmd_hf(0x30);//----- " " " "
5
lcd_cmd_hf(0x20);//----- " " " "
6
lcd_cmd(0x28);//-----Selecting 16 x 2 LCD in 4Bit mode
7
lcd_cmd(0x0C);//-----Display ON Cursor OFF
8
lcd_cmd(0x01);//-----Clear display
9
lcd_cmd(0x06);//-----Cursor Auto Increment
10
lcd_cmd(0x80);//-----1st line 1st location of LCD
11
}
Kann man daraus ableiten, welche I2C-Adresse das Display haben muss,
wenn man den Code so verwendet, wie er ist?
Hast Du ein Datenblatt vom verwendeten Display?
Wenn es ein PCF8574 oder die A Version ist: siehe Anhang
Ich vermute Ardu Dingens schiebt die Adresse durch das R/W Bit noch eine
Stelle nach links.
Also für die nicht A Version muß 0x4X gesendet werden.
Peter_Michael schrieb:> Kann man daraus ableiten, welche I2C-Adresse das Display haben muss,> wenn man den Code so verwendet, wie er ist?
Nein. Die Adresse muß in den lcd-Funktionen stecken, die die gezeigten
Kommandos in TWI umsetzten.
Oliver
pegel schrieb:> Wenn es ein PCF8574 oder die A Version ist: siehe Anhang
Danke Pegel! Ich hole mal die Lupe raus.
Der IC ist ein PCF8574T. Auf dem Modul sind drei Lötbrücken, darunter
steht
A0 A1 A2.
pegel schrieb:> Also für die nicht A Version muß 0x4X gesendet werden.
Muss man dann hier
Peter_Michael schrieb:> Der IC ist ein PCF8574T. Auf dem Modul sind drei Lötbrücken, darunter> steht> A0 A1 A2.
Zusatzinfo, die drei Lötbrücken sind offen. Das ist sicher wichtig zu
wissen.
Peter_Michael schrieb:> Unter Arduino läuft das Display problemlos.> LiquidCrystal_I2C lcd(0x27,16,2);
weil A0 bis A7 offen sind = high
Basis Adresse ist also 0x20 und A0-A2 offen +7 also 0x27
Aber das ist Arduino zählweise! (ohne R/W bit 0)
unter Atmel Studio wird aber ohne shift right gearbeitet
also Basis 0x40 und weil A0 bis A7 offen sind = high also 0x4E
der Code müsste also so laufen
Peter_Michael schrieb:> i2c_write(0x4E); //dirrectión del modulo I2C = Richtung oder Adresse?
switch(address<<1) {
case 0x40:
case 0x42:
case 0x44:
case 0x46:
case 0x48:
case 0x4A:
case 0x4C:
case 0x4E:
#ifdef I2C_TASTATUR_8574
i2c_test_flags|=(1<<I2C_TASTATUR_8574);
_i2c_key=' ';
i2c_tastatur_address=(address);
#endif // #ifdef I2C_TASTATUR_8574
DEBUG_PRINTLN(F("PCF8574 Tastatur"));
break;
case 0x70:
case 0x72:
case 0x74:
case 0x76:
case 0x78:
//#pragma message"I2C SCAN: 0x78 -> I2C_OLED ||
I2C_TASTATUR_8574A"
case 0x7A:
case 0x7C:
case 0x7E:
also ist bewiesen das dein PCF ein 8574 ohne a ist und das T für
irgendwas gehäusemäßiges steht, Plastic vermute ich
Danke Joachim!
Wenn ich in der Zeile mit den drei *** einfach nur die Adresse in von
0x70 in 0x4E tausche, wird auf dem Display leider immer noch nichts
angezeigt.
Peter_Michael schrieb:> Kann es sein, dass in den beiden h-Dateien auch noch jede Menge Adressen> von Hand geändert werden müssen?
copy&paste-Programiererei hat nunmal Grenzen, die du einfach akzeptieren
musst.
Du hast zwei Möglichkeiten:
a) verstehen, was das LCD und die Software macht, und es dann zum laufen
zu bringen
b) eine andere Copy&Paste-Quelle suchen und ausprobieren. Danach weiter
mit a) oder b)
Oliver
Mir ist auch noch etwas anderes aufgefallen.
Unter dem Video selber
https://www.youtube.com/watch?v=Uhq3Hp_P2xQ
hat ein gewisser Bad Behaviour vor 1 Monat gepostet:
"Hi. Im trying to use this library but it doesnt work. It get stucked in
the lcd_init program when it calls lcd_cmd_hf(0x30) (twice)"
Eventuell könnte es also noch andere Probleme mit dem Code geben.
;)
Oliver S. schrieb:> Du hast zwei Möglichkeiten:> a) verstehen, was das LCD und die Software macht, und es dann zum laufen> zu bringen> b) eine andere Copy&Paste-Quelle suchen und ausprobieren. Danach weiter> mit a) oder b)
Oliver
Du könntest aber einfach auch mal dein komplettes main Programm hier
zeigen. Ich sehe zum Beispiel nicht wo du i2c.h und lcd_i2c.h
inkludierst. Zusätzlich wäre der Compiler und Linkeroutput noch von
Interesse.
Generell Code in Header Files ist zwar ok aber zumindest in c nicht so
toll. In den Header Files fehlen auch include guards.
Peter_Michael schrieb:> Eventuell könnte es also noch andere Probleme mit dem Code geben.
Hmm.
Ich habe leider keine Atmel Hardware mehr, aber findest Du nicht es wird
Zeit die paar Befehle in den Libs zu entschlüsseln?
Am Besten als Kommentare in die Libs schreiben, dann sollte die Logik
dahinter erkennbar sein.
Noch etwas: wenn es in der Simulation funktioniert und im echten Leben
nicht, könnte es daran liegen, dass das Display ein gewisses Timing
braucht, die Simulation wohl nicht.
pegel schrieb:> es wird> Zeit die paar Befehle in den Libs zu entschlüsseln?
Das ging mir heute morgen auch durch den Kopf.
> könnte es daran liegen, dass das Display ein gewisses Timing> braucht, die Simulation wohl nicht.
Interessanter Ansatz. Im einfachsten Fall könnte man vielleicht einfach
die Div/8-Fuse setzen und schauen, was passiert.
Zu den Libs:
while(!(TWCR&(1<<TWINT)));//check for start condition
17
18
}
19
//I2C stop condition
20
voidi2c_write(charx){//Cpn esta funcion se escribe en el bus de TWDR
21
TWDR=x;//Move value to I2C
22
TWCR=(1<<TWINT)|(1<<TWEN);//Enable I2C and clear interrupt
23
while(!(TWCR&(1<<TWINT)));
24
}
25
26
chari2c_read(){
27
TWCR=(1<<TWEN)|(1<<TWINT);//Enable I2C and clear interrupt
28
while(!(TWCR&(1<<TWINT)));//Read successful with all data received in TWDR
29
returnTWDR;
30
}
In dieser Lib hier springt mir nichts Verdächtiges ins Auge.
Abgesehen von
> #define F_CPU 8000000UL
und
> TWBR = 0x62; // Baud rate is set by calculating
offensichtlich nichts timing-Relevantes.
Und nichts, was mit der I2C-Adresse des Display-Treiber-ICs zu tun hat.
(man darf mich gerne korrigieren, wenn ich falsch liege)
Wie auf Seite 46 zu sehen, muss das Delay zwischen die gesendeten Bytes.
15ms, 5ms, >100µs bzw 1ms.
Peter_Michael schrieb:> Im einfachsten Fall könnte man vielleicht einfach> die Div/8-Fuse
Reicht nicht. Es braucht Millisekunden.
So lahm ist der Atmel nicht.
Im einfachsten Fall ein ms-Delay nutzen.