PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Weihnachtsstern :Muster aus Tabelle auslesen



the_Ghost666
26.01.2006, 00:24
Moin zusammen.
erstmal zum Thema: ich weiß , dass es langsam etwas spät dafür ist, aber das projekt liegt schon seit oktober rum und wartet auf vollendung.
Ich schreibe den Code in Assembler (und dabei würde ich auch gerne bleiben)

Bei http://www.hanf-elektrotechnik.de/ gibt es einen Weihnachtsstern unter Projekte. Dort wird ein MAX 7219 LED-Treiber seriell angesteuert. Für die Ansteuerung hab ich bereits eine Routine fertig, die auch klappen sollte. Jetzt sollen Leuchtmuster ausgegeben werden.
Jedes Muster kann man in Sequenzen aufteilen je 8Byte, was einem Einzelbild entspricht. Interruptgesteuert wird nun alle 500ms das nächste Einzelbild gezeigt.
Als Controller nehme ich einen PIC 16F648A, mit 4kB Programmspeicher

Nun zum Problem: Wie lege ich die Muster ab, sodass ich sie ohne großen aufwand verwalten kann?

Ich möchte es folgendermaßen organisieren:
Ein Muster besteht aus max 24 Sequenzen. Jede Sequenz aus 8Byte, eins für jeden Ast des Sterns (siehe URL oben). Vor jedem dieser Musterblöcke ist ein Byte, dass die Länge des Musters angibt (ich will ja manchmal auch kürzere Muster mit nur 4 Sequenzen). Das macht also pro Muster 192Byte Daten + vorne weg ein Infobyte zur länge der Muster.

Es gibt die DT anweisung, mit der man ein oder mehrere Byte hintereinander im Programmspeicher als RTWL Befehl(Return with Literal in Work Register) ablegen kann.

Aber wie lese ich nun diese Stellen mit den Blöcken richtig aus?
Und wo muss ich diese platzieren, damit genug platz ist?
Muss ich indirekte adressierung benutzen?

Ich hoffe jemand kann mir helfen. Bei interesse poste ich den Quellcode

the_Ghost666
26.01.2006, 04:05
Ich liebe es, wenn ich meine Threads selbst beantworte *G*
Ich habe weiter mit einigen Sachen rumexperimentiert und es scheint nun zu einem guten Ergebnis geführt zu haben. Ich verwende jetzt eine einfache Tabelle und den Befehl ADDWF PCL um auf Tabelleneinträge zuzugreifen, wie es auch oft bei der Decodierung von SiebenSegmentAnzeigen gemacht wird. In Verbindung mit einigen Sicherungen, damit diese Tabelle nicht aus dem Ruder läuft, hab ich jetzt eine im MPLAB Simulator laufende Version gebaut. Das Timing klappt, und wenn man die Muster richtig eingibt (mit länge in der definition statt im separaten byte) bekommt man auch soweit ich das sehe richtige ergebnisse. nun muss ich noch den code "Play_PatternX" so umschreiben, dass er universell benutzbar ist, statt ihn für jedes muster zu kopieren und anzupassen. ich bin sehr gespannt ob der code auch in der echten anwendung funktioniert, das ist ja meistens der knackpunkt und das, was die sache so deprimierend macht. Ich poste hier mal den code und werde bei updates immer mal aktualisieren. vielleicht hilfts ja irgendwem. ich hab mich angestrengt alles in englisch und mit guter kommentierung zu versehen. vielleicht findet ja jemand ein paar worte die es zu sagen gibt, ein "mhm sieht gut aus" ist gern gehört *G* aber ist schon spät geworden, deswegen erstmal schluss für heute

achja, das programm ist noch nicht vollständig, zb fehlt noch die möglichkeit einzelne muster per taster auszuwählen. tricky wirds noch einen modus zu schreiben, in dem er alle muster durchgeht. aber da hab ich schon eine idee.


;LEDStern Progam
;Internal Oscillator without Pinout
; PortPin Directiom Function
; RA0
; RA1
; RA2
; RA3
; RA4
; ----------------------------
; RB0
; RB1 Output Clock
; RB2 Output Load
; RB3 Output Din
; RB4
; RB5
; RB6 Input Next
; RB7 Input OK
; Shape of Pattern-Informations: LengthX -> lenght of the pattern in Byte
;

list p=16f648A
include "P16F648A.inc"

__config _INTOSC_OSC_NOCLKOUT & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BOREN_OFF & _DATA_CP_OFF & _CP_OFF


#define CLK PORTB,1
#define LOAD PORTB,2
#define DIN PORTB,3
#define NEXT PORTB,6
#define OK PORTB,7

DATAHIGH equ 0x20 ;register adress for max7219, used by "SEND"
DATALOW equ 0x21 ;data for max7219, used by "SEND"
counter equ 0x22 ;counter used by "send"
W_TEMP equ 0x23 ;temporal storage while in interrupt service routine
STATUS_TEMP equ 0x24 ;temporal storage while in interrupt service routine
PCLATH_TEMP equ 0x25 ;temporal storage while in interrupt service routine
Pattern_No equ 0x26 ;no of pattern to be played
counter2 equ 0x27 ;multi purpose counter
STEP equ 0x28 ;multi purpose counter for Pattern readout
SEQUENCE equ 0x29 ;time keeping variable, cleared by interrupt, set by routine,prevents routine from running through more than once between interrupts
;MAX7219 register adresses
NOOP equ 0x00
DIGIT0 equ 0x01
DIGIT1 equ 0x02
DIGIT2 equ 0x03
DIGIT3 equ 0x04
DIGIT4 equ 0x05
DIGIT5 equ 0x06
DIGIT6 equ 0x07
DIGIT7 equ 0x08
DECODE equ 0x09
INTENSITY equ 0x0A
SCANLIMIT equ 0x0B
SHUTDOWN equ 0x0C
TEST equ 0x0F

; Length of Pattern
Length1 equ 0x48
Length2 equ 0x48
;Length3 equ 0x09
;Length4 equ 0x09
;Length5 equ 0x09
;Length6 equ 0x09
;Length7 equ 0x09
;Length8 equ 0x09
;Length9 equ 0x09
;Length10 equ 0x09
;Length11 equ 0x09
;Length12 equ 0x09
;Length13 equ 0x09
;Length14 equ 0x09
;Length15 equ 0x09
;Length16 equ 0x09


ORG 0x00
GOTO MAIN
ORG 0x04

INT_VEC ;save important registers
MOVWF W_TEMP
SWAPF STATUS,W
CLRF STATUS
MOVWF STATUS_TEMP
MOVF PCLATH, W
MOVWF PCLATH_TEMP
CLRF PCLATH ; Bank 0
ISR ;interrupt service routine
BTFSC INTCON,RBIF ;check source of interrupt
GOTO BUTTON_PRESSED
BTFSC PIR1,TMR1IF
GOTO TMR1_OVERFLOW
GOTO END_INT
BUTTON_PRESSED
BCF INTCON,RBIF ;clear interrupt flag
BTFSC NEXT
GOTO DO_NEXT
BTFSC OK
GOTO DO_OK
GOTO END_INT
TMR1_OVERFLOW
BCF PIR1,TMR1IF ;clear interrupt flag
MOVLW 0x0B ;set timer to 500ms delay
MOVWF TMR1H
MOVLW 0xDE
MOVWF TMR1L
CLRF SEQUENCE ;clear sequence to signal new timeslot
GOTO END_INT

END_INT ;restore important registers and leave interrupt
MOVF PCLATH_TEMP, W
MOVWF PCLATH
SWAPF STATUS_TEMP,W
MOVWF STATUS
SWAPF W_TEMP,F
SWAPF W_TEMP,W
RETFIE

DO_NEXT
INCF Pattern_No
GOTO END_INT
DO_OK
GOTO END_INT

MAIN
;Setup
MOVLW 0x07
MOVWF CMCON ;comparator off
BSF STATUS,RP0 ;bank1
BSF PCON, OSCF ;internal oscillator @ 4MHz
MOVLW 0xF1
MOVWF TRISB ;setting portb directions
MOVLW B'00001000'
MOVWF OPTION_REG ;setting timer0 and weak pullups
MOVLW 0x01
MOVWF PIE1 ;configure peripherial interrupts
BCF STATUS,RP0 ;bank0
MOVLW 0x31 ;prescaler 8
MOVWF T1CON ;configure Timer1
MOVLW 0x48
MOVWF INTCON ;configure interrupts
CLRF PORTB
BSF LOAD ;set LOAD high, inactive
BSF INTCON,GIE ;enable global interrupt

;test
CLRF Pattern_No
;setting up MAX7219
MOVLW TEST ;disable test-mode
MOVWF DATAHIGH
CLRF DATALOW
CALL SEND

MOVLW DECODE ;setting decode (no decoding)
MOVWF DATAHIGH
CLRF DATALOW
CALL SEND

MOVLW SCANLIMIT ;setting scan limit (number of leds)
MOVWF DATAHIGH
MOVLW 0x07
MOVWF DATALOW
CALL SEND

MOVLW SHUTDOWN ;setting shutdown (normal operation)
MOVWF DATAHIGH
MOVLW 0x01
MOVWF DATALOW
CALL SEND

CLRF STEP
;main loop
MAINLOOP
; MOVLW 0x0F ;check if pattern_no > 15, then set to 0
; SUBWF Pattern_No,w
; BTFSC STATUS,C
;CLRF Pattern_No
MOVFW Pattern_No
ADDWF PCL
GOTO Play_Pattern1
GOTO Play_Pattern2
; GOTO Pattern3
; GOTO Pattern4
; GOTO Pattern5
; GOTO Pattern6
; GOTO Pattern7
; GOTO Pattern8
; GOTO Pattern9
; GOTO Pattern10
; GOTO Pattern11
; GOTO Pattern12
; GOTO Pattern13
; GOTO Pattern14
; GOTO Pattern15
; GOTO Pattern16
GOTO MAINLOOP

Play_Pattern1
MOVF SEQUENCE,W ;check if pattern is running more than once between interrupts
BTFSS STATUS,Z
GOTO MAINLOOP
MOVLW 0x08 ;preparing for a single sequence of 8byte
MOVWF counter2
MOVLW DIGIT0
MOVWF DATAHIGH
LOOP_P1
MOVFW STEP ;get byte
CALL Pattern1
MOVWF DATALOW
CALL SEND ;send byte
INCF STEP ;preparing for next byte
INCF DATAHIGH
DECFSZ counter2
GOTO LOOP_P1 ;until 8 bytes were send
MOVLW Length1
SUBWF STEP,W
BTFSC STATUS,C
CLRF STEP ;check if complete pattern was send, then reset step to restart pattern
INCF SEQUENCE ;prohibit another execution of this code in this timeslot
GOTO MAINLOOP

Play_Pattern2
MOVF SEQUENCE,W ;check if pattern is running more than once between interrupts
BTFSS STATUS,Z
GOTO MAINLOOP
MOVLW 0x08 ;preparing for a single sequence of 8byte
MOVWF counter2
MOVLW DIGIT0
MOVWF DATAHIGH
LOOP_P2
MOVFW STEP ;get byte
CALL Pattern2
MOVWF DATALOW
CALL SEND ;send byte
INCF STEP ;preparing for next byte
INCF DATAHIGH
DECFSZ counter2
GOTO LOOP_P2 ;until 8 bytes were send
MOVLW Length2
SUBWF STEP,W
BTFSC STATUS,C
CLRF STEP ;check if complete pattern was send, then reset step to restart pattern
INCF SEQUENCE ;prohibit another execution of this code in this timeslot
GOTO MAINLOOP

;************************************************* ***********************************
;Data Table for Different Pattern
;Pattern 2 -> Blink one LED of each row from outside to inside
Pattern1
addwf PCL
;Number of Sequences for Pattern 1
DT 0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10
DT 0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10
DT 0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10
DT 0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10
DT 0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10
DT 0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10
DT 0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10
DT 0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10
DT 0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10

Pattern2
addwf PCL
;Number of Sequences for Pattern 2
DT 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
DT 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40
DT 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
DT 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10
DT 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08
DT 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04
DT 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
DT 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
DT 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00


;+++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++
;+++++++++++++++++++++++++++++++++Subroutines+++++ +++++++++++++++++++++++++++++++++++

;***************************SEND TO MAX7219******************************************
SEND
BCF LOAD ;LOAD is low, starting transfer
MOVLW 0x08
MOVWF counter ;load with 8 loops
HIGH_BYTE
BCF CLK ;prepare clock
RLF DATAHIGH,F ;rotate high byte through carry
BTFSS STATUS,C
GOTO HIGHBYTE_DIN_LOW ;set DIN low
GOTO HIGHBYTE_DIN_HIGH ;set DIN high
HIGHBIT_DONE
BSF CLK ;raise clock to send bit
DECFSZ counter
GOTO HIGH_BYTE ;loopback
RLF DATAHIGH
MOVLW 0x08
MOVWF counter ;load with 8 loops
LOW_BYTE
BCF CLK ;prepare clock
RLF DATALOW,F ;rotate low byte through carry
BTFSS STATUS,C
GOTO LOWBYTE_DIN_LOW ;set DIN low
GOTO LOWBYTE_DIN_HIGH ;set DIN high
LOWBIT_DONE
BSF CLK ;raise clock to send bit
DECFSZ counter
GOTO LOW_BYTE ;loopback
BSF LOAD ;LOAD is high, transfer completed
RLF DATALOW
RETURN

HIGHBYTE_DIN_HIGH
BSF DIN
GOTO HIGHBIT_DONE
HIGHBYTE_DIN_LOW
BCF DIN
GOTO HIGHBIT_DONE
LOWBYTE_DIN_HIGH
BSF DIN
GOTO LOWBIT_DONE
LOWBYTE_DIN_LOW
BCF DIN
GOTO LOWBIT_DONE

END ;end program