Forum: Mikrocontroller und Digitale Elektronik Tonerzeugung mit DAC - PIC16F15376 - C Problem


von Max M. (maxmicr)


Lesenswert?

Ich versteh gerade die Welt nicht mehr, ich versuche einen "Ton" mit 
einem DAC zu erzeugen, das funktioniert auch, sobald ich allerdings die 
Schleifen in eine Funktion auslagere, hör ich nichts mehr, also z.B. 
sollte
1
playFreq(8,4000);
 das selbe tun wie
1
        for(long j = 0; j < 4000; j++){
2
            DAC1CON1 = DAC1CON1++;
3
            __delay_us(8);
4
        }

allerdings passiert gar nix (d.h. eine Pause zwischen den 3 anderen 
"Tönen", außerdem ist diese Pause viel länger als der nachfolgende Ton, 
obwohl er die selbe Anzahl an Schleifendurchläufe hat und auch die 
Delaydauer gleich ist). Was übersehe ich?
1
#include <xc.h>
2
#define _XTAL_FREQ 4000000
3
4
#pragma config WDTE = OFF // WDT operating mode (WDT Disabled, SWDTEN is ignored)
5
6
void initDAC(){
7
    DAC1CON0bits.DAC1EN = 1;    //Enable DAC
8
    DAC1CON0bits.DAC1OE1 = 1;   //Tie voltage level to DAC1OUT1 pin
9
    
10
    DAC1CON0 &=~(1<<2);
11
    DAC1CON0 &=~(1<<3);  //Use VDD
12
}
13
14
void playFreq(short delayTime, int howLong){
15
    for(int n = 0; n < howLong; n++){
16
        DAC1CON1 = DAC1CON1++;
17
        __delay_us(delayTime);
18
    }
19
}
20
21
void main(void) {
22
    initDAC();
23
    
24
    while(1){
25
        playFreq(8,4000);
26
        
27
        for(long j = 0; j < 4000; j++){
28
            DAC1CON1 = DAC1CON1++;
29
            __delay_us(8);
30
        }
31
        
32
        for(long k = 0; k < 4000; k++){
33
            DAC1CON1 = DAC1CON1++;
34
            __delay_us(16);
35
        }
36
        
37
        for(long i = 0; i < 12000; i++){
38
            DAC1CON1 = DAC1CON1++;
39
            __delay_us(32);
40
        }
41
    }
42
}

von Volker S. (vloki)


Lesenswert?

__delay_us ist keine Funktion sondern ein Makro.
Es ist nicht möglich eine Variable zu übergeben...

von Toralf W. (toralf)


Lesenswert?

... also eine minimale Konstante reinsetzen und in einer Schleife so oft 
aufrufen, bis deine gewünschte Verzögerungszeit erreicht ist.

von Volker S. (vloki)


Lesenswert?

Toralf W. schrieb:
> ... also eine minimale Konstante reinsetzen und in einer Schleife
> so oft
> aufrufen, bis deine gewünschte Verzögerungszeit erreicht ist.

Bei einem us Makro und einem Instruction Cycle von 1us?
Das geht schief ;-)

@Max
Warum wird der Ton eigentlich nicht mit einer PWM erzeugt?

btw:
    DAC1CON0 &=~(1<<2);
    DAC1CON0 &=~(1<<3);  //Use VDD

>>> DAC1CON0bits.PSS = 0b00;  //Use VDD

: Bearbeitet durch User
von Max M. (maxmicr)


Lesenswert?

Volker S. schrieb:
> __delay_us ist keine Funktion sondern ein Makro.
> Es ist nicht möglich eine Variable zu übergeben...

Ah, danke für den Hinweis, allerdings funktioniert es so auch nicht :(
1
void playFreq(short delayTime, int howLong){
2
    for(int n = 0; n < howLong; n++){
3
        DAC1CON1 = DAC1CON1++;
4
        for(int d = 0; d < delayTime; d++){
5
            asm("nop");
6
        }
7
    }
8
}
9
10
void main(void) {
11
    initDAC();
12
    
13
    while(1){
14
        playFreq(8,4000);
15
        playFreq(16,4000);
16
        playFreq(32,4000);
17
    }
18
}

Volker S. schrieb:
> Warum wird der Ton eigentlich nicht mit einer PWM erzeugt?

Hab ich mir nicht überlegt, aber wäre wahrscheinlich sinnvoller, da man 
dort die Periode einstellen kann, oder?

Ich hatte vor, ein analoges Tonsignal einzulesen und dann über den DAC 
wieder auszugeben, ich bin mir nicht sicher, ob das realisierbar ist? 
Ich steige aber nicht durch, warum der oben gezeigte Code nicht 
funktioniert :(

von Volker S. (vloki)


Angehängte Dateien:

Lesenswert?

Der Simulator sagt, deine delay Schleife braucht 19us ;-)

<edit>
Wenn du als Schliefenvariable ein unsigned char nimmst und das Nop() weg 
lässt, braut die Schleife immer noch 10us.

: Bearbeitet durch User
von Max M. (maxmicr)


Lesenswert?

Wie kann es denn 19 Zyklen dauern, um ein Register hochzuzählen und zu 
prüfen, ob sie unterhalb eines bestimmten Wertes liegt?

Gibt es eine Funktion delay die eine Variable als Parameter annimmt?

von Volker S. (vloki)


Lesenswert?

Max M. schrieb:
> Wie kann es denn 19 Zyklen dauern, um ein Register hochzuzählen...

Wenn du ein int (16bit) nimmst muss erst mal ein Register hochgezählt 
werden und überprüft werden, ob dieses übergelaufen ist.
Dann muss gegebenenfalls noch ein zweites Register hochgezählt werden...

<edit>
Schau doch mal da: 
http://www.hs-ulm.de/users/vschilli/Mikrocontroller/uCQ/_downloads/uCquick-X.pdf
 4.1 Blink Variante 1 – Zählen

: Bearbeitet durch User
von Volker S. (vloki)


Lesenswert?

Max M. schrieb:
> Gibt es eine Funktion delay die eine Variable als Parameter annimmt?

Was schätzt du, wie viele Zyklen für einen Funktionsaufruf benötigt 
werden?

von Max M. (maxmicr)


Lesenswert?

Volker S. schrieb:
> Was schätzt du, wie viele Zyklen für einen Funktionsaufruf benötigt
> werden?

2 Zyklen braucht der call Assemblerbefehl, also nehme ich an, er 
braucht bei 1MHz 2µs?

von Volker S. (vloki)


Lesenswert?

Context saving?
Kann man aber leicht im Simulator...

: Bearbeitet durch User
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.