AtmelStudio 6.2 Analogsignal simulieren

OP #4008472
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
#4008505
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.
Gast #4008570
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
}
OP #4008767
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
#4008926
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.
OP #4009908
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.
#4009980
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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren