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.
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
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.
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.
>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);
1
// Auswählen von Kanal 0
2
kan=0;
3
// Einlesen des AD Kanals 0 in n1
4
n1=max147_read(kan);
5
// Wagenrücklauf am Terminal, Ausgeben von der Spannung aus n1 ohne Nachkommastellen als Zahl der Länge 4, Wagenrücklauf im Terminal
6
printf("\r%4u\r",(unsigned)((long)n1*VREF/4096));
7
8
// Einlesen des AD Kanals 0 in n2
9
n2=max147_read(kan);
10
// Ausgeben von der Spannung aus n2 ohne Nachkommastellen als Zahl der Länge 4, Wagenrücklauf im Terminal
11
printf("%4u\r",(unsigned)((long)n2*VREF/4096));
12
13
// Einlesen des AD Kanals 0 in n3
14
n3=max147_read(kan);
15
// Ausgeben von der Spannung aus n3 ohne Nachkommastellen als Zahl der Länge 4, Wagenrücklauf im Terminal
16
printf("%4u\r",(unsigned)((long)n3*VREF/4096));
17
// Ausrechnen des Mittelwerts von n1, n2, n3
18
mittelw=(float)((n1+n2+n3)/3);
19
// Ausgeben der mittleren Spannung der letzten 3 Messungen an AD Kanal 0
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
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.
> 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 ;-)
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.