Forum: PC Hard- und Software AtmelStudio 6.2 Analogsignal simulieren


von Kaan A. (deranfaenger)


Lesenswert?

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
von Falk B. (falk)


Lesenswert?

@ 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.

von Schiko (Gast)


Lesenswert?

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
}

von Schiko (Gast)


Lesenswert?

Nachtrag:
In der Studio 4.x Zeit habe ich eien freien Port per Simuli missbraucht,
um PINX als ADCH zurückzugeben.

von Kaan A. (deranfaenger)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@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.

von Kaan A. (deranfaenger)


Lesenswert?

> 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.

von Falk B. (falk)


Lesenswert?

@ 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
Noch kein Account? Hier anmelden.