Första Multiplexing försöket. PIC - ASM

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
PopUnoNkoK
Inlägg: 789
Blev medlem: 10 december 2007, 12:40:08
Ort: Piteå

Första Multiplexing försöket. PIC - ASM

Inlägg av PopUnoNkoK »

Hej.

Tänkte ge mig på att testa multiplexa för första gången.
Tänker börja med "vanligt" multiplexning och vänta med CharliePlexing så länge.

Jag har läst en del på nätet och tror att jag har koll på grunderna.
Nu har jag en lite specifik fråga som inte besavars i de texter jag hittat på nätet.

Så här har jag tänkt mig.
7segmentsdisplayer som är av CommonCatod typ.
Alla segment är kopplade i serie till en Port på PICen och alla Catoder till varsin pinne i en annan port.
(Alltså alla "a"-segment är kopplade i serie till en pinne och alla "b"-segment i serie till en pinne osv. Med ett strömbegränsande motstånd per serie)

Sedan tänkte jag mig så här.

Pseudo kod

Kod: Markera allt

ISR

Sätt Common Catod på digit 2,3,4 hög
Sätt Common Catod på digit 1 låg
Tänd rätt segment på digit 1 genom att sätta rätt segmentspinnar höga.

(resten av klock koden hamnar här, för att räkna upp klockan)

End ISR



Nästa gång vi hamnar i ISRen ska det se ut så här:

ISR

Sätt Common Catod på digit 1,3,4 hög
Sätt Common Catod på digit 2 låg
Tänd rätt segment på digit 2 genom att sätta rätt segmentspinnar höga.

(resten av klock koden hamnar här, för att räkna upp klockan)

End ISR 

Osv
Problemet jag har är hur jag på ett smidigt sätt ska få det att byta (rulla) till nästa siffra varje gång jag hamnar i ISRen.

Är detta ett "snyggt" sätt att sköta det på eller gör jag det onödigt krångligt?
Känns "stelt" att sköta multiplexingen i "MainLoop"en.

Tacksam för synpunkter.

MVH Peter
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Första Multiplexing försöket. PIC - ASM

Inlägg av sodjan »

Hur då "kopplade i serie" ???
Om de verkligen är i serie så är det fel, det ska vara parr.
D.v.s alla "a" segment till samma pinne med var sitt motstånd.
Och alla "b" segment till en annan pinne också med var sitt motstånd.

> Problemet jag har är hur jag på ett smidigt sätt ska få det att byta (rulla) till nästa siffra varje gång jag hamnar i ISRen.

Du får hålla reda på vilken display som är aktiv och aktivera nästa.
Exakt hur beror lite på hur de är anslutna. Om de sitter på pinnar i följd
så kan en enkel shift lösa det. Och en "test-bit" för att se om det är
dags att börja om igen.
v-g
EF Sponsor
Inlägg: 7875
Blev medlem: 25 november 2005, 23:47:53
Ort: Kramforce

Re: Första Multiplexing försöket. PIC - ASM

Inlägg av v-g »

En "global" variabel som räknar från 1-3 bara så är det kirrat.
ie
EF Sponsor
Inlägg: 1375
Blev medlem: 23 oktober 2006, 13:12:57
Ort: Tyresö

Re: Första Multiplexing försöket. PIC - ASM

Inlägg av ie »

Om du med klocka menar en som visar t ex timmar-minuter, så funkar det inte då du bara multiplexar ut en gång per klockpuls.

När du driver siffrorna med multiplexing måste du skriva till dem hela tiden, t ex 1000ggr/sekund.

Alltså bör du ha en interruptrutin som räknar upp klockan, t ex en gång per sekund, och en som uppdaterar displayen t ex 1000 ggr per sekund.

Med reservation för att jag missuppfattat hur du menar.

Edit: Förtydligande att jag menar att det bör vara två interruptrutiner
Senast redigerad av ie 21 november 2011, 14:20:34, redigerad totalt 1 gång.
PopUnoNkoK
Inlägg: 789
Blev medlem: 10 december 2007, 12:40:08
Ort: Piteå

Re: Första Multiplexing försöket. PIC - ASM

Inlägg av PopUnoNkoK »

ie: Hastigheten är jag inte så orolig för. Min påbörjade kod hamnar i ISRen 211ggr/sekund. Detta borde innebära att hela klockan (digits) hinner uppdateras lite mer än 50ggr per sekund. Jag gissar att detta kommer att flimra en del men att man ändå kan se om resten av koden fungerar eller inte.
För att sedan få bort flimret så tänker jag lägga till ytterligare en 8bits "tillägsräknare" i början av ISRen.


Catoderna är tänkta att vara kopplade till en och samma port och i följd. Tex porta 0-3. Så där tänkte jag köra RRF eller RLF.
Jag antar att ni menar att man kör en if sats för varje DIGIT. Typ


pseudokod

Kod: Markera allt

DEFINE		sekund_ental	porta,0
DEFINE		sekund_tiotal	porta,1
osv

MOVLW		b'00000001'
MOVWF		PORTA


ISR

RLF		PORTA

BTFSS 		sekund_ental
		(skicka ut sekundernas ental till segmenten)

BTFSS		sekund_tiotal
		(skicka ut sekundernas tiotal till segmenten)
OSV
ENDISR
Om jag får detta att funka känns det väldigt smidigt..



Angående att jag skrev att dom var kopplade i serie: :oops:

EDIT: Blandade ihop PORTA och B
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Första Multiplexing försöket. PIC - ASM

Inlägg av sodjan »

> Angående att jag skrev att dom var kopplade i serie: :oops:

Och vad betyder det mer konkret ??
PopUnoNkoK
Inlägg: 789
Blev medlem: 10 december 2007, 12:40:08
Ort: Piteå

Re: Första Multiplexing försöket. PIC - ASM

Inlägg av PopUnoNkoK »

Mer konkret betyder det att jag lyckas skriva fel trots att jag verkligen försökt tänkta efter. Alla "a"-segment ska, som du säger, vara kopplade parallellt. Alla "b"-segment, parallellt osv.

Det är tyvärr inte första gången jag skrivit fel angående saker kopplade i serie eller parallellt.

Tanken är att koppla likt denna bild.
http://www.maxim-ic.com/images/appnotes ... 7Fig01.gif
Med en transistor på varje catod för att hantera alla segments gemensamma ström.
Dock bara med 4 siffror. (Eventuellt 6st)

Bilden kommer från en artikel om CharliePlexing men i början (där bilden återfinns) beskriver dom skillnaden mellan "vanlig" multiplexing och Charlieplexing.

MVH Peter
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Första Multiplexing försöket. PIC - ASM

Inlägg av sodjan »

OK, ja men då så... :-)
Bara att lägga ut segmenten för en display, "tända" den via gemensamma pinne och vänta ett tag.
Sedan släcka den, byta till segmenten för nästa display och tända den o.s.v.
Inget konstigt alls.

Det är bättre att släcka ner helt innan man byter segment-info för att
undvika "överhörning" mellan displayerna. D.v.s att bara köra rotate/shift
är inte helt optimalt. Eller, ja, du kan ju släcka segmenten istället i och för sig...
PopUnoNkoK
Inlägg: 789
Blev medlem: 10 december 2007, 12:40:08
Ort: Piteå

Re: Första Multiplexing försöket. PIC - ASM

Inlägg av PopUnoNkoK »

Nu ska vi se om jag har förstått dig rätt när det gäller "överhörning".

Nu har jag testat att skriva ihop en kod som borde fixa själva multiplexingen. Jag har dock inte haft tid att koppla upp nåt än så jag vet ej.
Men som sagt, överhörningen.

Här är den del av koden i ISRen som sköter multiplexningen av 4st 7segmentsdisplayer.

segments är definierad till PORTC

CC_all står för CommonCatod porten. PORTB i detta fall.
CC_min_1 = PORTB,4
CC_min_10 = PORTB,5
osv

Kod: Markera allt

	CLRF		segments		;Släck alla segment
	CLRF		STATUS
	RLF			CC_all			;"Rotera" till nästa siffra
	BTFSS		STATUS,C
	GOTO		minuter_ental
	BSF			CC_min_1

minuter_ental
	BTFSS		CC_min_1		;Kolla om minuternas ental ska tändas
	GOTO		minuter_tiotal
	
	MOVFW		min_one			;Hämta rätt siffra 		
	MOVWF		segments		;Och lägg ut på rätt port.

	GOTO		tillaggsraknare
	

minuter_tiotal
	BTFSS		CC_min_10		;Kolla om minuternas tiotal ska tändas
	GOTO		timmar_ental
	
	MOVFW		min_ten			;Hämta rätt siffra 		
	MOVWF		segments		;Och lägg ut på rätt port.

	GOTO		tillaggsraknare


timmar_ental
	BTFSS		CC_hour_1		;Kolla om minuternas tiotal ska tändas
	GOTO		timmar_tiotal
	
	MOVFW		hour_one			;Hämta rätt siffra 		
	MOVWF		segments		;Och lägg ut på rätt port.

	GOTO		tillaggsraknare

timmar_tiotal
	BTFSS		CC_hour_10		;Kolla om minuternas tiotal ska tändas
	GOTO		tillaggsraknare
	
	MOVFW		hour_ten			;Hämta rätt siffra 		
	MOVWF		segments		;Och lägg ut på rätt port.

	GOTO		tillaggsraknare
Alltså, jag börjar med att släcka alla segment, oavsett vilken siffra som är tänd. Sedan roterar jag det registret som är kopplade till de olika gemensamma catoderna. Jag har även lagt till en snutt som fixar att "ettan" (som är tänkt att jorda catoderna) bara roterar på de 4 övre bitarna.

Sedan kontrolleras vilken siffra som ska tändas (minut ental, minut tiotal osv) och så hämtas rätta information för den siffran och detta läggs ut på den port som är kopplad till alla segmenten.
I mitt huvud borde det i alla fall funka.

Så till frågan. Har jag löst det du menar med överhörning genom att släcka segmenten precis innan jag skiftar siffra och tänder segmenten igen?




Hela koden i fall någon är intresserad.

Kod: Markera allt

;**********************************************************************
;   This file is a basic code template for object module code         *
;   generation on the PIC16F690. This file contains the               *
;   basic code building blocks to build upon.                         *
;                                                                     *
;   Refer to the MPASM User's Guide for additional information on     *
;   features of the assembler and linker (Document DS33014).          *
;                                                                     *
;   Refer to the respective PIC data sheet for additional             *
;   information on the instruction set.                               *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Filename:      xxx.asm                                           *
;    Date:                                                            *
;    File Version:                                                    *
;                                                                     *
;    Author:                                                          *
;    Company:                                                         *
;                                                                     *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Files required: P16F690.INC                                      *
;                                                                     *
;                                                                     *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Notes:                                                           *
;                                                                     *
;                                                                     *
;                                                                     *
;                                                                     *
;**********************************************************************

    list      p=16F690           ; list directive to define processor
    #include <p16F690.inc>        ; processor specific variable definitions

    errorlevel  -302              ; suppress message 302 from list file

    __CONFIG   _CP_OFF & _CPD_OFF & _BOR_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _FCMEN_OFF & _IESO_OFF 

; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See data sheet for additional information on configuration word settings.

#define	segments	PORTC
#define	CC_min_1	PORTB,4
#define	CC_min_10	PORTB,5
#define	CC_hour_1	PORTB,6
#define	CC_hour_10	PORTB,7
#define	CC_all		PORTB


value_2_7seg	MACRO
		movfw	sec_one
		call	bin2seg
		movwf	sec_one

		movfw	sec_ten
		call	bin2seg
		movwf	sec_ten

		movfw	min_one
		call	bin2seg
		movwf	min_one

		movfw	min_ten
		call	bin2seg
		movwf	min_ten

		movfw	hour_one
		call	bin2seg
		movwf	hour_one

		movfw	hour_ten
		call	bin2seg
		movwf	hour_ten

		ENDM




;***** VARIABLE DEFINITIONS (examples)
TMR0_extra	EQU .122			;Ska vara 122 för sekuknder med 4mHz

; example of using Shared Uninitialized Data Section
INT_VAR     UDATA_SHR     
w_temp      RES     1       ; variable used for context saving 
status_temp RES     1       ; variable used for context saving
pclath_temp RES     1       ; variable used for context saving


	udata	0x20				;Minnesbanker som används i koden
d1			res	1					;Tilläggs räknare till TMR0 för att öka tiden		
sec			res	1					;Råvärdet för sec, min hour dagar, 2 siffror
min			res	1
hour		res	1
days		res	1	

count		res	1					;Rådata för counten
setting		res	1					;För att ställa in vilket läge counten är min,hour eller dagar.

sec_one		res 1					;Entalet i counten
sec_ten		res 1					;Tiotalet i counten

min_one		res 1					;Entalet i counten
min_ten		res 1					;Tiotalet i counten

hour_one	res 1					;Entalet i counten
hour_ten	res 1					;Tiotalet i counten

					

t1			res 1
w2			res 1
getones		res 1

debug		res	1


;**********************************************************************
RESET_VECTOR    CODE    0x0000       ; processor reset vector
        goto    start                ; go to beginning of program

INT_VECTOR      CODE    0x0004       ; interrupt vector location

INTERRUPT

        movwf   w_temp            ; save off current W register contents
        movf    STATUS,w          ; move status register into W register
        movwf   status_temp       ; save off contents of STATUS register
        movf    PCLATH,w          ; move pclath register into W register
        movwf   pclath_temp       ; save off contents of PCLATH register



; isr code can go here or be located as a call subroutine elsewhere

	
	MOVLW		.0				; Nollställ TMR0
	MOVWF		TMR0			; 
	BCF			INTCON, T0IF	;Nolla TMR0s interrupt flagga



	CLRF		segments		;Släck alla segment
	CLRF		STATUS
	RLF			CC_all			;"Rotera" till nästa siffra
	BTFSS		STATUS,C
	GOTO		minuter_ental
	BSF			CC_min_1

minuter_ental
	BTFSS		CC_min_1		;Kolla om minuternas ental ska tändas
	GOTO		minuter_tiotal
	
	MOVFW		min_one			;Hämta rätt siffra 		
	MOVWF		segments		;Och lägg ut på rätt port.

	GOTO		tillaggsraknare
	

minuter_tiotal
	BTFSS		CC_min_10		;Kolla om minuternas tiotal ska tändas
	GOTO		timmar_ental
	
	MOVFW		min_ten			;Hämta rätt siffra 		
	MOVWF		segments		;Och lägg ut på rätt port.

	GOTO		tillaggsraknare


timmar_ental
	BTFSS		CC_hour_1		;Kolla om minuternas tiotal ska tändas
	GOTO		timmar_tiotal
	
	MOVFW		hour_one			;Hämta rätt siffra 		
	MOVWF		segments		;Och lägg ut på rätt port.

	GOTO		tillaggsraknare

timmar_tiotal
	BTFSS		CC_hour_10		;Kolla om minuternas tiotal ska tändas
	GOTO		tillaggsraknare
	
	MOVFW		hour_ten			;Hämta rätt siffra 		
	MOVWF		segments		;Och lägg ut på rätt port.

	GOTO		tillaggsraknare
	
	


tillaggsraknare
	DECFSZ		d1				;Räkna ner TMR0 tillägsräknare, kolla om den är noll
	GOTO		endIsr			;NEJ, fortsätt räkna
	movlw		TMR0_extra		;JA, Återställ TMR0 Tillägsräknare
	movwf		d1

;------ Dela upp i ental tiotal och shifta ut, en ggr i sekunden



;---------Sekunder



sekunder
	INCF		sec
	MOVFW		sec				; Sekunder ++
	MOVF		sec,W			; Kolla om sekunderna = 60
	SUBLW		.60				; Kolla om sekunderna = 60
	BTFSS		STATUS,Z		; Kolla om sekunderna = 60
	GOTO		endIsr						;     else {
	clrf		sec				;	sec = 0;

;---------Minuter


minuter
	INCF		min
	MOVFW		min				; Minuter ++
	MOVF		min,W			; Kolla om Minuterna = 60
	SUBLW		.60				; Kolla om Minuterna = 60
	BTFSS		STATUS,Z		; Kolla om Minuterna = 60
	GOTO		endIsr						;     else {
	clrf		min				;	min = 0;

;---------Timmar


timmar
	INCF		hour
	MOVFW		hour				; Timmar ++
	MOVF		hour,W			; Kolla om Timmar = 24
	SUBLW		.24				; Kolla om Timmar = 24
	BTFSS		STATUS,Z		; Kolla om Timmar = 24
	GOTO		endIsr						;     else {
	clrf		hour				;	hour = 0;

;---------Dagar

dagar
	INCF		days
	MOVFW		days				; Dagar ++
	MOVF		days,W			; Kolla om Dagar = 24
	SUBLW		.150				; Kolla om Dagar = 24
	BTFSS		STATUS,Z		; Kolla om Dagar = 24
	GOTO		endIsr						;     else {
	clrf		days				;	Dagar = 0;

endIsr

        movf    pclath_temp,w     ; retrieve copy of PCLATH register
        movwf   PCLATH            ; restore pre-isr PCLATH register contents
        movf    status_temp,w     ; retrieve copy of STATUS register
        movwf   STATUS            ; restore pre-isr STATUS register contents
        swapf   w_temp,f
        swapf   w_temp,w          ; restore pre-isr W register contents
        retfie                    ; return from interrupt

MAIN_PROG       CODE

start
; remaining code goes here

	BANKSEL	PORTA		;Init Port A & B & C
	CLRF 	PORTA 
	BANKSEL	PORTB
	CLRF 	PORTB
	BANKSEL	PORTC
	CLRF 	PORTC  		

	BANKSEL	ANSEL
	CLRF 	ANSEL 		;digital I/O
	BANKSEL	ANSELH
	CLRF 	ANSELH 		;digital I/O

	BANKSEL	TRISA
	MOVLW 	b'00000000' ;Set RA<0-7> as Outputs
	MOVWF 	TRISA 	

	BANKSEL	TRISB
	MOVLW 	b'00000000' ;Set RB<0-7> as Outputs 
	MOVWF 	TRISB 

	BANKSEL	TRISC
	MOVLW 	b'00000000' ;Set RC Outputs and Inputs
	MOVWF 	TRISC 	

	BCF 	STATUS,RP0 	;Bank 0
	CLRWDT 				;Clear WDT and prescaler

	BANKSEL	OPTION_REG
	MOVLW 	b'00000100' ;Select TMR0, prescale, and clock source b'00000100'
	MOVWF 	OPTION_REG
	NOP
	NOP
	NOP
	BANKSEL	INTCON
	MOVLW	b'10100000'		;Global interrupt and TMR0 interrupt enabled
	MOVWF	INTCON 		

	movlw	TMR0_extra	;Ladda TMR0s extraräknare med förbestämt värde, 
	movwf	d1			;definieras i början av koden.

	MOVLW	.12			;Nollställ klockan på uppstart.
	MOVWF	sec
	MOVWF	min
	MOVWF	hour
	
	movlw	.1
	movwf	debug

	banksel	PORTB
	BSF		CC_min_1


MainLoop

; remaining code goes here
		call	SplitNum			;Delar upp sekunder till sec_one och sec_ten, minuter och timmar åxå.
		nop
		value_2_7seg				;sec_one ändras från värdet till samma värde men för en 7 segments display.
MainLoop1	
		nop
		rlf		debug,f
		nop

        goto    MainLoop1             ; loop forever

;---------------- LookUpTable för 7 segments displayerna
bin2seg	
	addwf	PCL, F	; Jump into the lookup table
;	retlw	H'C0'	; Return segment code for 0
;	retlw	H'F9'	; Return segment code for 1
;	retlw	H'A4'	; Return segment code for 2
;	retlw	H'B0'	; Return segment code for 3
;	retlw	H'99'	; Return segment code for 4
;	retlw	H'92'	; Return segment code for 5
;	retlw	H'82'	; Return segment code for 6
;	retlw	H'F8'	; Return segment code for 7
;	retlw	H'80'	; Return segment code for 8
;	retlw	H'98'	; Return segment code for 9

	retlw	b'00111111'	; Return segment code for 0
	retlw	b'00000110'	; Return segment code for 1
	retlw	b'01011011'	; Return segment code for 2
	retlw	b'01001111'	; Return segment code for 3
	retlw	b'01100110'	; Return segment code for 4
	retlw	b'01101101'	; Return segment code for 5
	retlw	b'01111101'	; Return segment code for 6
	retlw	b'00000111'	; Return segment code for 7
	retlw	b'01111111'	; Return segment code for 8
	retlw	b'01100111'	; Return segment code for 9



SplitNum
	MOVFW	sec			;Ladda W med sekunder för att få entalen
	CALL	GETONES
	MOVWF	sec_one		;Här lagras entalen
	MOVFW	sec			;Ladda W med sekunder för att få tiotalen
	CALL	GETTENS
	MOVWF	sec_ten		;Här lagras tiotalen

	MOVFW	min			;Ladda W med sekunder för att få entalen
	CALL	GETONES
	MOVWF	min_one		;Här lagras entalen
	MOVFW	min			;Ladda W med sekunder för att få tiotalen
	CALL	GETTENS
	MOVWF	min_ten		;Här lagras tiotalen

	MOVFW	hour			;Ladda W med sekunder för att få entalen
	CALL	GETONES
	MOVWF	hour_one		;Här lagras entalen
	MOVFW	hour			;Ladda W med sekunder för att få tiotalen
	CALL	GETTENS
	MOVWF	hour_ten		;Här lagras tiotalen

	RETURN




;This routine will return the number of decimal 
;hundreds from an 8-bit binary
;Input: w
;Output: w
;RAM:2
;Cycles: 12-24

GETHNDS	
		movwf	t1
		clrf    w2
gethnds_loop
		movlw	.100
		incf	w2,f
		subwf	t1,f
		btfsc	STATUS,C
		goto 	gethnds_loop
		decf	w2,w
		return		
;---
;This routine will return the number of decimal 
;tens from an 8-bit binary
;Loop based, so it might take some time...
;It needs getones too
GETTENS		
		movwf	t1
		clrf    w2
gettens_loop
		movlw	.10
		incf	w2,f
		subwf	t1,f
		btfsc	STATUS,C
		goto 	gettens_loop
		decf	w2,w
		return

;---
;This routine will return the number of decimal 
;ones from an 8-bit binary	
GETONES
		movwf	w2
		movlw	.10
deltens_loop
		subwf	w2,f
		btfsc	STATUS,C
		goto 	deltens_loop
		addwf	w2,w	
		return





; initialize eeprom locations

EE      CODE    0x2100
        DE  0x00, 0x01, 0x02, 0x03

        END                       ; directive 'end of program'
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Första Multiplexing försöket. PIC - ASM

Inlägg av sodjan »

> Har jag löst det du menar med överhörning...

Av din beskrivning låter det så ja. Det är ju ingen raketforskning direkt,
bara att släcka den aktuella siffran/tecknet *innan* man byter display.

Beroende på multiplexhastighet så syns det mer eller mindre. Det uppträder
som att siffrorna bredvid "glöder" lite svagt på andra displayer. Beroeonde
på ljusförhållanden så kanske det inte syns alls. Ju snabbare man kör, ju
mer kan det synas.
Skriv svar