Hallo zusammen, ich bin grad dabei einen RGB-Sensor über I2C mit einem PIC18F45K20 auszulesen. Anmerkung: erstes uC-Projekt... Studienarbeit Hardware ist fertig, ich sitz an der Software. Der Sensor sitzt als Slave mit der Adresse 0x29 am I2C-Bus. Problem ist, ich bekomm kein ACK vom Sensor. würdest ihr euch das bitte mal ansehen? bin kurz vor dem Verzweifeln... an den Variablendeklarationen tüftel ich noch, das ist nicht das Thema im Moment. Ich befürchte, ich mach was falsch beim Initialisieren des Sensors... Ich schreib in den SSPBUF erst das Register, in das geschrieben werden soll und dann den Wert. liegt es daran oder mach ich was anderes falsch? Zum auslesen: wie geb ich dem Sensor die Information, welches Register er auslesen soll? Das auslesen erfolgt zweistufig pro Farbe (RGB und Clear), beide 8-bit Werte werden anschließend verknüpft. Vielen Dank schon mal für eure Hilfe! Viele Grüße, Thomas /** C O N F I G U R A T I O N B I T S ******************************/ #pragma config FOSC = INTIO67, FCMEN = OFF, IESO = OFF // CONFIG1H #pragma config PWRT = OFF, BOREN = SBORDIS, BORV = 30 // CONFIG2L #pragma config WDTEN = OFF, WDTPS = 32768 // CONFIG2H #pragma config MCLRE = OFF, LPT1OSC = OFF, PBADEN = ON, CCP2MX = PORTC // CONFIG3H #pragma config STVREN = ON, LVP = OFF, XINST = OFF // CONFIG4L #pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF // CONFIG5L #pragma config CPB = OFF, CPD = OFF // CONFIG5H #pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF // CONFIG6L #pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF // CONFIG6H #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF // CONFIG7L #pragma config EBTRB = OFF // CONFIG7H /** I N C L U D E S **************************************************/ #include <xc.h> #define I2C_V1 // Erst das Makro für I2C setzten, #include <plib.h> // dann die Headerdatei einbinden! Hier wird die i2c.h eingebunden. #include "i2cprog.h" /** D E C L A R A T I O N S *******************************************/ volatile float R; volatile float G; volatile float B; double X; //volatile float X; volatile float Y; volatile float Z; volatile float x; volatile float y; volatile float n; volatile float Illu; volatile float CCT; unsigned int clear_low; unsigned int clear_high; unsigned int clear; volatile float red_low; volatile float red_high; volatile float red; volatile float green_low; volatile float green_high; volatile float green; volatile float blue_low; volatile float blue_high; volatile float blue; void main (void) { // I/O Ports konfigurieren //PORTC = 0b00000000; // Alle Pins des Port C auf low schalten --> output LATA = 0; LATB = 0; LATC = 0; LATD = 0; //////////////////////////////////////////////////////////////////////// ////////////////// PIN IO Config ////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// // TRISA Pins. TRISA = 0; // All pins output //TRISB = 0b11111111; //TRISC Pins. Set SDA and SCL as inputs. Necessary for I2C mode --> PORTC ist Input TRISC = 0b00011000; //TRISD = 0b11111111; // PORTB-D bits 7:0 are all inputs (1) //SSPCON1 SSPCON1 = 0b00101000; // SDA+SCL als serielle Port Pins schalten (Bit 5) Hardware Master Mode einstellen (Bit 3-0) //Konfigurationsregister setzen //SSPADD SSPADD = 0b00011001; // Baud Rate einstellen im Master Mode SSPAD = ( 16MHz / 4*100kHz ) - 1 = 39 //SSPSTAT SSPSTATbits.SMP = 1; // Disable slew rate control in sspstat, for Standard Speed mode. (100 kHz) //SSPCON2 //SSPCON2bits.SEN = 1; // Start enable bit gesetzt - start condition timing for transmitting //SSPCON2bits.RCEN = 1; // Receive Mode anschalten //Sensor initialisieren //Startcondition ausführen - Bus übernehmen SSPCON2bits.SEN = 1; //initiate Start condition on SDA+SCL - Senden while (PIR1bits.SSPIF == 0); // Bus übernommen? (SSPIF = 1) PIR1bits.SSPIF = 0; //SSPIF zurücksetzen //TCS37725 Slave address schreiben - 0x29 - 0101001 SSPBUF = 0b01010010; //7 bit-Adresse + LSB=0 while (PIR1bits.SSPIF == 0); PIR1bits.SSPIF = 0; //TCS37725 Kontrollregister schreiben - 1000 0000 - Command Register für schreiben aktivieren - Type repeated byte protocol transaction SSPBUF = 0x80; while (PIR1bits.SSPIF == 0); PIR1bits.SSPIF = 0; //TCS37725 Enableregister schreiben - 0000 0011 - Sensor - Enable register - power on SSPBUF = 0b00000000 & 0b00000011; while (PIR1bits.SSPIF == 0); PIR1bits.SSPIF = 0; //TCS37725 RGBC Time Register schreiben SSPBUF = 0b00000001 & 0b00000000; while (PIR1bits.SSPIF == 0); PIR1bits.SSPIF = 0; //TCS37725 Control Register schreiben - RGBC Gain control SSPBUF = 0x0F & 0b00000011; while (PIR1bits.SSPIF == 0); PIR1bits.SSPIF = 0; //RGBC time register schreiben - 0x00 - 256 Integration cycles //SSPBUF = 0b00000000; //while (PIR1bits.SSPIF == 0); //PIR1bits.SSPIF = 0; //Stopcondition setzen SSPCON2bits.PEN = 1; // Initiate Stop condition on SDA and SCL pins. //Empfangsmodus //Daten vom Sensor empfangen //Startcondition ausführen - Bus übernehmen SSPCON2bits.SEN = 1; //initiate Start condition on SDA+SCL - Senden while (PIR1bits.SSPIF == 0); // Bus übernommen? (SSPIF = 1) PIR1bits.SSPIF = 0; //SSPIF zurücksetzen //Slave address schreiben - 0x29 / TCS37725 SSPBUF = 0b01010011; //7 bit-Adresse=0101001 + LSB=1 (Lesen) while (PIR1bits.SSPIF == 0); PIR1bits.SSPIF = 0; SSPCON2bits.RCEN = 1; // Receive Mode einschalten clear_low = SSPBUF; // clear lesen SSPCON2bits.ACKEN = 1; // ACK senden SSPCON2bits.RCEN = 1; clear_high = SSPBUF; SSPCON2bits.ACKEN = 1; // ACK senden clear = clear_high*256 + clear_low; // beide clear-Variablen zusammenfassen ...... }
kurze Frage, bist du ganz sicher, dass der Hardware richtig funktioniert? Viele vergessen immer den Pull-Up Widerstand.
danke für den Tipp, aber die Pull-ups sind drin für SDA, SCL und INT. Gruß, Thomas
Und du glaubst das dir ab dieser Stelle die Daten einfach so innerhalb kürzester Zeit zugeflogen kommen? Schau noch mal ins Datenblatt. > SSPCON2bits.RCEN = 1; // Receive Mode einschalten > > clear_low = SSPBUF; // clear lesen > SSPCON2bits.ACKEN = 1; // ACK senden > SSPCON2bits.RCEN = 1; > clear_high = SSPBUF;
Nein, das war ja Teil meiner Frage. Das Datenblatt ist hierzu leider nicht sehr aussagefreudig... Genau hier bleibt er jedesmal hängen: //Slave address schreiben - 0x29 / TCS37725 SSPBUF = 0b01010011; //7 bit-Adresse=0101001 + LSB=1 (Lesen) while (PIR1bits.SSPIF == 0); PIR1bits.SSPIF = 0; also genau vor der Empfangssequenz... hier steck ich fest. Hab da leider eher wenig Erfahrung, daher frag ich ja... Danke, Thomas
Okay, danke schon mal vorab an alle, ich glaub ich bin einen Schritt weiter. Sobald ich durch bin, werd ich das Ergebnis hier posten. Viele Grüße Thomas
I2c ist meißtens so: -du sendest die Slaveadresse +W -dann die Registeradresse, von der du lesen willst. -repeated start condition -slaveadresse + R -solange ACK, bis du genug register gelesen hast. -STOP
Dann müsste das ja eigentlich passen oder? Noch eine Frage zur Initialisierung des Sensors, wie gebe ich beim Schreiben der Config-Werte die Registeradresse für den Slave an? Hab ich das richtig gemacht mit dem & zwischen Registeradresse und Wert oder muss ich die nacheinander schreiben? Danke & Viele Grüße Thomas
1 | //Sensor initialisieren
|
2 | //Startcondition ausführen - Bus übernehmen
|
3 | SSPCON2bits.SEN = 1; //initiate Start condition on SDA+SCL - Senden |
4 | while (PIR1bits.SSPIF == 0); // Bus übernommen? (SSPIF = 1) |
5 | PIR1bits.SSPIF = 0; //SSPIF zurücksetzen |
6 | |
7 | //TCS37725 Slave address schreiben - 0x29
|
8 | SSPBUF = 0x29,0; //7 bit-Adresse + LSB=0 |
9 | while (PIR1bits.SSPIF == 0); |
10 | PIR1bits.SSPIF = 0; |
11 | |
12 | //TCS37725 Kontrollregister schreiben - 1000 0000 - Command Register für schreiben aktivieren - Type repeated byte protocol transaction
|
13 | SSPBUF = 0x80; |
14 | while (PIR1bits.SSPIF == 0); |
15 | PIR1bits.SSPIF = 0; |
16 | |
17 | //TCS37725 Enableregister schreiben - 0000 0001 - Sensor - Enable register - power on
|
18 | SSPBUF = 0b00000000 & 0b00000011; |
19 | while (PIR1bits.SSPIF == 0); |
20 | PIR1bits.SSPIF = 0; |
21 | |
22 | //TCS37725 RGBC Time Register schreiben
|
23 | SSPBUF = 0b00000001 & 0b00000000; |
24 | while (PIR1bits.SSPIF == 0); |
25 | PIR1bits.SSPIF = 0; |
26 | |
27 | //TCS37725 Control Register schreiben - RGBC Gain control
|
28 | SSPBUF = 0x0F & 0b00000011; |
29 | while (PIR1bits.SSPIF == 0); |
30 | PIR1bits.SSPIF = 0; |
31 | |
32 | //RGBC time register schreiben - 0x00 - 256 Integration cycles
|
33 | //SSPBUF = 0b00000000;
|
34 | //while (PIR1bits.SSPIF == 0);
|
35 | //PIR1bits.SSPIF = 0;
|
36 | |
37 | //Stopcondition setzen
|
38 | SSPCON2bits.PEN = 0; // Initiate Stop condition on SDA and SCL pins. |
39 | |
40 | |
41 | //Empfangsmodus
|
42 | |
43 | //Daten vom Sensor empfangen
|
44 | //************************
|
45 | //Clear Low-Byte lesen
|
46 | //Startcondition ausführen - Bus übernehmen
|
47 | SSPCON2bits.SEN = 1; //initiate Start condition on SDA+SCL - Senden |
48 | while (PIR1bits.SSPIF == 0); // Bus übernommen? (SSPIF = 1) |
49 | PIR1bits.SSPIF = 0; //SSPIF zurücksetzen |
50 | |
51 | //Slave address schreiben - 0x29 / TCS37725
|
52 | SSPBUF = 0b01010010; //7 bit-Adresse=0101001 + LSB=0 (Schreiben) |
53 | while (PIR1bits.SSPIF == 0); |
54 | PIR1bits.SSPIF = 0; |
55 | |
56 | //Registeradresse senden an Command Register
|
57 | SSPBUF=0b00010100; //5bit Adresse für clear_low senden = 0x14 = 10100 |
58 | while (PIR1bits.SSPIF == 0); //ACK abwarten |
59 | PIR1bits.SSPIF = 0; |
60 | |
61 | //Repeated Start condition
|
62 | SSPCON2bits.RSEN=1; |
63 | |
64 | //Slave address schreiben - 0x29 / TCS37725
|
65 | SSPBUF = 0b01010011; //7 bit-Adresse=0101001 + LSB=1 (Lesen) |
66 | while (PIR1bits.SSPIF == 0); |
67 | PIR1bits.SSPIF = 0; |
68 | |
69 | //REceive enable bit setzen
|
70 | SSPCON2bits.RCEN=1; // |
71 | |
72 | //Register lesen
|
73 | clear_low = SSPBUF; // clear lesen |
74 | |
75 | //STOP condition setzen
|
76 | SSPCON2bits.PEN = 1; |
Hallo nochmal, hab die Probleme lösen können. Der Thread kann geschlossen werden. Hab am Ende ReadI2C(), WriteI2C() etc verwendet. Das Ack hab ich dann auch irgendwann bekommen, der Sensor hat wie gewünscht die richtigen Werte geliefert (gemessen mit verscheidenen Leuchten , deren Farbtemperatur bekannt ist) Die Bachelor-Arbeit ist abgegeben und bewertet, also Ende gut, alles gut. Vielen Dank an alle, die mich hier unterstützt haben! Viele Grüße, Thomas
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.