Hi Leute, ich schreibe an einem Programm, welches 6 verschiedene PWM erzeugt. Die Frequenz und das Tastverhältnis werden über Analogsignale eingestellt. An 6 Binäreingängen kann man definieren, für welche PWM die neuen Werte eingestellt werden sollen. Nun möchte ich das Programm in der Simulation testen, da ich noch kein Board zum Mikrocontroller habe(Dieser wird im laufe der nächsten Tage/Wochen gebaut). Mit Stimuli kann ich ja angeben zu welcher Zeit welche Pins gesetzt werden sollen, aber ich verstehe nicht, wie ich Analogsignale immitieren kann. Dies wäre wichtig, um die Laufzeit zu testen. Nicht dass ich später zeitkritische Probleme habe, da der ADC zu lange dauert oder so. Ich möchte dazu sagen, dass ich neu im C-Programmieren bin und auch mit Stimuli noch nicht so gut klar komme. Meine .log daTei ist irgendwie immer leer. Grüße Der Anfänger
:
Verschoben durch Moderator
@ Kaan Ayhan (deranfaenger) >werden sollen, aber ich verstehe nicht, wie ich Analogsignale immitieren >kann. Soweit mir bekannt, geht das nicht. >Dies wäre wichtig, um die Laufzeit zu testen. Nicht dass ich >später zeitkritische Probleme habe, da der ADC zu lange dauert oder so. Die Geschwindigkeit des ADC ist bekannt, 13 ADC-Takte. Ausserdem kann man das auch ohne Analogeinagngswert simulieren, auch wenn dann immer 0 rauskommt.
und darum findet sich bei mir im Code meist sowas:
1 | #ifdef _DEBUG |
2 | uint8_t g_arDebugADC[8] = {0x7F,0x7F,0x7F,0x7F,0x00,0x00,0x00,0xFF}; |
3 | #endif |
4 | |
5 | |
6 | uint8_t ADC_ReadOnce( uint8_t nADC_Nr) |
7 | { |
8 | ADMUX = nADC_Nr | ADMUX_INIT; |
9 | ADCSRA |= (1<<ADSC); // eine ADC-Wandlung |
10 | while (ADCSRA & (1<<ADSC) ) |
11 | {} // auf Abschluss der Konvertierung warten |
12 | #ifdef DEBUG |
13 | return g_arDebugADC[nADC_Nr]; |
14 | #endif // DEBUG |
15 | return ADCH; |
16 | } |
Nachtrag: In der Studio 4.x Zeit habe ich eien freien Port per Simuli missbraucht, um PINX als ADCH zurückzugeben.
Ah verstehe der ADC arbeitet auch mit einem "leeren" Eingang genau so schnell. Bei mir wären das dann 23Takte, weil ich jedesmal die ADCquelle ändern muss und deshalb disable und enable. Kann ich dann wärend dem Simulieren einfach ein Breakpoint setzen und manuell die Werte für ADCH und ADCL setzen? Theoretisch würde das ja gehen. @Schiko Kannst du mir erklären was du genau in deinem Code machst? Die Blöcke mit
1 | #ifdef _DEBUG
|
2 | //bzw
|
3 | #ifdef DEBUG
|
verstehe ich nicht ganz. Ich habe nie damit gearbeitet. Und warum machst du
1 | ADMUX = nADC_Nr | ADMUX_INIT; |
das verstehe ich auch nicht ganz
@Kaan Ayhan (deranfaenger) >Ah verstehe der ADC arbeitet auch mit einem "leeren" Eingang genau so >schnell. Sicher. >Bei mir wären das dann 23Takte, weil ich jedesmal die ADCquelle ändern >muss und deshalb disable und enable. Das glaub ich kaum. Du musst vielleicht den Eingangsmultiplexer umstellen, dazu muss man ihn aber nicht ausschalten! >Kann ich dann wärend dem Simulieren einfach ein Breakpoint setzen und >manuell die Werte für ADCH und ADCL setzen? Theoretisch würde das ja >gehen. Nicht sinnvoll. Du setzt deine Variable, in welche ADCH und ADCL kopiert wird anders. Ausserdem gibt es ADCW, das ist ADCH und ADCL zusammengefasst. >Kannst du mir erklären was du genau in deinem Code machst? >Die Blöcke mit >#ifdef _DEBUG >//bzw >#ifdef DEBUG Das ist eine bedingte Kompilierung. Damit kann man ein Stück Code aktivieren, wenn das #define _DEBUG definiert ist, eben zum Debuggen. >Und warum machst du >ADMUX = nADC_Nr | ADMUX_INIT; >das verstehe ich auch nicht ganz Er schaltet nur den Eingangsmultiplexer um, OHNE den ADC auszuschalten.
> Nicht sinnvoll. Du setzt deine Variable, in welche ADCH und ADCL kopiert > wird anders. Ausserdem gibt es ADCW, das ist ADCH und ADCL > zusammengefasst. Hmm warum ist das nicht sinnvoll? Und ein ADCW gibt es bei mir nicht zumindest nicht in meinem Datenblatt http://www.atmel.com/Images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet.pdf Das mit DEBUG habe ich jz auch verstanden dann kann ich das ja verbinden und sagen:
1 | #ifdef DEBUG
|
2 | adcResult = 0x00F7; // Beispielwert als ADC Ergebnis |
3 | #endif // DEBUG
|
>>ADMUX = nADC_Nr | ADMUX_INIT; > >>das verstehe ich auch nicht ganz > > Er schaltet nur den Eingangsmultiplexer um, OHNE den ADC auszuschalten. Klar aber würde hier nicht einfach folgendes reichen?
1 | ADMUX |= nADC_Nr; // wenn nADC_Nr so definiert ist, dass die Bits 4-7 = 1 sind. bspw.: nADC_Nr = 0xF2 für ADC-Port 2 |
Woher kommt das ADMUX_INIT? Das war mir unklar.
@ Kaan Ayhan (deranfaenger) >> Nicht sinnvoll. Du setzt deine Variable, in welche ADCH und ADCL kopiert >> wird anders. Ausserdem gibt es ADCW, das ist ADCH und ADCL >> zusammengefasst. >Hmm warum ist das nicht sinnvoll? Weil man ADCL und ADCH nicht beschreiben kann! > Und ein ADCW gibt es bei mir nicht >zumindest nicht in meinem Datenblatt Dort gibt es das auch nicht, aber in deinem Compiler! >Das mit DEBUG habe ich jz auch verstanden dann kann ich das ja verbinden >und sagen: >#ifdef DEBUG > adcResult = 0x00F7; // Beispielwert als ADC Ergebnis >#endif // DEBUG Ja. >Klar aber würde hier nicht einfach folgendes reichen? >ADMUX |= nADC_Nr; Nein. Du musst erst die Bits löschen, welche den Multiplexer umschalten. Denn |= setzt nur Bits von 0 auf 1, aber nicht von 1 auf 0. >Woher kommt das ADMUX_INIT? Das war mir unklar. Das musst du festlegen. Kann man sich aber auch schenken. Mach es einfach so. Der Der Konfiguration wird der ADC einmalig ausgelesen und das Ergebnis weggeworfen, weil es "schlecht" ist.
1 | void adc_init(void) { |
2 | |
3 | ADMUX = (1<<REFS0); // AVCC als Referenzspannung nutzen |
4 | // Frequenzvorteiler auf 8 setzen und ADC aktivieren
|
5 | ADCSRA = (1<<ADPS1)| (1<<ADPS0)|(1<<ADIE)|(1<<ADEN); |
6 | |
7 | adc_read(0); // erstes ADC Ergebnis ist "schlecht", wegwerfen |
8 | }
|
9 | |
10 | uint16_t adc_read(uint8_t channel) { |
11 | ADMUX = (ADMUX & 0xF0) | channel; // Kanal waehlen |
12 | ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" |
13 | while (ADCSRA & (1<<ADSC)); // Warte auf das Ende |
14 | return ADCW; |
15 | }
|
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.