Hi Leute!
Ich möchte mit einem 16F88 eine RGB-LED steuern und zwar sollen alle drei Farben mit 10 bit Auflösung ansteuerbar sein. Dazu habe ich eine 3-fache Software PWM mit 10 bit geschrieben.
Der PIC wird mit 20MHz betrieben, der Timer2 ist so konfiguriert das er bis 70 zählt, Vorteiler 1:1, Nachteiler 1:1. Wenn der Timer überläuft wird in der ISR ein Zähler erhöht (pwmCounter). In der ISR wird der Zähler mit den 3 Duty-Cycles verglichen und die entsprechenden Pins dann deaktiviert oder aktiviert. Damit komme ich auf eine Frequenz von 70Hz aber man merkt noch ganz leichtes flackern weshalb ich gerne 100Hz hätte. Ich kann die Frequenz aber nicht erhöhen (Timer2-Obergrenze) weil die ISR dafür einfach zu lang ist, 70Hz ist schon die Grenze. Durch Inline-Assambler konnte ich die ISR schon drastisch kürzen (was macht CCS blos in den unzähligen Codezeilen???):
#int_global
isr()
{
#asm ASIS
MOVWF W_TEMP ;Copy W to TEMP register
SWAPF STATUS,W ;Swap status to be saved into W
CLRF STATUS ;bank 0, regardless of current bank, Clears
MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP register
MOVF PCLATH, W ;Only required if using page 1
MOVWF PCLATH_TEMP ;Save PCLATH into W
CLRF PCLATH ;Page zero, regardless of current page
BTFSS PIR1,1 ;TMR2IF interrupt?
goto ISR_END;
#endasm
pwmCounter++;
if(pwmCounter==1024)
pwmCounter=0;
if(pwmCounter<pwmRedDS_10)
PIN_RED=1;
else
PIN_RED=0;
if(pwmCounter<pwmGreenDS_10)
PIN_GREEN=1;
else
PIN_GREEN=0;
if(pwmCounter<pwmBlueDS_10)
PIN_BLUE=1;
else
PIN_BLUE=0;
#asm ASIS
ISR_END:
MOVF PCLATH_TEMP, W ;Restore PCLATH
MOVWF PCLATH ;Move W into PCLATH
SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register (sets bank to original)
MOVWF STATUS ;Move W into STATUS register
SWAPF W_TEMP,F ;Swap W_TEMP
SWAPF W_TEMP,W ;Swap W_TEMP into W
BCF TMR2IF ;TMR2 Interrupt Flag löschen
#endasm
}
Der Compiler macht das draus:
.................... #int_global
.................... isr()
.................... {
.................... #asm ASIS
.................... MOVWF W_TEMP ;Copy W to TEMP register
*
0004: MOVWF 70
.................... SWAPF STATUS,W ;Swap status to be saved into W
0005: SWAPF 03,W
.................... CLRF STATUS ;bank 0, regardless of current bank, Clears
0006: CLRF 03
.................... MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP register
0007: MOVWF 71
.................... MOVF PCLATH, W ;Only required if using page 1
0008: MOVF 0A,W
.................... MOVWF PCLATH_TEMP ;Save PCLATH into W
0009: MOVWF 72
.................... CLRF PCLATH ;Page zero, regardless of current page
000A: CLRF 0A
....................
.................... BTFSS PIR1,1 ;TMR2IF interrupt?
000B: BTFSS 0C.1
.................... goto ISR_END;
000C: GOTO 040
.................... #endasm
....................
.................... pwmCounter++;
000D: INCF 26,F
000E: BTFSC 03.2
000F: INCF 27,F
.................... if(pwmCounter==1024)
0010: MOVF 26,F
0011: BTFSS 03.2
0012: GOTO 019
0013: MOVF 27,W
0014: SUBLW 04
0015: BTFSS 03.2
0016: GOTO 019
.................... pwmCounter=0;
0017: CLRF 27
0018: CLRF 26
....................
.................... if(pwmCounter<pwmRedDS_10)
0019: MOVF 27,W
001A: SUBWF 29,W
001B: BTFSS 03.0
001C: GOTO 025
001D: BTFSS 03.2
001E: GOTO 023
001F: MOVF 28,W
0020: SUBWF 26,W
0021: BTFSC 03.0
0022: GOTO 025
.................... PIN_RED=1;
0023: BSF 06.4
.................... else
0024: GOTO 026
.................... PIN_RED=0;
0025: BCF 06.4
....................
.................... if(pwmCounter<pwmGreenDS_10)
0026: MOVF 27,W
0027: SUBWF 2B,W
0028: BTFSS 03.0
0029: GOTO 032
002A: BTFSS 03.2
002B: GOTO 030
002C: MOVF 2A,W
002D: SUBWF 26,W
002E: BTFSC 03.0
002F: GOTO 032
.................... PIN_GREEN=1;
0030: BSF 06.3
.................... else
0031: GOTO 033
.................... PIN_GREEN=0;
0032: BCF 06.3
....................
.................... if(pwmCounter<pwmBlueDS_10)
0033: MOVF 27,W
0034: SUBWF 2D,W
0035: BTFSS 03.0
0036: GOTO 03F
0037: BTFSS 03.2
0038: GOTO 03D
0039: MOVF 2C,W
003A: SUBWF 26,W
003B: BTFSC 03.0
003C: GOTO 03F
.................... PIN_BLUE=1;
003D: BSF 06.6
.................... else
003E: GOTO 040
.................... PIN_BLUE=0;
003F: BCF 06.6
....................
.................... #asm ASIS
.................... ISR_END:
.................... MOVF PCLATH_TEMP, W ;Restore PCLATH
0040: MOVF 72,W
.................... MOVWF PCLATH ;Move W into PCLATH
0041: MOVWF 0A
.................... SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register (sets bank to original)
0042: SWAPF 71,W
.................... MOVWF STATUS ;Move W into STATUS register
0043: MOVWF 03
.................... SWAPF W_TEMP,F ;Swap W_TEMP
0044: SWAPF 70,F
.................... SWAPF W_TEMP,W ;Swap W_TEMP into W
0045: SWAPF 70,W
....................
.................... BCF TMR2IF ;TMR2 Interrupt Flag löschen
0046: BCF 0C.1
.................... #endasm
.................... }
....................
0047: RETFIE
Das sind 67 Anweisungen, wenn ich den Code auf 50 kürzen könnte dann wären ungefähr 100 Hz drin. Sieht einer von euch irgendwo Einsparungsmöglichkeiten?
Gruß Wolfi