Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC16F628A-Temp sensor-7 Seg Multiplexing issue :(

Status
Not open for further replies.
Arr ok. I see what you mean about testing bit 3 of the digit reg. I'm getting sloppy, I just wish this bloody thing would work. With the interrupt driver.

And yourq uick-n'-dirty analysis of that 2 instruction code is pretty cool. Makes sense to me now...

Well, I'm back at work now, so there goes all my free time. I'm sqeezing bits in here and there.
I'll have another shot at it tommorrow and post my results.

Thanks alot mike. I have learnt heaps from you this week. And pommie too, you've both been a great help so far. I really appreciate your persistance.
 
Hi Jake.

I commend you for jumping into assembly language with both feet. It's not easy but I believe it's a good foundation to have when you move on to C or some other high level language.

Please note that I found and corrected a couple mistakes and updated my example program listing in post #35.

Sometimes when you're changing the architecture dramatically it's easier to back track a bit and just get the new piece (the interrupt display driver) working first. For example, write a new program that simply multiplexes the displays to make sure your hardware and driver are working correctly;

Code:
;******************************************************************
;*                                                                *
;*  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
Then you'll have a working display driver template of sorts for an Indoor/Outdoor Thermometer, or a RTC/Calendar/Alarm, or an Appliance/Photo Timer, or a Stop Watch, etc.

Regards, Mike
 
Last edited:
Yeah good idea mike.
I will do that.

And I will start from scratch. You's have shown me many different, and better, ways of doing things so I dont think I going to try and patch my version up so it works.
But I will start with getting nothing else but the interrupt working with the display.

And Mike, this line of code;
Code:
MOVLW   56/4
Does it acctually move decimal 14 to W (56 divide by 4)?

And what does your ABSFUNC lable imply. I know what the routine does but what does ABS stand for?
 
Last edited:
And Mike, this line of code;
Code:
MOVLW   56/4
Does it acctually move decimal 14 to W (56 divide by 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 what does your ABSFUNC lable imply. I know what the routine does but what does ABS stand for?
That's an "absolute value" function.
 
Yeah I thought that about the 56/4 line... Thanks for clearing that up. Learnt something else new.

So, my progress tonight has been;

I wanted to re-vamp my REARRANGE_RESULT routine.
Using some of yours (mike) and some of pommies routine, while keeping some of my own, I have managed to compact it down to around 56 instructions where as yours (mike) in your example txt file was around 66 instructions. (considering mine used to around 72 instructions im pretty happy) Plus using pommies x 10 / 16 with rounding routine I managed to get rid of my second table too.
Here it is below...
Code:
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                    ;

It is running on my breadboard right now so its working nicely.

I had a breif play with a program using the tmr2 interrupt and the exact same ISR and all i did was move a dummy figure to TEMPHI and LO and increment every second ish and it worked fine. (no DS18B20 routines)

Which leads me to beleive my enable and disable of the global interrupts while the DS18B20 is communicating is messed up somewhere, beaucse when i turn interrupts on, (and comment out the multiplex routine) all i get is ---0 displayed.

Oh I also added a short routine at the top in the ONCE_OFF_INTIALISATION to clear all 96 bytes of RAM in bank 0. got it from the mid range ref man. It uses indirect addressing.

not much to see but here's whats working.... PIC16F628A - DS18B20 Digital Thermometer
think im going to have a hard look at your OW routine and re-write all mine.
 
Hi Jake,

I don't mean to distract you from your project but I wanted to tell you that your bin2bcd routine was very interesting, unusual, and insightful.

In the past I often used the following routine to convert an 8-bit binary number to 'Huns', 'Tens', and 'Ones'. Unfortunately, it uses an "addlw" instruction which is not available on the 12-bit core devices;

Code:
;
;  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          ;
Your unique bin2bcd method inspired the following new bin2bcd routine which is surprisingly small and quick (and should work on the 12-bit core devices);

Code:
; 
;  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
Thank you.

Cheerful regards, Mike
 
Thanks for the Kudos mike.

I have started analysing Pommie and your OW.Routine's to try to improve mine.
I think doing this will solve my issues when it comes to useing TMR2 interrupts.
I will start doing that on the weekend i think when i've got some time.

Just another quick question...
I see you use things like,
Code:
MOVLW   56/4
and even Address lables like this,
Code:
GOTO    DELAY-1

Im not sure when or if I'd need to but is it possible to use x or * (times) aswel as minus plus and divide.
Like this,
Code:
MOVLW   10*4      ; 40
I thought I could try it, then I thought it would just be easier to ask you lol
 
"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
 
Hello again...

I've made a little progress with condensing my Temperature sensor program.

I have been studying Mike's untested example he generously provided and I have written my program based on that.
I does look very similar, but is very different.

So, the with this current version, I am still not using interrupts to drive the display yet, I am trying to communicate with the DS18B20 with this newer & smaller GET_TEMP routine.
The non-ISR multiplex routine is still working and when TEMPHI & TEMPLO are loaded with dummy figures, it works fine.
So no issue with the display.
All i am getting displayed though, is xx0.0 on my display.
Because ALL GPR's in RAM are being cleared (ONCE_OFF_INITIALISE routine) this leads me to believe there is no communication with the sensor.

I have been over it many times and I cant see why It shouldn't work.
Any help, again, would be appreciated.

Once again the program is over 20,000 characters so I have linked it here: PIC16F628A - DS18B20 Digital Thermometer

edit: this webpage shows the same file as above, but colour scheme included: http://www.jakeselectronics.net/other/trialwebpage.php
 
Last edited:
Hi Jake,

I was concerned when you said my 'untested' example program didn't work so I tested the "OneWire" routines from that program on a 16F690 board which has a 2x16 LCD display. The routines worked first time (after minor changes to use RB6 for the OneWire pin on the '690 board instead of RA4). I would be happy to post the 16F690 program and schematic if you or anyone wants to see it.

More later. Regards, Mike
 
Last edited:
Hi Jake,

I just spotted a couple missing instructions in the 'untested' version I posted but I'm not sure they're really necessary or that they would keep the routines from working. Here are the missing lines (in red).

Mike

Code:
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
...
 
Last edited:
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).
Yeah I doubt it too.
Isn't that the purpose of the RdSlot routine... to test when the Conversion is complete. When complete, move on.

I would be happy to post the 16F690 program and schematic if you or anyone wants to see it.

More later. Regards, Mike
I would love to mike. It may help me realise what I'm doing wrong in my program.....
 
Here's the crude 16F690 + DS18B20 + LCD program and schematic. It could be ported to a 16F628A pretty easily.

Regards, Mike
 

Attachments

  • DS18B20 + LCD.PNG
    DS18B20 + LCD.PNG
    13.3 KB · Views: 679
  • DS18B20+690+LCD.ASM.txt
    21.9 KB · Views: 323
Thanks Mike.

picked this up on line 241...
Code:
bcf     OPTION_REG,NOT_R[COLOR="darkorange"]A[/COLOR]BPU
is it supose to be NOT_RBPU ?

And I wanted to ask what exactly is this for....
Code:
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
Why is that delay there for ??
I cant see why... Please clear this up for me.

PS. I have checked everything in my program by itself. The interrupt routine, the (what you call ABSFUNC) re-arrange result routine and its all working, except for my One Wire Communication routines. so the problem lies there.
All I need is to get my OW routine working and get the 16bit number into SCRATCHPAD_BYTE0 & SCRATCHPAD_BYTE1 and my project will work.

My broken GET_TEMP and OW routine's:
GET_TEMP:
Code:
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
And OW routines:
Code:
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

Full program: DS18B20 Digital Thermometer ASM WITH colour scheme
 
Hi Jake,

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.

I don't think that delay is necessary. I copied it from an old program. The Datasheet doesn't say anything about a required delay between sending the "convert" command and reading slots. Sorry!

I'll take another look at your code but I'm not very good at analyzing other peoples code. Sorry!

More later... Regards, Mike
 
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.
Ohhh ok. That makes a lot of sense..

I'll take another look at your code but I'm not very good at analyzing other peoples code. Sorry!
And thanks a lot.
I have tried doing it before to other peoples programs and know how hard it can be. I try to make my programs as easy as I can to read and put a comment on every line, not only for others but for myself.
 
When you disable interrupts you should clear bit 4 of portA. This is because it will get set whenever a write to portA happens such as in the interrupt routine.
Code:
  ; 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
As portA.4 is mostly an input it will read as a high and a 1 will be written back to the latch.

Actually, it's probably best to do it everywhere you make A4 an output, those RMW instructions are nasty little things.

Mike.
 
That's got to be it!!! Thanks Mike (Pommie).

We're assuming the RA4 latch is staying low and that instruction in the ISR is setting it. Easiest fix is probably to change the andlw b'11110000' instruction to andlw b'11100000'. Or, if you're not doin' anything with RA7..RA5 then this might work;
Code:
; Refresh display
        CLRF    PORTB           ; Blank the display
        MOVF    COLSEL, W       ; New column select bit
        MOVWF   PORTA           ; Select new Column
Can you try either of those changes Jake?

Regards, Mike
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top