Forum: Mikrocontroller und Digitale Elektronik Hilfe bei Programmierung in Mplab


von Lisa Z. (lisa0411)


Lesenswert?

Hallo!
Ich bin neu hier und brauche dringend Hilfe. Ich muss für mein Studium 
ziemlich bald ein Projekt abgeben, habe jedoch keine Ahnung, wie ich 
überhaupt beginne. Es wird mit MPLAB-IDE im Assembler programmiert, 
Demoboard mit PICKit3 und Prozessor 16F886. Unser Professor hat uns ein 
Grundgerüst zur Verfügung gestellt und folgende Aufgabe muss ich jetzt 
selbst programmieren:

## Projekt µController:
Schreiben sie ein Programm, welches die Helligkeit der roten Led mittels 
Poti einstellen kann.
Der AD-Wert des Poti wird ausgelesen und modifiziert am Display 
ausgegeben.
z.B AD=0 --> Anzeige „-00-„  AD=255 --> Anzeige „-99-„   (Anzeige der 
Helligkeit in Prozent)
Der AD-Wert des Poti wird auch zur Ansteuerung der roten Led verwendet, 
die Helligkeit lässt sich
am besten mit einer einfachen PWM (Pulsweitenmodulation) realisieren.
Hinweis: Da die rote Led nicht am PWM-Pin des PICs angeschlossen ist, 
kann nicht die Standard PWM
des Controllers genommen werden. Die PWM Realisierung muss daher mittels 
Software (richtiges ein/ausschalten)
realisiert werden.


Es wäre wirklich toll, wenn mir jemand helfen könnte. Nicht falsch 
verstehen, ich brauch niemanden, der mir das Programm schreibt, sondern 
einfach nur Hilfe.

Liebe Grüße
Lisa

von Peter X. (peter_x)


Lesenswert?

Lisa Zwiletitsch schrieb:
> Es wird mit MPLAB-IDE im Assembler programmiert

Muß in deinem Prjekt in Assembler programmiert werden?

von Stefan (Gast)


Lesenswert?

Schau dich hier mal um:

http://pic-projekte.de/
http://sprut.de/

von Lisa Z. (lisa0411)


Lesenswert?

Peter Xuang schrieb:
> Lisa Zwiletitsch schrieb:
>> Es wird mit MPLAB-IDE im Assembler programmiert
>
> Muß in deinem Prjekt in Assembler programmiert werden?

Ja, es muss in Assembler programmiert werden.

von nicht"Gast" (Gast)


Lesenswert?

hallo,

natürlich wird dir hier geholfen. Was konkret ist denn dein Problem?

von Manuel W. (multisync)


Lesenswert?

Hallo Lisa,

Wie ist dein aktueller Stand?
Benötigst du Unterstützung beim Schreiben des Programms, oder hängts 
bereits bei der Inbetriebnahme der Toolchain?

von Ottmar K. (wil1)


Lesenswert?

Hallo Lisa,

Indem Euer Prof die Nutzung des CCP/PWM-Moduls nicht zulaesst, bleibt 
Dir nur uebrig PWM per Software zu verwirklichen.
Eine gute Einfuehrung hierfuer ist die microchip Druckschrift AN654 
"PWM, a Software Solution for the PIC16CXXX"
Darin sind diverse Codebeispiele sowie auch einige Flussdiagramme 
enthalten. Allerdings ist das Ganze in englischer Sprache. Google 
einfach nach "AN654" oder besorge Dir das PDF-File direkt bei 
[http://www.microchip.com].

Gruss Ottmar

von Lisa Z. (lisa0411)


Lesenswert?

Manuel W. schrieb:
> Hallo Lisa,
>
> Wie ist dein aktueller Stand?
> Benötigst du Unterstützung beim Schreiben des Programms, oder hängts
> bereits bei der Inbetriebnahme der Toolchain?

Ich benötige nur unterstützung beim schreiben.

von Manuel W. (multisync)


Lesenswert?

Lisa Zwiletitsch schrieb:
> Manuel W. schrieb:
>> Hallo Lisa,
>>
>> Wie ist dein aktueller Stand?
>> Benötigst du Unterstützung beim Schreiben des Programms, oder hängts
>> bereits bei der Inbetriebnahme der Toolchain?
>
> Ich benötige nur Unterstützung beim schreiben.

Okay. Und was genau ist das Problem an dem du hängst? Ich denke es 
fehlen noch einige Infos um dir helfen zu können.

von Michael S. (rbs_phoenix)


Lesenswert?

Man könnte das Programm in 4 Bestandteile zerlegen.
1. AD Wandlung
2. Soft-PWM
3. Von 8bit in Prozent (in C eine Zeile, in ASM schon umständlicher)
4. Display ansteuern

Die Frage ist: Wo brauchst du Hilfe? Und ist das Problem bei der 
Software - Realisierung oder beim Verständnis.

von Lisa Z. (lisa0411)


Lesenswert?

Manuel W. schrieb:
> Lisa Zwiletitsch schrieb:
>> Manuel W. schrieb:
>>> Hallo Lisa,
>>>
>>> Wie ist dein aktueller Stand?
>>> Benötigst du Unterstützung beim Schreiben des Programms, oder hängts
>>> bereits bei der Inbetriebnahme der Toolchain?
>>
>> Ich benötige nur Unterstützung beim schreiben.
>
> Okay. Und was genau ist das Problem an dem du hängst? Ich denke es
> fehlen noch einige Infos um dir helfen zu können.

Ich habe schon mal ein Programm mit AD-Wandlung geschrieben, jedoch kann 
man mittels Poti nur die Frequenz verstellen, mit der die rote und die 
grüne LED abwechselnd blinken sollen. Wie kann ich das auf die 
Helligkeit umschreiben und dann habe ich noch keine Idee, wie das mit 
der Ausgabe der Prozentzahlen funktionieren könnte.

von Lisa Z. (lisa0411)


Lesenswert?

Michael Skropski schrieb:
> Man könnte das Programm in 4 Bestandteile zerlegen.
> 1. AD Wandlung
> 2. Soft-PWM
> 3. Von 8bit in Prozent (in C eine Zeile, in ASM schon umständlicher)
> 4. Display ansteuern
>
> Die Frage ist: Wo brauchst du Hilfe? Und ist das Problem bei der
> Software - Realisierung oder beim Verständnis.

Das Problem liegt schon beim Verständnis, da ich nicht weiß, wie ich 
diese Punkte im Programm realisieren kann. Ich habe jedoch schon mal ein 
Programm geschrieben, bei dem mittels AD-Wandlung die abwechselnde 
Blinkfrequenz von roter und grüner LED eingestellt werden kann. Wie kann 
ich das auf die Helligkeit umlegen? Bei der PWM und der Prozentausgabe 
habe ich keine Idee, wie ich das realisieren könnte.

von Lisa Z. (lisa0411)


Lesenswert?

nicht"Gast" schrieb:
> hallo,
>
> natürlich wird dir hier geholfen. Was konkret ist denn dein Problem?

Ich weiß nicht, wie ich die PWM und die Ausgabe realisieren könnte.

von lala (Gast)


Lesenswert?

also wenn du per poti die frequenz der led´s ändern kannst, heißt das 
eigentlich duty cycle. bei pwm ist normalerweise die frequenz fest und 
du änderst nur den duty cycle. um dir jetzt allerdings helligkeitswerte 
in form einer gedimmten led auszugeben versuchst, musst du tatsächlich 
die frequenz der pwm erhöhen. irgendwo in den khz bereich... wenn du 
dann mit dem duty cycle rumspielst, wirst du sehen wie sich die 
helligkeit der led verändert.

von Volker S. (vloki)


Lesenswert?

Lisa Zwiletitsch schrieb:
> Ich weiß nicht, wie ich die PWM und die Ausgabe realisieren könnte.

Die PWM sollte einfach zu realisieren sein.
Einfach mit einem Timer einen IR auslösen, darin zählen
auf den Periodenendwert (z.B. 255) Bei Null LED einschalten
Den Wert vom AD Wandler als Duty Cycle verwenden.
(Mit Zähler vergleichen und gegebenenfalls die LED ausschalten)

Gibt es für die Displayausgabe eine Bibliothek ?

: Bearbeitet durch User
von Purzel H. (hacky)


Lesenswert?

Den PWM macht man mit einem timer, den man jeweils anders laedt.

T1 + T2 ergeben die Repetitionsfrequenz, waehrend T1, die Einschaltzeit 
ist.
Also definieren der timer frequenz auf zB 1ms. Ergibt N counts.
Nun ist dann T1_counts : = T1 * N /(T1+T2) und T2_counts := N - 
T1_counts. Im Timer interrupt bewegt man dann den Port-Pin, und laedt 
den timer neu.

: Bearbeitet durch User
von Volker S. (vloki)


Lesenswert?

Michael Skropski schrieb:
> 3. Von 8bit in Prozent (in C eine Zeile, in ASM schon umständlicher)

Umständlicher als in C auf jeden Fall aber nicht unbedingt schwierig
- das MSB entspricht der Hälfte von 100%
- das jeweils nächste der Hälfte des vorherigen ...

Es gibt vielleicht weniger langweilige Lösungen, aber Umsetzten in 
Assembler Code sollte so absolut kein Problem darstellen.

von Michael S. (rbs_phoenix)


Lesenswert?

Volker SchK schrieb:
> Michael Skropski schrieb:
>> 3. Von 8bit in Prozent (in C eine Zeile, in ASM schon umständlicher)
>
> Umständlicher als in C auf jeden Fall aber nicht unbedingt schwierig
> - das MSB entspricht der Hälfte von 100%
> - das jeweils nächste der Hälfte des vorherigen ...

Ja, aber ohne weiteres addieren, je nach dem ob ein bit gesetzt ist, ist 
auch umständlich. Bei 50% und 25% macht es ja noch nichts, aber bei 
12,5% muss man schon "Komma"Zahlen nehmen, was in ASM nicht direkt 
machbar ist (LSB wäre 0.390625%). Zumindest nicht, dass ichs wüsste.

Und dann kommt noch ein Runden der Zahl und Trennung der einzelnen 
Ziffern für die Anzeige. Da lobe ich mir einen * und / Operator und ein 
printf().

Das ganze gerechne und Datentypen ist für mich ein großer Vorteil einer 
Hochsprache. Pinwackeln, Register beschreiben, das ist in ASM ja auch 
kein Ding. Aber manches..

Ich weiß noch, einmal sollte ich in der Ausbildung was in ASM 
realisieren, u.a. eine Berechnung. Da habe ich einen C Compiler 
genommen, die Berechnung da realisiert und hab mir neben der Hex noch 
die ASM ausgeben lassen. Ich konnte es dann auch nachvollziehen, aber 
wenn ich es von vornherein selbst hätte lösen sollen, hätte es deutlich 
länger gedauert. Dafür ist eine Hochsprache ja da, also nehme ich sie 
dafür auch.

von Volker S. (vloki)


Lesenswert?

Michael Skropski schrieb:
> Volker SchK schrieb:
>> Michael Skropski schrieb:
>>> 3. Von 8bit in Prozent (in C eine Zeile, in ASM schon umständlicher)
>>
>> Umständlicher als in C auf jeden Fall aber nicht unbedingt schwierig
>> - das MSB entspricht der Hälfte von 100%
>> - das jeweils nächste der Hälfte des vorherigen ...
>
> Ja, aber ohne weiteres addieren, je nach dem ob ein bit gesetzt ist, ist
> auch umständlich. Bei 50% und 25% macht es ja noch nichts, aber bei
> 12,5% muss man schon "Komma"Zahlen nehmen, was in ASM nicht direkt
> machbar ist (LSB wäre 0.390625%). Zumindest nicht, dass ichs wüsste.

Das ist doch theoretischer Unfug
50,25,12,6,3,2,1,0 und fertig (gibt genau 99 ;-)

Das Ganze ist eh ein bisschen fragwürdig, da das Auge keine lineare
Wahrnehmung der Helligkeitsänderungen hat. Bei den kleinen Prozentzahlen
wird man das viel stärker empfinden.

Wenn man die % Anzeige an das Auge "anpassen" wollte, dann könnte
man sich so einfach seine Wertigkeiten anpassen.

: Bearbeitet durch User
von Volker S. (vloki)


Lesenswert?

Michael Skropski schrieb:
> Ich weiß noch, einmal sollte ich in der Ausbildung was in ASM
> realisieren, u.a. eine Berechnung. Da habe ich einen C Compiler
> genommen, die Berechnung da realisiert und hab mir neben der Hex noch
> die ASM ausgeben lassen. Ich konnte es dann auch nachvollziehen, aber
> wenn ich es von vornherein selbst hätte lösen sollen, hätte es deutlich
> länger gedauert. Dafür ist eine Hochsprache ja da, also nehme ich sie
> dafür auch.

Manchmal hab ich das Gefühl, Gleitkommazahlen werden nur benutzt weil 
eine Hochsprache das so einfach erscheinen lässt.
Wirklich notwendig ist es doch in einer 8bit Umgebung eher selten.

: Bearbeitet durch User
von Michael S. (rbs_phoenix)


Lesenswert?

Volker SchK schrieb:
> Das ist doch theoretischer Unfug
> 50,25,12,6,3,2,1,0 und fertig (gibt genau 99 ;-)

Naja. Wenn man 12 und 6 addiert, kommt 18 raus, wenn man 12,5 und 6,25 
addiert, kommt 18.75, also gerundet 19 raus.


Volker SchK schrieb:
> Das Ganze ist eh ein bisschen fragwürdig, da das Auge keine lineare
> Wahrnehmung der Helligkeitsänderungen hat. Bei den kleinen Prozentzahlen
> wird man das viel stärker empfinden.

Das ist richtig, vielleicht will der Lehrer darauf hinaus. Wer weiß.


Volker SchK schrieb:
> Manchmal hab ich das Gefühl, Gleitkommazahlen werden nur benutzt weil
> eine Hochsprache das so einfach erscheinen lässt.
> Wirklich notwendig ist es doch in einer 8bit Umgebung eher selten.

Würde ich nicht sagen. 8bitter werden ja da genutzt, wo es nicht auf 
Rechenleistung ankommt. Also Labornetzteile, Waagen, Messschieber, 
Abstandsmesser... Alles da, wo genau gemessen wird (z.B. externer ADC) 
und intern dann mit einer (Gleit) kommazahl gearbeitet und ggf auch 
angezeigt wird.

Ich arbeite fast ausschließlich mit PIC18, also 8bitter und habe schon 
oft float/double genutzt. Wäre manchmal vielleicht auch ohne gegangen, 
aber das würde dann das Programm umständlicher machen. Und nur, damit 
man sagen kann: "ich habs ohne hinbekommen" ? Vorausgesetzt, man ist 
nicht am Leistungslimit und muss Ressourcen sparen, wo es nur geht.

von Volker S. (vloki)


Lesenswert?

Michael Skropski schrieb:
> Naja. Wenn man 12 und 6 addiert, kommt 18 raus, wenn man 12,5 und 6,25
> addiert, kommt 18.75, also gerundet 19 raus.

Klar ist das nicht so genau wie eine Gleitkomma Berechnung
(13,6,3,1,1,0 wäre vielleicht auch besser)
aber brauch ich das wirklich ?

Michael Skropski schrieb:
> Würde ich nicht sagen. 8bitter werden ja da genutzt, wo es nicht auf
> Rechenleistung ankommt. Also Labornetzteile, Waagen, Messschieber,
> Abstandsmesser... Alles da, wo genau gemessen wird (z.B. externer ADC)
> und intern dann mit einer (Gleit) kommazahl gearbeitet und ggf auch
> angezeigt wird.

Da wo es notwendig ist, sollte man es natürlich machen, aber dann 
vielleicht nicht unbedingt in ASM.

Oft hilft es ja auch schon viel, wenn man bei der Maßeinheit in der 
gerechnet werden soll eine Stufe runter geht
(z.B von Gramm auf 1/10, 1/100, Milligramm ... )
Den Dezimalpunkt in der Anzeige wird man dann schon noch hinkriegen.

von Ottmar K. (wil1)


Lesenswert?

Hallo Lisa,

ich versuche mal Dir nachfolgend konkret Hilfestellung zu geben.
Mit den nachstehenden Lösungsansätzen müsstes Du eigentlich zurecht
kommen. Wenn nicht - frage bitte konkret nach.

mfG Ottmar

Zunächst das PWM-Prinzip mittels Interrupt-Service-Routine (ISR):
1
ORG   0x004               ;Interrupt-Vector
2
   TMR0-Overflow-Interrupt
3
   z.B. Zyklus 100µs, wird erreicht mit fosc=8MHz, Prescaler TMR0 1:2 
4
   ergibt mit korrektem TMR0-Preset einen overflow nach 100cyclen
5
   (2.000.000Hz / 2 / 100 = 10.000 entspricht 0,0001s = 100µs
6
   verwendete Register: OPTION_REG (clock source, Prescaler)
7
                        INTCON     (GIE, T0IE, T0IF)
8
   WREG + STATUS Register retten
9
 ISR:
10
   clrf   INTCON,T0IF   ;Interruptflag zurücksetzen
11
   Preset TMR0 für overflow nach 100 TMR0-counts
12
   ;                      
13
   incf cntCycle,f         ;bei jedem Interrpt +1
14
   ;
15
   movlw .100              ;Reset des Zykluszählers beim wert=100
16
   xorwf cntCycle,w
17
   btfsc  STATUS,Z
18
   clrf   cntCycle
19
   ;
20
   ;PWM-Pin auf H setzen wenn cntPulsewidth >= cntCycle
21
   ;PWM-Pin auf L setzen wenn cntPulsewidth <  cntCycle
22
   ; |  PulseWidth     |
23
   ; |-ADC-Ergebnis/41-|           
24
   ; | z.b.50          |
25
   ; |_________________| 
26
   ; |                 |____________| 
27
   ; 0                 50          100 cntCycle
28
   ;
29
   ;PWM-OUTPUT  
30
   ;PWM-Pin = H wenn PulseWidth >= cntCycle
31
   ;        = L "    "          <  cntCycle   
32
   movf     cntCycle,w     ;Zyklus innerhalb der Pulsbreite?
33
   bcf      STATUS,C       ; (wird durch Subtraktion ermittelt)
34
   subwf    PulseWidth,w
35
   btfsc    STATUS,C       ;C=1 Set PWM-Pin = H wenn C=1 
36
   bsf      PWM_OUT        ;  cntPulseWidth > cntCycle
37
   btfss    STATUS,C       ;C=0 Set PWM-Pin = L Wenn C=0
38
   bcf      PWM_OUT    
39
   ;
40
   WREG + STATUS wieder herstellen
41
   RETFIE
42
;---------------------------------------------------------
43
;  
44
-INIT
45
ADC-PORT initialsieren, analog-Input und PWM-Output-Pin festlegen
46
                 Register: PORTA, ANSEL, TRISA
47
Interner Oscillator  max. 8MHz (entfällt bei Quarzoszillator)
48
                 PIC-CONFIG  _INTRC_OSC_NOCLKOUT 
49
                 Register:   OSCCON
50
ADC-Modul
51
                 Register:   ADCON0, ADCON1
52
TMR0-Overflow-Interrupt
53
                 Register:   INTCON,GIE, -,T0IE, -,T0IF
54
;----------------------------------------------------------
55
56
-MAIN
57
   CALL  ADC            ;Schleiferspannung des Poti in Binaerwert
58
   CALL  DIV16_8        ;(16Bit : 8Bit Ergebnis 8Bit)
59
   movf f_divlo,w       ;nomierten ADC-Wert kopieren
60
   movf PulseWidth      ;ISR-Vergleichsvariable fuer Pulsbreite
61
   CALL  Out_7Segment   ;Duty Cycle 0-99 in LED-Anzeige ausgeben
62
   GOTO MAIN
63
;----------------------------------------------------------
64
                        
65
ADC - siehe Datenblatt des 16F886 S. 101 und Codebeispiel S. 106
66
   movf  ADRESH,w       ;ADC-Ergebnis in Übergabevariable für
67
   movwf f_divHi
68
   movf  ADRESL,w
69
   movwf f_divlo
70
   RETURN
71
;----------------------------------------------------------
72
ADC-Ergebnis =  0 - 4095 normiert auf 0 - 100 durch Division des ADC-
73
Ergebnisses durch 41 (4095/100 = 41 aufgerundet).
74
;
75
DIV16_8 - siehe www.piclist.com/techref/microchip/math/div/16by8lz.htm
76
                     ;Divident: f_divhi:f_divlo, Ergebnis in f_divlo
77
   movlw  .41        ;Divident im WREG übergeben
78
   CALL DIV16_8
79
   ;
80
   movf   f_divlo,w   ;Quotient in Pulsbreitenzähler kopieren
81
   movwf  PulseWidth
82
   RETURN
83
   
84
Out_7Segment
85
   vgl.: www.sprut.de/electronic/pic/programm/led.htm
86
   RETURN
87
    ; 7-Segment-Tabelle
88
    Segmente
89
     addwf PCL, f
90
     retlw B'00011000' ; 0
91
     retlw B'11011110' ; 1
92
     retlw B'00110010' ; 2
93
     retlw B'01010010' ; 3
94
     retlw B'11010100' ; 4
95
     retlw B'01010001' ; 5
96
     retlw B'00010001' ; 6
97
     retlw B'11011010' ; 7
98
     retlw B'00010000' ; 8
99
     retlw B'01010000' ; 9
100
-END

: Bearbeitet durch User
von Volker S. (vloki)


Lesenswert?

Ottmar K. schrieb:
> Hallo Lisa,
>
> ich versuche mal Dir nachfolgend konkret Hilfestellung zu geben ...

Und ich hab gedacht wir hätten schon viel zu viel geholfen und sollten
abwarten ob konkrete Fragen von Lisa kommen, die ja auch selber was tun 
wollte ;-)

Wirklich "ORG" ?
Hoffentlich benutzt der Prof. in seinem "Grundgerüst" schon "CODE"
(so wie die "relocatable" templates welche mit MPASM kommen)
1
RESET_VECTOR    CODE    0x0000    ; processor reset vector
2
        pagesel start
3
        goto   start              ; go to beginning of program
4
5
6
INT_VECTOR      CODE    0x0004    ; interrupt vector location

von Ottmar K. (wil1)


Lesenswert?

Volker SchK schrieb:
> Wirklich "ORG" ?
> Hoffentlich benutzt der Prof. in seinem "Grundgerüst" schon "CODE"

Na ja, wenn es da nicht mehr zu kritisieren gibt...
Es duerfte ja jemanden mit ein bisschen Ahnung von MPASM-Assembler 
ueberhaupt nicht schwerfallen, absoluten code in relocatable umzusetzen! 
Von relocatable code war ja bisher nicht die Rede...

mfG Ottmar

von Volker S. (vloki)


Lesenswert?

Ok sorry.
(das mit dem "ORG" und am besten noch Variablen über EQU scheint so 
einen Reflex bei mir auszulösen ;-)

Ich habe die Auffassung, absoluten Code sollte man einem Anfänger gar 
nicht mehr zeigen.
Zugegeben an meiner Hochschule gibt es sowas auch noch.
"Aus didaktischen Gründen" :-(

von chris (Gast)


Lesenswert?

Absoluten Code hat gewisse Vorteile, aber es stimmt, wenn man sowieso 
nur ARDUINO MEGA und STM32 verwenden wird, bzw gleich RPI weil man mit 
kleineren nicht zurechtkommt, wie es heute ist, dann stimmt der 
Gedankengang.

Speziell bei Pic ist relativer code problematisch,
 da man lcall verwenden muss, aber bei Lcall sind skipc, usw praktisch
nicht verwendbar, da lcall ein macro aus 2-3 Befehlen ist.

von Volker S. (vloki)


Lesenswert?

chris schrieb:
> Absoluten Code hat gewisse Vorteile...

Echt, welche ?
Mir fällt jetzt spontan nichts ein, was ich relocatable nicht auch 
machen könnte.
ABER, ich verwende nur noch sehr selten Assembler, also bin ich da 
vielleicht nicht so sensibel ...

von Lisa Z. (lisa0411)


Lesenswert?

Ottmar K. schrieb:
> Hallo Lisa,
>
> ich versuche mal Dir nachfolgend konkret Hilfestellung zu geben.
> Mit den nachstehenden Lösungsansätzen müsstes Du eigentlich zurecht
> kommen. Wenn nicht - frage bitte konkret nach.
>
> mfG Ottmar
>
> Zunächst das PWM-Prinzip mittels Interrupt-Service-Routine (ISR):
> ORG   0x004               ;Interrupt-Vector
>    TMR0-Overflow-Interrupt
>    z.B. Zyklus 100µs, wird erreicht mit fosc=8MHz, Prescaler TMR0 1:2
>    ergibt mit korrektem TMR0-Preset einen overflow nach 100cyclen
>    (2.000.000Hz  2  100 = 10.000 entspricht 0,0001s = 100µs
>    verwendete Register: OPTION_REG (clock source, Prescaler)
>                         INTCON     (GIE, T0IE, T0IF)
>    WREG + STATUS Register retten
>  ISR:
>    clrf   INTCON,T0IF   ;Interruptflag zurücksetzen
>    Preset TMR0 für overflow nach 100 TMR0-counts
>    ;
>    incf cntCycle,f         ;bei jedem Interrpt +1
>    ;
>    movlw .100              ;Reset des Zykluszählers beim wert=100
>    xorwf cntCycle,w
>    btfsc  STATUS,Z
>    clrf   cntCycle
>    ;
>    ;PWM-Pin auf H setzen wenn cntPulsewidth >= cntCycle
>    ;PWM-Pin auf L setzen wenn cntPulsewidth <  cntCycle
>    ; |  PulseWidth     |
>    ; |-ADC-Ergebnis/41-|
>    ; | z.b.50          |
>    ; |_________________|
>    ; |                 |____________|
>    ; 0                 50          100 cntCycle
>    ;
>    ;PWM-OUTPUT
>    ;PWM-Pin = H wenn PulseWidth >= cntCycle
>    ;        = L "    "          <  cntCycle
>    movf     cntCycle,w     ;Zyklus innerhalb der Pulsbreite?
>    bcf      STATUS,C       ; (wird durch Subtraktion ermittelt)
>    subwf    PulseWidth,w
>    btfsc    STATUS,C       ;C=1 Set PWM-Pin = H wenn C=1
>    bsf      PWM_OUT        ;  cntPulseWidth > cntCycle
>    btfss    STATUS,C       ;C=0 Set PWM-Pin = L Wenn C=0
>    bcf      PWM_OUT
>    ;
>    WREG + STATUS wieder herstellen
>    RETFIE
> ;---------------------------------------------------------
> ;
> -INIT
> ADC-PORT initialsieren, analog-Input und PWM-Output-Pin festlegen
>                  Register: PORTA, ANSEL, TRISA
> Interner Oscillator  max. 8MHz (entfällt bei Quarzoszillator)
>                  PIC-CONFIG  _INTRC_OSC_NOCLKOUT
>                  Register:   OSCCON
> ADC-Modul
>                  Register:   ADCON0, ADCON1
> TMR0-Overflow-Interrupt
>                  Register:   INTCON,GIE, -,T0IE, -,T0IF
> ;----------------------------------------------------------
>
> -MAIN
>    CALL  ADC            ;Schleiferspannung des Poti in Binaerwert
>    CALL  DIV16_8        ;(16Bit : 8Bit Ergebnis 8Bit)
>    movf f_divlo,w       ;nomierten ADC-Wert kopieren
>    movf PulseWidth      ;ISR-Vergleichsvariable fuer Pulsbreite
>    CALL  Out_7Segment   ;Duty Cycle 0-99 in LED-Anzeige ausgeben
>    GOTO MAIN
> ;----------------------------------------------------------
>
> ADC - siehe Datenblatt des 16F886 S. 101 und Codebeispiel S. 106
>    movf  ADRESH,w       ;ADC-Ergebnis in Übergabevariable für
>    movwf f_divHi
>    movf  ADRESL,w
>    movwf f_divlo
>    RETURN
> ;----------------------------------------------------------
> ADC-Ergebnis =  0 - 4095 normiert auf 0 - 100 durch Division des ADC-
> Ergebnisses durch 41 (4095/100 = 41 aufgerundet).
> ;
> DIV16_8 - siehe www.piclist.com/techref/microchip/math/div/16by8lz.htm
>                      ;Divident: f_divhi:f_divlo, Ergebnis in f_divlo
>    movlw  .41        ;Divident im WREG übergeben
>    CALL DIV16_8
>    ;
>    movf   f_divlo,w   ;Quotient in Pulsbreitenzähler kopieren
>    movwf  PulseWidth
>    RETURN
>
> Out_7Segment
>    vgl.: www.sprut.de/electronic/pic/programm/led.htm
>    RETURN
>     ; 7-Segment-Tabelle
>     Segmente
>      addwf PCL, f
>      retlw B'00011000' ; 0
>      retlw B'11011110' ; 1
>      retlw B'00110010' ; 2
>      retlw B'01010010' ; 3
>      retlw B'11010100' ; 4
>      retlw B'01010001' ; 5
>      retlw B'00010001' ; 6
>      retlw B'11011010' ; 7
>      retlw B'00010000' ; 8
>      retlw B'01010000' ; 9
> -END


Zuerst mal danke für die Hilfe!!
Theoretisch habe ich die Vorgehensweise verstanden, aber nachfolgend 
noch ein paar Fragen:
1. Wo realisiere ich die PWM im Programm? Vor der Mainroutine oder 
danach?
2. Das Programm, das ich als "Vorlage" verwende, sieht derzeit 
folgendermaßen aus:
1
    TITLE   "UE1.asm"    ;
2
                LIST      C=135           ;number of columns
3
                LIST      N=65            ;number of lines
4
             #include   <p16f886.inc>
5
                LIST      p=16F886
6
7
8
;#################  Configurationsbits Einstellung
9
        __config  _CONFIG1,0x23E4
10
        __config  _CONFIG2,0x3EFF
11
;############
12
13
;**************************************************************************************
14
;       HW Konfiguration declaration
15
;**************************************************************************************
16
;## 7 Segmentanzeige
17
#define    A_SEG  PORTC,0
18
#define    B_SEG  PORTC,1
19
#define    C_SEG  PORTC,2
20
#define    D_SEG  PORTC,3
21
#define    E_SEG  PORTC,4
22
#define    F_SEG  PORTC,5
23
#define    G_SEG  PORTA,4
24
#define    DP_SEG  PORTB,4
25
26
#define    SEG0  PORTB,0
27
#define    SEG1  PORTB,1
28
#define    SEG2  PORTB,2
29
#define    SEG3  PORTB,3
30
31
;## Leds
32
#define    LED_GRUEN  PORTA,5
33
#define    LED_ROT    PORTA,6
34
#define    LED_GELB  PORTA,7
35
36
;## Analogpins
37
#define    POTI  PORTA,0
38
#define    TEMP  PORTA,1
39
#define    LDR    PORTA,2
40
41
;## Taster
42
#define    S1    PORTB,5
43
#define    S2    PORTA,3
44
45
;## RS232
46
#define    TX    PORTC,6
47
#define    RX    PORTC,7
48
;**************************************************************************************
49
50
;Makros
51
Bank0    MACRO      ;macro to select data RAM bank 0
52
      bcf  STATUS,RP0
53
      bcf  STATUS,RP1
54
      ENDM
55
56
Bank1    MACRO      ;macro to select data RAM bank 1
57
      bsf  STATUS,RP0
58
      bcf  STATUS,RP1
59
      ENDM
60
Bank2    MACRO      ;macro to select data RAM bank 2
61
      bcf  STATUS,RP0
62
      bsf  STATUS,RP1
63
      ENDM
64
65
Bank3    MACRO      ;macro to select data RAM bank 3
66
      bsf  STATUS,RP0
67
      bsf  STATUS,RP1
68
      ENDM
69
70
71
;**************************************************************************************
72
;       declaration of used variables (register)
73
;**************************************************************************************
74
           CBLOCK  20h             ;starting adress of variables
75
        zahl
76
        temp
77
        wait_tmp1
78
        wait_tmp2
79
        ad_low
80
        ad_high
81
          ENDC                    ;end of byte variables
82
83
84
;**************************************************************************************
85
;       Program:
86
;       *******************************************************************************
87
;       written by ZWILETITSCH
88
;
89
;       Date: 05.10.2012      Version: 1.0
90
;       Last modify:
91
;       *******************************************************************************
92
;       CPU running with 4 MHz oscillator
93
;**************************************************************************************
94
             ORG     0000
95
         goto    main
96
            ORG    0004
97
            ;goto   int_sub        ;falls benutzt einblenden
98
            ORG     0008
99
100
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
101
;Lookup Tabelle             -a-
102
;  Segmentaufteilung -gfedcba    f   b
103
;                   -g-
104
;                  e   c
105
;                   -d-
106
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
107
get_value  addwf  PCL,f
108
      retlw  b'00111111'    ;Zahl 0
109
      retlw  b'00000110'    ;Zahl 1
110
      retlw  b'01011011'    ;Zahl 2
111
      retlw  b'01001111'    ;Zahl 3
112
      retlw  b'01100110'    ;Zahl 4
113
      retlw  b'01101101'    ;Zahl 5
114
      retlw  b'01111101'    ;Zahl 6
115
      retlw  b'00000111'    ;Zahl 7
116
      retlw  b'01111111'    ;Zahl 8
117
      retlw  b'01101111'    ;Zahl 9
118
      retlw  b'01110111'    ;Zahl 10=A
119
      retlw  b'01111100'    ;Zahl 11=b
120
      retlw  b'01011000'    ;Zahl 12=c
121
      retlw  b'01011110'    ;Zahl 13=d
122
      retlw  b'01111001'    ;Zahl 14=E
123
      retlw  b'01110001'    ;Zahl 15=F
124
125
126
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
127
;Beginn des Mainprogrammes
128
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
129
130
;**************************************************************************************
131
;       MAINROUTINE:    main
132
;**************************************************************************************
133
main      call   init_pic    ;Aufruf Subroutinen
134
      call   wait_1ms
135
136
;Aktivierung rote LED
137
set_0    bsf   LED_ROT      ;Rote LED einschalten
138
139
;Tastenabfrage
140
frage    btfss  S1        ;Taste 1 gedrückt?
141
      goto  $-1             ; goto previous instruction
142
143
;Aktivierung LEDs blinken
144
set_wechsel call    init_adc        
145
            call    adc_8bit
146
147
148
            bsf   LED_ROT
149
150
151
      movwf   ad_low
152
      call    wait_xms
153
154
      bcf   LED_ROT
155
156
;      bsf   LED_GRUEN
157
;
158
;
159
;      movwf   ad_low
160
;      call    wait_xms
161
;
162
;      bcf   LED_GRUEN
163
;
164
;
165
;            btfss   S2          ;wenn S2 gedrückt, nächste Zeile überspringen
166
;            goto    set_wechsel
167
;      goto  set_0       ;wenn S2 gedrückt, zurück zu nur roter LED 
168
;
169
170
171
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
172
;Beginn der Subroutines
173
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
174
175
;**************************************************************************************
176
;       SUBROUTINE:     Wartezeiten
177
;    @ 4MHz
178
;    1Takt=1usec    exakte wartezeit=1028us
179
;**************************************************************************************
180
wait_1ms  clrf  wait_tmp1
181
      nop
182
      decfsz  wait_tmp1,f
183
      goto  $-2
184
      return
185
186
wait_xms  movwf  wait_tmp2
187
      call  wait_1ms
188
      decfsz  wait_tmp2,f
189
      goto  $-2
190
      return
191
192
;**************************************************************************************
193
;       SUBROUTINE:     initial PIC
194
;**************************************************************************************
195
init_pic  Bank0        ;select Bank 0
196
            clrf    PORTA       ;initialice porta, portb and portc
197
      clrf  PORTB
198
      clrf  PORTC
199
200
  ;register configure BANK 1
201
      Bank1        ;select Bank 1
202
203
      ;Internen Oszilator einstellen 4MHz
204
      movlw  b'01100001'
205
      movwf  OSCCON
206
207
      ;option_reg  Control-Register???
208
        movlw   b'10000111'     ;pullup disable,
209
      movwf   OPTION_REG    ;option_reg register (tm0 1:256 etc.)
210
211
      ;Port  Control-Register???
212
          movlw   b'00001111'     ;OUT/IN definieren
213
      movwf   TRISA
214
          movlw   b'11100000'     ;OUT/IN definieren
215
      movwf   TRISB
216
          movlw   b'10000000'     ;OUT/IN definieren
217
      movwf   TRISC
218
219
      ;Interrupt  Control-Register???
220
            movlw   b'00000000'     ;all Interrupts disable
221
            movwf   INTCON
222
223
  ;register configure BANK 3
224
      Bank3                   ;select Bank 3
225
      movlw  b'00000111'
226
      movwf  ANSEL      ;AN0,1,2 = Analog
227
      clrf  ANSELH      ;Rest digital
228
229
  ;register configure BANK 0
230
      Bank0          ;select Bank 0
231
      clrf  ADCON0      ;AD Converter = off
232
233
      retlw  00h
234
;**************************************************************************************
235
236
;**************************************************************************************
237
;       SUBROUTINE:     Zahl ausgeben
238
;**************************************************************************************
239
set_zahl  andlw  b'00001111'    ;auf 0-15 limitieren
240
      call  get_value    ;Wert aus Lookup holen
241
      movwf  temp      ;Zwischenspeichern
242
      movwf  PORTC      ;Segmente setzen
243
      btfss  temp,6      ;Segment g extra setzen
244
      bcf    G_SEG
245
      btfsc  temp,6
246
      bsf    G_SEG
247
      return
248
;**************************************************************************************
249
250
;**************************************************************************************
251
;       SUBROUTINE:     ADC - Messung
252
;**************************************************************************************
253
254
init_adc  ;AD0,1,2 als Input und Analog (bereits in Init_pic passiert)
255
256
      ;ADCON Register konfigurieren
257
258
      Bank1
259
      movlw  b'10000000'    ;Right justified, Vss,Vdd=Referenz
260
      movwf  ADCON1
261
      Bank0
262
      movlw  b'01000001'    ;FOSC/8, AN0(poti) default, AD=on
263
      movwf  ADCON0
264
      return
265
266
;-----------------
267
268
adc_8bit  Bank1
269
      bcf    ADCON1,ADFM    ;left justified
270
      Bank0
271
      bsf    ADCON0,GO_DONE  ;Messung starten
272
      btfsc  ADCON0,GO_DONE  ;Messung fertig?
273
      goto  $-1
274
      movf  ADRESH,w
275
      movwf  ad_low      ;Wert ins Low eintragen
276
      clrf  ad_high      ;High loeschen
277
      return
278
279
280
      end

Kann ich diesen grundsätzlich so weiterverwenden?

LG Lisa

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