Hallo zusammen,
ich habe einen SSM2603 Audio-Codec an einem Linux-System und möchte den
nun gerne über I²C konfigurieren.
Über I²C-Tools bekomme ich folgende Ausgabe
Jetzt habe ich mir ein Programm geschrieben um mir die Registerinhalte
des Chips ausgeben zu lassen:
1
#include <string.h>
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <unistd.h>
5
#include <linux/i2c-dev.h>
6
#include <sys/ioctl.h>
7
#include <sys/types.h>
8
#include <sys/stat.h>
9
#include <fcntl.h>
10
11
int main()
12
{
13
int Counter = 0;
14
int Bus_File;
15
int Address = 0x1a;
16
char *Bus = "/dev/i2c-0";
17
char Buffer[10] = {0};
18
19
if ((Bus_File = open(Bus, O_RDWR)) < 0)
20
{
21
printf("Failed to open the i2c bus");
22
exit(1);
23
}
24
25
if (ioctl(Bus_File, I2C_SLAVE, Address) < 0)
26
{
27
printf("Failed to acquire bus access and/or talk to slave.\n");
28
exit(1);
29
}
30
31
for(Counter = 0; Counter < 9; Counter++)
32
{
33
Buffer[0] = Counter;
34
if (write(Bus_File, Buffer, 1) != 1)
35
{
36
printf("Failed to write to the i2c bus.\n");
37
}
38
39
if (read(Bus_File, Buffer, 1) != 1)
40
{
41
printf("Failed to read from the i2c bus.\n");
42
}
43
else
44
{
45
printf("Data %i %i\n", Counter, Buffer[0]);
46
}
47
}
48
49
return 0;
50
}
Beim starten des Programmes bekomme ich jetzt aber nur
Data 0 151
Data 1 151
Data 2 151
Data 3 151
Data 4 151
Data 5 151
Data 6 151
Data 7 151
Data 8 151
ausgegeben. Der Wert 151 ist dabei der Defaultwert des 1. Registers,
sprich ich lese wohl nur das 1. Register aus.
Aber warum?
Danke für die Hilfe!
Daniel K. schrieb:> ich lese wohl nur das 1. Register aus.> Aber warum?
Laut Datenblatt will der SSM2603 beim Lesen ein "repeated start" haben
(Start-Bit ohne vorheriges Stop-Bit).
Mit normalen write()/read()-Aufrufen ist das nicht möglich; du brauchst
ioctl(I2C_RDWR).
Normalerweise sollte zwischen dem Write der Registernummer und dem Lesen
keine Stop-Condition sein, nur ein neues Start. Zu der simplen
read-write-API finde ich keine Doku, die beschreibt ob/wie sie das mit
Start/Stop eigentlich macht. Versuch mal die Beispiele mit den
I2C_RDWR-ioctl, die sind explizit für sowas ausgelegt und man kann per
Flags kontrollieren, was passiert.
Ist auch nicht viel komplizierter, hier ein Beispiel für Lesen von zwei
Bytes:
Danke für die Info :)
Genau sowas hatte ich gesucht. Ich werde es mir mal durchlesen und
testen.
Edit: Hat vielleicht jemand einen Link zu einer Doku zur Hand?
Finde auf die Schnelle nichts.
Ich habe aus den Analog-Devices Modulen einen Alsa-SoC-Plattform Treiber
für das Zybo zusammengesetzt. Das funktioniert recht gut inklusive
alsamixer-Einbindung. Richtig aufgeräumt und getestet ist es aber noch
nicht.
https://github.com/noonien-d/linux-Digilent-Dev/tree/zybo-audio
noonien schrieb:> Ich habe aus den Analog-Devices Modulen einen Alsa-SoC-Plattform Treiber> für das Zybo zusammengesetzt. Das funktioniert recht gut inklusive> alsamixer-Einbindung. Richtig aufgeräumt und getestet ist es aber noch> nicht.>> https://github.com/noonien-d/linux-Digilent-Dev/tree/zybo-audio
Hallo,
wo finde ich den den?
Weil das Board für das ich das machen möchte ist auch ein Zybo :)
struct i2c_rdwr_ioctl_data Data = { I2C_Nachricht, 2 };
44
45
ioctl(fd, I2C_RDWR, &Data);
46
47
printf("LSB: %i\n", Buffer[0]);
48
printf("MSB: %i\n", Buffer[1]);
49
return 1;
50
}
Die Ausgabe sieht auch besser aus, nur bekomme ich jetzt folgendes
ausgegeben:
1
LSB: 151
2
MSB: 0
3
-----
4
LSB: 0
5
MSB: 151
6
-----
7
LSB: 151
8
MSB: 0
9
-----
10
LSB: 0
11
MSB: 121
12
-----
13
LSB: 121
14
MSB: 0
15
-----
16
LSB: 0
17
MSB: 121
18
-----
19
LSB: 121
20
MSB: 0
21
-----
22
LSB: 0
23
MSB: 10
24
-----
25
LSB: 10
26
MSB: 0
27
-----
Das ist auch nicht ganz richtig. Warum tauscht er die Werte?
Normalerweise müssen die Werte ja immer an der selben Stelle stehen.
Edit:
Fehler gefunden. Musste die Adresse ein Bit schieben - hab ich im
Protokoll übersehen.