hallo, hätte eine frage zu einem simplen i2c programm.
hab mir ein SD21 Servocontroller bestellt
(www.robotikhardware.de/download/sd21.pdf)
den man über I2C ansteuert.
habe einen P89LPC936 für die Programmierung.
vorerst sieht meine Routine so aus:
1 | void i2c_init()
|
2 | {
|
3 | //SDA und SCL auf Open Drain => beide auf 1
|
4 | //SCL P1.2
|
5 | //SDA P1.3
|
6 |
|
7 | P1M1 |= 0x0C;
|
8 | P1M2 |= 0x0C;
|
9 |
|
10 | //Takt erzeugen von internem SCL Generator
|
11 | //Reloadwert setzen
|
12 |
|
13 | I2SCLH = 5;
|
14 | I2SCLL = 5;
|
15 | //369 kBit/s
|
16 |
|
17 | //I2C Hardware aktivieren (STOP, STA, SI = 0)
|
18 | I2CON = 0x44;
|
19 | //I2C Interrupt freigeben
|
20 | //EI2C = 1;
|
21 | //EA = 1;
|
22 |
|
23 | //Slave Adresse setzen
|
24 | SlaveAdr = 0xC2; //Adresse des SD21 Servo Controllers
|
25 | }
|
1 | void write_byte_I2C(unsigned char data_out1, unsigned char data_out2)
|
2 | {
|
3 | STA = 1; //Startbedingung setzen
|
4 |
|
5 | while(!SI); //warten bis Startbedingung gesendet wurde
|
6 |
|
7 | //Nun auf richtige Rückmeldung abfragen
|
8 | if(I2STAT == 0x08) //1. Status: "START transmitted"
|
9 | {
|
10 | I2DAT = SlaveAdr;
|
11 | I2CON = 0x44; //STO, STA, SI = 0, ACK = 1)
|
12 | }
|
13 |
|
14 | //Nachdem das Startbit gesendet wurde, wird jetzt
|
15 | //der Write-Befehl an den Slave gesendet, damit
|
16 | //der Bus vom Master beschrieben werden kann
|
17 | while(!SI);
|
18 | if(I2STAT == 0x18) //2. Status: "SLA+W transmitted; ACK received"
|
19 | {
|
20 | I2DAT = data_out1; //Datenbyte senden. Unser uC verschiebt das Byte automatisch
|
21 | I2CON = 0x44; //STO, STA, SI = 0, ACK = 1)
|
22 | //I2CStatus = ACK_RECEIVED;
|
23 | }
|
24 |
|
25 | while(!SI);
|
26 | if(I2STAT == 0x28) //3. Status: Databyte transmitted; ACK received"
|
27 | {
|
28 | I2DAT = data_out2; //Datenbyte senden. Unser uC verschiebt das Byte automatisch
|
29 | I2CON = 0x44; //STO, STA, SI = 0, ACK = 1)
|
30 | //I2CStatus = ACK_RECEIVED;
|
31 | }
|
32 |
|
33 | //Nachdem das Datenbyte gesendet wurde, müssen wir
|
34 | //wieder den Bus freigeben anhand einer Stopbedingung
|
35 | while(!SI);
|
36 | if(I2STAT == 0x28) //3. Status: "Datenbyte received; ACK received"
|
37 | {
|
38 | I2CON = 0x54; //Stopbedingung senden / Bus freigeben / SI = 0;
|
39 | }
|
40 | }
|
wollte nun fragen, ob das so stimmen kann?
hab mal ein testprogramm geschrieben
1 | void Interrupt_Button (void) interrupt 2
|
2 | {
|
3 | int i;
|
4 |
|
5 | set_speed_I2C(1,100); //set servo 1, speed 100%
|
6 | set_position_I2C(1,1500); //set servo 1, nullstellung
|
7 |
|
8 | set_speed_I2C(3,50);
|
9 | set_position_I2C(3,1500);
|
10 |
|
11 | set_position_I2C(1,1000); //set servo 1, nullstellung
|
12 | set_position_I2C(3,2000);
|
13 | }
|
kann das so funktionieren?
1) ich muss eh nichts extra anbringen für den sd21 (extern pullup oder
so beim bus), also ich hab jedenfalls nichts gesehen im datenblatt ?!
2) ich hab schon versucht das programm zu simulieren mit Keil uVision4,
nur da passt irgendetwas nicht und der Slave gibt mir immer ein "Not
Acknowledge" (is aber auch logisch, denn müsste irgendwie manuell den
Slave simulieren).
Ich weiß, dass ich TROTZDEM senden kann, obwohl kein Acknowledge bit
herkommt, aber funktioniert das auch?
Stimmt meine Denkweise? oder ist daran etwas falsch? Ab nächster Woche
werd ich den SD21 bekommen und dann kann ich das mal genauer austesten
Danke im Voraus!!!