PIC16F1827 Code Help

Status
Not open for further replies.

Suraj143

Active Member
First time I'm using this chip.I need to verify the initialisation part.The wiered thing that I noticed is.. before I write to a register everytime I have to call BANKSEL directive.Then what's the point of BSR core register?Is my code ok?

Code:
            List        P=16F1827
            #include    <P16F1827.INC>
            errorlevel    -302
            __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
            __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_19 & _LVP_OFF

            org        0000h
            goto        Initialise_Ports

            org        0004h
            retfie
Initialise_Ports   
            BANKSEL        PORTA
            clrf        PORTA
            BANKSEL        LATA
            clrf        LATA
            BANKSEL        ANSELA
            clrf        ANSELA
            BANKSEL        TRISA
            clrf        TRISA
            ;           
            BANKSEL        PORTB
            clrf        PORTB
            BANKSEL        LATB
            clrf        LATB
            BANKSEL        ANSELB
            clrf        ANSELB
            BANKSEL        TRISB
            clrf        TRISB
               
Setup_TMR2       
            BANKSEL        T2CON
            movlw        b'00011101'        ; pre scaler = 1:4,Post Scaller = 1:4
            movwf        T2CON           
            movlw        .249
            movwf        PR2
            BANKSEL        PIE1
            bsf        PIE1,TMR2IE           
            movlw        b'11000000'        ; turn on GIE & PEIE
            movwf        INTCON
            BANKSEL        PORTA
            bcf        PIR1,TMR2IF   
            goto        Clear_Registers
 
Go to Table 3-3, page 24 and following of the datasheet. You will see which banks the various registers are in. If you organize your initialization, you can minimize the number of banksel's you must use. You can also use the instruction, "movlb (insert bank #)" to do the same thing.

Overall, it is not a huge waste of time to do it the way you did. What is important is that you know why, because if you don't, it will bite you later.

Your code looks OK as far as it goes. You enable interrupts, but don't have an Interrupt Service Routine (ISR).

I am checking into the default oscillator settings, as I always set that up too. Edit: Looks like default is 500 kHz, so be sure to consider that in your timings.
 
Last edited:
Good info. The default frequency is 500Khz.I have to change that to 4Mhz in the OSCCON register. But after setting the OSCCON register do I also need to check the OSCSTAT register? Medium OSC ready bit?
 
As already pointed out, you have no ISR (just a retfie) but you do enable Timer2 interrupt. When this fires your code will lock up as it will continually execute the ISR.

Mike.
 
Hi here is my ISR routine. I'm multiplexing 4 seven segments.Segments are RB0 to RB7 & common pins are RA0,1,2,3.I also share RB0,1,2,3 as input switches.
I need to compact my code. Any improvements...!! Really tired of shifting banks...:-(

Code:
            org        0004h
;====================================================================        
;TMR2 interrupt rate = 4mS
;====================================================================
            btfss        PIR1,TMR2IF
            goto        ISR_Exit
            bcf        PIR1,TMR2IF
            ;
            decfsz        Key_Counter,F
            goto        Multiplex_Display
            movlw        .4
            movwf        Key_Counter
;-------------------------------------------------------------------
;KEY read rate = 4mS X 4 = 16mS
Read_Keys    
            BANKSEL        LATB
            clrf        LATB            ; clear segment data
            clrf        LATA            ; clear common cathodes
            BANKSEL        PORTB
            clrf        PORTB
            BANKSEL        TRISB
            movlw        b'00001111'        ; make RB0,1,2,3 = inputs for a short time
            movwf        TRISB
            BANKSEL        WPUB
            movlw        b'00001111'
            movwf        WPUB
            BANKSEL        PORTB
            btfss        PORTB,0
            bsf        SW_Flag,SW_1
            btfss        PORTB,1
            bsf        SW_Flag,SW_2
            btfss        PORTB,2
            bsf        SW_Flag,SW_3
            btfss        PORTB,3
            bsf        SW_Flag,SW_4
;==================================================
;Display Multiplex @ 4mS rate
;Common Cathodes [RA0=D1, RA1=D2, RA2=D3,RA3=D4]
;==================================================
Multiplex_Display
            BANKSEL        LATB
            clrf        LATB            ; clear segment data
            clrf        LATA            ; clear common cathodes
            movlb        00h            ; back to Bank 0
            btfss        Display_Select,0
            goto        Display_1
            btfss        Display_Select,1
            goto        Display_2
            btfss        Display_Select,2
            goto        Display_3
            goto        Display_4
            ;        
Display_1        movf        Digit_1,W        ; Show D1 segment
            call        Segment_Table        ; //
            movlb        01h            ; Bank 1
            movwf        LATB                    
            bsf        LATA,0            ; turn on D1
            movlb        00h            ; back to Bank 0                                                
            bsf        Display_Select,0
            goto        ISR_Exit
                
Display_2        movf        Digit_2,W        ; Show D2 segment
            call        Segment_Table        ; //    
            movlb        01h            ; Bank 1
            movwf        LATB                    
            bsf        LATA,1            ; turn on D1
            movlb        00h            ; back to Bank 0                    
            bsf        Display_Select,1
            goto        ISR_Exit
        
Display_3        movf        Digit_3,W        ; Show D3 segment
            call        Segment_Table        ; //    
            movlb        01h            ; Bank 1
            movwf        LATB                    
            bsf        LATA,2            ; turn on D1
            movlb        00h            ; back to Bank 0
            bsf        Display_Select,2
            goto        ISR_Exit        

Display_4        movf        Digit_4,W        ; Show D4 segment
            call        Segment_Table        ; //    
            movlb        01h            ; Bank 1
            movwf        LATB                    
            bsf        LATA,3            ; turn on D1
            movlb        00h            ; back to Bank 0
            clrf        Display_Select
            ;        
Backup_Digits        movf        S_Digit_1,W        ; 1
            movwf        Digit_1
            movf        S_Digit_2,W        ; 2
            movwf        Digit_2
            movf        S_Digit_3,W        ; 3
            movwf        Digit_3
            movf        S_Digit_4,W        ; 4
            movwf        Digit_4
ISR_Exit    
            retfie
 
I notice in your ISR you aren't saving the context (W, Status & BSR) or restoring them before the retfie. Unless your main code is in a very tight loop waiting for the interrupt to complete, it will most likely crash.

Some suggestions to shorten your code,
No need to clr PORTB as clearing LATB will do this.
Leave the WPUs on all the time.
Instead of testing bits of portb, read it all, and with 0x0f and store in SW_Flag. Rearrange the flags as necessary or use a new variable.
Use indirect addressing to do the different digits.

Here a code snippet to get you started,
Code:
        cblock
Digit_1:4            ;4 bytes for the numbers
Mask                ;1 byte for the mask
        endb

initDisplay
            movlw    Digit_1+3    ;point to last so first is shown
            movwf    FSR0L
            clrf     FSR0H
            movlw    0b00001000    ;mask for digit 4
            movwf    Mask
            ret

Multiplex_Display
            BANKSEL      LATB
            clrf         LATB            ; clear segment data
            clrf         LATA            ; clear common cathodes
            movlb        00h                ; back to Bank 0
            movlw        Digit_1+4        ;has it done all 4
            xorwf        FSR0L,w            ;zero if yes
            movlw        Digit_1            ;so reset
            btfss        STATUS,Z        ;if zero
            movwf        FSR0L            ;to digit 1
            moviw        FSR0++            ;get the value and inc FSR0
            call         Segment_Table
            movlb        01h                ;Bank 1
            movwf        LATB             
            movlb        0
            rlf          Mask,f            ;rotate the cathode mask
            btfsc        Mask,4            ;does it need to wrap
            swapf        Mask,f            ;yes so swap niddles
            movf         Mask,w            ;get the mask
            movlb        01h                ;Bank 1
            movwf        LATA              ;turn on segment
            goto         ISR_Exit
Note the digit locations have to be contiguous.

Mike.
 
Hi Mike,

I believe the 16F1827 is enhanced midrange with automatic context saving.

John
 
Hi Mike,

I believe the 16F1827 is enhanced midrange with automatic context saving.

John
I knew it was enhanced but didn't know about the auto save bit.
Guess that's what happens when you do everything in C these days.

Edit, just read up on the auto save and FSRs are included so the above code won't work.
Not got time now to edit it but will be able to tomorrow.

Mike.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…