So nun hab ich gleich noch ein nächstes Problem nachdem das erste gelöst
wurde. ;) Ich poste mal den Code hierher, auch wenn es bißchen viel
wird.
Ich möchte zwischen den beiden besagten PICs eine bidirektionale
Kommunikation herstellen. Das heißt, der Master sendet dem Slave das
Start Kommando, dann die Adresse mit WRITE, dann 3Byte und ein Stop
Signal, Als nächstes wird erneut ein Start Signal gesendet und wieder
die Adresse, allerdings mit READ, danach hört einfach der Takt auf und
die angeforderten Daten vom Slave werden nicht übernommen. Dieses
Phänomen kann ich mir grad nicht erklären. Wie kann ich den Takt des
Masters wieder aktivieren?
-> Ein Oszibild ist anbei.
Die Hauptfunktionen des Slave: In der main.c wird innerhalb der while
Schleife die requestI2C() aufgerufen.
1 | void requestI2C(void)
|
2 | {
|
3 | /** \brief This function decide according to its variable status which case receive/transmit will used. \n
|
4 | * \var uint8 status Transfer the value from function scanRWI2C() - check R/W bit.
|
5 | */
|
6 | unsigned char status = 0;
|
7 | unsigned char read = 0;
|
8 |
|
9 | status = scanRWI2C(); // Returns the "mode" - communication Master -> Slave
|
10 |
|
11 | switch(status) // If the slave is selected through "General Call" or "Slave Address" than do ...
|
12 | { // case 1 means Slave is not selected by address
|
13 | case 1:
|
14 | break;
|
15 |
|
16 | // case 2 means Slave is selected by address and Write Bit is set
|
17 | case 2: while(!SSPSTATbits.P) // As long as the stop condition for I2C transmission does not occur
|
18 | {
|
19 | read = getByteI2C(); // Read new byte from bus
|
20 | receiveDataI2C(read); // Read "Identifier"
|
21 | }
|
22 | break;
|
23 |
|
24 | // case 3 means Slave is selected by address and Read Bit is set
|
25 | case 3: while(!SSPSTATbits.P) // As long as the stop condition for I2C transmission does not occur
|
26 | {
|
27 | transmitDataI2C(); // Send the states of "MOSFET-Test" to Master
|
28 | }
|
29 | break;
|
30 | }
|
31 | }
|
32 |
|
33 | void clearFlagsI2C(void)
|
34 | {
|
35 | SSPCON1bits.SSPOV = 0; // after reading the SSPBUF, the SSPOV bit properly clear an overflow condition
|
36 | PIR1bits.SSPIF = 0; // Clear interrupt flag, to continiue communication
|
37 | SSPCON1bits.CKP = 1; // Release clock, when = 1
|
38 | }
|
39 |
|
40 | unsigned char getByteI2C(void)
|
41 | {
|
42 | /** \brief This function read a byte from the I2C bus. \n
|
43 | * \var uint8 buffer transfer the value of SSPBUF-Register. \n
|
44 | * \return buffer is the returned value of SSPBUF.
|
45 | */
|
46 | uint8 bufSSPBUF = 0;
|
47 |
|
48 | while (!SSPSTATbits.BF); // Wait until byte received, returns 1 if the BF bit is set, or 0 if not
|
49 | bufSSPBUF = SSPBUF; // Save incoming byte
|
50 | clearFlagsI2C();
|
51 | return bufSSPBUF;
|
52 | }
|
53 |
|
54 | unsigned char transmitDataI2C(void)
|
55 | {
|
56 | /** \brief This function write a byte to the bus (master).
|
57 | */
|
58 | clearFlagsI2C();
|
59 | if(WriteI2C(0x33) == 0) // 0 if acknowledge was received
|
60 | {
|
61 | clearFlagsI2C();
|
62 | return 1;
|
63 | }
|
64 | else
|
65 | return 0;
|
66 | }
|
Die Hauptroutine des Master wird ebenso innerhalb der while Schleife der
main.c aufgerufen. Die Funktionen getByte und clearFlags sind die
gleichen wie beim Slave.
So nun liegt der Fehler wahrscheinlich in der folgenden Funktion. Aber
wo genau?
1 | main()
|
2 | {
|
3 | CloseI2C(); // close i2c if was operating earlier
|
4 | sync_mode = MASTER; // I2C Master mode, 7-bit address
|
5 | slew = SLEW_OFF; // 100kHz
|
6 | OpenI2C(sync_mode,slew); // initialize master mode
|
7 |
|
8 | SSPADD = 0x60; //64 // 100kHz Baud clock(3) @20MHz, Fcy=10MHz (0x18 wenn Fosc = 10MHz, 0x64 wenn Fosc = 40MHz)
|
9 | slave_adr = 0x10; // initialize slave address, da /Bit, um eins nach links schieben
|
10 | readmode1 = (slave_adr & 0xFE); // 0x00 = Write
|
11 | readmode2 = (slave_adr | 0x01); // 0x01 = Read
|
12 |
|
13 | while(1)
|
14 | {
|
15 | IdleI2C();
|
16 | StartI2C();
|
17 | IdleI2C();
|
18 | if(WriteI2C(readmode1)== 0) // write SLAVE Adress and write command
|
19 | {
|
20 | if(WriteI2C(0x01) == 0) // Send Identifier 1
|
21 | {
|
22 | // clearFlagsI2C();
|
23 | }
|
24 | if(WriteI2C(0x11) == 0) // Send highbyte
|
25 | {
|
26 | // clearFlagsI2C();
|
27 | }
|
28 | if(WriteI2C(0x11) == 0) // Send lowbyte
|
29 | {
|
30 | // clearFlagsI2C();
|
31 | }
|
32 | }
|
33 | IdleI2C();
|
34 | //RestartI2C();
|
35 | StopI2C();
|
36 | IdleI2C();
|
37 | StartI2C();
|
38 | IdleI2C();
|
39 | if(WriteI2C(readmode2)== 0) // Write SLAVE Adress and write command
|
40 | {
|
41 | /* Ab hier steigt der Master aus */
|
42 | uint8 bufSSPBUF = 0;
|
43 | clearFlagsI2C();
|
44 | // SSPCON2bits.RCEN = 1; // Set master receive enable
|
45 | // while(!SSPCON2bits.RCEN)
|
46 | bufSSPBUF = ReadI2C(); // Read byte from bus
|
47 | clearFlagsI2C();
|
48 | AckI2C(); // Master receive enable = 1 and ACKDT = 0 (acknowledge will be send)
|
49 | clearFlagsI2C();
|
50 | }
|
51 | IdleI2C();
|
52 | StopI2C(); // Send the Stop condition
|
53 | } // while_end
|
54 | }
|
Danke im voraus für diverse Tipps.