i2ctools gehört zu lmsensors-Projekt.
Doku : http://www.lm-sensors.org/wiki/i2cToolsDocumentation
Btw. man i2c-tools hilft eventuell.
Auch nett : http://www.e-reflexes.de/oxy_blog/?tag=i2c-scanner
Druckbare Version
i2ctools gehört zu lmsensors-Projekt.
Doku : http://www.lm-sensors.org/wiki/i2cToolsDocumentation
Btw. man i2c-tools hilft eventuell.
Auch nett : http://www.e-reflexes.de/oxy_blog/?tag=i2c-scanner
Aber die Doku erklärt immer noch nicht so richtig warum ich keinen Zugriff auf meinen PSoC habe (also via I²C).
Bei meinem RN-Control geht das problemlos nur das Raspberry zickt bisschen. Da kommt sowohl beim lesen als auch beim schreiben der selbe Fehler obwohl das Device bei i2cdetect auftaucht.
Das mag daran liegen, dass die ursprüngliche Frage auf den PCF8574 bzw. die Verwendung der R/W-Adressen zielte und nicht auf deinen PSoC. Des Weiteren habe ich gerade den Thread von vorn bis hintern noch einmal gelesen und keine Frage dies bezüglich finden können. (Ist noch früh daher kann es auch sein, dass ich etwas übersehen habe).
Von daher kann man ein Problem nicht lösen, wenn man es nicht kennt.
Auf Seite 4 ganz oben wird es erwähnt :)
Also das Problem ist dieses (nochmal zusammengefasst):
Ich habe einen I²C Bus aus einem Raspberry Pi als Master, einem 24C128 EEPROM, einem PCF8574 und einem PSoC als I²C Slave (benutze das EzI²C Modul http://www.cypress.com/?docID=34801).
Per i2cdetect werden ALLE Geräte am Bus erkannt, aber das Schreiben und Lesen klappt nur beim PCF8574 richtig. Beim EEPROM lese ich was anderes aus als ich rein geschrieben habe und beim PSoC schlägt das Lesen und das Schreiben fehl.
Den PSoC als I²C Slave habe ich aber bereits mit einem Mega32 als Master ausprobiert und da klappte sowohl das Lesen als auch das Schreiben des Mega32 von dem PSoC problemlos.
Hier ist mal der Testcode vom Mega32:
Und vom PSoC:Code:'Mikrocontroller
$regfile = "m32def.dat"
$crystal = 16000000
$baud = 19200
'Stacks
$hwstack = 200
$swstack = 200
$framesize = 400
'TWI konfigurieren
Config Sda = Portc.1
Config Scl = Portc.0
Config Twi = 100000 'TWI Frequenz
'Adresse des PCF
Const Psocw = &H80
Const Psocr = &H81 'Adresse vom PSoC. Der PSoC hat softwareseitig die
'0x40 als 7-Bit Adresse bekommen. Mit R/W Bit ergibt
'Variablen 'dies 0x80
Dim Bitmuster As Byte
Dim Buffer As Byte
Bitmuster = 0
Buffer = 0
'I²C initialisieren
I2cinit
Do
'PSoC beschreiben
I2cstart 'TWI Startkondition
I2cwbyte Psocw
I2cwbyte 0 'Startadresse des I²C Buffers vom PSoC
I2cwbyte Bitmuster 'Daten übertragen
I2cstop
'PSoC auslesen
I2cstart
I2cwbyte Psocr
I2crbyte Buffer , Nack
Print "Wert: " ; Buffer 'Ausgabe der Daten
Incr Bitmuster 'Bitmuster um eins erhöhen
Wait 1
Loop
End
Hoffe das Problem ist dadurch etwas klarer geworden :)Code://----------------------------------------------------------------------------
// C main line
//----------------------------------------------------------------------------
#include <m8c.h> // Part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules
// Variablen
char Wert = 100;
// Funktionen
void I2C_Init(void);
void main(void)
{
M8C_EnableGInt;
LCD_Start(); // LCD Modul aktivieren
LCD_Position(0,0);
LCD_PrCString("PSoC I2C Slave");
EzI2Cs_SetRamBuffer(1, 1, (char *)&Wert); // I²C Buffer setzen, 1 Byte Größe, 1 Byte Schreib/Lesbar
I2C_Init();
while(1)
{
LCD_Position(1,0);
LCD_PrCString("Wert:");
LCD_Position(2,0);
LCD_PrHexInt(Wert);
}
}
void I2C_Init(void)
{
EzI2Cs_Start(); // I²C Modul starten
EzI2Cs_EnableInt(); // I²C Interrupts aktivieren
}
Edit:
Den PSoC betreibe ich mit 5V. Da das Raspberry Pi nur 3,3V Pegel verwendet, nutze ich die Pull-Ups vom Raspberry Pi und habe damit einen 3,3V I²C Pegel.
Laut dem Datenblatt von dem Chip
http://www.datasheetcatalog.org/data...j2lq6ps83y.pdf
reichen 2,1V für einen High Pegel aus. Es kann also auch nicht sein das er die Pegel nicht erkennt.
Hallo Daniel,
Laut I2C Spezifikation müssten es für HIGH Pegel VCC*0.7 sein. Bei 5V VCC wären das 3.5V, bei 3.3V VCC 2.31V. Die 2.1V beziehen sich demnach auf 3V VCC. Wenn du den Chip mit 5V betreibst, gilt 3.5V.
Dass manche Bauteile trotzdem noch gehen, mag Zufall sein. Du brauchst wohl einen Level Shifter für I2C oder du betriebst den PSOC auch mit 3.3V.
Erstmal danke für den Hinweis.
Wieso muss ich den für die Pegel die Betriebsspannung des Chips nehmen?
Der Bus läuft doch auf 3,3V und I²C ist doch Open Collector von daher sollte da doch die Betriebsspannung des Chips egal sein (oder habe ich da einen Denkfehler?)
Weil ich bin bisher immer von der Busspannung ausgegangen.
Ansonsten kennt jemand einen Levelshifter im DIP Gehäuse ;)? Weil das Board mit 3,3V betreiben geht (glaube ich) nicht.
So ist es.
Mindestens bedeutet, daß es auch weniger sein kann. Und wenn das Datenblatt des Chips sagt, 2,1V ist das voll in den Specs. Da die Chips erkannt werden, liegt das Problem woanders. Jetzt noch eine zweite Baustelle mit Pegelwandlern aufzumachen ist nicht zielführend.Zitat:
Laut I2C Spezifikation müssten es für HIGH Pegel VCC*0.7 sein.
MfG Klebwax
Im PSOC Datenblatt steht nur was von 2.1V für GPIO. Ob damit auch I2C gemeint ist, würde ich nicht von ausgehen. Mindestens 0.7*VCC für HIGH Pegel heisst gleich oder größer, aber nicht weniger. Wenn es mit dem Mega32 (ich nehme an unter 5V) geklappt hat und mit dem Raspberry Pi unter 3.3V nicht, dann spricht das für Pegelprobleme. Es kann natürlich auch ein Software Fehler im RasPi Code sein.
5V zu 3V Pegelwandler gibt es von AdaFruit oder Sparkfun.
Ja der Mega32 wurde mit 5V betrieben.
Im Grunde hat der PSoC nur GPIOs. Die Pins werden erst in der Software konfiguriert. Da kann man sich aussuchen wo man den I²C hinlegen will (gibt glaube ich P1.0 und 1.1 sowie 1.5 und 1.7 zur Auswahl). Von daher vermute ich das diese Spezifikationen egal für welches Protokoll/Anwendung sind.
Sicher bin ich mir da aber nicht.
Der Pegelwandler von Sparkfun eignet sich aber nicht für I²C soweit ich sehe. I²C ist bidirektional und der ist nur für eine Richtung. Oder sehe ich das falsch?
Um aber mit der SW weiterzukommen, habe aus einem Beispiel-Code aus dem Netz ein Stück zusammengeschnitten, mit dem ich auf meinem Desktop-PC vermutlich das EEPROM meines Monitors auslesen kann. Wegen der Übersichtlichkeit sind die Adressen hardcoded und ein wirkliches Schreiben habe ich nicht probiert, um den Rechner nicht zu gefärden.
Vielleicht hilftsCode:#include <linux/i2c-dev.h>
#include <stdio.h>
#include <fcntl.h>
#define NUMBYTES 20
int main() {
int file;
char filename[] = "/dev/i2c-0";
char buffer[20];
int i;
file = open(filename, O_RDWR);
if (file < 0) {
perror("i2c-test open: ");
return -1;
}
/* You can do plain i2c transactions by using read(2) and write(2) calls.
* You do not need to pass the address byte; instead, set it through
* ioctl I2C_SLAVE before you try to access the device.
*/
if (ioctl(file, I2C_SLAVE, 0x50) < 0) {
perror("i2c-test set slave address: ");
return -1;
}
buffer[0] = 0; // set read pointer in I2C slave
if(write(file, buffer, 1) != 1) {
perror("i2c-test write: ");
return -1;
}
if (read(file, buffer, NUMBYTES) != NUMBYTES) {
perror("i2c-test read: ");
return -1;
} else {
for(i = 0; i < NUMBYTES; i++) {
printf("%02x ", (unsigned char)buffer[i]);
}
printf("\nok\n");
}
return 0;
}
MfG Klebwax
Pegelwandler ist bidirektional wegen der MOSFETs. Habe mir den auch schon selber aufgebaut. Nicht schön, aber schneller aufzubauen und günstiger als ein PCA9603 oder ähnliche Wandler.
Anhang 23398
Gut.
Das Programm teste ich heute/morgen mal. Wenn das klappt ist das Problem mit dem EEPROM schon mal beiseite. Dann bleibt nur noch der PSoC.... :/
Wenn Google bei allem helfen würde, bräuchten wir kein Forum mehr. Oftmals ist es einfach nur zu spät und die zündende Idee für den passenden Suchbegriff fehlt.
Ist auch keine Frage : "Wie steuer ich bei meinem Arduino die LED an..."
Anhang 23399
MfG Klebwax
$ sudo ./i2c-test
00 ff ff ff ff ff ff 00 04 72 be 00 e7 7d 11 01 0b 14 01 03
Das geht bei mir beliebig oft.
Write bei einem EEPROM sollte so gehen:
buffer[0] = Adresspointer im EEPROM
buffer[1] = Datenbyte
..
buffer[x] = Datenbyte
write(fd, buffer, x+1)
Wieviel man auf einmal schreiben kann, hängt vom EEPROM ab. Wenn man nicht auf eine Ready wartet, sollte man vor dem nächsten read oder write etwas Pause machen.
MfG Klebwax
Also ich habs nochmal probiert und es kommt immer nur 0xff raus. Selbst nach einem Reboot ändert sich nichts.
Ich vermute stark, dass das EEPROM einen Schuss hat da du ja sagst das es bei dir funktioniert.
Ich probier das nachher auch mal mit meinem PSoC der soll sich laut Datenblatt ja wie ein EEPROM verhalten....mal schauen ob das stimmt.....
Also das I²C Problem hat sich wohl gelöst.
Ich Depp habe vergessen, dass das EEPROM eine 16-Bit Adresse hatte und beim PSoC habe ich ein Byte zuviel gesendet, da ich dachte man müsse einen Pointer setzen ab wann man das EEPROM auslesen will.
Wenn ich aber nur
i2cget -y 0 0x40
sende, statt wie vorher
i2cget -y 0 0x40 0x00
klappt es 1a.
Ja aber erstmal nur mit dem EEPROM. Den PSoC kann ich bisher nur auslesen aber mit dem Schreiben weiß ich noch nichts neues.
Da kommt immer ein Error :/
Heyho,
hab mal wieder bisschen rumgespielt und dabei ist ein Programm rausgekommen um eine DS1307 auszulesen (gar nicht gewusst das man das Ding nicht mit 3,3V betreiben kann. Habs erst gemacht und dann gewundert warum ich das Ding nicht im Bus gesehen habe..... -.-)
Code:// Compile with: gcc /Programme/DS1307.c -o /Programme/DS1307
#include <stdio.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define Buffer 7
char BCD2D(char Wert)
{
return (Wert%16 + 10 * (Wert/16));
}
int main()
{
int File;
char Device[] = "/dev/i2c-0";
char RTC = 0x68;
char Date[7];
int i;
if ((File = open("/dev/i2c-0", O_RDWR)) < 0) // I²C aktivieren
{
printf("I²C Modul kann nicht geladen werden!\n");
return -1;
}
if (ioctl(File, I2C_SLAVE, RTC) < 0) // Port und Adresse setzen
{
printf("Deviceadresse wurde nicht gefunden!\n");
exit(1);
}
Date[0] = 0; // Pointer auf Adresse 0 (Startadresse) setzen
if(write(File, Date, 1) != 1)
{
printf("Fehler beim Schreiben der Daten!\n");
return -1;
}
if (read(File, Date, Buffer) != Buffer)
{
printf("Fehler beim Lesen der Daten!\n");
return -1;
}
else
{
// Werte von BCD in Dezimal umwandeln
for(i = 0; i < Buffer; i++)
{
Date[i] = BCD2D(Date[i]);
}
printf("DS1307 Ausgabe");
printf("\n");
printf("\n");
// Uhrzeit ausgeben
printf("Stunden: %d", Date[2]);
printf("\n");
printf("Minuten: %d", Date[1]);
printf("\n");
printf("Sekunden: %d", Date[0]);
printf("\n");
// Tage ausgeben
printf("Jahr: 20%d", Date[6]);
printf("\n");
printf("Monat: %d", Date[5]);
printf("\n");
printf("Tag: %d", Date[4]);
printf("\n");
printf("Wochentag: %d", Date[3]);
printf("\n");
}
close(File);
return 0;
}
Laesst du deine i2c Funktionen im main()?
Ich hab mich gestern noch ein wenig mit C befasst (kompletter C-Anfaenger) und angefangen dass nach bestem Wissen und Gewissen in Funktionen und in separate files zu packen.
Vllt. kann ich dich ja als debug user begeistern wenn ich fertig bin :D
(bevor ich wieder erschlagen werd, ja ich bin mir sicher da gibts schon *.h und *.c files fuer, aber der Lerneffekt... ;) )
Das Programm nutze ich jetzt eh nimmer. Hab mein Raspberry Pi so eingestellt, dass es die Uhrzeit aus der DS1307 holt. Dadurch wird die RTC quasi blockiert und die Systemzeit des Pis immer aktuell.....netter kleiner Stolperstein war noch die Zeitzone....hab mich gewundert warum die Zeit dauernd zwei Stunden hinterher ging ^.^
Aber ansonsten wüsste ich bei dem Programm keinen Grund die Sachen nochmal in Funktionen zu packen.
Also ich habe eben nochmal bisl rumprobiert (diesmal mit einem anderen PSoC Board).
Das Lesen klappt auf einmal problemlos.......sogar mit dem ersten Board.....
Schreiben schlägt noch immer fehl......aber zumindest habe ich jetzt meine CapSense Tasten am Pi hängen und kann die auswerten. Bei denen brauche ich eigtl nicht schreiben ^.^
Hey,
ich wollte nur mal einen aktuellen Stand posten......
Ich habe es nun mittlerweile geschafft den PSoC als Slave zu nutzen.
Der Fehler war anscheinend die Geschwindigkeit. Mit 100k kann ich nur lesen und nicht schreiben. Aber bei 400k klappt beides (hätte ich mal früher drauf kommen können dies zu testen >.<)
Hey wo bekomm ich die includes für das I"c auf dem Pi her ??
Die sind schon auf dem Pi. Ich habe zumindest nichts installieren müssen.