;******************************************************************
;* *
;* Filename: 16F628A Mux Test.asm *
;* Author: Mike McLaren, K8LH *
;* (C)2010: Micro Application Consultants *
;* Date: 25-May-10 *
;* *
;* test the 4-digit interrupt display driver architecture *
;* *
;* MPLab: 8.50 (tabs = 8) *
;* MPAsm: 5.35 *
;* *
;******************************************************************
include "P16F628A.inc"
errorlevel -302 ; suppress bank warnings
list st=off ; suppress symbol table
radix dec ; default radix = decimal
__CONFIG _LVP_OFF & _WDT_OFF & _INTOSC_OSC_NOCLKOUT & _MCLRE_OFF
;--< variables >---------------------------------------------------
column equ 0x20 ; column number, 0..3
colsel equ 0x21 ; column select bit
huns equ 0x22 ; huns, 0..1
tens equ 0x23 ; tens, 0..9
ones equ 0x24 ; ones, 0..9
tenths equ 0x25 ; tenths, 0..9
w_isr equ 0x70 ;
s_isr equ 0x71 ;
p_isr equ 0x72 ;
f_isr equ 0x73 ;
;******************************************************************
; reset vector *
;******************************************************************
org 0x000
vReset
clrf STATUS ; force bank 0, IRP = 0 |B0
goto Init ; |B0
;******************************************************************
; interrupt vector, 1 msec Timer 2 interrupts *
;******************************************************************
;
; unsigned char column = 0; // column (digit) number, 0..3
; unsigned char colsel = 8; // column select bit '00001000'
;
; unsigned char disp[] = { 1,2,3,4 }; // huns,tens,ones,tenths
;
; const rom char seg[] = { 0b11101110, // "0" B|A|F|-|E|D|C|-
; 0b10000010, // "1" B|-|-|-|-|-|C|-
; 0b11011100, // "2" B|A|-|G|E|D|-|-
; 0b11010110, // "3" B|A|-|G|-|D|C|-
; 0b10110010, // "4" B|-|F|G|-|-|C|-
; 0b01110110, // "5" -|A|F|G|-|D|C|-
; 0b01111110, // "6" -|A|F|G|E|D|C|-
; 0b11000010, // "7" B|A|-|-|-|-|C|-
; 0b11111110, // "8" B|A|F|G|E|D|C|-
; 0b11110110, // "9" B|A|F|G|-|D|C|-
; 0b00000000, // " " -|-|-|-|-|-|-|-
; 0b00010000 }; // "-" -|-|-|G|-|-|-|-
;
; void interrupt()
; { pir1.TMR2IF = 0; // clear timer 2 interrupt flag
; portb = 0; // blank the display
; porta &= 0xF0 // turn off column select bits
; porta |= colsel; // select new column (digit)
; portb = seg[disp[column]]; // display new column (digit)
; column = (column + 1) & 3; // bump column, 0..3 inclusive
; colsel >>= 1; // shift column select bit
; if(colsel == 0) // if last column
; colsel = 8; // reset to '00001000'
; } //
;
org 0x004
vInt
movwf w_isr ; save WREG |B?
swapf STATUS,W ; don't change STATUS bits |B?
movwf s_isr ; save STATUS reg |B?
clrf STATUS ; bank 0 |B0
movf PCLATH,W ; |B0
movwf p_isr ; save PCLATH |B0
clrf PCLATH ; force page 0 |B0
movf FSR,W ; |B0
movwf f_isr ; save FSR |B0
bcf PIR1,TMR2IF ; clear TMR2 interrupt flag |B0
;
; refresh display
;
clrf PORTB ; blank the display |B0
movf PORTA,W ; |B0
andlw b'11110000' ; clear column select bits |B0
iorwf colsel,W ; `1000,`0100, `0010, or `0001 |B0
movwf PORTA ; select new column |B0
movf column,W ; column number, 0..3 |B0
addlw huns ; add to 'huns' address |B0
movwf FSR ; FSR = &temp[column] |B0
movf INDF,W ; WREG = 0..9 |B0
call segtable ; get segment data |B0
btfsc colsel,1 ; 2nd column? no, skip, else |B0
iorlw 1 ; set "decimal point" bit |B0
movwf PORTB ; display new column |B0
;
; prepare for next column interrupt
;
incf column,F ; bump column number |B0
bcf column,2 ; 0..3, inclusive |B0
clrc ; |B0
rrf colsel,F ; advance column select bit |B0
skpnc ; last column? no, skip, else |B0
bsf colsel,3 ; reset to column 1 (00001000) |B0
;
; restore context
;
movf f_isr,W ; |B0
movwf FSR ; restore FSR |B0
movf p_isr,W ; |B0
movwf PCLATH ; restore PCLATH |B0
swapf s_isr,W ; |B0
movwf STATUS ; restore STATUS |B?
swapf w_isr,f ; don't change STATUS bits |B?
swapf w_isr,W ; restore WREG |B?
retfie ; |B?
;
; segment data table (caveat, non-boundary tolerant)
;
segtable ; map B|A|F|G|E|D|C|P
addwf PCL,F ; |B0
retlw b'11101110' ; "0" B|A|F|-|E|D|C|- |B0
retlw b'10000010' ; "1" B|-|-|-|-|-|C|- |B0
retlw b'11011100' ; "2" B|A|-|G|E|D|-|- |B0
retlw b'11010110' ; "3" B|A|-|G|-|D|C|- |B0
retlw b'10110010' ; "4" B|-|F|G|-|-|C|- |B0
retlw b'01110110' ; "5" -|A|F|G|-|D|C|- |B0
retlw b'01111110' ; "6" -|A|F|G|E|D|C|- |B0
retlw b'11000010' ; "7" B|A|-|-|-|-|C|- |B0
retlw b'11111110' ; "8" B|A|F|G|E|D|C|- |B0
retlw b'11110110' ; "9" B|A|F|G|-|D|C|- |B0
retlw b'00000000' ; " " -|-|-|-|-|-|-|- |B0
retlw b'00010000' ; "-" -|-|-|G|-|-|-|- |B0
;******************************************************************
; main.init *
;******************************************************************
Init
movlw 7 ; |B0
movwf CMCON ; |B0
bsf STATUS,RP0 ; bank 1 |B1
movlw b'11110000' ; |B1
movwf TRISA ; A7-A4 inputs, A3-A0 outputs |B1
clrf TRISB ; portb all outputs |B1
bcf STATUS,RP0 ; bank 0 |B0
clrf PORTB ; clear portb output latches |B0
;
; init program variables
;
clrf column ; column = 0 (1st column) |B0
movlw b'00001000' ; column select bit mask |B0
movwf colsel ; |B0
movlw 1 ; display "123.4"
movwf huns ;
movlw 2 ;
movwf tens ;
movlw 3 ;
movwf ones ;
movlw 4 ;
movwf tenths ;
;
; setup TMR2 for 1 msec periodic interrupts (4 MHz clock)
;
clrf TMR2 ; clear TMR2 register |B0
bsf STATUS,RP0 ; bank 1 |B1
clrf PIE1 ; mask all peripheral irqs |B1
bsf PIE1,TMR2IE ; except for TMR2 irq |B1
bcf STATUS,RP0 ; bank 0 |B0
clrf PIR1 ; clear peripheral irq flags |B0
movlw b'00000001' ; '00000001' |B0
; '0-------' unused
; '-0000---' postscale 1
; '-----0--' TMR2 off
; '------01' prescale 4
movwf T2CON ; for 4-usec ticks (4-MHz clk) |B0
bsf STATUS,RP0 ; bank 1 |B1
movlw d'250'-1 ; 250 X 4-usec ticks = 1-msec |B1
movwf PR2 ; for 1-msec interrupts |B1
bcf STATUS,RP0 ; bank 0 |B0
bsf INTCON,GIE ; enable global irqs |B0
bsf INTCON,PEIE ; enable peripheral irqs |B0
bsf T2CON,TMR2ON ; start TMR2 |B0
Loop
goto $ ; |B0
;******************************************************************
end
MOVLW 56/4
Yes, WREG = 14. Just a way to remind me that I want a 56 cycle (56 usec) delay using a 4 cycle loop.And Mike, this line of code;
Does it acctually move decimal 14 to W (56 divide by 4)?Code:MOVLW 56/4
That's an "absolute value" function.And what does your ABSFUNC lable imply. I know what the routine does but what does ABS stand for?
REARRANGE_RESULT ; This routine rearranges the 2 Temperature result bytes into useable data;
MOVF SCRATCHPAD_BYTE0, W ; MOVE Temperature LSbyte to W
MOVWF TEMPLO ; MOVE W to TEMPLO GPR
MOVF SCRATCHPAD_BYTE1, W ; MOVE Temperature MSbyte to W
MOVWF TEMPHI ; MOVE W to TEMPHI GPR
TEST_IF_NEGATIVE
BTFSS TEMPHI, 7 ; If 1, Temperature is Negative
GOTO $+D'7' ; NOT Negative, skip over next 6 instructions (Don't Invert & + 1)
; Invert & + 1 ; EXAMPLE Negative Temperature TEMPHI = 1111 1110 TEMPLO = 0110 1110 = -25.1250 (see datasheet)
COMF TEMPLO, F ; Invert TEMPLO (when in Negative Temperature, the DS18B20 inverts the output so this inverts the register back so its positive)
COMF TEMPHI, F ; Invert TEMPHI
BCF STATUS, Z ; Clear Zero bit of STATUS register
INCF TEMPLO, F ; Increment TEMPLO to add .0625 (after inverting the register, the positive equivelent is .0625 more so this rectifies the negative value being .0625 short)
BTFSC STATUS, Z ; Test Z bit of STATUS register to see if last instruction = 0000 0000
INCF TEMPHI, F ; IS 0 (if TEMPLO overflowed to 0, increment TEMPHI once, if not, skip)
; EXAMPLE Negative Temperature AFTER Invert & + 1 TEMPHI = 0000 0001 TEMPLO = 1001 0010 = +25.1250
; EXAMPLE, TEMPHI = 0000 0001 TEMPLO = 1001 0010
MOVLW B'11110000' ; W = 1111 0000
ANDWF TEMPLO, W ; F = 1001 0010 W = 1001 0000
IORWF TEMPHI, F ; F = 0000 0001 F = 1001 0001
SWAPF TEMPHI, F ; F = 1001 0001 F = 0001 1001 = New TEMPHI
MOVLW B'00001111' ; W = 0000 1111
ANDWF TEMPLO, F ; F = 1001 0010 F = 0000 0010 = New TEMPLO
BIN_TO_DEC ; This routine converts an 8-bit number to Decimal and stores the answer in 3 GPR's; HUNS, TENS & ONES
; HUNS holds amount of hundreds (i.e. 0000 0010 = 2x100), TENS holds amount of tens (i.e. 0000 0010 = 2x10) & ONES holds amount of ones (i.e. 0000 0101 = 5x1)
INCF TEMPHI ; Preload TEMPHI + 1
CLRF HUNS ; HUNS = 0000 0000
MOVLW D'246' ; MOVE Decimal'246' to W
MOVWF TENS ; TENS GPR = 1111 0101
MOVWF ONES ; ONES GPR = 1111 0101
DECFSZ TEMPHI, F ; Decement TEMPHI register
GOTO $+2 ; NOT 0, skip next instruction
GOTO $+7 ; IS 0, TEMPHI = 0000 0000, skip next 6 instructions and calculate how many tens and hundreds
INCFSZ ONES, F ; Increment ONES register, skip if 0
GOTO $-D'4' ; NOT 0, GOTO here - 4 instructions
INCFSZ TENS, F ; IS 0, Increment TENS register skip if 0
GOTO $-D'7' ; GOTO here - 7 instructions & reset the ONES register to D'246'
INCF HUNS, F ; TENS overflowed, Increment HUNS
GOTO $-D'10' ; GOTO here - 10 instructions & reset the ONES and TENS registers to D'246'
SUBWF TENS, F ; W still holds D'246 so subract it from TENS register to determine how many 'TENS'
SUBWF ONES, F ; W still holds D'246 so subract it from ONES register to determine how many 'ONES'
; TENTHS = Fraction * 10 / 16 (Pommies routine to convert 4 bit number wher each bit represents 0.625 degrees, into rounded deciaml number)
MOVLW B'00001111' ;
ANDWF TEMPLO,F ;
MOVF TEMPLO,W ;
ADDWF TEMPLO,F ; *2, C=0
RLF TEMPLO,F ; *4, C=0
ADDWF TEMPLO,F ; *5, C=0
RLF TEMPLO,F ; *10
MOVLW B'00001000' ;
ADDWF TEMPLO,F ; Rounding
SWAPF TEMPLO,W ; Pseudo divide by 16
ANDLW B'00001111' ;
MOVWF TENTHS ;
; Leading zero suppression & minus (-) sign if Temperature Negative
MOVF HUNS, W ; Does HUNS equal 1 or 2? MOVF instruction affects Z bit of STATUS register
BTFSC STATUS, Z ; Test Z bit of STATUS register to see if last instruction = 0000 0000
MOVLW B'00001010' ; Jump Pointer for " " arrangement (blank)
BTFSC SCRATCHPAD_BYTE1, 7 ; Is Temperature Negative?
MOVLW B'00001011' ; YES, Jump Pointer for "-" arrangement
MOVWF HUNS ;
MOVF TENS, W ; Does TENS equal 0?
BTFSC STATUS, Z ; Test Z bit of STATUS register to see if last instruction = 0000 0000
MOVLW B'00001010' ; Jump Pointer for " " arrangement (blank)
MOVWF TENS ;
;
; Binary-to-Decimal, 8 bit input to ones, tens, huns output
;
; 14 words, 3 variables, 14 to 176 cycles
;
btod255
clrf Tens ;
clrf Huns ;
div10
movwf Ones ;
incf Tens,F ;
addlw -10 ;
bc div10 ;
decf Tens,W ;
div100
movwf Tens ;
incf Huns,F ;
addlw -10 ;
bc div100 ;
decf Huns,F ;
;
; 13 words, 3 variables, 10 to 166 cycles Mike, K8LH
;
btod255
movwf ones ; put WREG (total) into 'ones'
clrf huns ; clear 'huns'
movlw -10 ; wreg = -10
resetx movwf tens ; reset 'tens' to -10
div10x addwf ones,F ; ones = ones - 10, borrow?
skpc ; no, skip, else, fall thru'
goto b2done ; branch (we're done)
incfsz tens,F ; increment 'tens', overflow?
goto div10x ; no, branch, else, fall thru'
incf huns,F ; increment 'huns'
goto resetx ; reset 'tens'
b2done subwf tens,F ; fix -10 offset
subwf ones,F ; fix -10 offset
MOVLW 56/4
GOTO DELAY-1
MOVLW 10*4 ; 40
It was only the '508 that did not have addlw. The latest 12-bit devices have this instruction, such as: PIC12F629 etc"addlw" instruction which is not available on the 12-bit core devices;
It was only the '508 that did not have addlw. The latest 12-bit devices have this instruction, such as: PIC12F629 etc
Loop
call Ow.Reset ; |B0
movlw 0xCC ; |B0
call Ow.WrByte ; send 'skip rom' command |B0
movlw 0x44 ; |B0
call Ow.WrByte ; send 'convert' command |B0
[COLOR=Red]movlw 60/4 ; |B0[/COLOR]
[COLOR=Red]call Delay ; delay 60-usecs |B0[/COLOR]
RdSlot
call Ow.RdBit ; conversion complete? |B0
bnc RdSlot ; no, branch (wait), else |B0
RdTemp
call Ow.Reset ; |B0
movlw 0xCC ; |B0
...
Yeah I doubt it too.I just spotted a couple missing instructions in the 'untested' version I posted but I'm not sure that would keep the routines from working. Here are the missing lines (in red).
I would love to mike. It may help me realise what I'm doing wrong in my program.....I would be happy to post the 16F690 program and schematic if you or anyone wants to see it.
More later. Regards, Mike
bcf OPTION_REG,NOT_R[COLOR="darkorange"]A[/COLOR]BPU
Loop
call Ow.Reset ; |B0
movlw 0xCC ; |B0
call Ow.WrByte ; send 'skip rom' command |B0
movlw 0x44 ; |B0
call Ow.WrByte ; send 'convert' command |B0
[COLOR="red"] movlw 60/4 [/COLOR] ; |B0
[COLOR="red"] call Delay ; delay 60-usecs [/COLOR] |B0
RdSlot
call Ow.RdBit ; conversion complete? |B0
bnc RdSlot ; no, branch (wait), else |B0
RdTemp
call Ow.Reset ; |B0
movlw 0xCC ; |B0
call Ow.WrByte ; send 'skip rom' command |B0
movlw 0xBE ; |B0
call Ow.WrByte ; send 'read scratchpad' command |B0
GET_TEMP
CALL DS18B20_RESET ; Issue device reset command
MOVLW H'CC' ; ROM Command - Skip ROM
CALL DS18B20_WRITE_BYTE ; Write to DS18B20
MOVLW H'44' ; Function Command - Convert T
CALL DS18B20_WRITE_BYTE ; Write to DS18B20
CALL DS18B20_READ_BIT ; Master can issue read time slots after the Convert T command and the DS18B20 will respond by transmitting a 0 while the temperature conversion is in progress and a 1 when the conversion is done
BTFSS STATUS, C ; Is Carry flag Set, to indicate Temperature Conversion finished?
GOTO $-2 ; NO, GOTO previous instruction and continue testing
CALL DS18B20_RESET ; Issue device reset command
MOVLW H'CC' ; ROM Command - Skip ROM
CALL DS18B20_WRITE_BYTE ; Write to DS18B20
MOVLW H'BE' ; Function Command - Read Scratchpad
CALL DS18B20_WRITE_BYTE ; Write to DS18B20
CALL DS18B20_READ_BYTE ; Read from DS18B20
MOVWF SCRATCHPAD_BYTE0 ; Move read byte to corresponding GPR
CALL DS18B20_READ_BYTE ; Read from DS18B20
MOVWF SCRATCHPAD_BYTE1 ; Move read byte to corresponding GPR
DS18B20_RESET ; RESET
BSF STATUS, RP0 ; }
BCF TRISA, 4 ; } DQ LOW
BCF STATUS, RP0 ; }
MOVLW D'123' ; Move 123 to W register
CALL DELAY ; CALL Delay: 500 cycle delay including CALL/GOTO & RETURN. Send Reset Pulse
MOVLW D'123' ; Move Decimal 123 to W register
GOTO DELAY ; GOTO Delay: 500 cycle delay including CALL/GOTO & RETURN. Wait MIN 480uS for DS18B20 & return with DQ line High Z
DS18B20_WRITE_BYTE ; WRITE BYTE
MOVWF SHIFT_IN_OUT ; Store Byte to shift into DS18B20
MOVLW D'08' ; Move Decimal 8 to W
MOVWF COUNT ; Store in COUNT GPR. This is how many bit will be read
RRF SHIFT_IN_OUT, F ; Rotate Right File Register SHIFT_IN_OUT to move bit out of SHIFT_IN_OUT and into Carry
CALL DS18B20_WRITE_BIT ; Send bit
DECFSZ COUNT, F ; Have all 8 bits been written?
GOTO $-3 ; NO, GOTO here - 3 instructions to write next bit
RETURN ;
DS18B20_WRITE_BIT ; WRITE BIT
BCF INTCON,GIE ; Disable Interrupts
BSF STATUS, RP0 ; }
BCF TRISA, 4 ; } DQ LOW
BCF STATUS, RP0 ; }
BTFSS STATUS, C ; Test Carry bit of STATUS register to determine which Logic Level to send
GOTO $+4 ; Carry = 0, Skip next 3 instructions, maintain Low Logic Level for MNI 60uS
BSF STATUS, RP0 ; }
BSF TRISA, 4 ; } DQ HIGH Z (Input, Pullup resistor forces line to Logic 1, unless DS18B20 pulls it low)
BCF STATUS, RP0 ; }
MOVLW D'16' ; Move 16 to W register
GOTO DELAY ; GOTO Delay: 72 cycle delay including CALL/GOTO & RETURN
DS18B20_READ_BYTE ; READ BYTE
MOVLW D'08' ; Move Decimal 8 to W
MOVWF COUNT ; Store in COUNT GPR. This is how many bit will be read
CALL DS18B20_READ_BIT ; CALL DS18B20_READ_BIT and return with read bit in Carry bit of STATUS register
RRF SHIFT_IN_OUT, F ; Rotate Right File Register SHIFT_IN_OUT to move bit out of Carry and into SHIFT_IN_OUT GPR
DECFSZ COUNT, F ; Have all 8 bits been read?
GOTO $-3 ; NO, GOTO here - 3 instructions to read next bit
MOVF SHIFT_IN_OUT, W
RETURN ;
DS18B20_READ_BIT ; READ BIT
BCF INTCON,GIE ; Disable Interrupts
BSF STATUS, RP0 ; }
BCF TRISA, 4 ; } DQ LOW
BCF STATUS, RP0 ; }
BSF STATUS, RP0 ; }
BSF TRISA, 4 ; } DQ HIGH Z (Input, Pullup resistor forces line to Logic 1, unless DS18B20 pulls it low)
BCF STATUS, RP0 ; }
BCF STATUS, C ; Clear Carry bit of STATUS register
BTFSC PORTA, 4 ; Output data from the DS18B20 is valid for 15µs after the falling edge that initiated the read time slot
BSF STATUS, C ; DQ line Logic 1, therefore set Carry bit of STATUS register
BSF INTCON,GIE ; DQ line Logic 0, leave Carry bit of STATUS register clear and Enable Interrupts
MOVLW D'16' ; Move 16 to W register
GOTO DELAY ; GOTO Delay: 72 cycle delay including CALL/GOTO & RETURN
DELAY ; This routine is used for delays from 12 cycles to 1028 cycles (Move D'1' for 12 cycle delay or a D'0' for 1028 cycle delay)
MOVWF DELAYGPR1 ; Formula for this delay shown below (includes 'MOVLW number' and 'CALL/GOTO DELAY' instructions)
DECFSZ DELAYGPR1, W ; Cycles = 8 + (Number x 4) OR Number = (C - 8) / 4
GOTO $-2 ; Example. If a delay of at least 480uS is required (4MHz OSC), Number = (480 - 8) / 4 = 118. Therefore MOVLW D'118' before CALLing the DELAY
BSF STATUS, RP0 ; Bank 1
BSF TRISA, 4 ; Make Pin 3 an Input, Pullup resistor forces line to logic 1, unless DS18B20 pulls it low
BCF STATUS, RP0 ; Bank 0
BSF INTCON, GIE ; Enable Interrupts
RETURN
Ohhh ok. That makes a lot of sense..I suspect that bit label is called "NOT_RABPU" on the 16F690 instead of "NOT_RBPU" as it is on the 16F628A because the 16F690 has weak pull-ups on PORTA and PORTB while the 16F628A only has weak pull-ups on PORTB.
And thanks a lot.I'll take another look at your code but I'm not very good at analyzing other peoples code. Sorry!
; Refresh display
CLRF PORTB ; Blank the display
MOVF PORTA, W ; MOVE PORTA's current state to W
ANDLW B'11110000' ; Clear ONLY Column Select Bits & leave upper nibble unchanged
IORWF COLSEL, W ; Inclusive OR above with COLSEL register
MOVWF PORTA ; Leave upper nibble of PORTA unchanged & select new Column
; Refresh display
CLRF PORTB ; Blank the display
MOVF COLSEL, W ; New column select bit
MOVWF PORTA ; Select new Column
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?