1 | #define BYTE unsigned char
|
2 | #define WORD unsigned short
|
3 |
|
4 | #define I2C_PORT_SEL P3SEL
|
5 | #define EEPROM_ADDRESS 0x50
|
6 |
|
7 |
|
8 | void I2C_Init(void) // Initialisierung des I²C-Moduls
|
9 | {
|
10 | I2C_PORT_SEL |= 0x0A; // P3.1 und P3.3 --> SDA/SCL des USART0-Moduls
|
11 | U0CTL |= I2C+SYNC; // USART0 auf I²C-Betrieb stellen
|
12 | U0CTL &= ~I2CEN; // I²C-Modul vor der Konfiguration deaktivieren
|
13 | I2CTCTL = I2CTRX+I2CSSEL_2; // Transmit Mode und SMCLK als Taktquelle
|
14 | I2CSA = EEPROM_ADDRESS; // Adresse des EEPROM festlegen
|
15 | I2CPSC = 0x00; // Vorteiler für I²C-Takt = SMCLK/1
|
16 | I2CSCLH = 0x03; // Zeit für SCL=1 ist 10 SMCLK-Taktzyklen
|
17 | I2CSCLL = 0x03; // Zeit für SCL=0 ist 10 SMCLK-Taktzyklen
|
18 | // bei SMCLK=4MHz ist SCL=200kHz
|
19 | U0CTL |= I2CEN; // I²C-Modul aktivieren
|
20 | }
|
21 |
|
22 |
|
23 | void I2C_Write_Init(void) // I²C-Initialisierung für Schreiben
|
24 | {
|
25 | U0CTL |= MST; // Master Mode einstellen
|
26 | I2CTCTL |= I2CTRX; // Transmit Mode (R/W-Bit ist 0)
|
27 | I2CIFG &= ~TXRDYIFG; // Transmit-Ready-Flag löschen
|
28 | I2CIE = TXRDYIE; // Transmit-Ready-Interrupt aktivieren
|
29 | }
|
30 |
|
31 |
|
32 | void I2C_Read_Init(void) // I²C-Initialisierung für Lesen
|
33 | {
|
34 | I2CTCTL &= ~I2CTRX; // Receive Mode (R/W-Bit ist 1)
|
35 | I2CIE = RXRDYIE; // Receive-Ready-Interrupt aktivieren
|
36 | U0CTL |= MST; // Master Mode einstellen
|
37 | }
|
38 |
|
39 |
|
40 | void EEPROM_Write(WORD adr, BYTE data) // Schreiben eines Bytes in das EEPROM
|
41 | {
|
42 | BYTE adr_hi;
|
43 | BYTE adr_lo;
|
44 |
|
45 | while(I2CDCTL & I2CBUSY); // warten, solange I²C-Modul noch aktiv ist
|
46 |
|
47 | adr_hi = adr >> 8; // High-Byte der Adresse berechnen
|
48 | adr_lo = adr & 0xFF; // Low-Byte der Adresse berechnen
|
49 |
|
50 | I2C_buffer[2] = adr_hi; // I²C-Buffer mit den zu sendenden Bytes füllen
|
51 | I2C_buffer[1] = adr_lo;
|
52 | I2C_buffer[0] = data;
|
53 | pointer = 2; // Buffer-Pointer setzen
|
54 |
|
55 | I2C_Write_Init();
|
56 | I2CNDAT = 3; // Zähler der zu übertragenden Bytes
|
57 | I2CTCTL |= I2CSTT+I2CSTP; // Start-Zustand senden - I²C-Kommunikation aktiv
|
58 | } // Stop-Zustand wird automatisch gesendet, sobald
|
59 | // alle Bytes übertragen sind
|
60 |
|
61 |
|
62 | BYTE EEPROM_Read(WORD adr) // Lesen eines Bytesatzes aus dem EEPROM
|
63 | {
|
64 | BYTE adr_hi;
|
65 | BYTE adr_lo;
|
66 |
|
67 | while(I2CDCTL & I2CBUSY); // warten, solange I²C-Modul noch aktiv ist
|
68 |
|
69 | adr_hi = adr >> 8; // High-Byte der Adresse berechnen
|
70 | adr_lo = adr & 0xFF; // Low-Byte der Adresse berechnen
|
71 |
|
72 | I2C_buffer[1] = adr_hi; // I²C-Buffer mit den zu sendenden Bytes füllen
|
73 | I2C_buffer[0] = adr_lo;
|
74 | pointer = 1; // Buffer-Pointer setzen
|
75 |
|
76 | I2C_Write_Init();
|
77 | I2CNDAT = 2; // Zähler der zu übertragenden Bytes
|
78 | I2CIFG &= ~ARDYIFG; // Access-Ready-Flag löschen
|
79 | I2CTCTL |= I2CSTT; // Start-Zustand senden - I²C-Kommunikation aktiv
|
80 | // Stop-Zustand wird automatisch gesendet, sobald
|
81 | // alle Bytes übertragen sind
|
82 |
|
83 | while((~I2CIFG) & ARDYIFG); // Ende der Übertragung abwarten
|
84 |
|
85 | I2C_Read_Init();
|
86 | I2CNDAT = 1; // Zähler der zu empfangenden Datenbytes
|
87 |
|
88 | I2CIFG &= ~ARDYIFG; // Access-Ready-Flag löschen
|
89 | I2CTCTL |= I2CSTT+I2CSTP; // Start-Zustand senden - I²C-Kommunikation aktiv
|
90 | // Stop-Zustand wird automatisch gesendet, sobald
|
91 | // alle Bytes übertragen sind
|
92 | while((~I2CIFG) & ARDYIFG); // Ende der Übertragung abwarten
|
93 | return I2C_buffer[0]; // empfangenes Byte übergeben
|
94 | }
|
95 |
|
96 |
|
97 | void EEPROM_Ack_Polling(void) // Testen auf Abschluss des Schreibzyklus
|
98 | {
|
99 | WORD count;
|
100 | while(I2CDCTL & I2CBUSY); // warten, solange I²C-Modul noch aktiv ist
|
101 | count = 0;
|
102 | U0CTL &= ~I2CEN; // I²C-Modul vor der Rekonfiguration deaktivieren
|
103 | I2CTCTL |= I2CRM; // Software kontrolliert Übertragung
|
104 | U0CTL |= I2CEN; // I²C-Modul aktivieren
|
105 | I2CIFG = NACKIFG; // No-Acknowledge-Flag setzen
|
106 | while (NACKIFG & I2CIFG)
|
107 | {
|
108 | I2CIFG = 0x00; // Interrupt-Flags löschen
|
109 | U0CTL |= MST; // Master Mode einstellen
|
110 | I2CTCTL |= I2CTRX; // Transmit Mode (R/W-Bit ist 0)
|
111 | I2CTCTL |= I2CSTT; // Start-Zustand senden
|
112 |
|
113 | while (I2CTCTL & I2CSTT); // warten, bis I2CSTT-Bit wieder gelöscht ist
|
114 |
|
115 | I2CTCTL |= I2CSTP; // nach Adress-Übertragung Stop-Zustand senden
|
116 | // --> I²C-Kommunikation aktiv
|
117 | while (I2CDCTL & I2CBUSY); // warten, solange I²C-Modul noch aktiv ist
|
118 | count = count+1;
|
119 | }
|
120 | U0CTL &= ~I2CEN; // I²C-Modul vor der Rekonfiguration deaktivieren
|
121 | I2CTCTL &= ~I2CRM; // I²C-Modul kontrolliert Übertragung
|
122 | U0CTL |= I2CEN; // I²C-Modul aktivieren
|
123 | return;
|
124 | }
|
125 |
|
126 |
|
127 | #pragma vector = USART0TX_VECTOR // ISR
|
128 | __interrupt void ISR_I2C(void)
|
129 | {
|
130 | switch (I2CIV)
|
131 | {
|
132 | case I2CIV_AL: // Interrupt-Vektor: Arbitrierung verloren (ALIFG)
|
133 | break;
|
134 | case I2CIV_NACK: // Interrupt-Vektor: Kein Acknowledge (NACKIFG)
|
135 | break;
|
136 | case I2CIV_OA: // Interrupt-Vektor: Eigene Adresse (OAIFG)
|
137 | break;
|
138 | case I2CIV_ARDY: // Interrupt-Vektor: Zugriff bereit (ARDYIFG)
|
139 | break;
|
140 | case I2CIV_RXRDY: // Interrupt-Vektor: Empfang bereit (RXRDYIFG)
|
141 | I2C_buffer[0] = I2CDRB; // empfangene Daten in den Buffer speichern
|
142 | break;
|
143 | case I2CIV_TXRDY: // Interrupt-Vektor: Übertragung bereit (TXRDYIFG)
|
144 | I2CDRB = I2C_buffer[pointer];
|
145 | pointer = pointer-1;
|
146 | if (pointer<0)
|
147 | I2CIE &= ~TXRDYIE; // Transmit-Ready-Interrupt deaktivieren
|
148 | break;
|
149 | case I2CIV_GC: // Interrupt-Vektor: Allgemeiner Aufruf (GCIFG)
|
150 | break;
|
151 | case I2CIV_STT: // Interrupt-Vektor: Start-Zustand empfangen (STTIFG)
|
152 | break;
|
153 | }
|
154 | }
|