IIC und ADT7461

Dies ist das deutsche Forum für alle Themen um den IO-Warrior. Beiträge bitte nur in Deutsch.

Moderator: Guido Körber

dereulenspiegel
Posts: 14
Joined: Mon Dec 26, 2005 7:55 pm

IIC und ADT7461

Post by dereulenspiegel »

Ich würde gerne mit dem IOW die Temperatur, die ein ADT7461 misst per IIC auslesen. Leider klappt das nicht so ganz. Ich habe echt keine Ahnung wo der Fehler liegt. Vielleicht weiß ja einer von euch Rat oder hat einen Tipp.

Danke im Voraus

Code: Select all

#include <iostream>
#include <windows.h>
#include "iowkit.h"
using namespace std;

typedef CHAR special_report[8];

double gettemp(IOWKIT_HANDLE iohandle)
{
       char temp_high=0;
       char temp_low=0;
       double temp=0.0;
       ULONG ret;
       cout << "Setting Write-Register" << endl;
       special_report report;
       report[0]=2;
       report[1]=2;
       report[2]=0x4C;
       report[3]=0x01;
       report[4]=0;
       report[5]=0;
       report[6]=1;
       report[7]=1;
       
       
       ret=IowKitWrite(iohandle,1,report,8);
       cout << "Write-Register set" << endl;
       if(ret==8){
                                           cout << "Sending Read-Request" << endl;
                                           report[0]=3;
                                           report[1]=1;
                                           report[2]=0x4C;
                                           report[3]=0;
                                           report[4]=0;
                                           report[5]=0;
                                           report[6]=0;
                                           report[7]=0;
                                           
                                           ret=IowKitWrite(iohandle,1,report,8);
                                           cout << "Read-Request send" << endl;
                                           report[0]=3;
                                           report[1]=0;
                                           report[2]=0;
                                           report[3]=0;
                                           report[4]=0;
                                           report[5]=0;
                                           report[6]=0;
                                           report[7]=0;
                                           cout << "Getting Results of High-Byte" << endl;
                                           ret=IowKitRead(iohandle,1,report,8);
                                           cout << "Got Results" << endl;
                                           for(int i=0;i<=8;i++) {
                                           int x=0;
                                           x=report[i];
                                           cout << x << endl;
                                           }
                                           
                                           if(report[0]==2){
                                                            cout << "Writing to Variable" << endl;
                                                                  temp_high=report[1];
                                                                  }
                                                                  
                                           }
                                           else cout << "Fehler!" << endl;
                                           
       cout << "Setting Write-Register" << endl;
       report[0]=2;
       report[1]=2;
       report[2]=0x4C;
       report[3]=0x10;
       report[4]=0;
       report[5]=0;
       report[6]=1;
       report[7]=1;
       
       ret=IowKitWrite(iohandle,1,report,8);
       cout << "Write-Register set" << endl;
       if(ret==IOWKIT_SPECIAL_REPORT_SIZE){
                                           cout << "Sending Read-Request for Low-Byte" << endl;
                                           report[0]=3;
                                           report[1]=2;
                                           report[2]=0x4C;
                                           report[3]=0;
                                           report[4]=0;
                                           report[5]=0;
                                           report[6]=0;
                                           report[7]=0;
                                           
                                           ret=IowKitWrite(iohandle,1,report,8);
                                           cout << "Read-Request send" << endl;
                                           report[0]=3;
                                           report[1]=0;
                                           report[2]=0;
                                           report[3]=0;
                                           report[4]=0;
                                           report[5]=0;
                                           report[6]=0;
                                           report[7]=0;
                                           cout << "Getting Resulsts for Low-Byte" << endl;
                                           ret=IowKitRead(iohandle,1,report,8);
                                            for(int i=0;i<=8;i++) {
                                           int x=0;
                                           x=report[i];
                                           cout << x << endl;
                                           }
                                           if(report[0]==2){
                                                                  cout << report[0] << endl;
                                                                  cout << report[1] << endl;
                                                                  cout << report[2] << endl;
                                                                  temp_low=report[1];
                                                                  }
                                                                  
                                           }
                                           else cout << "Fehler!" << endl;
                                           
       switch(temp_low){
                        case 0:temp=temp+0.0;break;
                        case 64:temp=temp+0.25;break;
                        case 128:temp=temp+0.5;break;
                        case 192:temp=temp+0.75;break;
                        default:break;
                        }
                        
       temp=temp+(double)temp_high;
       return temp;

                                           
}
       
       


int main()
{
    cout << "Start!" << endl;
    IOWKIT_HANDLE iohandle;
    cout << "create iohandle" << endl;
    iohandle = IowKitOpenDevice();
    cout << "Device open" << endl;
    if(iohandle!=NULL){
                       cout << "Start IIC" << endl;
                       ULONG res;
                       special_report start_iic;
                       start_iic[0] = 1;
                       start_iic[1] = 1;
                       start_iic[2] = 0;
                       start_iic[3] = 0;
                       start_iic[4] = 0;
                       start_iic[5] = 0;
                       start_iic[6] = 0;
                       start_iic[7] = 0;
                       res=IowKitWrite(iohandle,1,start_iic,8);
                       cout << "IIC started" << endl;
                       if(res!=8){
                                  cout << "Fehler!" << endl;
                                 }
                       else{
                       special_report send_rep;
                       send_rep[0]=2;
                       send_rep[1]=3;
                       send_rep[2]=0x4C;
                       send_rep[3]=0x0A;
                       send_rep[4]=0x0A;
                       send_rep[5]=0;
                       send_rep[6]=1;
                       send_rep[7]=1;
                       cout << "Setting up ADT" << endl;
                       
                       res=IowKitWrite(iohandle,1,send_rep,8);
                       Sleep(1000);
                       cout << "ADT set up" << endl;
                       double x = gettemp(iohandle);
                       cout << "Got temp" << endl;
                       cout << x << endl;
                       cout << "Fertig" << endl;
                       }
                       }
    else{
         cout << "Fehler: Kann IOWarrior nicht oeffnen!" << endl;
         }
                       
    IowKitCloseDevice(iohandle);
}
Guido Körber
Site Admin
Posts: 2876
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Post by Guido Körber »

Gleich zwei Fehler:
Beim Schreiben
send_rep[1]=3;
Macht sich nicht gut, da dann kein Start und kein Stop erzeugt werden. Besser wäre 0xC3 als Wert.

Beim Lesen
report[2]=0x4C;
Auch nicht so gut, das R/W Bit im Commandbyte ist 0, also Schreiben. 0x4D benutzen.
dereulenspiegel
Posts: 14
Joined: Mon Dec 26, 2005 7:55 pm

Post by dereulenspiegel »

Hi!

Warum denn 0xC3 als Wert. Ich dachte da muss die Anzahl der Bytes die auf den Bus geschrieben werden rein. Und laut Datenblatt werden durch Byte 6 und 7 des Reports das Start und Stop erzeugt. Aber auch mit den Änderungen von dir kann ich immer noch nicht die Temperatur korrekt auslesen. Der Antwortreport den ich lese hat zum Beispiel immer die ID 2. Das sollte doch auch nicht sein, oder? Und wie kann ich das Ack-Bit welches ich zurückbekommen sollte auslesen?

Danke im Voraus.
Guido Körber
Site Admin
Posts: 2876
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Post by Guido Körber »

Bit, nicht Byte, 6 und 7 bestimmen Start und Stop. Wäre ja ziemlich ineffektiv zwei ganze Bytes dafür zu verschwenden.

Und natürlich kommt ein Report mit ID 2 zurück, es ist ja vorher ein Schreizugriff erfolgt und auf dem IIC kann es nun mal Fehler geben, also bekommt man eine Quittung für den Schreibzugriff. Wenn man die nicht abholt liegt die natürlich vor dem Report vom Lesezugriff im Puffer.
dereulenspiegel
Posts: 14
Joined: Mon Dec 26, 2005 7:55 pm

Post by dereulenspiegel »

Ok, das habe ich soweit verstanden. Das Problem ist nur, dass ich immer dieselben Daten zurückbekomme. Egal ob der Report die ID 2 oder 3 hat. Es kommt im Byte danach immer -128. Ihm scheint sogar die Deviceadresse egal zu sein. Da kann ich Eintragen was ich will und es kommt immer das gleiche. So langsam werde ich echt bekloppt. Oder sind diese Phänomene vielleicht ein Hinweis darauf, dass der ADT falsch angeschlossen ist oder gar kaputt ist?
Guido Körber
Site Admin
Posts: 2876
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Post by Guido Körber »

Datenblatt lesen...

$80 ist eine Fehlermeldung, der IIC Chip hat nicht ein Byte angenommen.
dereulenspiegel
Posts: 14
Joined: Mon Dec 26, 2005 7:55 pm

Post by dereulenspiegel »

Ich habe mein Testprogramm von Grund auf neu geschrieben. Ist jetzt etwas übersichtlicher. Es funtioniert aber immer noch nicht. Er nimmt kein Byte an. Ist das ein Zeichen für einen Hardwaredefekt irgendeiner Art?

Hier mein neuer Code:

Code: Select all

#include<iostream>
#include<windows.h>
#include"iowkit.h"
using namespace std;

class iic{
      private:
              int address;
              IOWKIT_HANDLE iow;
              char report[8];
              ULONG res;
              
      public:
             iic(IOWKIT_HANDLE,int);
             ~iic();
             bool read(char*,int);
             bool write(char*);
};

iic::iic(IOWKIT_HANDLE localiow, int add)
{
                       for(int i=0; i<=7;i++){
                               report[i]=0;
                               }
                       iow=localiow;
                       address=add;
                       report[0]=1;
                       report[1]=1;
                       res=IowKitWrite(iow,1,report,8);
                       if(res==8){
                                  cout << "IIC-Mode started succesfully" << endl;
                                  }
                       else{
                            cout << "Trouble with startring IIC" << endl;
                            }
};

iic::~iic()
{
           for(int i=0; i<=7;i++){
                               report[i]=0;
                               }
           report[0]=1;
           report[1]=0;
           res=IowKitWrite(iow,1,report,8);
           if(res==8){
                      cout << "IIC-Mode stopped successfully" << endl;
                      }
           else{
                cout << "Trouble with stopping IIC" << endl;
                }
};

bool iic::read(char* rep, int count)
{
     report[0]=3;
     report[1]=count;
     report[2]=address+1;
     res=IowKitWrite(iow,1,report,8);
     if(res!=8){
                cout << "Read-Request not send successfully" << endl;
                return false;
                }
     do{
                IowKitRead(iow,1,rep,8);
                }while(report[0]!=3);
     
     int x=rep[1];
     if(x==-128){
                     cout << "Error: Slave does not Ack read command" << endl;
                     return false;
                     }
     else{
          return true;
          }
};

bool iic::write(char* rep)
{
     int count=0;
     
     for(int i=0;i<=5;i++){
             if(rep[i]!=0)count++;
             }
             
     report[0]=2;
     report[1]=192+count;
     report[2]=address;
     int j=0;
     for(int i=3;i<=7;i++){
             report[i]=rep[j];
             j++;
             }
     res=IowKitWrite(iow,1,report,8);
     if(res!=8){
                cout << "Send-Request not send successfully" << endl;
                return false;
                }
     report[0]=0;
     do{
                IowKitRead(iow,1,report,8);
                }while(report[0]!=2);
     
     int x=report[1];
     if(x==-128){
                        cout << "Error: Slave not Ack write operation" << endl;
                        return false;
                        }
     else{
          return true;
          }
};

int main()
{
    IOWKIT_HANDLE iohandle;
    iohandle = IowKitOpenDevice();
    if(iohandle!=NULL){
                       cout << "IOWarrior started successfully" << endl;
                       if(IowKitGetProductId(iohandle)==IOWKIT_PRODUCT_ID_IOW24){
                                                                              cout << "Device is IOWarrior24" << endl;
                                                                              }
                       if(IowKitGetProductId(iohandle)==IOWKIT_PRODUCT_ID_IOW40){
                                                                              cout << "Device is IOWarrior40" << endl;
                                                                              }
                       
                       cout << IowKitGetRevision(iohandle) << endl;                                                        
                       if(IowKitGetRevision(iohandle)==0) cout << "Invalid IOHandle" << endl;
                       if(IowKitGetRevision(iohandle)<0x1010) cout << "Device is Legacy IOW" << endl;
                       
                       iic adt(iohandle,0x4C);
                       char rep[8];
                       rep[0]=0x00;
                       if(adt.write(rep)){
                                          if(adt.read(rep,1)){
                                                              for(int i=0;i<=7;i++){
                                                                      int x=rep[i];
                                                                      cout << x << endl;
                                                                      }
                                                                      }
                                                                      }
                       
                       
                       }
    else{
         cout << "No IOWarrior found" << endl;
         }
                       
                       
                       
                       
                       
                       
                       
}
Guido Körber
Site Admin
Posts: 2876
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Post by Guido Körber »

Ja, das heisst dann wohl, dass der Chip sich nicht angesprochen fühlt. Dafür kann es viele Gründe geben, Leitungen vertauscht, Adresse falsch, Chip kaputt...

Wie weit vom IO-Warrior entfernt ist der Chip?
Robert Marquardt
Posts: 543
Joined: Mon Dec 01, 2003 6:09 pm

Post by Robert Marquardt »

Meine Empfehlung ist erst mal die Datenstrukturen und Namen aus iowkit.h zu verwenden. Das macht die Sache deutlich uebersichtlicher.
Man sollte auch die Basisfunktionen der C Standardlib beherrschen. Namentlich memset().

Der Fehler duerfte im iic::write liegen.

Code: Select all

     int count=0;
     
     for(int i=0;i<=5;i++){
             if(rep[i]!=0)count++;
             }
Das zaehlt komplett falsch. Es wird nicht am ersten 0-Byte abgebrochen.
Die korrekt zaehlende Funktion waere hier strlen().
Da der uebergebene rep eine lokale Variable ist, enthaelt er natuerlich Zufallszahlen. Die Initialisierung "rep[0]=0x00;" fuehrt daher nicht dazu das 0 Bytes an den IIC geschrieben werden. 0 Bytes an den IIC zu schreiben ist vermutlich ebenfalls die falsche Idee.
dereulenspiegel
Posts: 14
Joined: Mon Dec 26, 2005 7:55 pm

Post by dereulenspiegel »

Ich habe meine write-Funktion so umgeschrieben, dass nun nur noch ein Byte geschrieben wird. Dadurch muss ich nicht mehr zählen. Das hat bisher aber nichts verbessert. Das mit den 0 Bytes ist ein Missverständniss. Es soll der Wert 0x00 auf den IIC geschrieben werden. Also der Chip ist nicht defekt und die Leitungen auch nicht vertauscht. Der ADT ist auch nur wenige Millimeter vom IOW entfernt.
Ich habe die Write- und Read-Funktionen in einer Do-While-Schleife laufen lassen. Nach einigen Minuten (in denen wir die SDA und SCL-Leitungen per Oszilloskop beobachtet haben) funktionierte es auf einmal. Das ließ sich aber nicht replizieren.
Guido Körber
Site Admin
Posts: 2876
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Post by Guido Körber »

Geht es denn wenn die Reports von Hand mit SimpleHIDwrite erzeugt werden?

Das ist immer die einfachste Möglichkeit zu testen ob die Hardware tut was sie soll.
dereulenspiegel
Posts: 14
Joined: Mon Dec 26, 2005 7:55 pm

Post by dereulenspiegel »

Dummerweise bekomme ich da die gleiche Fehlermeldung im Report. Kann es vielleicht ein Timingproblem sein? Ich habe am Oszilloskop beobachtet, dass der IOW nicht kontinuierlich ein Signal an SCL hält. Kann es vielleicht daran liegen? In einer anderen Schaltung funktioniert der IOW jedoch (auch mit IIC). Den ADT haben wir auch schon ausgetauscht. Es hat aber nichts genutzt.
Guido Körber
Site Admin
Posts: 2876
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Post by Guido Körber »

SCL muss nicht kontinuierlich erzeugt werden, sollte es auch nicht, wenn die am Bus angeschlossenen Chips eine Chance haben sollen in einen Schlafmodus zu gehen.

Wenn es auch mit SimpleHID nicht geht, dann liegt ein Hardwareproblem vor, oder es wird eine falsche Adresse versucht anzusprechen.
dereulenspiegel
Posts: 14
Joined: Mon Dec 26, 2005 7:55 pm

Post by dereulenspiegel »

Jetzt bin ich ganz verwirrt. Habe gerade mein Programm alle Adressen des IIC-Busses durchgehen lassen. Ich bekomme auf drei Adressen ($80, $98 und $99) einen erfolgreiche Verbindung. Aber ich bekomme jedes mal dieselben Daten zurück. Egal was ich lesen will. Das ist sehr merkwürdig. Es gibt doch einen Slave am Bus und der hat die Adresse $4C. Das aktuellste Datenblatt habe ich mir auch angesehen. Die Adresse und die Register die ich ansprechen will sollten korrekt sein.
Guido Körber
Site Admin
Posts: 2876
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Post by Guido Körber »

Also nachdem ich mir mal das Datenblatt angesehen habe ist es klar: Analog Devices hat eine etwas komische Darstellung der IIC Adresse. Die $4C bezieht sich auf eine 7 Bit Darstelung, also ohne R/W Bit.

Richtig ist also $98 als Adresse.
Post Reply