Datum:
Hallo kann jemand mir helfen ich muss mit Atmega 16 spi bus und ADW max 146 umgehen. Die Analoge werte eines Kanals des ADW(MAX146)werden uber spi bus mit dem ATmega 16 kommuniziert und an PC über RS232 gesendet.Die Analoge werte können durch das Poti auf der SPI-Platine des Evaluationsboards verändert werden. Ich habe folgendes Programm zur Verfügung. //polli2_max146.c //Verwendung des MAX146/147 (8 Kanäle, 12 Bit AD-Wandler) //auf ext. Erweiterungsboard (Polli_V2_spi) //zum Einlesen von analogen Daten über SPI //und Ausgabe über RS 232 zum PC //Taste 1 (int0) unterbricht SPI-Aktivität kurzzeitig, LEDs blinken //Compiler: CodeVision 1.24.8 // #include <mega16.h> #include <stdio.h> #include <spi.h> #include <delay.h> // MAX147 externe Spannungsreferenz [mV] - nicht für MAX 146 erf. #define VREF 2500 // MEGA 16 SPI-Leitungen für MAX146/147 #define NCS PORTB.4 // MAX146-Pin 18 ---> 13 CON 1 auf Erweiterungsboard #define DOUT PINB.5 // MAX146-Pin 17 ---> 14 // SCLK MAX146 Pin 19 ---> 19 // DOUT MAX146 Pin 15 ---> 15 union adcu { unsigned char byte[2]; unsigned int word; }; interrupt [EXT_INT0] void ext_int0_isr(void) // Taste 1 auf Polliboard { PORTD=0x60; //Leds ein-aus delay_ms (1000); PORTD=0x00; delay_ms(1000); } void uartinit(void) { UCSRA=0x00; UCSRB=0x58; //TXD enable, 8 Bit bei 90S8535 UCR UBRRL=0x33; //9600 Baud bei 8 MHz Quarz bei 90S8535 UBRR } // Funktion f. eine AD-Wandlung - Wert zurück unsigned int max147_read(unsigned char kan) { union adcu adc_data; unsigned char TB1, RB1, RB2, RB3; //control byte f. Max 147 //TB1=0x8F; Kan. 0 ..., externe clock f. AD TB1=0x8e; //Start, Kan. 7, unipolar, //single ended, interne clock für AD if (kan==0) TB1=0x8e; else if (kan==1) TB1=0xce; else if (kan==2) TB1=0x9e; else if (kan==3) TB1=0xde; else if (kan==4) TB1=0xae; else if (kan==5) TB1=0xee; else if (kan==6) TB1=0xbe; else if (kan==7) TB1=0xfe; NCS=0; //Chip Select f. Max 147 delay_us(100); SPDR=TB1; RB1=spi(0); //SPDR=0x00; RB2=spi(0); //SPDR=0x00; RB3=spi(0); NCS=1; //deselect f. MAX147 delay_us(10); adc_data.byte[1]=RB2; adc_data.byte[0]=RB3; return(adc_data.word>>3)&0xfff; } void main(void) { unsigned n1, n2, n3; // Ergebnis der AD-Wandlung float mittelw; // Einstellung f. printf auf float with precision unsigned char kan; // Input/Output Ports initialization // Port A DDRA=0x00; PORTA=0x00; DDRD=0x60; //Leds // Port B // the /SS pin is set as an output // with level 1, it's required by // the SPI to work in master mode //------ mega16 ------ // //PB.7=SCLK PB.6=MISO PB.5=MOSI PB.4=SS // DDRB=0xB0; PORTB=0xB0; // Port C DDRC=0x00; PORTC=0x00; uartinit(); // SPI initialization des uP 90S8535 // SPI Type: Master // SPI Clock Rate: 921.6 kHz=3.6864 MHz/4 // // SPI Clock Phase: Cycle Half // SPI Clock Polarity: Low // SPI Data Order: MSB First SPCR=0x50; //putsf("\rMAX147 Demo\n"); //putsf("\r***********************************************\n"); delay_us(100); while (1) { /* for (kan=0; kan<8; kan++) { n=max147_read(kan); printf("Kanal= %2u N=%4u U=%4umV\r\n",kan, n,(unsigned) ((long) n*VREF/4096)); } */ kan=0; n1=max147_read(kan); printf("\r%4u\r", (unsigned) ((long) n1*VREF/4096)); n2=max147_read(kan); printf("%4u\r", (unsigned) ((long) n2*VREF/4096)); n3=max147_read(kan); printf("%4u\r", (unsigned) ((long) n3*VREF/4096)); mittelw= (float) ((n1+n2+n3)/3); printf("------> Mittelw: %f\r", mittelw*VREF/4096); delay_ms(500); GICR=0x40; MCUCR=0x02; #asm("sei") }; } ich muss das Programm ändert so ab,dass die Datenerfassung in Abstand von einer Sekunde erfolgt. Kan jemand mir helfen da ich weiß genau nicht wo ich das programm modifizieren muss und die lösung zu haben.
Datum:
Entweder du lässt den Contoroller im Mainloop hängen und entfernst die For-Schleife mit der Messung. Die For Schleife wird in eine void-Funktion ausgelagert. Dann nimmst du einen der 3 Timer wie im AVR-GCC-Tutorial als Interruptquelle, der dann die For-Schleife, die in die Mess-Funktion ausgelagert wurde, einmal pro Sekunde auführt. Oder du änderst da delay_ms auf 1000(nicht so schön). Vorteil der Interrrupt-Methode: Der Prozessor wird durch das Delay nicht blockiert und kann noch viele andere schöne Dinge erledigen, an die du bis jetzt noch nicht gedacht hast. Vielleicht eine Menüführung und Display, wo man die Zeit zwischen 2 Messungen einstellen kann. Dir ist bewusst, dass das Rechnen mit Floatvariablen auf diesem Prozessor nicht in Hardware gegossen ist? Das verschwendet Rechenzeit und Flashspeicher. Such mal nach "Festkommaarithmetik". mfg mf
Datum:
Ich bedanke mich sehr für ihre Antwort, es ist wirklich sehr nette von Ihnen. Das problem ist dass ich mich nich gut kennnt mit dem Mikrocontroller, da ich Medizintechnik,studiert. Es ist ein projektarbeit, und jede muss aussuchen,aber ohne grundkenntnis es ist schwer ich habe schon so viel zeit darüber gemacht ohne Fortsetzung. Please können sie das teile des geänderten Progr. beispielweise schreiben. Es kann mich vielleich helfen. Noch eine frage was muss ich verstehen und welche unterlagen brauche ich und wo muss ich achten. Noch vielen dank.
Datum:
Noch eine Frage Minifloat wenn si das Prog verstehen. Warum werden die variable n1,n2,und n3 initialisiert. Was macht das Prog im mainloop genau. vielen dank Minifloat.
Datum:
>Warum werden die variable n1,n2,und n3 initialisiert. >unsigned n1, n2, n3; // Ergebnis der AD-Wandlung Diese Variablen werden nicht initialisiert. Das müssen sie auch nicht, da sie bei der ersten Verwendung einen definierten Wert erhalten, nämlich den vom AD-Wanlder am Kanal, der in der Variablen kan steht: >n1=max147_read(kan);
// Auswählen von Kanal 0 kan=0; // Einlesen des AD Kanals 0 in n1 n1=max147_read(kan); // Wagenrücklauf am Terminal, Ausgeben von der Spannung aus n1 ohne Nachkommastellen als Zahl der Länge 4, Wagenrücklauf im Terminal printf("\r%4u\r", (unsigned) ((long) n1*VREF/4096)); // Einlesen des AD Kanals 0 in n2 n2=max147_read(kan); // Ausgeben von der Spannung aus n2 ohne Nachkommastellen als Zahl der Länge 4, Wagenrücklauf im Terminal printf("%4u\r", (unsigned) ((long) n2*VREF/4096)); // Einlesen des AD Kanals 0 in n3 n3=max147_read(kan); // Ausgeben von der Spannung aus n3 ohne Nachkommastellen als Zahl der Länge 4, Wagenrücklauf im Terminal printf("%4u\r", (unsigned) ((long) n3*VREF/4096)); // Ausrechnen des Mittelwerts von n1, n2, n3 mittelw= (float) ((n1+n2+n3)/3); // Ausgeben der mittleren Spannung der letzten 3 Messungen an AD Kanal 0 printf("------> Mittelw: %f\r", mittelw*VREF/4096); // 500 ms CPU belasten, ohne etwas zu tun delay_ms(500); // Irgendeinen Interrupt einschalten, dazu Datenblatt lesen! GICR=0x40; // Datenblatt lesen! MCUCR=0x02; |
Interrupts soll man immer so kurz wie möglich halten, das hier ist folglich überhaupt keine gute Idee:
interrupt [EXT_INT0] void ext_int0_isr(void) // Taste 1 auf Polliboard { PORTD=0x60; //Leds ein-aus delay_ms (1000); PORTD=0x00; delay_ms(1000); } |
(Normale) Taster sollte man gar nicht an Interrupts anschließen, das ist ganz schlechter Stil. So macht man das besser: http://www.mikrocontroller.net/articles/AVR-GCC-Tu... Genauso schlecht ist das:
GICR=0x40;
MCUCR=0x02;
|
Hier weiß niemand, ohne das Datenblatt zu lesen, was da genau passiert. Entweder man kommentiert das ordentlich, oder man verwendet die aussagekräftigen Bitnamen aus dem Datenblatt statt der Werte als Hexzahl. Nicht nur, dass es unübersichtlich ist, es ist auch noch gefährlich, ganze Register zu beschreiben, ohne, dass man den Überblick hat, was die einzelnen Bits daraus machen. Ich bezweifle, dass die Mehrzahl an Programmieren auf Anhieb und ohne Datenblatt wissen, welche Funktion die Bits haben, die hier gerade alle auf Null gesetzt werden: MCUCR=0x02; Ein Programm sollte man immer so schreiben, dass es ein anderer Programmierer ohne weiteres verstehen kann, ohne dass er dazu ein Datenblatt braucht. Und wenn man solche Sachen wie mit MCUCR macht, dann sollte man ganz genau als Kommentar dazuschreiben, warum das genau so gemacht wird. Grüße, Peter
Datum:
Angehängte Dateien:Vielen Dank für Ihre Hilfe PDIENER,wie ich schon vorher gesagt hast ich habe keine ahnung wo ich das programm ändert muss um die Aufgabestellung zu lösung. Ich füge einfach mal das Datenblatt von Mega16 bei, die seite 32 erklärt was macht der Register MCUCR und ab seite 14 erklärt für den register GICR. ich muss das Programm ändert so ab,dass die Datenerfassung in Abstand von einer Sekunde erfolgt. Ich füge ein auch die datablatt für MAX146. BITTE HILFE SONST BIN ICH TOD MIT DIESEM PROJETARBEIT. Noch vielen Dank,dass sie Interess haben. Noch frage wenn ich das progr-. mit avr compiliere, kommt ssolche fehlermeldung: ../ffffm.c:12:20: error: mega16.h: No such file or directory ../ffffm.c:14:17: error: spi.h: No such file or directory In file included from ../ffffm.c:15: ../ffffm.c:35: error: 'EXT_INT0' undeclared here (not in a function) ../ffffm.c:35: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void' ../ffffm.c: In function 'max147_read': ../ffffm.c:77: error: expected ';' before numeric constant was solche genau machen um die Fehler zu beheben. Vielen Dank nochmal für ihre Antwort.
Datum:
> BITTE HILFE SONST BIN ICH TOD MIT DIESEM PROJETARBEIT.
hui
Na dann geh doch einfach zu Deinem Kollegen oder Kommilitone hin und
drück ihm nen 100€-Schein in die Hand und sag: Mach mal bitte ;)
... oder Du änderst die 500 von delay_ms(500); in 1000 und guckst dass
Dus erst mal kompiliert bekommst.
Ansonsten, ruhe bewahren und tief durchatmen. So grau ist die Welt nun
auch wieder nicht ;-)
Datum:
Angehängte Dateien:Hallo kann jemand mir helfen ich muss mit Atmega 16 spi bus und ADW max 146 umgehen. Die Analoge werte eines Kanals des ADW(MAX146)werden uber spi bus mit dem ATmega 16 kommuniziert und an PC über RS232 gesendet.Die Analoge werte können durch das Poti auf der SPI-Platine des Evaluationsboards verändert werden. Ich habe folgendes Programm zur Verfügung. //polli2_max146.c //Verwendung des MAX146/147 (8 Kanäle, 12 Bit AD-Wandler) //auf ext. Erweiterungsboard (Polli_V2_spi) //zum Einlesen von analogen Daten über SPI //und Ausgabe über RS 232 zum PC //Taste 1 (int0) unterbricht SPI-Aktivität kurzzeitig, LEDs blinken //Compiler: CodeVision 1.24.8 // #include <mega16.h> #include <stdio.h> #include <spi.h> #include <delay.h> // MAX147 externe Spannungsreferenz [mV] - nicht für MAX 146 erf. #define VREF 2500 // MEGA 16 SPI-Leitungen für MAX146/147 #define NCS PORTB.4 // MAX146-Pin 18 ---> 13 CON 1 auf Erweiterungsboard #define DOUT PINB.5 // MAX146-Pin 17 ---> 14 // SCLK MAX146 Pin 19 ---> 19 // DOUT MAX146 Pin 15 ---> 15 union adcu { unsigned char byte[2]; unsigned int word; }; interrupt [EXT_INT0] void ext_int0_isr(void) // Taste 1 auf Polliboard { PORTD=0x60; //Leds ein-aus delay_ms (1000); PORTD=0x00; delay_ms(1000); } void uartinit(void) { UCSRA=0x00; UCSRB=0x58; //TXD enable, 8 Bit bei 90S8535 UCR UBRRL=0x33; //9600 Baud bei 8 MHz Quarz bei 90S8535 UBRR } // Funktion f. eine AD-Wandlung - Wert zurück unsigned int max147_read(unsigned char kan) { union adcu adc_data; unsigned char TB1, RB1, RB2, RB3; //control byte f. Max 147 //TB1=0x8F; Kan. 0 ..., externe clock f. AD TB1=0x8e; //Start, Kan. 7, unipolar, //single ended, interne clock für AD if (kan==0) TB1=0x8e; else if (kan==1) TB1=0xce; else if (kan==2) TB1=0x9e; else if (kan==3) TB1=0xde; else if (kan==4) TB1=0xae; else if (kan==5) TB1=0xee; else if (kan==6) TB1=0xbe; else if (kan==7) TB1=0xfe; NCS=0; //Chip Select f. Max 147 delay_us(100); SPDR=TB1; RB1=spi(0); //SPDR=0x00; RB2=spi(0); //SPDR=0x00; RB3=spi(0); NCS=1; //deselect f. MAX147 delay_us(10); adc_data.byte[1]=RB2; adc_data.byte[0]=RB3; return(adc_data.word>>3)&0xfff; } void main(void) { unsigned n1, n2, n3; // Ergebnis der AD-Wandlung float mittelw; // Einstellung f. printf auf float with precision unsigned char kan; // Input/Output Ports initialization // Port A DDRA=0x00; PORTA=0x00; DDRD=0x60; //Leds // Port B // the /SS pin is set as an output // with level 1, it's required by // the SPI to work in master mode //------ mega16 ------ // //PB.7=SCLK PB.6=MISO PB.5=MOSI PB.4=SS // DDRB=0xB0; PORTB=0xB0; // Port C DDRC=0x00; PORTC=0x00; uartinit(); // SPI initialization des uP 90S8535 // SPI Type: Master // SPI Clock Rate: 921.6 kHz=3.6864 MHz/4 // // SPI Clock Phase: Cycle Half // SPI Clock Polarity: Low // SPI Data Order: MSB First SPCR=0x50; //putsf("\rMAX147 Demo\n"); //putsf("\r***********************************************\n"); delay_us(100); while (1) { /* for (kan=0; kan<8; kan++) { n=max147_read(kan); printf("Kanal= %2u N=%4u U=%4umV\r\n",kan, n,(unsigned) ((long) n*VREF/4096)); } */ kan=0; n1=max147_read(kan); printf("\r%4u\r", (unsigned) ((long) n1*VREF/4096)); n2=max147_read(kan); printf("%4u\r", (unsigned) ((long) n2*VREF/4096)); n3=max147_read(kan); printf("%4u\r", (unsigned) ((long) n3*VREF/4096)); mittelw= (float) ((n1+n2+n3)/3); printf("------> Mittelw: %f\r", mittelw*VREF/4096); delay_ms(500); GICR=0x40; MCUCR=0x02; #asm("sei") }; } ich muss das Programm ändert so ab,dass die Datenerfassung in Abstand von einer Sekunde erfolgt. Kan jemand mir helfen da ich weiß genau nicht wo ich das programm modifizieren muss und die lösung zu haben. Die Daten Blatte habe ich beigefügt. Ich bedanke mich.
Datum:
Danke Düsendieb, was soll ich machen mit dem delay nur da muss ich das Prog ändern oder gibt noch was. Danke Düsendieb.



