Guten Tag liebe Gemeinde...
Seit ner halben Ewigkeit versuche ich den Wii Nunchuk Controller per I2C
an einen AtMega88 anzuschließen. Allerdings bekomm ich einfach keine
vernünftigen Daten, immer nur 0xff.
Der I2C Code kommt aus nem anderen Thread, irgendwas mit einem EEPROM,
ich find ihn nicht mehr. Aber auch mit Hard-TWI wars dasselbe.
Checkliste:
-SDA an PC4 und SCL PC5 an
-Pullups sind da
-SCL SDA sind nicht vertauscht
-Betriebsspannung 3,3V stimmt auch
-AVR läuft mit 8Mhz
-an den Pins wird laut Oszi rumgewackelt
Könnt ihr mir sagen, wo das Problem liegen könnte?
Hier der Code:
1 | #define F_CPU 8000000L
|
2 | #include <avr/io.h>
|
3 | #include <util/delay.h>
|
4 | #include <avr/interrupt.h> //Interrupt-funktionen
|
5 | #include <stdlib.h>
|
6 | #define nunchukaddr 0xA4 //A4
|
7 | #define true 1
|
8 | #define false 0
|
9 |
|
10 | //!Pin definitions
|
11 | #define SDA_LOW DDRC |= (1<<PC4); // low, open drain
|
12 | #define SDA_HIGH DDRC &= ~(1<<PC4); // high, Z
|
13 | #define SCL_LOW DDRC |= (1<<PC5); // low, open drain
|
14 | #define SCL_HIGH DDRC &= ~(1<<PC5); // high, Z
|
15 | #define SDA (PINC & (1<<PC4)) // get SDA
|
16 | int i=0;
|
17 | uint8_t x=0;
|
18 |
|
19 |
|
20 | void i2c_start(void){
|
21 | SDA_LOW
|
22 | asm("nop");
|
23 | SCL_LOW
|
24 | }
|
25 | void i2c_stop(void){
|
26 | SDA_HIGH
|
27 | asm("nop");
|
28 | SCL_HIGH
|
29 | }
|
30 | uint8_t i2c_write(uint8_t data){
|
31 | uint8_t cnt=8;
|
32 | for (; cnt>0; cnt--) {
|
33 | if (data & 0x80)
|
34 | SDA_HIGH
|
35 | else
|
36 | SDA_LOW
|
37 | SCL_HIGH
|
38 | data <<= 1;
|
39 | SCL_LOW
|
40 | }
|
41 | SDA_HIGH
|
42 | SCL_HIGH
|
43 | asm("nop"); // WICHTG, wegen der Eingangsverzögerung!
|
44 | if (SDA) cnt=0; else cnt=1; // check ACK
|
45 | SCL_LOW
|
46 | return cnt;
|
47 | }
|
48 | uint8_t i2c_read(uint8_t ack){
|
49 | uint8_t tmp=0, cnt=8;
|
50 |
|
51 | for (; cnt>0; cnt--) {
|
52 | SCL_HIGH
|
53 | tmp <<= 1;
|
54 | if (SDA) tmp |= 0x01;
|
55 | SCL_LOW
|
56 | }
|
57 | if (ack) SDA_LOW else SDA_HIGH
|
58 | SCL_HIGH
|
59 | SCL_LOW
|
60 | SDA_HIGH
|
61 | return tmp;
|
62 | }
|
63 |
|
64 | int main(void){
|
65 | PORTC = 0x00; //
|
66 | DDRC = 0x00; //Eingänge
|
67 | PORTB = 0x00; //
|
68 | DDRB = 0xff; //Ausgänge
|
69 | PORTD = 0x00; //
|
70 | DDRD = 0xff; //Ausgänge
|
71 |
|
72 | i2c_start(); //init-sequenz
|
73 | i2c_write(nunchukaddr);
|
74 | i2c_write(0x40);
|
75 | i2c_write(0x00);
|
76 | i2c_stop();
|
77 | while (1)
|
78 | { i2c_start(); //6 bytes holen
|
79 | i2c_write(nunchukaddr+1);
|
80 | x=i2c_read(0);
|
81 | x=i2c_read(0);
|
82 | x=i2c_read(0);
|
83 | x=i2c_read(0);
|
84 | x=i2c_read(0);
|
85 | x=i2c_read(0);
|
86 | i2c_stop(); //Ausgabe über Schieberegister(nicht gelistet)
|
87 | shift( x);
|
88 |
|
89 | i2c_start(); //0 senden
|
90 | i2c_write(nunchukaddr);
|
91 | i2c_write(0x00);
|
92 | i2c_stop();
|
93 |
|
94 | }
|
95 | }
|
PS.: Bei Bedarf kann ich auch den Sourcecode anhängen, der Hard-TWI
benutzt