Forum: Mikrocontroller und Digitale Elektronik suche Code-Beispiel für Poti PIC30F2020


von Ede (Gast)


Lesenswert?

Hallo Zusammen,

ich möchte mit einem Poti zwischen zwei PWM-Modi's umschalten können.
Bin aber ein blutiger Anfänger beim uC-programmieren.
Kann mir vll jemand einen Link zu eine einfach Beispielprogramm geben?
-->ich will nur kurz sehn wie man den Wert eigentlich einliest und 
welche Register ich dafür setzten muss.


Gruß Ede

von Sascha F. (sascha_focus) Benutzerseite


Lesenswert?

Hi,

diesen Code habe ich bei einem 30F4013 benutzt.
Wirst du wohl noch für dein AD-Eingänge anpassen müssen.

void init_ADC(void)
{
  ADPCFG=0xC0;
  ADCSSL=0x00;
  ADCON1bits.ADON = 0;   // ADC aus
  ADCON1bits.ADSIDL = 0;   // Continue im Idle Mode
  ADCON1bits.FORM = 0;  // Integer
  ADCON1bits.SSRC = 7;  // Interner Counter beendet Sampling und startet 
Conversion
  ADCON1bits.ASAM = 0;  //
  ADCON1bits.SAMP = 0;  //
  ADCON1bits.DONE = 0;  //

  ADCON2bits.VCFG = 1;  //
  ADCON2bits.CSCNA = 0;  //
  ADCON2bits.BUFS = 0;  //
  ADCON2bits.SMPI = 0;  //
   ADCON2bits.BUFM = 0;  //
  ADCON2bits.ALTS = 0;  //
//  ADCON3 = 0x1f02;
  ADCON3bits.SAMC = 1;  //
   ADCON3bits.ADRC = 0;  //
  ADCON3bits.ADCS = 22;  //
  ADCHS=0;
  ADCON1bits.ADON = 1; // turn ADC ON
}


unsigned int read_adc(unsigned char channel)
{
  ADCHS=channel;
  ADCON1bits.SAMP = 1; // start sampling then ...
  Nop();
  Nop();
  // after 31Tad go to conversion
  while (!ADCON1bits.DONE);// conversion done?
  return ADCBUF0;
}

unsigned int AV_ADC(unsigned char channel)
{
  unsigned long av=0;
  unsigned char i;
  for(i=32;i>0;i--)
    {
    av = av+read_adc(channel);
    }
  av = av/32;
  return av;
}

Gruß Sascha

von Ede (Gast)


Lesenswert?

wow, Danke für die schnelle Anwtwort!!

Die Leute hier im Forum sind echt Hilfsbereit.
Jetzt schau ich mir mal deinen Code an...Danke

Gruß Ede

von Sascha F. (sascha_focus) Benutzerseite


Lesenswert?

Hi,

gern geschehen. Nur nicht vergessen, das TRISbit für den jeweiligen 
AD-Eingang auf Eingang zu setzen. Sonst misst du Blödsinn......

Ansonsten als Tip:

http://ww1.microchip.com/downloads/en/DeviceDoc/70064E.pdf
http://ww1.microchip.com/downloads/en/DeviceDoc/70065D.pdf

Dort findest du die Reference Manuals

Gruß Sascha

von Benedikt K. (benedikt)


Lesenswert?

Und den Kühlkörper nicht vergessen, der F2020 wird extrem heiß (>70°C 
Gehäusetemperatur ohne zusätzliche Kühlung!), falls das IC nicht direkt 
mit einer ausreichenden Massefläche verlötet wird.

Er funktioniert zwar auch ohne aber ob das ganze gut geht, bezweifle ich 
doch etwas.

von Ede (Gast)


Lesenswert?

Hallo Sascha,

ich hab mir gerade die Beispiele rein gezogen. Und da ist mir 
aufgefallen, dass in den Quellcode's Register angesprochen werden, die 
ich nicht habe:

z.B. "ADCON1", ich habe nur ein ADCON-Register.
oder "ADCHS", oder "ADCSSL" u.s.w.

Das ist merkwürdig, denn da steht ja, das der Quellcode für die 
"30F-Familie" sei. Ich habe einen "30F2020".

Auch der Quellcode den du mir gezeigt hast, hatte leider Register die 
ich nicht habe.

Kannst du mir noch mal einen Ratschalg geben, was ich jetzt tun soll?
Soll ich vll einfach nach "ähnlichen" Registern bei mir suchen, oder 
soll ich weiter nach Beispielen für meinen uC suchen?

Es ist mir schon etwas peinlich dich noch einmal zu fragen, denn 
eigentlich habe ich ja "nur" einen Poti an "AN0", und da möchte ich den 
Wert einlesen und vergleichen...ist ja nichts großes :-(



hier ein kleines Beispiel:
******************************************************************
ADPCFG = 0xFFFB;       // all PORTB = Digital; RB2 = analog
ADCON1 = 0x0000;       // SAMP bit = 0 ends sampling ...
          // and starts converting
ADCHS = 0x0002;         // Connect RB2/AN2 as CH0 input ..
          // in this example RB2/AN2 is the input

ADCSSL = 0;
ADCON3 = 0x0002;       // Manual Sample, Tad = internal 2 Tcy
ADCON2 = 0;
ADCON1bits.ADON = 1;       // turn ADC ON


while (1)         // repeat continuously
{
ADCON1bits.SAMP = 1;       // start sampling ...
DelayNmSec(100);       // for 100 mS
ADCON1bits.SAMP = 0;       // start Converting
while (!ADCON1bits.DONE);     // conversion done?
ADCValue = ADCBUF0;       // yes then get ADC value
}           // repeat
************************************************************************ 
*



Gruß Ede

von Benedikt K. (benedikt)


Lesenswert?

Ede wrote:

> Das ist merkwürdig, denn da steht ja, das der Quellcode für die
> "30F-Familie" sei. Ich habe einen "30F2020".

Der 30F2020 ist eine kleine Ausnahme, bei dem weicht einiges (u.a. der 
ADC und die PWM) vom Standard der normalen 30F ab.
Verwende also am besten Quellcodes die speziell für den 30F2020 
geschrieben sind, da die anderen nur bedingt auf den 30F2020 übertragbar 
sind.

von Ede (Gast)


Lesenswert?

man, das ich immer genau die Ausnahme treffe. :-(

aber danke für den Tipp, Benedikt!!

Gruß Ede

von Benedikt K. (benedikt)


Lesenswert?

Der 30F2020 ist so ziemlich der einzige 30er der speziell auf irgendwas 
zugeschnitten ist.
Die anderen sind eher universell.
Davon abgesehen gibts 2 Varianten: GP und MC (bei den 33ern heißen die 
so, bei den 30ern ist das nicht so eindeutig erkennbar):
Die GP haben meist langsamere aber hochauflösendere ADCs und die 
größeren ein Interface für Audio ADCs/DACs.
Die MC haben schnellere ADCs meist mit mehreren S&H Stufen und anstelle 
des Audiointerface eine zusätzliche PWM Stufe.
Zwischen den Typen muss man bei den Beispielcodes nämlich auch 
unterscheiden. Davon abgesehen sollten die Typen bis auf die Ausstattung 
alle ziemlich Software kompatibel sein, die Software ist zumindest ohne 
viel Aufwand anpassbar.

Einige weit verbreiteten Typen die auch in DIL erhältlich sind, sind 
z.B. 30F4013 oder 30F3013 für die GP Typen oder 30F4012 für den MC Typ.

von ede (Gast)


Lesenswert?

ehm, okaaay...

ich glaube da hab ich in dir den absolten 30FXXX-Spezialisten gefunden 
:-)

schönen Abend noch!!

Gruß vom Ede

von Ede (Gast)


Lesenswert?

Hallo nochmal,

ich hab heute mal diesen Code an meinen 30F2020 ausprobiert, aber 
irgendwo ist ein Wurm drin.....wahrscheinlich sogar mehrere^^

Ich habe am AN0 einen Poti, und da will ich eigentlich nur den Wert von 
Analog in Digital umwandeln und vergleichen...je nach Position des Potis 
soll eine andere LED leuchten.

Was mach ich falsch?
**********************************************************************


#include "p30f2020.h"


// Configuration Bit Settings 
****************************************************

_FOSCSEL(FRC_PLL)        // 30MHz oscillator selection configuration 
register (internal RC oscillator, PLL enabled)
_FOSC(CSW_FSCM_OFF & FRC_HI_RANGE & OSC2_IO & WDT_OFF & FRC_PLL) 
//oscillator configuration register (no clock out)
_FPOR(PWRT_128)          // power on reset configuration register (128ms 
power on reset timer)
_FGS(CODE_PROT_OFF)        // general code segment configuration 
register
_FBS(BSS_NO_FLASH)        // boot code segment configuration register
_FWDT(0)            // watchdog timer off





int main()   // WICHTIG, ICH HAB NOCH FRC_PLL EINGESTELLT
{

int ADCVALUE;    //Variable setzen
//TRISBbits.TRISB5 = 1;     //-->RB5 als Input (AN0),wenn ich das setze, 
dann leuchtet garnix
              //ohne diesen Befehl leuchtet die gelbe LED

//ADCPC0bits.TRGSRC0 = 1;  //individual software trigger, ändert nichts


while (1)         // repeat continuously
{

ADCONbits.ADON = 1;     //Converter ist ein
ADCONbits.FORM = 0;  //Integer Ausgabe
ADPCFGbits.PCFG0 = 1;


ADCVALUE = ADCBUF0;  //BUF0 wird in Variable geschrieben


if (ADCVALUE >= 2)
{
TRISEbits.TRISE5 = 0;  //grüne LED an
}
else
{
  if (ADCVALUE >= 1)
  {
  TRISEbits.TRISE4 = 0;    //gelbe LED an
  }
  else
  {
    if (ADCVALUE >= 0)
    {
    TRISEbits.TRISE3 = 0;    //rote LED an
    }
  }



}




//TRISEbits.TRISE3 = 0;    //rote LED an
//TRISEbits.TRISE4 = 0;    //gelbe LED an
//TRISEbits.TRISE5 = 0;    //grüne LED an

}        //end while


}        // end main



**********************************************************************

Gruß Ede

von Willivonbienemaya .. (willivonbienemaya)


Lesenswert?

Ich hab nur kurz drübergeschaut. Aber so wie ich das sehe startest du 
nirgends das Sampling.

von Ede (Gast)


Lesenswert?

Hallo Willi, und danke für deine Anwtwort.

Aber der Befehl,

ADCONbits.ADON = 1;     //Converter ist ein

startet doch die Umwandeln vom Analog in den Digitalwert?

Aber warum ändert sich eigentlich nie der Wert vom "ADCBUF0-Register".
Ich dachte nach dem Convertieren wir das Ergebnis in dieses Register 
geschrieben....Pustekuchen

Hast du vll eine Idee, warum er nichts ins ADCBUF0-Register schreibt?


Gruß Ede

von Benedikt K. (benedikt)


Lesenswert?

Ede wrote:

> Aber der Befehl,
>
> ADCONbits.ADON = 1;     //Converter ist ein
>
> startet doch die Umwandeln vom Analog in den Digitalwert?

Nicht ganz.
Damit schaltest du zwar den ADC ein, aber arbeiten tut er noch nicht.

Im ADCPCx Register musst du mit den TRGSRCx Bits die Startbedingung für 
den ADC einstellen und diese dann erfüllen.

von Ede (Gast)


Lesenswert?

Hallo Benedikt!!!

ich glaube mir ist gerade ein Licht aufgegangen....dank dir!!

Gruß Edgar

von Benedikt K. (benedikt)


Lesenswert?

Ging mir genauso als ich den 2020 zum ersten mal verwendet habe.
Ich habe am Ende den Code hiervon übernommen, da ich rein zufällig etwas 
ähnliches vorhatte:
http://www.circuitcellar.com/microchip2007/winners/DE/MT2292.html

von Ede (Gast)


Lesenswert?

Hallo nochmal,

mit dem ADC hat es jetzt wunderbar geklappt.
Aber schon hab ich ein neues Problem. Vielleicht kannst du mir auch bei 
dem behilflich sein?
Ich möchte die LED'S diesmal mit einem Interrupt(INT0) steuern.
Ich habe das Programm beobachtet und dabei bemerkt, das er nicht in das 
UP "_ISR_INT0Interrupt(void)" geht. Wahrscheinlich der falsche Name für 
das UP, aber wie soll ich ihn den nennen?
Ich hab mir "30F2020.h" angeschaut, da war es so ungefähr als Beispiel.
(fast ganz unten bei "nützliche Macro's")
*********************************************************************
int main(void)
{

TRISEbits.TRISE3 = 0;  //rot als ausgang
TRISEbits.TRISE4 = 0;  //gelb ausgang
TRISEbits.TRISE5 = 1;  //Die PIN's als eingänge


INTCON2bits.INT0EP = 0;    //interrupt on positive edge
IFS0bits.INT0IF = 0;    //interrupt request has not occurred
IPC0bits.INT0IP = 7;    //priorität Ext. Int.0
IEC0bits.INT0IE = 1;    //INT0 request enable

while (1);

}      // end main


void _ISR_INT0Interrupt(void)
{

IFS0bits.INT0IF = 0;    //interrupt request has not occurred
PORTEbits.RE3 = 1;  //rot aus
PORTEbits.RE4 = 0;  //gelb ein
//hier eine kleine Zeitschleife
}
************************************************************************ 
*

von Ede (Gast)


Lesenswert?

******************************************************

void _attribute_ ((_interrupt_)) _INT0Interrupt(void)

*******************************************************

schon gefunden :-)

von Willivonbienemaya .. (willivonbienemaya)


Lesenswert?

Ede wrote:
> void _ISR_INT0Interrupt(void)

Das war schon fast richtig.
Da fehlt ein Leerzeichen.
So gehts:
void _ISR _INT0Interrupt(void)

von Ede (Gast)


Lesenswert?

Hallo Willi,

hmm, hat dann auch anders funktioniert...  ;-)

also bis jetzt hat alles so funktioniert, wie ich es mir vorgestellt 
habe.
Ich habe zuerst gelernt, ein PWM-Signal zu programmieren, dann habe ich 
gelernt wie man einen AD-Wandler steuert. Jetzt weiß ich auch, wie man 
einen Interrupt programmiet. Und jetzt möchte ich dem ganzen noch die 
Krone aufsetzten:

Ich habe nämlich zwei uC die gleichzeitig arbeiten müssen, und deswegen 
müssen sie irgendwie miteinander kommunizieren...der eine muss immer 
wissen, was der andere gerade so für Spannungen misst....

Wie können sich zwei uC "Unterhalten" ? ...welche PIN's brauch ich dafür 
eigentlich ? gibt es dafür auch schon Beispiele ?
ich habe leider keine gefunden...

wäre cool, wenn du mir da wieder helfen könntest!
ich wünsch dir noch ein schönes Wochenende!

Gruß Edgar

von Willivonbienemaya .. (willivonbienemaya)


Lesenswert?

Am einfachsten über Uart.

Hardwareseitig müssen die Pins UTX und URX gekreuzt verbunden werden.

Softwareseitig kannst du dir folgendes ansehen:
http://ww1.microchip.com/downloads/en/DeviceDoc/CE137_UART_noDMA_091207.zip

Ist zwar für dsPIC33, es sollten aber nicht viel Änderungen nötig sein.

von Ede (Gast)


Lesenswert?

alles klar....ich zieh mir das mal rein!!
thx!!

von Ede (Gast)


Lesenswert?

Hallo Willi,

ich hab mal ne Frage zum Osci:

ich habe den Verdacht, dass bei meinem uC die Frequenz zu hoch 
eingestellt ist...wenn ich mein Programm mit eiem Breakpoint 
durchklicke, funktioniert alles wunderbar....ohne Breakpoint beachtet er 
menen Poti garnicht...

so sieht der Anfang von meinem Programm aus:

*************************************************************

_FOSCSEL(FRC_PLL)
_FOSC(CSW_FSCM_OFF & FRC_HI_RANGE & OSC2_IO & WDT_OFF)
_FPOR(PWRT_128)
_FGS(CODE_PROT_OFF)
_FBS(BSS_NO_FLASH)
_FWDT(0)

***************************************************************

in einem Kommentar steht irgendwo das der uC gerade mit 30MHz läuft,
gibt es einen einfachen Weg, seine Taktrate zu verringern?
(ich glaube ich muss etwas in FOSCSEL und FOSC verändern)


gruß Edgar

von Willivonbienemaya .. (willivonbienemaya)


Lesenswert?

Ede wrote:
> in einem Kommentar steht irgendwo das der uC gerade mit 30MHz läuft,
> gibt es einen einfachen Weg, seine Taktrate zu verringern?

Der einfache weg ist die Einstellungen im Code auszukommentieren und es 
in MPLAB einstellen.

> (ich glaube ich muss etwas in FOSCSEL und FOSC verändern)

Kann ich auswendig nicht sagen, das steht in dem Headerfile des 
Controllers.

Wenns nicht klappt noch mal Bescheid sagen, dann schau ich morgen nach 
wies genau geht.

von ede (Gast)


Lesenswert?

Hallo Willi,

ich bin am verzweifeln. Ich hab es nicht geschafft, die Frequenz vom 
Oszi runter zu drehen. Ich hab mir die entsprechenden Kapitel im 
Datenblatt genau durchgelesen...aber irgendwie bin ich wohl zu doof.

Ich hab mir auch die Header-Datei genau angesehn....

Ich hab es mit "Low- Range" ausprobiert, aber viel mehr ist mir 
eigentlich auch nicht eingefallen, denn ich brauch für das PWM den PLL = 
enable.
also:
_FOSC(CSW_FSCM_OFF & FRC_LO_RANGE & OSC2_IO & WDT_OFF)

-->damit hat es auch nicht funktioniert.

Vor zwei Wochen habe ich einen interessanten Fehler gefunden, den ich 
dann aber nicht weiter verfolgt habe:

Der uC scheint ab und zu einen Befehl zu überspringen....

Bei diesem einfachen Programm sollen die drei Pin's als Ausgänge 
deklariert werden, aber die daran angeschlossenen LED's sollen nicht(!) 
leuchten.

Zuerst dachte ich, es ist ein Fehler mit dem Pin. Wenn ich aber z.B die 
beiden letzten Zeilen im Quellcode tausche, dann leuchtet immer die 
grüne LED und die gelbe ist dunkel. Er scheint also immer die mittlere 
Befehlszeile zu überspringen.
Ich vermute mal, dass hat auch etwas mit der Frequenz vom Oszi zu tun.
Was hällst du davon??

************************************************************************ 
*
#include "p30f2020.h"

_FOSCSEL(FRC_PLL)        // 30MHz oscillator selection configuration 
register (internal RC oscillator, PLL enabled)
_FOSC(CSW_FSCM_OFF & FRC_HI_RANGE & OSC2_IO) //oscillator configuration 
register (no clock out)
_FPOR(PWRT_128)          // power on reset configuration register (128ms 
power on reset timer)
_FGS(CODE_PROT_OFF)        // general code segment configuration 
register
_FBS(BSS_NO_FLASH)        // boot code segment configuration register
_FWDT(0)            // watchdog timer off

int main()

{

TRISEbits.TRISE3 = 0;
TRISEbits.TRISE4 = 0;
TRISEbits.TRISE5 = 0;  //Die PIN's als Ausgänge


PORTEbits.RE3 = 1;  //rot aus
PORTEbits.RE4 = 1;  //gelb  leuchtet trotzdem !!!egal ob 0 oder 1
PORTEbits.RE5 = 1;  //grün  aus

}        // end main
************************************************************************



Gruß Edgar

von Benedikt K. (benedikt)


Lesenswert?

ede wrote:

> Der uC scheint ab und zu einen Befehl zu überspringen....
>
> Bei diesem einfachen Programm sollen die drei Pin's als Ausgänge
> deklariert werden, aber die daran angeschlossenen LED's sollen nicht(!)
> leuchten.
>
> Zuerst dachte ich, es ist ein Fehler mit dem Pin. Wenn ich aber z.B die
> beiden letzten Zeilen im Quellcode tausche, dann leuchtet immer die
> grüne LED und die gelbe ist dunkel. Er scheint also immer die mittlere
> Befehlszeile zu überspringen.
> Ich vermute mal, dass hat auch etwas mit der Frequenz vom Oszi zu tun.
> Was hällst du davon??

Das ist die übliche Port Falle:
http://www.sprut.de/electronic/pic/fallen/fallen.html#inout
Lösung: Anstelle der PORT Register besser die LAT Register beschreiben.

von Willivonbienemaya .. (willivonbienemaya)


Lesenswert?

ede wrote:
> ich bin am verzweifeln. Ich hab es nicht geschafft, die Frequenz vom
> Oszi runter zu drehen. Ich hab mir die entsprechenden Kapitel im
> Datenblatt genau durchgelesen...aber irgendwie bin ich wohl zu doof.

Ich hatte nicht dran gedacht, dass du einen 2020 hast, der hat ja eine 
andere PLL wie die anderen 30Fxxx.
Bei dem kann man nur die PLL ein- und ausschalten und zwischen "Low 
Range" und "High Range" wechseln.

Aber das eigentliche Problem scheint auch woanders zu liegen.

Ich denke es wäre das einfachste wenn du Code und Schaltplan hochladen 
würdest, dann könnte man dein Problem nachstellen.


Die andere Frage wurde ja schon beantwortet: Immer die LAT Register für 
Ausgaben benutzen !

von Pic- gangster E. (Firma: FH) (ede84)


Angehängte Dateien:

Lesenswert?

Hallo Benedikt, Hallo Willi,

Danke für eure Hilfe!

ich hab hier mal meinen vorläufigen Code hoch geladen....wie gesagt, mit 
Breakpoint funktioniert es....ohne Breakpoint gibt er immer nur ein PWM- 
Signal aus....ohne zwischen den beiden PWM- Modis zu wechseln.


Gruß Edgar

von Pic- gangster E. (Firma: FH) (ede84)


Lesenswert?

Die Schaltung ist eigentlich nicht weiter erwähnenswert.
Außer der Versorgungsspannung und dem Poti an AN0 ist nicht viel dran.
Die PWM- Pin's oszi ich mit Hilfe einfacher Brücken.

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.