Datum:
12Bit ADC Board - MAX1238 Hab mir vor einiger Zeit einen ADC benötigt, den man relativ schnell über I2C abfragen kann. Außerdem sollte dieser eine Auflösung von mindestens 10 bis 12 Bit besitzen. Dabei bin ich auf den MAX1238 (12Bit) und MAX1138 (10Bit)gestoßen. Zum Testen hab ich mir kleine Boards für die Chips gebaut. Das Entwicklungs Board besteht aus dem analog digital Converter Chip MAX1238 der Firma Maxim (http://www.maxim-ic.com/datasheet/index.mvp/id/3271) * 12Bit ADC * 12-Channel Single-Ended or 6-Channel Fully Differential * High-Speed I²C-Compatible Serial Interface o 400kHz Fast Mode o 1.7MHz High-Speed Mode * Internal Reference 4.096V * External Reference: 1V to VDD * Low Power o 670µA at 94.4ksps o 230µA at 40ksps o 60µA at 10ksps o 6µA at 1ksps o 0.5µA in Power-Down Mode Der Chip ist sehr einfach anzusteuern und besitzt verschiedene Betriebsmodi (Single-Ended und Fully Differential). mehr Infos hier:http://www.jtronics.de/elektronik-boards/adc-12bit... Beispiel für die Ansteuerung im Modus Single-Ended und externer Referenzspannung an Pin Ref. Benutzt wurde die I2C/TWI Lib von peter fleury Der 12Bit Wert wird vom Max1238 über mit 2 Nachrichten zu je 1 Byte gesendet. Nachteilig hierbei ist, dass der Max1238 die ungenutzen Bit Stellen mit 1 auffüllt.
//############ Adresse MAX1238 #define Adr_MAX1238 0b01101010 Data_Array_Messwert[11]; //############ init MAX1238 via I2C void ADC_MAX1238_init(void) { i2c_start_wait(Adr_MAX1238+I2C_WRITE); // device address & write mode i2c_write(0b10100010); // write Register i2c_write(0b00010111); // write Register i2c_stop(); // stop i2c } //############ auslesen MAX1238 via I2C void ADC_MAX1238(void) { uint8_t hig,low ; // hight und Low Byte i2c_start_wait(Adr_MAX1238+I2C_READ); // device address & read mode for (uint8_t i=0; i<=10; i++) // alle 10 Kanäle auslesen { low = i2c_read(1); low &= ~((1 << 7) | (1<<6)| (1<<5)| (1<<4) ); hig = i2c_read(1); Data_Array_Messwert[i]= ((low << 8)| hig); } i2c_stop(); } |
Grüße martin
Datum:
Hallo, ich versuche mich gerade an dem Max1238. Leider bekomme ich beim auslesen immer für das Highbyte 15 und für das Lowbyte 255 übermittelt. Andere I2C Bausteine wie z.B. PCF8574 oder 24LC512 funktionieren einwandfrei. Ich kann mir nicht erklären, warum der hier nicht so will wie ich es gerne hätte. Hat da jemand evtl. eine Idee? Ich hänge mal die Routine an: //***Aufruf der Funktion in main.c**** //**Konfiguration Max1238out(0B10100010); Max1238out(0B00000111); //lesen des Istwert in main.c ADWandler[i] = Max1238in(); //Max1238 schreiben unsigned char Max1238out (unsigned char adr){ starti2c(); sendbytei2c(0b01101000); sendbytei2c(adr); //Configuration Byte stopi2c(); } //Max1238 lesen unsigned char Max1238in (void){ unsigned char daten, daten2; starti2c(); sendbytei2c(0b01101101); for (i=0; i<=10; i++){ daten = readbyteI2C(1); //Lowbyte daten &= ~((1 << 7) | (1<<6)| (1<<5)| (1<<4) ); daten2 = readbyteI2C(1); //Highbyte ADWandler[i]= ((daten << 8)| daten2); } stopi2c(); }
Datum:
Die fragen beantworten sich mit dem Code-Beispiel weiter oben ... Das Beispiel funktioniert einwandfrei
Datum:
//####################################### I2C i2c_init(); //####################################### init MAX1238 via I2C if(i2c_start(Adr_MAX1238+I2C_WRITE)) { i2c_stop(); // failed to issue start condition, possibly no device found } else // issuing start condition ok, device accessible { i2c_write(0b10100010); // write address = 5 i2c_write(0b00010111); // write value 0x75 to EEPROM i2c_stop(); } //####################################### messen_adc MAX1238 void I2C_ADC_MAX1238(void) { uint8_t hig,low = 0; // hight und Low auslese Variable für uniq uint16_t dummy = 0; //############# I2C MAX1238 - 12Bit ADC if (i2c_start(Adr_MAX1238+I2C_READ)) { i2c_stop(); // failed to issue start condition, possibly no device found } else // issuing start condition ok, device accessible { for (uint8_t i=0; i<=10;i++) { low = i2c_read(1); low &= ~((1 << 7) | (1<<6)| (1<<5)| (1<<4) ); hig = i2c_read(1); dummy = ((low << 8)| hig); //###### umrechnen in mV [ADC*VREF= Vin*Auflösung] //dummy = dummy*1.221001221; //###### Ausgabe uart1_puts("Kanal-"); // send string if(i<10) uart1_puts(" "); // send string itoa( dummy , buffer, 10); // interger to string & send uart1_puts(buffer); // send uart1_puts(": "); // send string if(dummy<10) uart1_puts(" "); // send string if(dummy<100) uart1_puts(" "); // send string if(dummy<1000) uart1_puts(" "); // send string itoa( dummy , buffer, 10); // interger to string & send uart1_puts(buffer); // send uart1_puts(" mV\r"); // send string } i2c_stop(); } } |
Datum:
den code hab ich grad aus einem laufenden Programm genommen. Der I2C Bus wird mit der fleury i2C lib betrieben. Grüße martin
Datum:
Hi,
meine Routine funktioniert ja auch, allerdings nur mit all den anderen
I2C Bausteinen. Der AD Wandler will allerdings nicht und ich habe keine
Idee warum nicht.
Wäre also ein feiner Zug, wenn sich das mal jemand anschauen könnte und
mir sagen an was es liegen könnte.
Ich füge einfach noch mal die eigentliche I2C Routine ein.
#define iic_sda_d pd3_0 /* 1=Ausgang, 0=Eingang */
#define iic_sda p3_0
#define iic_scl_d pd3_3
#define iic_scl p3_3
#define TRUE 1
#define FALSE 0
void sdah(void) { iic_sda = 1; }
void sdal(void) { iic_sda = 0; }
void sclh(void) { iic_scl = 1; }
void scll(void) { iic_scl = 0; }
void starti2c(void) { sdal(); scll(); }
void stopi2c(void) { sdal(); sclh(); sdah(); }
void restarti2c(void) { sdah(); sclh(); starti2c(); }
void I2C_init(void) { prc2=1;
iic_sda_d = 1;
prc2=1;
iic_scl_d = 1;
starti2c();
stopi2c(); }
unsigned char sdain(void)
{ unsigned char dummy=0;
//prc2=1;
iic_sda_d=0;
dummy = iic_sda;
//prc2=1;
iic_sda_d=1;
return(dummy);
}
/* Ab hier sind die Funktionen nicht mehr Hardwareabhaengig! */
/* Gibt ein Byte Âber den I2C-Bus aus, war das erfolgreich, wurde */
/* dieses Byte also von einem der ICs am Bus akzeptiert, dann */
/* liefert diese Funktion ein TRUE zurÂck. */
unsigned char sendbytei2c(unsigned char daten)
{
short x; unsigned char dummy;
for (x=7;x>=0;x--)
{
if (daten & 0x80) /* Die acht Datenbits ausgeben */
sdah();
else sdal();
daten = daten << 1 ; /* Ein Bit nach links schieben */
sclh(); scll(); /* Zum n„chsten Bit takten */
}
sdah(); /* SDA zum Eingang umschalten */
sclh(); /* Ack aus Slave takten */
dummy=sdain(); /* ACK lesen */
scll();
if (dummy==FALSE) return (TRUE); else return (FALSE);
}
/* Liesst ein Byte vom I2C-Bus, es wird ausserdem das ack-bit erwartet
*/
/* Diese ACK-Bit muss immer TRUE sein, es sei denn es wird das letzte
*/
/* Datenwort von einem Device gelesen, dann muss es FALSE sein.
*/
unsigned char readbyteI2C(unsigned char ack)
{ short x; unsigned char dummy;
dummy=0;
sdah();
for (x=7;x>=0;x--)
{ sclh();
dummy=dummy << 1;
if (sdain()==TRUE) dummy=dummy|(unsigned char)0x01;
scll();
}
if (ack==TRUE) sdal(); else sdah();
sclh();
scll();
return(dummy);
}
//Max1238 schreiben
unsigned char Max1238out (void){
starti2c();
sendbytei2c(0b01101010); //Adresse
sendbytei2c(0b10100010); //Configuration Byte
sendbytei2c(0b00010111); //Configuration Byte
stopi2c();
}
//Max1238 lesen
unsigned char Max1238in (void){
unsigned char daten, daten2;
starti2c();
sendbytei2c(0b01101011); //Adresse
for (i=0; i<=10; i++){
daten = readbyteI2C(1); //Lowbyte
daten &= ~((1 << 7) | (1<<6)| (1<<5)| (1<<4) );
daten2 = readbyteI2C(1); //Highbyte
ADWandler[i]= ((daten << 8)| daten2);
}
stopi2c();
return (daten);
}
Am AIN0 liegen ca. 3,5V an. Sollte doch funktionieren, oder?
Nur warum nicht...
DANKE
Michael


