;******************************************************************** ; ; Titolo : Test per 2xHC595 con display multiplexato ; a 4 digit. ; Processore : PIC16F1509 ; Hardware : ; Data : 28-01-2009 ; Modificato il : ; Versione : V0.1 ; Ref. hardware : ; Autore : afg ; ;******************************************************************** ; Due HC595, caricati attraverso SPI, multiplexano 4 display a ; 7 segmenti, anodo comune ; Assegnazioni: ; display # 1 2 3 4 ; dgtcntr # 0 1 2 3 ; #### #### #### #### ; # # # # # # # # ; #### #### #### #### ; # # # # # # # # ; #### #### #### #### ; | | | | ; HC595 pin QD QC QB QA ; driver 0x08 0x04 0x02 0x01 ; refresh ultimo <------- primo da destra ; ; txbuf2 byte anodi byte segmenti txbuf1 ; ---------- ---------- ; | HC595 | | HC595 | ; data in -->| |------>| |----> data out ; ---------- ---------- ; |||||||| |||||||| ; anodes segments ; ; I due HC595 sono in cascata. ; Il secondo HC595 è quello collegato ai segmenti ; La corrispondenza è diretta (QA= segm a, QB= segm b, ecc). ; Il valore che indica i segmenti da accendere è contenuto in ; txbuf2. Il segmento è acceso per il bit corrispondente a 0. ; ; Il primo HC595 è collegato agli anodi segmenti, che sono accesi se a 0. ; Il display è acceso gli anodi sono a 1. ; Il valore che indica il display da accendere è contenuto in ; txbuf1. Un solo display è acceso per volta. ; ; Ogni cifra richiede la trasmissione di due bytes: ; - per primo quello che indica i segmenti accendere ; - per secondo quello che ondica il digit da accendere ; ; I dati dei segmenti da inviare al display sono contenuti in ; un buffer (databuf). ; Dal buffer dati sono copiati nel buffer display dopo essere stati ; convertiti in segmenti. Il contenuto del buffer display sarà ; quello usato per il refresh dei digit. ; ; I punti decimali sono scritti nell'ultimo byte del buffer dati e ; sono aggiunti alla maschera dei segmenti durante le fasi del ; ciclo di refresh. ; ; Il caricamento del buffer dati in quello di display avviene solo ; a conclusione di un ciclo di refresh completo del display. ; La segnalazione del dato pronto è disponibile su un flag. ; Il ciclo è composto dall'emissione del contenuto del buffer display ; in sequenza, cadenzata dall'interrupt di Timer2. ; Viene usato un intrevallo di 2ms (2x8=16ms totale del ciclo). ; ;-------------------------------------------------------------------- ; ; Impiego pin : ; ---------------- ; 16F1507/8/9 @ 20 pin ; ; |¯¯\/¯¯| ; Vdd -|1 20|- Vss ; RA5 -|2 19|- RA0 ; RA4 -|3 18|- RA1 ; RA3/MCLR -|4 17|- RA2 ; RC5 -|5 16|- RC0 ; RC4 -|6 15|- RC1 ; RC3 -|7 14|- RC2 ; RC6 -|8 13|- RB4 ; RC7 -|9 12|- RB5 ; RB7 -|10 11|- RB6 ; |______| ; ; Vdd 1: + ; RA5/OSC1/T1CKI 2: ; RA4/OSC2/AN3/T1G 3: ; RA3/!MCLR/VPP 4: MCLR ; RC5/PWM1 5: ; RC4/C2OUT 6: ; RC3/AN7/C1IN3-/PWM2 7: ; RC6/AN8 8: ; RC7/AN9 9: Out SDO ; RB7/TX 10: ; RB6/SCL 11: Out SCK ; RB5/AN11/RX 12: Out LCK ; RB4/AN10/SDA 13: In SDI ; RC2/AN6/C1IN2- 14: ; RC1/AN5/C2IN-/PWM4 15: ; RC0/AN4/C2IN+ 16: ; RA2/C1OUT/AN2/T0CKI/PWM3 11: ; RA1/C1IN-/AN1/ICSPC 12: ICSPCLK ; RA0/C1IN+/AN0/ICSPD 13: ICSPDAT ; Vss 14: - ; ; 16F1507 non ha USART e MSSP ; Altre funzioni non elencate: IOC,INT,DAC,Vref,CLC,NCO,CWG,PWM ; ;#################################################################### ; selezione del processore #include radix dec errorlevel -302 ; escludi segnalazioni relative ai banchi ;#################################################################### ; CONFIGURAZIONE ; Oscillatore interno, no Clkout, no WDT, no CP, no MCLR __config _CONFIG1,(_FOSC_INTOSC & _CLKOUTEN_OFF & _WDTE_OFF & _MCLRE_ON & _PWRTE_OFF & _BOREN_ON & _CP_OFF) ;& H'3FFF' __config _CONFIG2,(_WRT_OFF & _STVREN_OFF & _BORV_LO & _LPBOR_ON & _LVP_OFF) ;& H'3FFF' ;******************************************************************** ;==================================================================== ; DEFINIZIONE DI IMPIEGO DEI PORT ; ;PORTC map ;| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ;|----|----|----|----|----|----|----|----| ;| SDO| | | | | | | | ; #define SDO LATC,7 ; SPI out #define SDOTRIS TRISC,7 ;PORTB map ;| 7 | 6 | 5 | 4 | ;|-----|-----|-----|-----| ;| | SCK | LCK | SDI | ; #define SCK LATB,6 ; SPI clock #define LCK LATB,5 ; HC595 Latch clock #define SDI PORTB,4 ; SPI in - non usato #define SCKTRIS TRISB,6 #define LCKTRIS TRISB,5 #define SDITRIS TRISB,4 ;PORTA map ;| 5 | 4 | 3 | 2 | 1 | 0 | ;|-----|-----|-----|-----|-----|-----| ;| | | MCLR| |ICCLK|ICDAT| ; ; ;#################################################################### ;#################################################################### ; MEMORIA RAM ; general purpose RAM GRAM UDATA dgtcntr res 1 ; digit counter txbuf1 res 1 ; 2 bytes buffer txbuf2 res 1 dispbuf res 4 ; display buffer dpstatc res 1 ; copia operativa di dpstat databuf res 4 ; buffer dati dpstat res 1 ; status of decimal points ;flags ;| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ;|-----|-----|-----|-----|-----|------|-----|-----| ;| | | | | dp | dp | dp | dp | ; dp=1 accende il dp del relativo digit lpcntr res 1 ; loop counter flags res 1 ; status del processo ;flags ;| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ;|-----|-----|-----|-----|-----|------|-----|-----| ;| | | | | | | |datok| ; datok=1 se il buffer dati è stato aggiornato ;#################################################################### ; COSTANTI ; CLOCK FOSC equ 16000000 ; crystal frequency [Hz] ; FCYC equ FOSC/4 ; processor clock [Hz] TCYC equ 1000000000/FCYC ; cycle time [ns] ;#################################################################### ; INCLUDE ;******************************************************************** ; MAIN RESVEC CODE 0x00 Start: nop pagesel Main goto Main ;-------------------------------------------------------------------- ; IRQ vector IRQVEC CODE 0x4 ; irq di Timer2 ? banksel PIR1 ; test flag di Timer2 btfss PIR1,TMR2IF retfie ; se =0 esci Int_serv: ; se =1 gestisci interruzione bcf PIR1,TMR2IF ; cancella flag banksel dgtcntr ; dgtcntr = 3: aggiorna digit 4 - first ; dgtcntr = 2: aggiorna digit 3 ; dgtcntr = 1: aggiorna digit 2 ; dgtcntr = 0: aggiorna digit 1 - last decf dgtcntr,f ; digitcounter-1 movf dgtcntr,w ; come indice per il digit brw bra Int_0 ; digit 1 bra Int_1 ; digit 2 bra Int_2 ; digit 3 bra Int_3 ; digit 4 ; il digit 0 è rinfrescato per ultimo Int_0: ; digit più a sinistra banksel dgtcntr ; last digit movlw .4 ; reload digit counter movwf dgtcntr movlw 0x08 ; select common of the digit movwf txbuf2 movf dispbuf,w ; load data btfsc dpstatc,0 ; add dp? bcf WREG,7 ; y - add dp movwf txbuf1 ; and copy to tx buffer bra Int_end ; digit on Int_1: banksel txbuf1 movlw 0x04 ; select common of the digit movwf txbuf2 movf dispbuf+1,w ; load data btfsc dpstatc,1 ; add dp? bcf WREG,7 ; y - add dp movwf txbuf1 bra Int_end ; digit on Int_2: banksel txbuf1 movlw 0x02 ; select common of the digit movwf txbuf2 movf dispbuf+2,w ; load data btfsc dpstatc,2 ; add dp? bcf WREG,7 ; y - add dp movwf txbuf1 bra Int_end ; digit on ; first digit scanned Int_3: ; right digit ; refresh cycle start point - new data to display? banksel flags ; new data ready? btfss flags,1 ; flag set? bra nonew ; n - don't copy buffer bcf flags,1 ; y - clear flag pagesel CopyBuf ; copy buffer call CopyBuf nonew: banksel txbuf1 movlw 0x01 ; select common of the digit movwf txbuf2 movf dispbuf+3,w ; load data btfsc dpstatc,3 ; add dp? bcf WREG,7 ; y - add dp movwf txbuf1 ; accendi cifra inviando di seguito txbuf1 e txbuf2 Int_end: pagesel HC595Wr2Byte call HC595Wr2Byte retfie CopyBuf: ; Convert data buffer in segments and copy to display buffer banksel lpcntr movlw 4 ; per 8 step movwf lpcntr movlw LOW (databuf) ; set indirect pointer movwf FSR1L ; to data buffer movlw HIGH (databuf) movwf FSR1H movlw LOW (dispbuf) ; set indirect pointer movwf FSR0L ; to display buffer movlw HIGH (dispbuf) movwf FSR0H cblp moviw INDF1++ pagesel segtblF_16e ; convert to segments call segtblF_16e xorlw 0xFF ; invert mask movwi INDF0++ decfsz lpcntr,f bra cblp ; copy dp status banksel databuf movf dpstat,w ; dp status movwf dpstatc return ;-------------------------------------------------------------------- ; Delay routines #include C:\PIC\LIBRARY\DelayUS\DelayUS24_16e.asm ;-------------------------------------------------------------------- ;-------------------------------------------------------------------- ; reset ; MAIN CODE Main: ; bank0 clrf PORTA clrf PORTB clrf PORTC banksel LATA ; bank2 clrf LATA ; clear latch del port clrf LATB clrf LATC banksel ANSELA ; bank3 clrf ANSELA ; no input analogici clrf ANSELB clrf ANSELC banksel WPUA ; bank4 movlw 0 ; no WPUA movwf WPUA movlw 0 ; no WPUB movwf WPUB banksel TRISC ; PORTC out clrf TRISC ; clock 16MHz movlw b'01111000' banksel OSCCON movwf OSCCON banksel OPTION_REG ; bank1 ; disable T0CKI, prescaler 1:16 to Timer0 ; b'00000000' ; 0------- !WPUEN abilitato ; -1------ INTEDG rising ; --0----- clock interno ; ---1---- falling ; ----0--- prescaler al Timer0 ; -----011 1:16 movlw b'01010011' movwf OPTION_REG ; initialize I/O for drive HC595 pagesel HC595IOInit call HC595IOInit ; configure Timer2 to generate periodic interrupt every 2ms ; postscaler 1:8, prescaler 1:4 banksel T2CON ; T2CON b'00000000' ; ni b7 0------- ; T2OUTPS b6:3 -0111--- 0111 Postscaler 1:8 ; TMR2ON b2 -----1-- 1 = timer on ; 0 = timer off ; T2CKPS b1:0 ------01 00 = Prescaler 1:1 ; 01 = Prescaler 1:4 ; 10 = Prescaler 1:16 ; 11 = Prescaler 1:64 movlw b'00111101' movwf T2CON movlw D'249' movwf PR2 ; configure MSSP for Master SPI banksel SSPSTAT ; SSPSTAT 00000000 SPI mode ; SMP b7 1------- 1 = In data sampled at end of data out time ; 0 = In data sampled at middle of data out time ; allways 0 for slave mode ; CKE b6 -1------ 1 = Tx on transition from active to Idle clock ; 0 = Tx on transition from Idle to active clock ; D/A b5 --0----- 0 - I2C only ; P b4 ---0---- 0 - I2C only ; S b3 ----0--- 0 - I2C only ; R/W b2 -----0-- 0 - I2C only ; UA b1 ------0- 0 - I2C only ; BF b0 -------0 1 = Receive complete, SSPxBUF is full ; 0 = Receive not complete, SSPxBUF is empty movlw b'11000000' movwf SSPSTAT ; data transmitted on rising edge ; SSPCON1 00000000 SPI mode ; WCOL b7 0------- 0 - I2C only ; SSPOV b6 -0------ 1 = New byte is received ; 0 = No overflow ; SSPEN b5 --1----- 1 = Enables serial port ; 0 = Disables serial port ; CKP b4 ---0---- 1 = Idle state for clock is a high level ; 0 = Idle state for clock is a low level ; SSMP b3:0 ----0001 0000 = SPI Master, clk = FOSC/4 ; 0001 = SPI Master, clk = FOSC/16 ; 0010 = SPI Master, clk = FOSC/64 ; 0011 = SPI Master, clk = TMR2 output/2 ; 0100 = SPI Slave , clk = SCKx pin, SS enabled ; 0101 = SPI Slave , clk = SCKx pin, SS disabled movlw b'00100001' movwf SSPCON1 ; data at FOSC/16, enable SPI ; carica buffer ; Preload 6 digit with chars from 1 to 4 banksel databuf movlw 1 ; 1 movwf databuf movlw 2 ; 2 movwf databuf+1 movlw 3 ; 3 movwf databuf+2 movlw 4 ; 4 movwf databuf+3 movwf databuf+7 movlw b'11110000' ; tutti i dp movwf dpstat ; set flag dato pronto banksel flags bsf flags,1 ; preload digit counter banksel dgtcntr movlw 4 movwf dgtcntr ; enable interrupt for Timer2 banksel PIR1 bcf PIR1,TMR2IF ; clear flag banksel TMR2 clrf TMR2 ; clear counter banksel PIE1 bsf PIE1,TMR2IE ; enable source bsf INTCON,PEIE ; enable peripheral bsf INTCON,GIE ; enable general loopk bra loopk ; closed loop ;******************************************************************** ; Tabella retlw di conversione dati-segmenti per display 7segmenti ; CodeB: cifre 0-9 e -, E,H,L,P,blank ; Maschere conversione 7 segmenti per display 7segmenti ; collegamento diretto, common catode - 8 bit in 1 byte ; Sequenza: dpgfedcba ; dpgfedcba _sa = 1 ; 00000001 _sb = 2 ; 00000010 _sc = 4 ; 01000000 _sd = 8 ; 10000000 _se = 0x10 ; 00010000 _sf = 0x20 ; 00100000 _sg = 0x40 ; 01000000 _dp = 0x80 ; 10000000 segtblCodeB_16e: brw retlw (_sa|_sb|_sc|_sd|_se|_sf) ; 0 retlw (_sb|_sc) ; 1 retlw (_sa|_sb|_sd|_se|_sg) ; 2 retlw (_sa|_sb|_sc|_sd|_sg) ; 3 retlw (_sb|_sc|_sf|_sg) ; 4 retlw (_sa|_sc|_sd|_sf|_sg) ; 5 retlw (_sa|_sb|_sc|_sd|_se|_sf) ; 6 retlw (_sa|_sb|_sc) ; 7 retlw (_sa|_sb|_sc|_sd|_se|_sf|_sg) ; 8 retlw (_sa|_sb|_sc|_sd|_sf|_sg) ; 9 retlw (_sg) ; - retlw (_sa|_sd|_se|_sf|_sg) ; E retlw (_sb|_sc|_se|_sf|_sg) ; H retlw (_sd|_se|_sf) ; L retlw (_sa|_sb|_se|_sf|_sg) ; P retlw 0 ; blank ;######################################################################## ;# DRIVERS # ;######################################################################## ;************************************************************************ ;** ** ;** Title : Driver for HC595 ** ;** Hardware : ** ;** Processor : PIC Enhanced Midrange ** ;** Date : 8-01-2009 ** ;** Version : V.01 ** ;** Autore : afg ** ;** ** ;************************************************************************ ;************************************************************************ ; Functions : ; ; HC595IOInit Initialize I/O for HC595 ; HC595WrByte Write a byte to HC595. Byte on WREG ; HC595Wr2Byte Write 2 bytes to HC595. Byte on txbuf2:1 ; ;************************************************************************ ; Note: ;************************************************************************ ;************************************************************************ ; HC595IOInit - sub - initialize I/O for HC595 with MSSP ; clk = 1 , dio = 1, lck = 0 ;************************************************************************ HC595IOInit: GLOBAL HC595IOInit banksel LATB bcf SCK ; preset sck=0 bcf SDO ; preset sdo=0 bcf LCK ; preset latch=0 banksel TRISC bcf SCKTRIS ; RB6 SCK pin for output bcf SDOTRIS ; RC7 SDO pin for output bcf LCKTRIS ; RC6 LCK pin for output bsf SDITRIS ; RB4 SDI pin for input return ;************************************************************************ ; HC595WrByte - sub - Write a byte to HC595 ; Byte come on WREG ; Locking routine - wait for BF ;************************************************************************ HC595WrByte: GLOBAL HC595WrByte banksel SSPBUF movwf SSPBUF sswait btfss SSPSTAT,BF ; wait for end of data transmission bra sswait movf SSPBUF,W ; clear the flag banksel LATB bsf LCK ; pulse latch clock bcf LCK ; return ;************************************************************************ ; HC595Wr2Byte - sub - Write a byte to HC595 ; Bytes on txbuf2:1 ; Locking routine - wait for BF ;************************************************************************ HC595Wr2Byte: GLOBAL HC595Wr2Byte banksel txbuf1 ; send txbuf1 to second HC595 movf txbuf1,w banksel SSPBUF movwf SSPBUF sswb1 btfss SSPSTAT,BF ; wait for end of data transmission bra sswb1 movf SSPBUF,W ; clear the flag banksel txbuf2 movf txbuf2,w ; send txbuf2 to first HC595 banksel SSPBUF movwf SSPBUF sswb2 btfss SSPSTAT,BF ; wait for end of data transmission bra sswb2 movf SSPBUF,W ; clear the flag banksel LATB bsf LCK ; pulse latch clock bcf LCK ; return ;************************************************************************ END