Forum: Mikrocontroller und Digitale Elektronik PIC18F & Sensor über I2C auslesen


von Thomas M. (thomas_m13)


Lesenswert?

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

......
}

von Peeko K. (peeko)


Lesenswert?

kurze Frage, bist du ganz sicher, dass der Hardware richtig 
funktioniert?
Viele vergessen immer den Pull-Up Widerstand.

von Thomas M. (thomas_m13)


Lesenswert?

danke für den Tipp, aber die Pull-ups sind drin für SDA, SCL und INT.

Gruß, Thomas

von holger (Gast)


Lesenswert?

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;

von Thomas M. (thomas_m13)


Lesenswert?

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

von Thomas M. (thomas_m13)


Lesenswert?

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

von wurstwasser (Gast)


Lesenswert?

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

von Thomas M. (thomas_m13)


Lesenswert?

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;

von Thomas M. (thomas_m13)


Lesenswert?

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
Noch kein Account? Hier anmelden.