Hallo, ich schlage mich gerade mit dem Externen AD7793 [[ http://www.analog.com/static/imported-files/data_sheets/AD7792_7793.pdf ]] rum (und meinem MSP230F248) Für meine Messung möchte ich den SingelConvert Modus benutzen. Ich habe aber einen Bedienfehler drin den ich nicht erkenne. Könntet ihr mir helfen? Also ich gehe wie folg vor: Ich habe die Kommunikation aufgebaut und kann alle Register auslesen nur mit den Messungen habe ich meine Probleme. Zu erst Resette ich den ADC: FF,FF,FF,FF Dann beschreibe ich das: - IO Register 28,02 - Mode Register 08,20,07 Dann möchte ich die Messungen Starten erst Ch1 dann Ch2: - Config Register 10,11,90 lese Data(C0 sende ich um einen Takt zu erzeugen) 58, while(RDY); //Warten bis der ADC sagt der er gemessen hat C0,C0,C0 - Config Register 10,11,92 lese Data(C0 sende ich um einen Takt zu erzeugen) 58, while(RDY); //Warten bis der ADC sagt der er gemessen hat C0,C0,C0 Das Problem was ich habe stellt sich so da das ich genau EINE Messung nach dem RESET machen kann. Beim 2. beschreiben des Config registers signalisiert mir der ADC nicht das er fertig mit der Messung sein. Muss ich ihm bevor er mit der Messung startet noch andere Sachen bereitstellen? Wenn ich nun nur einen durchlauf machen lasse, und ihn danach RESETe um dann den anderen Ch zu messen bekomme ich ein Ergebnisse. Aber ich muss doch nicht für jede Messung einen reset ausführen oder? LG und danke für jede Hilfe
MM keiner da der sowas schonmal gemacht hat ? Welche Register muss ich alle beschreiben um eine neue Messung zu starten? Oder muss ich den ADC nach JEDER Messung in den RESET bringen? LG
hier ist mal 7792 im single conversion :)
1 | void tempInit(void) |
2 | {
|
3 | tempReset(); |
4 | Delay10KTCYx(50); // Pause |
5 | |
6 | tempSetRegister16(ADCCONFREG, 0x1200); // Select buffered mode / chanel 1 / unipolar / gain 4 |
7 | tempSetRegister8(ADCIOREG, 0x02); |
8 | tempSetRegister16(ADCMODEREG, 0x0009); // 50Hz 80dB rejection |
9 | Delay10KTCYx(50); // Pause |
10 | }
|
11 | |
12 | void tempReset(void) |
13 | {
|
14 | TEMP_CS = 0; |
15 | SPIWrite8(0xFF); |
16 | SPIWrite8(0xFF); |
17 | SPIWrite8(0xFF); |
18 | SPIWrite8(0xFF); |
19 | TEMP_CS = 1; |
20 | }
|
21 | |
22 | double tempRead(void) |
23 | {
|
24 | double temp; |
25 | |
26 | tempSetRegister16(ADCMODEREG, 0x2009); // 50Hz 80dB rejection and start conversion |
27 | |
28 | TEMP_CS = 0; |
29 | while(SDI); // wait for conversion to finish |
30 | TEMP_CS = 1; |
31 | |
32 | temp = tempConvert(tempReadRegister16(ADCDATAREG)); // read last conversion result and convert |
33 | |
34 | return temp; |
35 | }
|
wie unschwer zu erkennen messe ich damit eine temperatur :D hoffe es hilft, die 2 ICs sind ja doch eng verwandt
Weil man mich gefragt hat, hier der restliche Code:
1 | void tempSetRegister16(unsigned char reg, unsigned int data) |
2 | {
|
3 | reg = reg << 3; |
4 | TEMP_CS = 0; |
5 | softSPIWrite8(0x00 | reg); // write to status reg |
6 | softSPIWrite16(data); |
7 | TEMP_CS = 1; |
8 | }
|
9 | |
10 | void tempSetRegister8(unsigned char reg, unsigned char data) |
11 | {
|
12 | reg = reg << 3; |
13 | TEMP_CS = 0; |
14 | softSPIWrite8(0x00 | reg); // write to status reg |
15 | softSPIWrite8(data); |
16 | TEMP_CS = 1; |
17 | }
|
18 | |
19 | unsigned char tempReadRegister8(unsigned char reg) |
20 | {
|
21 | unsigned char data; |
22 | |
23 | reg = reg << 3; |
24 | TEMP_CS = 0; |
25 | softSPIWrite8(0x40 | reg); // write to status reg |
26 | data = softSPIRead8(); |
27 | TEMP_CS = 1; |
28 | |
29 | return data; |
30 | }
|
31 | |
32 | unsigned int tempReadRegister16(unsigned char reg) |
33 | {
|
34 | unsigned int data; |
35 | |
36 | reg = reg << 3; |
37 | TEMP_CS = 0; |
38 | softSPIWrite8(0x40 | reg); // write to status reg |
39 | data = softSPIRead16(); |
40 | TEMP_CS = 1; |
41 | |
42 | return data; |
43 | }
|
Noch die notwendigen Defines:
1 | // ext. ADC
|
2 | #define ADCSTATREG 0x00 // 8bit
|
3 | #define ADCMODEREG 0x01 // 16bit
|
4 | #define ADCCONFREG 0x02 // 16bit
|
5 | #define ADCDATAREG 0x03 // 16bit
|
6 | #define ADCIDREG 0x04 // 8bit
|
7 | #define ADCIOREG 0x05 // 8bit
|
8 | #define ADCOFFREG 0x06 // 16bit
|
9 | #define ADCFSREG 0x07 // 16bit
|
Hoffe damit ist alles klar :)
Hallo, ich hab gerade das Datenblatt des AD7792/3 durchforstet und bin auf die Temeperatur-Messschaltung gestoßen. Diese arbeitet als 3-Leiter Messung. Ist mit diesem Baustein auch eine 4-Leiter Messung möglich? Danke! Martin
Hallo, ich haben den oben gennanten Code verwendet, krieg es aber ums verrecken nicht gebacken das er einigermaßen nachvollziehbare Werte anzeigt. Aktuell wechselt er willkürlich von 0 und 65535 hin und her. Verdrahtet ist das ganze wie im Bild zu sehen. Controller ist ein Atmega8 mit Standardgrunbechaltung. Hat jemand einen Idee wo der Fehler liegt, bin leider noch Anfänger!
Hi ! Du schreibst du hast einen 7793 eingesetzt und deine Werte liegen zwischen 0x0000 und 0xFFFF. Der 7793 hat aber kein 16Bit register sondern ein 24Bit Register. Also 0xFFFFFF = 16.777.216. Also ist die Frage: 1) liest due vielicht nur die 16 der 24 Bits aus? 2) Wenn du 24Bits ausliest aber im untersten berecht mist, könnte es dann sein das dein ADC die Werte nicht erfassen kann da er (überlegt) Spannungen nur Messen kann die Größer als 0,5V sind. 3) für welchen MODE hast du dich endschieden. Wenn du sehr schnell Messen must ist der ADC nicht die Optimale wahl. Ich habe gute erfahrungen bei eriner Messzeit von ca 120ms gemacht. Bei Temperaturn änmdern sich normalerweise nicht so schnell ;) 4) Funktiniert den die Kommunikation? Kannst du die beschriebenen Register wieder auslesen ? 5) Gibst du den Strom auch auf dem Richtigen Ausgang ? (Mit Multimeter die Spannung am RTD Prüfen) ------------- Oh ich habe gerade erst deinen Code gesehen. Versuch dochmal alle 24 Bits ab zu holen ;) SPDR = 0x00; /* Start transmission */ while(!(SPSR & (1<<SPIF))); /* Wait for transmission complete */ twobytes |= (SPDR << 8); SPDR = 0x00; /* Start transmission */ while(!(SPSR & (1<<SPIF))); /* Wait for transmission complete */ twobytes |= SPDR; SPDR = 0x00; /* Start transmission */ while(!(SPSR & (1<<SPIF))); /* Wait for transmission complete ------ LG
Fehler von mir, ich verwende natürlich den AD7792. Daher auch nur 16Bit. Geschwindigkeit liegt bei t(settle) = 120ms, müsste also passen. Ausgang der Stromquelle habe ich mit dem IO-Register auf 210uA auf IEXC1 to Pin iout1 gestellt. Den RTD hab ich mal mit einem poti simuliert das auf 200 Ohm steht. Dadurch müsste ich einen Spannungsabfall von 0,042V messen. Da tut sich aber rein gar nix!
Hab jetzt mal folgendes versucht:
1 | int main (void) { |
2 | |
3 | uint8_t data = 0x00; |
4 | char text2[8]; |
5 | spi_init(); |
6 | |
7 | PORTB &= ~_BV(PB2); |
8 | SPIWrite8(0x60); |
9 | PORTB |= _BV(PB2); |
10 | |
11 | PORTB &= ~_BV(PB2); |
12 | data = SPIRead8(); |
13 | PORTB |= _BV(PB2); |
14 | |
15 | |
16 | lcd_init(); |
17 | lcd_clear(); |
18 | utoa(data,text2,10); |
19 | lcd_string(text2); } |
Dies müsste eigentlich das ID-Register auslesen. Gibt aber wieder nur lauter Müll!
Hab jetzt nochmal folgendes probiert: Ich schreibe zuerst 4x 0xFF um den AD7792 zu resetten. Anschließend schreibe ich in das CommunicationRegister das die nächste Operation eine Schreiboperatoin in das IO-register ist. Dann schreibe ich einfach 0xFF in da IO-Register. Anschließend dann wieder in das Communications-Register das der nächste Befehl ein Lesezugriff auf das IO-Register ist. Dann sende ich 0x00 als Dummybyte um das Register zu lesen. Theoretisch müsste der vorherige Wert von 0xFF zurückkommen, es kommt aber nur 0. Hier noch der Code:
1 | #include <avr/io.h> |
2 | #include "lcd-routines.h" |
3 | #include <stdlib.h> |
4 | #include <util/delay.h> |
5 | |
6 | |
7 | void master_init (void); |
8 | uint8_t master_transmit (uint8_t cdata); |
9 | |
10 | |
11 | void master_init (void) { |
12 | /* Set MOSI and SCK output, all others input */
|
13 | DDRB |= (1<<PB2) | (1<<PB3) | (1<<PB5); |
14 | |
15 | /* Enable SPI, Master, set clock rate fck/32 */
|
16 | SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR1); |
17 | //Aktivierung des SPI, Master, Taktrate fck/16
|
18 | }
|
19 | |
20 | uint8_t master_transmit (uint8_t cdata) { |
21 | uint8_t daten; |
22 | PORTB &= ~_BV(PB2); |
23 | _delay_ms(1); //SS am Slave Low --> Beginn der Übertragung |
24 | SPDR = cdata; //Schreiben der Daten |
25 | while (!(SPSR & (1<<SPIF))); |
26 | daten = SPDR; |
27 | _delay_ms(1); |
28 | PORTB |= _BV(PB2); //SS High --> Ende der Übertragung |
29 | return daten; |
30 | }
|
31 | |
32 | int main (void) { |
33 | |
34 | master_init (); |
35 | lcd_init(); |
36 | uint8_t data; |
37 | |
38 | |
39 | _delay_ms(100); |
40 | master_transmit(0xFF); |
41 | _delay_ms(100); |
42 | master_transmit(0xFF); |
43 | _delay_ms(100); |
44 | master_transmit(0xFF); |
45 | _delay_ms(100); |
46 | master_transmit(0xFF); |
47 | |
48 | _delay_ms(100); |
49 | master_transmit(0x28); |
50 | _delay_ms(100); |
51 | master_transmit(0xFF); |
52 | |
53 | _delay_ms(100); |
54 | master_transmit(0x68); |
55 | _delay_ms(100); |
56 | data = master_transmit(0x00); |
57 | char text2; |
58 | |
59 | |
60 | lcd_clear(); |
61 | utoa(data,text2,10); |
62 | lcd_string(text2); |
63 | |
64 | }
|
Hat jemand eine Idee an was es liegen kann. Benötige echt drigend Hilfe!
Was Passiert den wenn du das Status register ausliest ? Evt. erzeugt dein µC ja keinen Tackt zum Auslesen oder der kommt nicht am IC an. Oder du hast einen dreher in der Leitung (Hatte ich auch schon :( )
Habs endlich zum Laufen gebracht. Du hattest recht mit dem Takt. Ich hatte einfach eine Leitung falsch gesetzt. Aktuell hab ich aber noch ein Problem was er misst. Ich hab als Temperaturwiderstand aktuell einen Festwiderstand von 1k dran. Eine kleine Routine rechnet mir laut Datenblatt (siehe Seite 24) den gelieferten Code erst in die Eingangsspannung um und anschließend durch den Strom von 210µA, das ergibt dann den Widerstandswert. Bei 1k wird aber nur 554 Ohm angezeigt. Also mehr oder weniger genau die Hälfte. An was kann das liegen? Gain habe ich auf 8 geändert da ADC Input Spannung bei rund 210mV liegt.
MM Spanntan hatte ich gesagt du hast nicht 210µA sonndern 420µA drauf gegeben :) aber dann wüde deine Messung ja nicht stimmen. Ich würde erstmal Andere Wiederstände messen 500Ohm 2k 4k ... damit könntest du dann schonmal sagen ob es ein Offset Fehler oder ein Fachktor Fehler ist. Welche Formel hast du den genommen? Habe gerade mal ins DB geschaut, und da stehen immerhin 2 ! Du must da bachten on du Unipolar/Bipolar Messen möchtest. Wenn du keine Negativen Spannungen erwartet würde ich immer UNI vorziehen! Mal davon abgesehen das du ein Bit mehr auflösung hast must du keine Fallunterscheidung im µC machen. LG Bergie
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.