1. 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.
    Dismiss Notice

PIC16F628A-Temp sensor-7 Seg Multiplexing issue :(

Discussion in 'Microcontrollers' started by jakeselectronics, May 19, 2010.

  1. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    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.
     
  2. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    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 (text):
    ;******************************************************************
    ;*                                                                *
    ;*  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: May 25, 2010
  3. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    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 (text):
    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: May 25, 2010
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA

    Yes, WREG = 14. Just a way to remind me that I want a 56 cycle (56 usec) delay using a 4 cycle loop.

    That's an "absolute value" function.
     
  6. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    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 (text):
    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.
     
  7. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    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 (text):
    ;
    ;  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 (text):
    ;
    ;  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
     
  8. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    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 (text):
    MOVLW   56/4
    and even Address lables like this,
    Code (text):
    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 (text):
    MOVLW   10*4      ; 40
    I thought I could try it, then I thought it would just be easier to ask you lol
     
  9. colin55

    colin55 Well-Known Member

    Joined:
    Feb 14, 2009
    Messages:
    3,534
    Likes:
    82
    Location:
    Melbourne Australia
    It was only the '508 that did not have addlw. The latest 12-bit devices have this instruction, such as: PIC12F629 etc
     
  10. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    You're mistaken, again. The 12F629 is a 14-bit core device.
     
  11. colin55

    colin55 Well-Known Member

    Joined:
    Feb 14, 2009
    Messages:
    3,534
    Likes:
    82
    Location:
    Melbourne Australia
    ok. Thanks.
     
  12. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    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: May 30, 2010
  13. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    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: Jun 3, 2010
  14. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    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 (text):
    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: Jun 5, 2010
  15. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    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 love to mike. It may help me realise what I'm doing wrong in my program.....
     
  16. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    Here's the crude 16F690 + DS18B20 + LCD program and schematic. It could be ported to a 16F628A pretty easily.

    Regards, Mike
     

    Attached Files:

    • Like Like x 1
  17. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    Thanks Mike.

    picked this up on line 241...
    Code (text):
    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 (text):
    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 (text):
    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 (text):
    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
     
  18. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    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
     
  19. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    Ohhh ok. That makes a lot of sense..

    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.
     
  20. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,022
    Likes:
    317
    Location:
    Brisbane Australia
    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 (text):

      ; 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.
     
    • Like Like x 2
  21. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    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 (text):

    ; 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: Jun 6, 2010

Share This Page