Hallo,
ich bin bald am verzweifeln.
Ich versuche einen I2C BUs zum laufen zu bringen, aber das einzige was
funktionniert ist, dass die Startcondition gesendet wird.
Ich verwende den LPC2148 auf dem MBC2140 EvaluatuonBorad von Keil und
debugge das Ganze mit Hitop5.
Pull-Ups habe ich bereits zwischen 1k und 10k variert.
Hier mein Source Code:
1 | #include "LPC214x.h" /* LPC21xx definitions */
|
2 | #include "type.h"
|
3 | #include "I2C.h"
|
4 | #include "irq.h"
|
5 |
|
6 | char buf[]={'A','B','C','D','E'};
|
7 | int count = 5, i = 0;
|
8 |
|
9 | int temp = 0;
|
10 | void i2c_init(void)
|
11 | {
|
12 | PINSEL0 = 0;
|
13 | PINSEL1 = 0;
|
14 | PCONP |= (1 << I2C_POWER);
|
15 |
|
16 | PINSEL0 |=(1 << SCL0_PINSEL) | (1 << SDA0_PINSEL); //SDA und SCL Pins auf I2C-MOdus
|
17 |
|
18 | I20CONCLR |= (1 << STO) | (1 << AA) | (1 << STA) | (1 << SI);
|
19 | temp = I20CONCLR;
|
20 |
|
21 | I20CONSET |= (1 << I2EN) ;//| (1 << STA); //enable the I2C function.
|
22 | //temp = I20CONSET;
|
23 |
|
24 | I20SCLH = 100;
|
25 | temp = I20SCLH;
|
26 | I20SCLL = 50;
|
27 | temp = I20SCLL;
|
28 |
|
29 | VICIntSelect = 0;
|
30 | temp = VICIntSelect;
|
31 | //VICIntEnable = (1 << IE_I2C);
|
32 | temp = VICIntEnable;
|
33 |
|
34 | VICVectCntl0 = (DWORD)(IRQ_SLOT_EN | IE_I2C);
|
35 | temp = VICVectCntl0;
|
36 | VICVectAddr0 = (DWORD) I2C_ISR;
|
37 | temp = VICVectAddr0;
|
38 |
|
39 | IOSET0 = 0x00000000; // clear the ZEROs output
|
40 | IODIR0 = 0x00000000; // set the output bit direction
|
41 | }
|
42 |
|
43 | int i2c_write()
|
44 | {
|
45 | while (count--)
|
46 | {
|
47 | I20DAT = buf[i++]; // load data into I2DAT-Register
|
48 | wait_for_SI();
|
49 | if (I20STAT != 0x28) return 0; // no acknowledge
|
50 | }
|
51 | return 1;
|
52 | }
|
53 |
|
54 | void warte(unsigned int dauer)
|
55 | {
|
56 | while(dauer--);
|
57 | }
|
58 |
|
59 |
|
60 | void i2c_start(int addr)
|
61 | {
|
62 | VICIntEnable = (1 << IE_I2C);
|
63 | I20CONSET |= (1 << STA) ; // set STA
|
64 | }
|
65 |
|
66 |
|
67 | void wait_for_SI(void)
|
68 | {
|
69 | long timeout = 400000;
|
70 | // clear SI starts action
|
71 | while (timeout-- && !(I20CONSET & SI)); // check SI with timeout
|
72 | }
|
73 |
|
74 |
|
75 | void i2c_stop(void)
|
76 | {
|
77 | I20CONSET |= (1 << STO); // set STO
|
78 | I20CONCLR |=(1 << SI); // clear SI
|
79 | }
|
80 |
|
81 | void CCLK_set(void)
|
82 | {
|
83 | PLLCFG |= (4 << MSEL);
|
84 | PLLCFG |= (1 << PSEL); //Fosc*5 =CCLK
|
85 | PLLFEED = 0xAA;
|
86 | PLLFEED = 0x55;
|
87 |
|
88 | PLLCON |= (1 << PLLE) | (1 << PLLC); //PLL Enable.//PLL Connect.
|
89 | PLLFEED = 0xAA;
|
90 | PLLFEED = 0x55;
|
91 |
|
92 |
|
93 | VPBDIV = 0;//00 VPB bus clock is one fourth of the processor clock.
|
94 | }
|
95 |
|
96 | void I2C_ISR(void) //__irq
|
97 | { int temp1 = 0;
|
98 | temp1 = I20STAT;
|
99 |
|
100 | switch(temp1)
|
101 | {
|
102 | case 0x08:
|
103 | {
|
104 | //I20DAT = 0x90; //addr
|
105 | temp1 = I20DAT;
|
106 | I20CONCLR |= (1 << SIC) | (1 << STA);
|
107 | break;
|
108 | }
|
109 | case 0x10:
|
110 | {
|
111 | I20DAT = 0x90;
|
112 | I20CONCLR |= (1 << SIC);
|
113 | break;
|
114 | }
|
115 | case 0x18:
|
116 | {
|
117 | if(count==0)
|
118 | i2c_stop();
|
119 | else
|
120 | count--;
|
121 | I20DAT = *(buf);
|
122 | I20CONCLR |= (1 << SIC);
|
123 | break;
|
124 | }
|
125 | case 0x20:
|
126 | {
|
127 | i2c_stop();
|
128 | I20CONCLR |= (1 << SIC);
|
129 | break;
|
130 | }
|
131 | case 0x28:
|
132 | {
|
133 | if(count==0)
|
134 | i2c_stop();
|
135 | else
|
136 | count--;
|
137 | I20DAT = *buf;
|
138 | I20CONCLR |= (1 << SIC);
|
139 | break;
|
140 | }
|
141 | case 0x30:
|
142 | {
|
143 | i2c_stop();
|
144 | I20CONCLR |= (1 << SIC);
|
145 | break;
|
146 | }
|
147 | }
|
148 |
|
149 | VICVectAddr = 0;
|
150 |
|
151 | }
|
Wie gesagt, Startcondition wird gesendet( erst SDA auf LOW gezogen und
dann SCL), im I2CStatusregister ist der Wert 0x08, dann bleibt beides
auf LOW, bis in der ISR das SI-Flag gelöscht wird.
Was komisch ist, ich hatte einmal den Jumper7(für die, die des
MCB2140Schematics zufällig vor sich haben) noch an, als ich den I2C1
verwendete, und dann bekamm ich ein CLocksignal auf SCL, das nicht mehr
aufhörte, aber das SI-Flag wurde nicht merh gesetzt. Über den Jumper 7
wird SDA über einen Kondensator mit 100nF auf Ground gezogen und über
einen 22k Wiederstand auf HIGH. Als ich den Jumper entfernte war es
genauso, wie als ich den I2c0 verwendet habe.
Wie bekomme ich es jetzt hin, dass nicht nur die Startcondition sondern
auch die Slaveaddresse gesendet wird? Und dann vielleicht auch mal Daten
gesendet werden können?