Haz una pregunta
  Foros de Electrónica » Diseño analógico » Circuitos de Radio
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

31/10/2013 #61


Gracias Miguelus,

la verdad es que ya me había fijado e incluso había intentado encontrar -por diferencias- una solución rápida, pero no le dediqué mucho tiempo y abandoné enseguida.

Ahora que me lo has puesto un poco más fácil con tu comentario, lo voy a intentar con un poco más de calma.

Gracias de nuevo.

Un saludo

P.D. He probado el frecuencímetro con el prescaler MB506 /64 y funciona perfectamente a 100 y a 446 Mhz que son las dos únicas pruebas que he efectuado.
31/10/2013 #62


Hola de nuevo,

he estado pegándome con el código asm y no avanzo. Supongo que en realidad -al ser cuatro registros de 8 bytes (creo que Acca) cada uno- debería de ser avanzar los valores e cada registro al registro anterior en las mismas posiciones, pero no sé como llevarlo a cabo.

¿Alguien puede indicarme cuales son las modificaciones que debo de efectuar para cambiar el archivo original que divide por 64 a uno nuevo que divida por 256?

La verdad es que si pido ayuda aquí es porque -para efectuar ese pequeño paso- considero que no me compensa dedicar unos meses a aprender a programar.

Muchas gracias
31/10/2013 #63


trifoncar dijo: Ver Mensaje
Hola de nuevo,

he estado pegándome con el código asm y no avanzo. Supongo que en realidad -al ser cuatro registros de 8 bytes (creo que Acca) cada uno- debería de ser avanzar los valores e cada registro al registro anterior en las mismas posiciones, pero no sé como llevarlo a cabo.

¿Alguien puede indicarme cuales son las modificaciones que debo de efectuar para cambiar el archivo original que divide por 64 a uno nuevo que divida por 256?

La verdad es que si pido ayuda aquí es porque -para efectuar ese pequeño paso- considero que no me compensa dedicar unos meses a aprender a programar.

Muchas gracias
Hola...Yo no se mucho de programación en asembler pero por que no probas con esta modificación en la multiplicación a ver si es así(mientras aparece alguien con conocimiento en el tema dispuesto a ayudar).
Saludos.
Ric.

Código:
;*******************************************************************
;
;    "Digital" Frequency display with /64 prescaler & no offsets
;
;    Crystal freq. = 4.000MHz +/- a bit
;
;*******************************************************************
;
;    First, let us choose our weapon - 16F84 or 16F628
;

;    Comment out the next line [;#define F84] if using a 16F628

#define    F84

#ifndef    F84
    #define    F628
#endif


;*******************************************************************
;
;    Some Testing Stuff(tm)
;

;#define    testing        1    ; Comment out when testing finished

;#define    Two_Line    1    ; Un-comment for two line displays


;************************ REVISION HISTORY *************************
;
;    FM1.000    Originally from FM3/4 9:39pm 14 May 2002
;        As implemented in experimental 3.5MHz receiver
;
;*******************************************************************
;
;    FM1.003    Fixed? major silliness in LO-IF code
;        Re-wrote USB/LSB suffix code
;        Added #defines for crook displays
;        Added #defines for two line displays
;        Wrapped #ifdef ... endif around debugging code
;
;*******************************************************************
;
;    FM1.004    Added code to allow user to fix crook display
;        Deleted #defines for crook displays
;        Pin 18 is now input. 1 = good display, 0 = crook
;
;*******************************************************************
;
;    FM2.000    New Hardware! Deleted external counter & gating
;        Now uses the same scheme as the LC Meter, with the
;        third byte of the count implemented in the PIC.
;        Basically, the "output" of the timer register is
;        counted within the gate timing loop.
;
;*******************************************************************
;
;    FM2.001    Discovered that I don't need to use RA0 as a gate
;        cos RA4 can be used as a timer input, even when
;        defined as an output - all that is required is to
;        set it high to count or low to inhibit.
;        Jeez, Microchip are smart arses.
;        I dunno why I didn't spot this long ago.
;        (Can't be used on the LC Meter, cos its oscillator
;        needs to be clamped HIGH, not low as in this case).
;
;*******************************************************************
;
;    FM2.002    Added 9600 baud serial output via RA0
;
;*******************************************************************
;
;    FM2.003    Rewrote RollOver subroutine to use INTCON,T0IF bit.
;        Incorporated two bits from OvrFlow counter
;        to extend range to over 80MHz.
;
;*******************************************************************
;
;    FM2.004    Changed to 32 bit counting.
;
;*******************************************************************
;
;    FM2.005    Added "Calibrate" mode.
;
;*******************************************************************
;
;    FM2.006    Moved "divide by 4" to increase resolution of
;        the stored IF offsets
;
;*******************************************************************
;
;    FM2.007    Moved "check for rollover" out of the inner MS400
;        timing loop and adjusted loop count appropriately
;        The aim - to improve the resolution of the software
;        calibration by a factor of around 13 to 15 times.
;
;*******************************************************************
;
;    fm2b.007    Ported to 16F628
;    FM2c.007    Introduced macros
;    fm2.008        Renumbered
;
;*******************************************************************
;
;    fm2.009        Cleaned up AM IF Offset calculation
;            Converted some inline code to subroutines
;            Created new 32 bit "copy" macro
;            Adjusted calibration slightly
;            Added a "Processor =" message
;            Removed advertising.
;
;*******************************************************************
;
;    ghzfm.000    Added multiply by 64
;            Rendered offsets ineffective
;            changed display format to
;            xxxx.xxxxxx MHz
;            Gate time now 1.000 Second
;
;
;
;*******************************************************************
;o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o
;*******************************************************************
;
;    Some frequently used code fragments
;    Use macros to make mistreaks consistently.
;
;-------------------------------------------------------------------
;    Select Register Bank 0

bank0    macro
    errorlevel    +302        ; Re-enable bank warning
    bcf        STATUS,RP0    ; Select Bank 0
    endm

;-------------------------------------------------------------------
;    Select Register Bank 1

bank1    macro
    bsf        STATUS,RP0    ; Select Bank 1
    errorlevel    -302        ; disable warning
    endm

;-------------------------------------------------------------------
;    Copy a 32 bit thing from one place to another

copy    macro    from,to

    movf    from+0,W
    movwf    to+0

    movf    from+1,W
    movwf    to+1

    movf    from+2,W
    movwf    to+2

    movf    from+3,W
    movwf    to+3

    endm

;*******************************************************************
;
;    CPU configuration
;

#ifdef    F84
    MESSG        "Processor = 16F84"
    #define     RAMStart    0x0C    ; by VK3BHR
    processor    16f84
    include        <p16f84.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF
#endif

#ifdef    F628
    MESSG        "Processor = 16F628"
    #define     RAMStart    0x20
    processor    16f628
    include        <p16f628.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF & _CP_OFF & _BODEN_ON & _LVP_OFF
#endif

;*******************************************************************
;
;    I/O configuration
;


#define S_out    PORTA,0x00    ; 9600 baud serial out
#define PUFF    PORTA,0x00    ; Testing counter out

;#define    FIXIT    PORTA,0x01    ; 1 = "good display"
                ; 0 = do CRLF at "chr 8"

#define    PSC    PORTA,0x01    ; 1 = multiply by 64
                
#define    ENA    PORTA,0x02    ; Display "E"
#define    RS    PORTA,0x03    ; Display "RS"
#define    CLAMP    PORTA,0x04    ; Pull-down the timer input

#define    Store    PORTB,0x04    ; Pin 10, 0 = Measure BFO
#define    Add_LO    PORTB,0x05    ; Pin 11, 0 = RF := LO + IF
                ;         1 = RF := | LO + (-IF) |
#define    BFO_Lo    PORTB,0x06    ; Pin 12, 0 = BFO on lower freq.
#define    BFO_Hi    PORTB,0x07    ; Pin 13, 0 = BFO on higher freq.

#define    Prg_FLG    FLAGS,0x05
#define    AMflag    FLAGS,0x03    ; 0 = Don't print USB/LSB suffix

#define    beq    bz        ; Motorola syntax branches
#define    BEQ    bz
#define    BNE    bnz
#define    bne    bnz

#define    BCC    bnc
#define    bcc    bnc
#define    BCS    bc
#define    bcs    bc

#define    BRA    goto
#define    bra    goto

;*******************************************************************
;
;    file register declarations: uses only registers in bank0
;    bank 0 file registers begin at 0x20 in the 16F628
;
;*******************************************************************

    cblock    RAMStart

    dbg0:4            ; Debugging stuff
    dbg1:4
    dbg2:4
    dbg3:4
    dbg4:4
    dbg5:4


    bcd:5            ; BCD, MSD first 

    SBflag            ; 0 = Lower BFO frequency
                ; 1 = Higher

    COUNT            ; Bin to BCD convert (bit count)
    cnt            ;                    (BCD BYTES)


    CHR
    TEMP            ; DATS/Putchr temporary
    pmsg_t            ; Used by PMSG

    FLAGS

    S_Wtemp            ; "debug" Variables
    S_count
    D_Wtemp
    D_Stemp
    D_FSR
    D_hex
    
    endc

#ifdef    F84
Part2    equ    D_hex+1        ; Just tack on end
#endif

#ifdef    F628
Part2    equ    0x70        ; $70-7F Visible from all banks
#endif

    cblock    Part2

    COUNT1            ; Used by delay routines
    COUNT2            ; Timing (100ms)
    COUNT3            ; Timing (100ms)
    COUNT4            ; Timing (400ms)

    AccA:4            ; Binary, MSByte first

    AccB:4            ; Intermediate frequency

    Hold:4            ; Used in "cal" mode

    endc

;**********************************************************
;
;    Begin Executable Stuff(tm)
;

    org    0

GO    clrwdt            ; 0 << Reset
    clrf    INTCON        ; 1 No interrupts

#ifdef    F628
    movlw    0x07        ; 2 Comparator off
    movwf    CMCON        ; 3
#endif

    goto    START        ; 4 << Interrupt.

;**********************************************************
;
;    Part of string printer
;

pmsub    movwf    PCL        ; Goto W
    nop            ; Just in case
pm_end    return

;**********************************************************
;
;    Text Strings (stored in RETLWs)
;

mhz    dt    " MHz",0
Spaces    dt    " ",0
USB    dt    "U",0
LSB    dt    "L",0
Prog    dt    "P",0
Cal    dt    "C",0

#ifdef    Two_Line

adv3    dt    "1234567890ABCDEF",0

 endif

;**********************************************************
;
;    Main Program
;

START    call    InitIO        ; INITIALISE PORTS
    CLRF    PORTA
    CLRF    PORTB
    bsf    S_out        ; Serial output to idle
    
    CALL    LCDINIT         ; INITIALIZE LCD MODULE    

;    MOVLW    adv1        ; Sign on
;    call    pmsg

;    btfss    FIXIT        ; Test input 1 = just return
;    CALL    LINE2        ; 0 = fix bad display

;    movlw    adv2
;    call    pmsg
    
;    CALL    MS512        ; Delay for about 1 sec.
;    CALL    MS512        ; 0.512 sec x 2

    CALL    CLEAR

;**********************************************************
;
;    Check if in "Calibrate" mode
;

    btfsc    Store        ; If grounded initially
    goto    newbit        ; then were in "cal"

    MOVLW    0xfa        ; Set initial counter        
    MOVWF    Hold+0        ; value

    MOVLW    0xff        ; 
    MOVWF    Hold+1        ; for a 4 MHZ XTAL

    MOVLW    0x5f
    MOVWF    Hold+2            

    MOVLW    0x00        ; Unused
    MOVWF    Hold+3            

GetCal    call    Measure    
    call    Display
    movlw    Cal        ; Say "we're calibrating"
    call    pmsg
    CALL    HOME

;
;    Adjust Cal value
;

cal_dn    btfsc    BFO_Lo
    goto    cal_up
    
    incf    Hold+2,f    ; Add 1
    bne    inc_xit
    incf    Hold+1,f
    bne    inc_xit
    incf    Hold+0,f
inc_xit    goto    StorCal

cal_up    btfsc    BFO_Hi
    goto    StorCal

;
;    Hold := Hold + (1-)    ; Subtract 1
;

Hadd_2    movlw    0xff        ; Process LS byte
    addwf    Hold+2,F
    bcc    Hadd_1        ; If no carry,do next

    incf    Hold+1,f    ; Else roll over higher
    bne    Hadd_1        ; bytes as appropriate

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_1    movlw    0xff        ; Process next byte
    addwf    Hold+1,F
    bcc    Hadd_0        ; If no carry,do next

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_0    movlw    0xff        ; Process next byte
    addwf    Hold+0,F

;
;    Time to save "Cal" value?
;

StorCal    btfss    Store        ; Ready to store it?
    goto    GetCal

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetCal

    copy    Hold,AccB    ; Write EEPROM from AccB

    movlw    0x10        ; EEADR of Cal value
    call    EE_WR


;**********************************************************
;
;    Begin a new measurement cycle
;

newbit    movlw    0x10        ; EEADR of Cal value
    call    EE_RD        ; in AccB
    
    copy    AccB,Hold    ; Get timing "constant"

    call    HOME        ; Display ready

    clrf    SBflag        ; 0 = Lower BFO frequency
                ; 1 = Higher

    bcf    AMflag        ; 0 = No USB/LSB suffix

    bcf    Prg_FLG

    btfsc    Store        ; Doing "BFO STORE"?
    goto    GetOffs

    call    MS512        ; Delay 0.5 sec

    btfsc    Store        ; De-bounce
    goto    GetOffs

GetIf    call    Measure        ; Get freq in AccA:4

    copy    AccA,AccB    ; For EEPROM Writing

    call    Display        ; Display freq in AccA
    
    movlw    Prog        ; Say "we're programming"
    call    pmsg
    CALL    HOME

    btfss    Store        ; Ready to store it?
    goto    GetIf

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetIf

    bsf    Prg_FLG        ; Flag "to be stored"

GetOffs    btfss    BFO_Hi        ; Which Offset??
    goto    Get2        ; Point @ EEPROM

    btfss    BFO_Lo        ; 4 bytes each
    goto    Ch2        ; BFO low link only
    goto    Ch3        ; No links

Get2    btfss    BFO_Lo
    goto    Ch0        ; Both links
    goto    Ch1        ; BFO high link only

Ch0    movlw    0x00        ; Offset channel 0 (both links fitted)
    goto    EndOff

Ch1    bsf    AMflag        ; We're gunna print
    comf    SBflag,f    ; that BFO is on higher frequency
    movlw    0x04        ; Offset channel 1 (BFO_Hi link fitted)
    goto    EndOff

Ch2    bsf    AMflag        ; We're gunna print
                ; that BFO is on lower frequency
    movlw    0x08        ; Offset channel 2 (BFO_Lo link fitted)
    goto    EndOff

Ch3    movlw    0x0C        ; Offset channel 3 (no links fitted)
;    goto    EndOff

EndOff    btfsc    Prg_FLG        ; Storing Offset?
    goto    Do_St        ; If not, then

    call    EE_RD        ; must be reading.
    goto    Do_Meas

Do_St    call    EE_WR

;
;    Now have IF in AccB
;

Do_Meas    call    Measure        ; Measure Local Osc Freq.

;
;    Now have LO in "AccA"
;        and  IF in "AccB"
;

Add_Sub    btfss    Add_LO        ; Add or Sub LO freq?
    goto    AddLSB        ; Clear = just add

    call    MinusA        ; RF := |IF - LO|
                ; SBflag is OK

AddLSB    call    AplusB

;
;    Fix overflow. If negative then make positive
;

    btfss    AccA+0,7    ; Set? (=Overflow)
    goto    OK2go        ; Clear = OK 2 print
    
    call    MinusA        ; Make positive and
    comf    SBflag,f    ; Swap USB/LSB

;
;    Display resulting number in AccA
;

OK2go    call    Display        ; display result at last

;
;    Print suffix - USB, LSB or nuffin
;    Now disabled

    btfsc    AMflag        ; Do we print at all?
    goto    trySBf

    movlw    Spaces        ; nuffin = spaces
    goto    EndMsg

trySBf    btfsc    SBflag,0    ; Which sideband?
    goto    pLSB

    movlw    USB        ; USB obviously
    goto    EndMsg

pLSB    movlw    LSB        ; LSB
;    goto    EndMsg

EndMsg    call    pmsg        ; Print selected trailer


#ifdef    Two_Line

    CALL    LINE2        ; WRITE second LINE

    movlw    adv3
    call    pmsg
 endif

    goto    newbit        ; Start next measurement


;**********************************************************
;
;    AccA := AccA + AccB
;

AplusB    movf    AccB+3,W    ; Process LSB
    addwf    AccA+3,F
    bcc    Add_2        ; If no carry,do next

    incf    AccA+2,f    ; Else roll over higher
    bne    Add_2        ; bytes as appropriate

    incf    AccA+1,f
    bne    Add_2

    incf    AccA+0,f    ; may roll over MSByte
    
Add_2    movf    AccB+2,W    ; Process next byte
    addwf    AccA+2,F
    bcc    Add_1        ; If no carry,do next

    incf    AccA+1,f    ; Else roll over higher
    bne    Add_1        ; bytes as appropriate

    incf    AccA+0,f    ; may roll over MSByte
        
Add_1    movf    AccB+1,W    ; Process next byte
    addwf    AccA+1,F
    bcc    Add_0        ; If no carry,do next

    incf    AccA+0,f    ; may roll over MSByte
        
Add_0    movf    AccB+0,W    ; Process next byte
    addwf    AccA+0,F
    return


;**********************************************************
;
;    Negate number in AccA (2's complement form)
;

MinusA    comf    AccA+0,f    ; Complement all bits
    comf    AccA+1,f    ; of number
    comf    AccA+2,f
    comf    AccA+3,f
    
    incf    AccA+3,f    ; Add 1
    bne    N_xit
    incf    AccA+2,f
    bne    N_xit
    incf    AccA+1,f
    bne    N_xit
    incf    AccA+0,f

N_xit    return

;**********************************************************
;
;    Divide AccA:4 by 4
;
;**********************************************************

Div4    call    Div2        ; Divide AccA:4 by 4

;**********************************************************
;
;    Divide AccA:4 by 2
;
;**********************************************************

Div2    rrf    AccA+0,f
    rrf    AccA+1,f    
    rrf    AccA+2,f
    rrf    AccA+3,f
    bcf    AccA+0,7    ; Possible bad carry in.
    return

;**********************************************************
;
;    Multiply AccA:4 by 64
;
;**********************************************************

Mul64    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2        ; then fall through
    call    Mul2
    call    Mul2
    
;**********************************************************
;
;    Multiply AccA:4 by 2
;
;**********************************************************

Mul2    rlf    AccA+3,f
    rlf    AccA+2,f    
    rlf    AccA+1,f
    rlf    AccA+0,f
    bcf    AccA+3,0    ; Possible bad carry in.
    return
;**********************************************************
;
;    Print String addressed by W
;    Note: Strings are in program space
;

pmsg    movwf    pmsg_t        ; Temp for pointer

pm1    movf    pmsg_t,W    ; Get current pointer
    call    pmsub
    andlw    0xff        ; Test returned value
    beq    pm_end        ; NULL = All done
    call    DATS
    incf    pmsg_t,F
    goto    pm1

;**********************************************************
;
;    Delay for 1000ms (trimmed for actual clock freq)
;    Check for Timer register roll over and count 'em
;
;    Uses: W, COUUNT1, COUNT2, COUNT3 & others
;
;**********************************************************

MS1000    MOVF    Hold+0,w    ; 100 MS DELAY LOOP        
    MOVWF    COUNT1        ; 4 MHZ XTAL

    MOVF    Hold+1,w    ; Count up
    MOVWF    COUNT2        ; to 24 bit overflow

    MOVF    Hold+2,w
    MOVWF    COUNT3

L3    INCFSZ    COUNT3,F
    GOTO    L3
    
    call    RollOver    ; Check for Timer0 RollOver

    INCFSZ    COUNT2,F
    GOTO    L3

    INCFSZ    COUNT1,F
    GOTO    L3

    RETLW    0

;**********************************************************
;
;    SEND A COMMAND BYTE TO LCD DISPLAY MODULE    
;

STROBE    BCF    RS        ; SELECT COMMAND REGISTER
    GOTO    CM

;**********************************************************
;
;    Put a BCD nybble to display
;

PutNyb    ANDLW    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    ADDLW    0x30        ; Convert BIN to ASCII

;**********************************************************
;
;    Put a data byte to display
;

DATS    movwf    TEMP        ; Save character for LCD
    call    putchr
    movf    TEMP,w
    
    BSF    RS        ; SELECT DATA REGISTER
CM    MOVWF    CHR        ; STORE CHAR TO DISPLAY
    SWAPF    CHR,W        ; SWAP UPPER AND LOWER NIBBLES (4 BIT MODE)

    call    PB_dly

    MOVF    CHR,W        ; GET CHAR AGAIN 

;**********************************************************
;
;    Put 4 bits to LCD & wait (untrimmed)
;

PB_dly    ANDLW    0x0F        ; MASK OFF UPPER 4 BITS
    MOVWF    PORTB        ; SEND DATA TO DISPLAY        
    BSF    ENA        ; ENA HIGH
    NOP            
    BCF    ENA        ; ENA LOW 
                ; Fall into 200us DELAY subroutine

;**********************************************************
;
;    Delay for 200us (untrimmed)
;
;    Uses: W, COUNT1
;
;**********************************************************

D200us
DELAY    MOVLW    0x42        ; DELAY 200us
    MOVWF    COUNT1    

NXT5    DECFSZ    COUNT1,F
    GOTO    NXT5    

    RETLW    0

;**********************************************************
;
;    Delay for 2ms (untrimmed)
;
;    Uses: W, COUNT2, COUNT1
;
;**********************************************************

MS2    MOVLW    0x0A        ; DELAY 2ms
    MOVWF    COUNT2

LP15    call    D200us

    DECFSZ    COUNT2,F
    GOTO    LP15

    RETLW    0        

;**********************************************************
;
;    Delay for 512ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS512    clrw            ; 0 -> 256 loops

;**********************************************************
;
;    Delay for multiples of 2ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS2xW    MOVWF    COUNT3    

LPx15    call    MS2

    DECFSZ    COUNT3,F
    GOTO    LPx15

    RETLW    0        

;******************************************************************
;
;    Convert 32-bit binary number at <AccA:4> into a bcd number
;    at <bcd:5>. Uses Mike Keitz's procedure for handling bcd 
;    adjust. Microchip AN526
;

B2_BCD

b2bcd    movlw    .32        ; 32-bits
    movwf    COUNT        ; make cycle counter

    clrf    bcd+0        ; clear result area
    clrf    bcd+1
    clrf    bcd+2
    clrf    bcd+3
    clrf    bcd+4
    
b2bcd2  movlw    bcd        ; make pointer
    movwf    FSR
    movlw    .5        ; Number of BCD bytes?
    movwf    cnt        ; 2 BCD digits per byte

; Mike's routine:

b2bcd3    movlw    0x33    
        addwf    INDF,f        ; add to both nybbles
        btfsc    INDF,3        ; test if low result > 7
        andlw    0xf0        ; low result >7 so take the 3 out
        btfsc    INDF,7        ; test if high result > 7
        andlw    0x0f        ; high result > 7 so ok
        subwf    INDF,f        ; any results <= 7, subtract back
        incf    FSR,f        ; point to next
        decfsz    cnt,f
        goto    b2bcd3
        
        rlf    AccA+3,f    ; get another bit
        rlf    AccA+2,f
        rlf    AccA+1,f
        rlf    AccA+0,f

        rlf    bcd+4,f        ; put it into bcd
        rlf    bcd+3,f
        rlf    bcd+2,f
        rlf    bcd+1,f
        rlf    bcd+0,f

        decfsz    COUNT,f        ; all done?
        goto    b2bcd2        ; no, loop
        return            ; yes


;*********** INITIALISE LCD MODULE 4 BIT MODE ***********************

LCDINIT    CALL    MS512        ; Wait 0.512 sec for LCD  RESET

    BCF    RS        ; REGISTER SELECT LOW
    BCF    ENA        ; ENABLE LINE LOW
    
    MOVLW    0x03        ; 1
    call    PB_dly
    
    CALL    MS512        ; WAIT FOR DISPLAY TO CATCH UP

    MOVLW    0x03        ; 2
    call    PB_dly

    MOVLW    0x03        ; 3
    call    PB_dly

    MOVLW    0x02        ; Fn set 4 bits
    call    PB_dly
    
    MOVLW    0x28        ; DISPLAY 2 Line , 5x7 Dot's
    CALL    STROBE        ; Suggested by PA0EJH
    CALL    DELAY        
    
    MOVLW    0x0C        ; 0x0C DISPLAY ON
    CALL    STROBE
    CALL    DELAY        
    
    MOVLW    0x06        ; 0x06 ENTRY MODE SET
    CALL    STROBE
    CALL    DELAY

    MOVLW    0x01        ; 0x01 CLEAR DISPLAY
    CALL    STROBE
    CALL    MS2

    RETLW    0


;************ MOVE TO START OF LINE 2 *****************

LINE2    MOVLW    0xC0        ; ADDRESS FOR SECOND LINE OF DISPLAY
    CALL    STROBE
    goto    DELAY


;************ CLEAR DISPLAY ***************************

CLEAR    MOVLW    0x01        ; COMMAND TO CLEAR DISPLAY
    CALL    STROBE
    goto    MS2        ; LONGER DELAY NEEDED WHEN CLEARING DISPLAY


;*********** MOVE TO HOME *****************************

HOME    call    crlf        ; Serial

    MOVLW    0x02        ; COMMAND TO HOME LCD DISPLAY
    CALL    STROBE
    goto    MS2


;********************************************************************
;       Initialise Input & Output devices
;********************************************************************

InitIO    bank1

    movlw    0x37        ; Option register
    movwf    OPTION_REG    ; Port B weak pull-up enabled
                ; INTDEG Don't care
                ; Count RA4/T0CKI
                ; Count on falling edge
                ; Prescale Timer/counter
                ; divide Timer/counter by 256

                ; PORTA:-
    movlw    0x02        ; initialise data direction
                ; 1 = input, 0 = output
                ;
                ; PORTA has 5 pins     4 3 2 1 0
                ; 0x02       =   0 0 0 0 0 0 1 0
                ;
    movwf    TRISA        ; PORTA<0>   = Serial + Debugging Out
                ; PORTA<1>   = FIXIT (input)
                ; PORTA<2>   = LCD "E" Out
                ; PORTA<3>   = LCD "RS" Out
                ; PORTA<4>   = "Input" with pull-down
                ;              Actually an output.
                ; PORTA<5:7> = not implemented in 16F84
                ;
                ; PORTB:-
    movlw    0xf0        ; initialise data direction
                ; PORTB has 8 pins
                ; port pin       7 6 5 4 3 2 1 0
                ; 0xf0       =   1 1 1 1 0 0 0 0
                ;
    movwf    TRISB        ; PORTB<0>   = LCD "DB4"
                ; PORTB<1>   =     "DB5"
                ; PORTB<2>   =     "DB6"
                ; PORTB<3>   =     "DB7"
                ; PORTB<4>   = Input
                ; PORTB<5>   = Input
                ; PORTB<6>   = Input
                ; PORTB<7>   = Input

    bank0

    return    

;**********************************************************
;
;    Measure Frequency. Stash in "AccA:4"
;

Measure    bcf    CLAMP        ; CLOSE GATE for safety

    bsf    PORTB,2        ; For compatibility with
    bsf    PORTB,3        ; Version 1 hardware
    
    bcf    INTCON,T0IF    ; Clear any previous overflow
  
    CLRF    TMR0        ; RESET INTERNAL COUNT (INCLUDING PRESCALER)
                ; See page 27 Section 6.0

    CLRF    AccA+0        ; Ready to receive 32 bit number
    CLRF    AccA+1
    CLRF    AccA+2
    CLRF    AccA+3

    bsf    CLAMP        ; OPEN GATE

    CALL    MS1000        ; 1.0 sec DELAY

    bcf    CLAMP        ; CLOSE GATE (COUNT COMPLETE)
    nop            ; and allow time for
    nop            ; the registers to catch up
    nop
    nop
    nop
    
    call    RollOver    ; Final check, just in case

    MOVF    TMR0,W        
    MOVWF    AccA+2

;    Now empty the prescaler

PSC1    bank1

    bcf    OPTION_REG,T0SE    ; Clock the prescaler
    nop
    bsf    OPTION_REG,T0SE

    bank0
    
    DECF    AccA+3,F    ; Decrement the counter
    
    movf    TMR0,W        ; Has TMR0 changed?
    xorwf    AccA+2,W    ; if unchanged, XOR -> 0

    beq    PSC1
        
; AccA : AccA+1 : AccA+2 : AccA+3 now holds 32 bit result
; Rollover subroutine has set AccA+0 and AccA+1 suitably.

    return

;**********************************************************
;
;    Account for TMR0 overflows when counting
;    Check at regular intervals and handle as
;    necessary.
;
;    Needs to be done at less than 936us (@ 70MHz in)
;    intervals, or else it can lose counts.
;

RollOver

    btfss    INTCON,T0IF    ; Rolled over?
    goto    RO3        ; No

RO1    bcf    INTCON,T0IF    ; Yes. ACK!

    INCF    AccA+1,f    ; Count it
    bne    RO2        ; Overflowed?

    incf    AccA+0,f    ; No need to check

RO2    return

;    Balance path lengths

RO3    nop
    nop
    goto    RO2

;**********************************************************
;
;    Display frequency
;
;    Display contents of AccA+0...AccA+3 on LCD
;    First convert to BCD, Then ASCII (nybble at a time)
;
;    In this version, multiply ACCA:4 by 64 since gate
;    time = 1.0 second and ext prescale=64
;

Display    btfsc    PSC        ; 1 = prescaler active = *64        

    call    Mul64        ; Account for prescaler

    CALL    B2_BCD        ; CONVERT all AccA TO BCD

;    Perform Leading Zero Blanking on first 3 digits

    swapf    bcd+0,W        ; 1000's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB1K

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    movf    bcd+0,W        ; 100's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB100

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    swapf    bcd+1,W        ; 10's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB10

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    goto    NoB1

;    Handle rest of number non blanked

NoB1K    SWAPF    bcd+0,W        ; 1000's of MHz
    CALL    PutNyb

NoB100    MOVF    bcd+0,W        ; 100's of MHz
    CALL    PutNyb

NoB10    SWAPF    bcd+1,W        ; 10's of MHz
    CALL    PutNyb

NoB1    MOVF    bcd+1,W        ; 1's of MHz
    CALL    PutNyb

    MOVLW    '.'        ; Decimal Point
    CALL    DATS

    SWAPF    bcd+2,W        ; 100's of KHz
    CALL    PutNyb

    MOVF    bcd+2,W        ; 10's of KHz
    CALL    PutNyb

    SWAPF    bcd+3,W        ; 1's of KHz
    CALL    PutNyb

    CALL    LINE2
    
    MOVF    bcd+3,W        ; 100's of Hz
    CALL    PutNyb

    SWAPF    bcd+4,W        ; 10's of Hz
    CALL    PutNyb

    MOVF    bcd+4,W        ; 1's of Hz
    CALL    PutNyb

    movlw    mhz        ; WRITE " Mhz" AT end OF LINE
    goto    pmsg        ; includes RETURN


;********************************************************************
;    Read EEPROM into "AccB"  (AccB must be visible in both
;    W -> memory to read          memory banks 0 & 1)
;********************************************************************    

EE_RD

#ifdef    F628
    bank1
#endif

    MOVWF    EEADR        ; Address to read

#ifdef    F628
    bank0
#endif
    
    XORLW    0x0C        ; Special case (no links)
    BEQ    AVERAGE

    CALL    EE_R
    MOVWF    AccB+0

    CALL    EE_Rinc
    MOVWF    AccB+1

    CALL    EE_Rinc
    MOVWF    AccB+2

    CALL    EE_Rinc
    MOVWF    AccB+3

    RETURN

;--------------------------------------------------------------------

#ifdef F84

EE_Rinc    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    bank0
    MOVF    EEDATA,W    ; W = EEDATA

    RETURN
#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_Rinc    bank1
    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    MOVF    EEDATA,W    ; W = EEDATA
    bank0

    RETURN
#endif

;--------------------------------------------------------------------

AVERAGE    movlw    0x04        ; AM - use avg BFO freq.
    call    EE_RD        ; Read in one BFO freq
    copy    AccB,AccA    ; Into AccA

    movlw    0x08        ; Then second
    call    EE_RD        ; into AccB

    call    AplusB        ; Add 'em
    call    Div2        ; get average in AccA
    copy    AccA,AccB    ; and in AccB
    return
    

;********************************************************************
;    Write EEPROM from "AccB"  (AccB must be visible in both
;    W -> memory to write          memory banks 0 & 1)
;********************************************************************    

#ifdef    F84

EE_WR    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    RETURN

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    bank1
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    BCF    EECON1,EEIF    ; clear interrupts
    bank0

    RETURN    

#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_WR    bank1
    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    bank0
    RETURN

    errorlevel    -302    ; In Bank 2

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    bank0
    BCF    PIR1,EEIF    ; clear interrupts
    bank1
    RETURN    

    errorlevel    +302
#endif


;********************************************************************
;    Testing counter 
;********************************************************************    

ctest    movlw    0xfe        ; MS byte of loop count
    movwf    COUNT3        ; Counted upward till it overflows

    movlw    0x1d
    movwf    COUNT2

    movlw    0xc0
    movwf    COUNT1

cloop    bcf    PUFF        ; Toggle counter input once
    bsf    PUFF

    incfsz    COUNT1,f
    goto    cloop

    incfsz    COUNT2,f
    goto    cloop

    incfsz    COUNT3,f
    goto    cloop

    return

;***********************************************************************
;
;    Debugging Memory & Register dump
;

debug
    MOVWF    D_Wtemp        ; Copy W to temp register,
    SWAPF    STATUS,W    ; Swap status to be saved into W
    MOVWF    D_Stemp        ; Save status to D_Stemp register
    movf    FSR,W        ; Save FSR
    movwf    D_FSR
    
    movlw    0x57        ; W=
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Wtemp,w
    call    hex_2
    
    movlw    0x20        ; 2 spaces, just to be neat
    call    putchr
    movlw    0x20
    call    putchr
    
    movlw    0x53        ; SR=
    call    putchr
    movlw    0x52
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Stemp,w
    call    hex_2
    
    call    crlf        ; Serial

    clrf    FSR        ; Ready for memory dump

D_loop    movf    0,W        ; Read indirect
    call    hex_2
    movlw    0x20
    call    putchr
    incf    FSR,f        ; to next byte

    movf    FSR,w        ; end of line?
    andlw    0x0F
    bne    next_ln

    call    crlf
    bra    chk4end

next_ln    andlw    0x03        ; Groups of 4
    bne    chk4end

    movlw    0x20
    call    putchr

chk4end    movf    FSR,w        ; All done?
    xorlw    0x80
    bne    D_loop

    call    crlf
    call    crlf
    
    movf    D_FSR,W        ; Restore FSR
    movwf    FSR
    
    SWAPF    D_Stemp,W    ; Swap nibbles in D_Stemp register
                ; and place result into W

    MOVWF    STATUS        ; Move W into STATUS register
                ; (sets bank to original state)
    SWAPF    D_Wtemp,F    ; Swap nibbles in D_Wtemp and place result in D_Wtemp
    SWAPF    D_Wtemp,W    ; Swap nibbles in D_Wtemp and place result into W
    
    return

    
;***********************************************************************
;
;    Print CRLF to serial
;

crlf    movlw    0x0d        ; CRLF
    call    putchr
    movlw    0x0a
    goto    putchr

;***********************************************************************
;
;    Print W as 2 Hex digits
;

hex_2    movwf    D_hex
    swapf    D_hex,w        ; Get big bit
    call    hex_3

    movf    D_hex,w        ; Get little bit

hex_3    andlw    0x0f        ; keep bottom 4 bits
    addlw    0xF6
    bcc    hex_4
    addlw    0x07        ; binary A -> ASCII A
hex_4    addlw    0x3A        ; binary 0 -> ASCII 0
;    goto    putchr

;********************************************************
;
;    Output Routines for PIC16F84
;    
;    Clock is 4.0 MHz.
;    ie. 1.0 us per cycle = 4/Fosc.
;
;    9600 Baud  = 104.17 us
;               = 104.17   CPU cycles
;
;********************************************************
;
;    Output the character in W. Assumes Mac is ready.
;       
;    Uses W
;

putchr    movwf    S_Wtemp        ; Character being output

    movlw    0x08        ; Bit count
    movwf    S_count

    bcf    S_out        ; Send a 0 - Start bit

put_clp    movlw    0xE7        ; Delay "104" cycles
txd_0    addlw    0x01
    bne    txd_0

    rrf    S_Wtemp,f    ; Transmit a bit
    bcs    t_0

    bcf    S_out        ; Send a 0
    bra    tx_1

t_0    bsf    S_out        ; Send a 1

tx_1    decfsz    S_count,f    ; Done all bits?
    goto    put_clp

    movlw    0xE7        ; Delay for last data
txd_1    addlw    0x01
    bne    txd_1

    bsf    S_out        ; Transmit two stop bit

    movlw    0xCD
txd_9    addlw    0x01
    bne    txd_9
    
    return
 
;********************************************************************
;    Tail End Charlie
;********************************************************************    
; initialize eeprom locations

        ORG 0x2100

        DE  0x00, 0x00, 0x00, 0x00    ; Unused (reserved for later)
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 1 Low  BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 2 High BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 3 No   BFO -AM-
        DE  0xfa, 0xff, 0x5f, 0x00    ; 4.000 MHz initial calibration

END
31/10/2013 #64


ricbevi dijo: Ver Mensaje
Hola...Yo no se mucho de programación en asembler pero por que no probas con esta modificación en la multiplicación a ver si es así(mientras aparece alguien con conocimiento en el tema dispuesto a ayudar).
Saludos.
Ric.

[/code]


¡¡Muchísimas gracias Ric!! El código funciona maravillosamente bien. He comprobado que los saltos de frecuencia ahora me los da de 256 en 256 hercios y he comprobado la medición de frecuencia con unos walkies y es correcta.

Te agradezco muchísimo el haberme ahorrado un montón de horas volviéndome loco con el "source" que no domino.

No sé si te parecerá abusar, pero lo que ahora me ocurre es que, así como en la página de Phil Rice https://sites.google.com/site/vk3bhr/home/fm2/prescale aparecen dos ficheros HEX (prehex1 y Prehex2) para presentación en 1 o dos líneas del LCD (display) me he encontrado que el fichero fuente (source) que tan amable y exitosamente has arreglado para *256, la presentación la hace en dos líneas del LCD. ¿Podrías decirme como arreglarlo? o quizá sea mucho pedir; si fuese así, disculpa por el posible abuso.

Un saludo

Gerardo
Imágenes Adjuntas
Tipo de Archivo: jpg DSCF0881-Resize.JPG (97,9 KB (Kilobytes), 29 visitas)
01/11/2013 #65

Avatar de miguelus

Buenos días trifoncar.

¿Has probado a poner un Display de 16x1?

Sal U2
01/11/2013 #66


miguelus dijo: Ver Mensaje
Buenos días trifoncar.

¿Has probado a poner un Display de 16x1?

Sal U2
Hola Miguelus,

No sé si comprendo lo que dices, pero puedo decirte que todos los displays que tengo son de 16x2.

Un saludo
01/11/2013 #67


Estoy "tocando" el código fuente del pic para intentar que me aparezca la frecuencia en una única línea y me está asaltando una duda "existencial", a saber: el tiempo que dedica el programa fuente a leer las instrucciones ¿hay que tenerlo en cuenta a la hora del cálculo de la frecuencia? es decir, ¿afecta a la medición de la frecuencia?

Me da la impresión de que mientras el pic lee el programa está perdiendo tiempo midiendo la frecuencia. ¿Es esto así? ¿Habría que tener en cuenta los ciclos de reloj que pierde el programa ejecutando las instrucciones?

¿O mientras el pic lee los pulsos no se dedica a otra cosa y no pierde ciclos de reloj leyendo el código fuente?

Un saludo
01/11/2013 #68

Avatar de miguelus

En cuanto a tus inquietudes acerca de la forma en la que este Frecuencímetro realiza la medida, es de suponer que el mismo está programado con la cabeza y su forma de funcionar es similar a un Frecuencímetro convencional.

Un frecuencímetro convencional tiene un tiempo de Puerta, durante este tiempo los impulsos de entrada pasan a un contador, después de un tiempo se corta la entrada a los contadores e inmediatamente son mostrados en el Display, mientras se visualiza la cuenta los contadores son reseteados y se comienza una nueva cuenta.

El programa tiene que funcionar de una manera similar, hay que suponer que mientras se realiza la cuenta por el Registro TMR0 (Pin 3), el software puede estar realizando otra función, pero cada cierto tiempo, p.e 1 segundo el software se detiene y lee el TMR0 que contendrá los impulsos recibidos.

Leer y seguir el programa no es una tarea sencilla, todo dependerá de los conocimientos de ensamblador que poseas hay cosas que se intuyen, afortunadamente podemos hacer todos los cambios que queramos, al ensamblar el programa y ponerlo en el PIC podemos ver que es lo ha pasado.

Sal U2
01/11/2013 #69


trifoncar dijo: Ver Mensaje


¡¡Muchísimas gracias Ric!! El código funciona maravillosamente bien. He comprobado que los saltos de frecuencia ahora me los da de 256 en 256 hercios y he comprobado la medición de frecuencia con unos walkies y es correcta.

Te agradezco muchísimo el haberme ahorrado un montón de horas volviéndome loco con el "source" que no domino.

No sé si te parecerá abusar, pero lo que ahora me ocurre es que, así como en la página de Phil Rice https://sites.google.com/site/vk3bhr/home/fm2/prescale aparecen dos ficheros HEX (prehex1 y Prehex2) para presentación en 1 o dos líneas del LCD (display) me he encontrado que el fichero fuente (source) que tan amable y exitosamente has arreglado para *256, la presentación la hace en dos líneas del LCD. ¿Podrías decirme como arreglarlo? o quizá sea mucho pedir; si fuese así, disculpa por el posible abuso.

Un saludo

Gerardo
Me alegro que era así lo del factor de multiplicación...prueba con mandar a GND el pin 18 que en algun momento el autor lo penso para solucionar dicho problema pero el programa ha sufrido muchas modificaciones y no se si se encuentra activa dicha función en ese pin.
Reitero que la programación en el lenguaje asembler del PIC no es mi fuerte.
Si no encuentras respuesta en este Sub-foro deberías plantear el problema especifico del dispaly en el de "Microcontroladores y sistemas embebidos " donde se encuentran los que realmente saben del tema(programación).
Suerte.

Ric.
02/11/2013 #70

Avatar de miguelus

Buenos días.

El Pin 18 (A0) Puesto a "1" provoca que el Frecuencímetro funcione en modo "Normal" esto es, sin ningún factor de división, la frecuencia máxima que podemos medir es de ~85Mhz.

Si el Pin 18 lo ponemos a "0" provoca que el Frecuencímetro tenga en cuenta el factor de división del Prescaler.

Si ponemos un Display de 16x2 (16 caracteres y 2 Líneas) la visualización se mostrará en dos Líneas, en la superior aparecerá la frecuencia y en la inferior mostrará la palabra "MHZ" (igual que en la foto del Post #64).

Si ponemos un Display de 16x1 (16 caracteres y 1 Línea) la visualización se mostrará, lógicamente, en una sola Línea, en primer lugar mostrará la frecuencia y a continuación la palabra "MHZ".

A mí me pasa como a recbyvi, la programación de PIC no es mi fuerte (en realidad dudo si hay algo que verdaderamente sea mi fuerte

Analizando por encima el ASM he visto algo que podría ser el principio para empezar a analizar, total no pondremos a nadie en peligro…

Casi al principio podemos ver la siguiente instrucción…

;#define Two_Line 1 ; Un-comment for two line displays

Esta instrucción, tal como está, no hace nada pero si quitamos “;” que hay al princio quedará así…

#define Two_Line 1 ; Un-comment for two line displays

Ahora la instrucción si que se ejecutará, le estamos diciendo que el Display es de dos Líneas.

Más adelante podemos encontrar la siguiente instrucción…

#ifdef Two_Line


#endif



Todo lo que haya entre estas dos Líneas se ejecutará. Si no hemos quitado ";" en la primera instrucción el programa se saltará este bloque de instrucciones

Esto aparece varias veces durante el programa.

Jugando con lo que hay entre las dos instrucciones, podemos hacer que el programa se comporte de otra forma, me refiero a la forma de visualizar.

Antes de hacer cambio alguno hay que tener la precaución de guardar una copia del ASM, de esta forma evitaremos perderlo

Sal U2
02/11/2013 #71


Gracias por los comentarios.
Ric, efectivamente en una primera versión del código, el pin 18 era para seleccionar si el display era de una o dos líneas, pero al hacer el autor las modificaciones para admitir un prescaler, el pin 18 pasó a sel el indicador de si debía o no multiplicar por el factor del prescaler ( 64 en el modelo de Phil Rice)
Estoy lejos de mi casa pasando el puente, pero el viernes por la mañana estuve analizando las líneas de código.
El pin 18 conectado a tierra provoca el funcionamiento normal del frecuencímetro, y conectado a Vdd funciona con el factor del prescaler definido por las líneas de código, que en mi caso ahora es 256.
Hice la prueba de quitar el punto y la coma a la línea que comentas, Miguelus.
Con ";" me aparecen el número entero de Mhz, el punto y los tres primeros decimales en la primera línea del display, y los decimales 4°, 5° y 6° seguido de MHz en la segunda línea, como puede verse en la última foto que he posteado un poco más arriba.
Quitándo ";" en la primera línea aparece lo mismo, y en la segunda línea aparece la cadena de caracteres "1234567890ABCDEF" que lo he visto en una de las líneas del código. De hecho, cambié esa línea de código para poner la cadena "16F84/MB506:x256" y me apareció en la segunda línea.

------------
------------- (ver Razón para Editar)

Un saludo y, gracias de nuevo.
03/11/2013 #72


Por no alargar un mensaje ya de por sí muy extenso, abro un nuevo post aquí.

He localizado la rutina que escribe los datos en dos líneas, y es:


; Handle rest of number non blanked

NoB1K SWAPF bcd+0,W ; 1000's of MHz ----------> gigahercios
CALL PutNyb

NoB100 MOVF bcd+0,W ; 100's of MHz ----------> centenas de Mhz
CALL PutNyb

NoB10 SWAPF bcd+1,W ; 10's of MHz ----------> decenas de Mhz
CALL PutNyb

NoB1 MOVF bcd+1,W ; 1's of MHz ----------> unidades de Mhz
CALL PutNyb

MOVLW '.' ; Decimal Point ----------> pone un punto decimal
CALL DATS

SWAPF bcd+2,W ; 100's of KHz ----------> centenas de Khz
CALL PutNyb

MOVF bcd+2,W ; 10's of KHz ----------> decenas de Khz
CALL PutNyb

SWAPF bcd+3,W ; 1's of KHz ----------> unidades de Khz
CALL PutNyb

CALL LINE2 ----------> llama a la subrutina de salto de línea

MOVF bcd+3,W ; 100's of Hz ----------> centenares de Hz
CALL PutNyb

SWAPF bcd+4,W ; 10's of Hz ----------> decenas de Hz
CALL PutNyb

MOVF bcd+4,W ; 1's of Hz ----------> unidades de Hz
CALL PutNyb

movlw mhz ; WRITE " Mhz" AT end OF LINE ----------> escribe " Mhz" a continuación
goto pmsg ; includes RETURN


El lunes, podré hacer nuevas pruebas modificando el código relacionado con estas líneas e intentando suprimir ese molesto salto de línea.

Por otra parte, ya que tengo un prescaler que alcanza los 2,4 Ghz, intenté localizar la frecuencia de mi router wifi porque tengo entendido que trabaja a 2,4 Ghz. pero el frecuencímetro no me pilla la señal; además creo que debería de captar la señal del wifi de una tableta ¿no?

Un saludo
03/11/2013 #73


"trifoncar" Prueba de esta forma a ver que pasa....comente la llamada a la sub-rutina de la linea 2 del dispay en el proceso de impresión.

Código:
;*******************************************************************
;
;    "Digital" Frequency display with /64 prescaler & no offsets
;
;    Crystal freq. = 4.000MHz +/- a bit
;
;*******************************************************************
;
;    First, let us choose our weapon - 16F84 or 16F628
;

;    Comment out the next line [;#define F84] if using a 16F628

#define    F84

#ifndef    F84
    #define    F628
#endif


;*******************************************************************
;
;    Some Testing Stuff(tm)
;

;#define    testing        1    ; Comment out when testing finished

;#define    Two_Line    1    ; Un-comment for two line displays


;************************ REVISION HISTORY *************************
;
;    FM1.000    Originally from FM3/4 9:39pm 14 May 2002
;        As implemented in experimental 3.5MHz receiver
;
;*******************************************************************
;
;    FM1.003    Fixed? major silliness in LO-IF code
;        Re-wrote USB/LSB suffix code
;        Added #defines for crook displays
;        Added #defines for two line displays
;        Wrapped #ifdef ... endif around debugging code
;
;*******************************************************************
;
;    FM1.004    Added code to allow user to fix crook display
;        Deleted #defines for crook displays
;        Pin 18 is now input. 1 = good display, 0 = crook
;
;*******************************************************************
;
;    FM2.000    New Hardware! Deleted external counter & gating
;        Now uses the same scheme as the LC Meter, with the
;        third byte of the count implemented in the PIC.
;        Basically, the "output" of the timer register is
;        counted within the gate timing loop.
;
;*******************************************************************
;
;    FM2.001    Discovered that I don't need to use RA0 as a gate
;        cos RA4 can be used as a timer input, even when
;        defined as an output - all that is required is to
;        set it high to count or low to inhibit.
;        Jeez, Microchip are smart arses.
;        I dunno why I didn't spot this long ago.
;        (Can't be used on the LC Meter, cos its oscillator
;        needs to be clamped HIGH, not low as in this case).
;
;*******************************************************************
;
;    FM2.002    Added 9600 baud serial output via RA0
;
;*******************************************************************
;
;    FM2.003    Rewrote RollOver subroutine to use INTCON,T0IF bit.
;        Incorporated two bits from OvrFlow counter
;        to extend range to over 80MHz.
;
;*******************************************************************
;
;    FM2.004    Changed to 32 bit counting.
;
;*******************************************************************
;
;    FM2.005    Added "Calibrate" mode.
;
;*******************************************************************
;
;    FM2.006    Moved "divide by 4" to increase resolution of
;        the stored IF offsets
;
;*******************************************************************
;
;    FM2.007    Moved "check for rollover" out of the inner MS400
;        timing loop and adjusted loop count appropriately
;        The aim - to improve the resolution of the software
;        calibration by a factor of around 13 to 15 times.
;
;*******************************************************************
;
;    fm2b.007    Ported to 16F628
;    FM2c.007    Introduced macros
;    fm2.008        Renumbered
;
;*******************************************************************
;
;    fm2.009        Cleaned up AM IF Offset calculation
;            Converted some inline code to subroutines
;            Created new 32 bit "copy" macro
;            Adjusted calibration slightly
;            Added a "Processor =" message
;            Removed advertising.
;
;*******************************************************************
;
;    ghzfm.000    Added multiply by 64
;            Rendered offsets ineffective
;            changed display format to
;            xxxx.xxxxxx MHz
;            Gate time now 1.000 Second
;
;
;
;*******************************************************************
;o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o
;*******************************************************************
;
;    Some frequently used code fragments
;    Use macros to make mistreaks consistently.
;
;-------------------------------------------------------------------
;    Select Register Bank 0

bank0    macro
    errorlevel    +302        ; Re-enable bank warning
    bcf        STATUS,RP0    ; Select Bank 0
    endm

;-------------------------------------------------------------------
;    Select Register Bank 1

bank1    macro
    bsf        STATUS,RP0    ; Select Bank 1
    errorlevel    -302        ; disable warning
    endm

;-------------------------------------------------------------------
;    Copy a 32 bit thing from one place to another

copy    macro    from,to

    movf    from+0,W
    movwf    to+0

    movf    from+1,W
    movwf    to+1

    movf    from+2,W
    movwf    to+2

    movf    from+3,W
    movwf    to+3

    endm

;*******************************************************************
;
;    CPU configuration
;

#ifdef    F84
    MESSG        "Processor = 16F84"
    #define     RAMStart    0x0C    ; by VK3BHR
    processor    16f84
    include        <p16f84.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF
#endif

#ifdef    F628
    MESSG        "Processor = 16F628"
    #define     RAMStart    0x20
    processor    16f628
    include        <p16f628.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF & _CP_OFF & _BODEN_ON & _LVP_OFF
#endif

;*******************************************************************
;
;    I/O configuration
;


#define S_out    PORTA,0x00    ; 9600 baud serial out
#define PUFF    PORTA,0x00    ; Testing counter out

;#define    FIXIT    PORTA,0x01    ; 1 = "good display"
                ; 0 = do CRLF at "chr 8"

#define    PSC    PORTA,0x01    ; 1 = multiply by 64
                
#define    ENA    PORTA,0x02    ; Display "E"
#define    RS    PORTA,0x03    ; Display "RS"
#define    CLAMP    PORTA,0x04    ; Pull-down the timer input

#define    Store    PORTB,0x04    ; Pin 10, 0 = Measure BFO
#define    Add_LO    PORTB,0x05    ; Pin 11, 0 = RF := LO + IF
                ;         1 = RF := | LO + (-IF) |
#define    BFO_Lo    PORTB,0x06    ; Pin 12, 0 = BFO on lower freq.
#define    BFO_Hi    PORTB,0x07    ; Pin 13, 0 = BFO on higher freq.

#define    Prg_FLG    FLAGS,0x05
#define    AMflag    FLAGS,0x03    ; 0 = Don't print USB/LSB suffix

#define    beq    bz        ; Motorola syntax branches
#define    BEQ    bz
#define    BNE    bnz
#define    bne    bnz

#define    BCC    bnc
#define    bcc    bnc
#define    BCS    bc
#define    bcs    bc

#define    BRA    goto
#define    bra    goto

;*******************************************************************
;
;    file register declarations: uses only registers in bank0
;    bank 0 file registers begin at 0x20 in the 16F628
;
;*******************************************************************

    cblock    RAMStart

    dbg0:4            ; Debugging stuff
    dbg1:4
    dbg2:4
    dbg3:4
    dbg4:4
    dbg5:4


    bcd:5            ; BCD, MSD first 

    SBflag            ; 0 = Lower BFO frequency
                ; 1 = Higher

    COUNT            ; Bin to BCD convert (bit count)
    cnt            ;                    (BCD BYTES)


    CHR
    TEMP            ; DATS/Putchr temporary
    pmsg_t            ; Used by PMSG

    FLAGS

    S_Wtemp            ; "debug" Variables
    S_count
    D_Wtemp
    D_Stemp
    D_FSR
    D_hex
    
    endc

#ifdef    F84
Part2    equ    D_hex+1        ; Just tack on end
#endif

#ifdef    F628
Part2    equ    0x70        ; $70-7F Visible from all banks
#endif

    cblock    Part2

    COUNT1            ; Used by delay routines
    COUNT2            ; Timing (100ms)
    COUNT3            ; Timing (100ms)
    COUNT4            ; Timing (400ms)

    AccA:4            ; Binary, MSByte first

    AccB:4            ; Intermediate frequency

    Hold:4            ; Used in "cal" mode

    endc

;**********************************************************
;
;    Begin Executable Stuff(tm)
;

    org    0

GO    clrwdt            ; 0 << Reset
    clrf    INTCON        ; 1 No interrupts

#ifdef    F628
    movlw    0x07        ; 2 Comparator off
    movwf    CMCON        ; 3
#endif

    goto    START        ; 4 << Interrupt.

;**********************************************************
;
;    Part of string printer
;

pmsub    movwf    PCL        ; Goto W
    nop            ; Just in case
pm_end    return

;**********************************************************
;
;    Text Strings (stored in RETLWs)
;

mhz    dt    " MHz",0
Spaces    dt    " ",0
USB    dt    "U",0
LSB    dt    "L",0
Prog    dt    "P",0
Cal    dt    "C",0

#ifdef    Two_Line

adv3    dt    "1234567890ABCDEF",0

 endif

;**********************************************************
;
;    Main Program
;

START    call    InitIO        ; INITIALISE PORTS
    CLRF    PORTA
    CLRF    PORTB
    bsf    S_out        ; Serial output to idle
    
    CALL    LCDINIT         ; INITIALIZE LCD MODULE    

;    MOVLW    adv1        ; Sign on
;    call    pmsg

;    btfss    FIXIT        ; Test input 1 = just return
;    CALL    LINE2        ; 0 = fix bad display

;    movlw    adv2
;    call    pmsg
    
;    CALL    MS512        ; Delay for about 1 sec.
;    CALL    MS512        ; 0.512 sec x 2

    CALL    CLEAR

;**********************************************************
;
;    Check if in "Calibrate" mode
;

    btfsc    Store        ; If grounded initially
    goto    newbit        ; then were in "cal"

    MOVLW    0xfa        ; Set initial counter        
    MOVWF    Hold+0        ; value

    MOVLW    0xff        ; 
    MOVWF    Hold+1        ; for a 4 MHZ XTAL

    MOVLW    0x5f
    MOVWF    Hold+2            

    MOVLW    0x00        ; Unused
    MOVWF    Hold+3            

GetCal    call    Measure    
    call    Display
    movlw    Cal        ; Say "we're calibrating"
    call    pmsg
    CALL    HOME

;
;    Adjust Cal value
;

cal_dn    btfsc    BFO_Lo
    goto    cal_up
    
    incf    Hold+2,f    ; Add 1
    bne    inc_xit
    incf    Hold+1,f
    bne    inc_xit
    incf    Hold+0,f
inc_xit    goto    StorCal

cal_up    btfsc    BFO_Hi
    goto    StorCal

;
;    Hold := Hold + (1-)    ; Subtract 1
;

Hadd_2    movlw    0xff        ; Process LS byte
    addwf    Hold+2,F
    bcc    Hadd_1        ; If no carry,do next

    incf    Hold+1,f    ; Else roll over higher
    bne    Hadd_1        ; bytes as appropriate

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_1    movlw    0xff        ; Process next byte
    addwf    Hold+1,F
    bcc    Hadd_0        ; If no carry,do next

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_0    movlw    0xff        ; Process next byte
    addwf    Hold+0,F

;
;    Time to save "Cal" value?
;

StorCal    btfss    Store        ; Ready to store it?
    goto    GetCal

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetCal

    copy    Hold,AccB    ; Write EEPROM from AccB

    movlw    0x10        ; EEADR of Cal value
    call    EE_WR


;**********************************************************
;
;    Begin a new measurement cycle
;

newbit    movlw    0x10        ; EEADR of Cal value
    call    EE_RD        ; in AccB
    
    copy    AccB,Hold    ; Get timing "constant"

    call    HOME        ; Display ready

    clrf    SBflag        ; 0 = Lower BFO frequency
                ; 1 = Higher

    bcf    AMflag        ; 0 = No USB/LSB suffix

    bcf    Prg_FLG

    btfsc    Store        ; Doing "BFO STORE"?
    goto    GetOffs

    call    MS512        ; Delay 0.5 sec

    btfsc    Store        ; De-bounce
    goto    GetOffs

GetIf    call    Measure        ; Get freq in AccA:4

    copy    AccA,AccB    ; For EEPROM Writing

    call    Display        ; Display freq in AccA
    
    movlw    Prog        ; Say "we're programming"
    call    pmsg
    CALL    HOME

    btfss    Store        ; Ready to store it?
    goto    GetIf

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetIf

    bsf    Prg_FLG        ; Flag "to be stored"

GetOffs    btfss    BFO_Hi        ; Which Offset??
    goto    Get2        ; Point @ EEPROM

    btfss    BFO_Lo        ; 4 bytes each
    goto    Ch2        ; BFO low link only
    goto    Ch3        ; No links

Get2    btfss    BFO_Lo
    goto    Ch0        ; Both links
    goto    Ch1        ; BFO high link only

Ch0    movlw    0x00        ; Offset channel 0 (both links fitted)
    goto    EndOff

Ch1    bsf    AMflag        ; We're gunna print
    comf    SBflag,f    ; that BFO is on higher frequency
    movlw    0x04        ; Offset channel 1 (BFO_Hi link fitted)
    goto    EndOff

Ch2    bsf    AMflag        ; We're gunna print
                ; that BFO is on lower frequency
    movlw    0x08        ; Offset channel 2 (BFO_Lo link fitted)
    goto    EndOff

Ch3    movlw    0x0C        ; Offset channel 3 (no links fitted)
;    goto    EndOff

EndOff    btfsc    Prg_FLG        ; Storing Offset?
    goto    Do_St        ; If not, then

    call    EE_RD        ; must be reading.
    goto    Do_Meas

Do_St    call    EE_WR

;
;    Now have IF in AccB
;

Do_Meas    call    Measure        ; Measure Local Osc Freq.

;
;    Now have LO in "AccA"
;        and  IF in "AccB"
;

Add_Sub    btfss    Add_LO        ; Add or Sub LO freq?
    goto    AddLSB        ; Clear = just add

    call    MinusA        ; RF := |IF - LO|
                ; SBflag is OK

AddLSB    call    AplusB

;
;    Fix overflow. If negative then make positive
;

    btfss    AccA+0,7    ; Set? (=Overflow)
    goto    OK2go        ; Clear = OK 2 print
    
    call    MinusA        ; Make positive and
    comf    SBflag,f    ; Swap USB/LSB

;
;    Display resulting number in AccA
;

OK2go    call    Display        ; display result at last

;
;    Print suffix - USB, LSB or nuffin
;    Now disabled

    btfsc    AMflag        ; Do we print at all?
    goto    trySBf

    movlw    Spaces        ; nuffin = spaces
    goto    EndMsg

trySBf    btfsc    SBflag,0    ; Which sideband?
    goto    pLSB

    movlw    USB        ; USB obviously
    goto    EndMsg

pLSB    movlw    LSB        ; LSB
;    goto    EndMsg

EndMsg    call    pmsg        ; Print selected trailer


#ifdef    Two_Line

    CALL    LINE2        ; WRITE second LINE

    movlw    adv3
    call    pmsg
 endif

    goto    newbit        ; Start next measurement


;**********************************************************
;
;    AccA := AccA + AccB
;

AplusB    movf    AccB+3,W    ; Process LSB
    addwf    AccA+3,F
    bcc    Add_2        ; If no carry,do next

    incf    AccA+2,f    ; Else roll over higher
    bne    Add_2        ; bytes as appropriate

    incf    AccA+1,f
    bne    Add_2

    incf    AccA+0,f    ; may roll over MSByte
    
Add_2    movf    AccB+2,W    ; Process next byte
    addwf    AccA+2,F
    bcc    Add_1        ; If no carry,do next

    incf    AccA+1,f    ; Else roll over higher
    bne    Add_1        ; bytes as appropriate

    incf    AccA+0,f    ; may roll over MSByte
        
Add_1    movf    AccB+1,W    ; Process next byte
    addwf    AccA+1,F
    bcc    Add_0        ; If no carry,do next

    incf    AccA+0,f    ; may roll over MSByte
        
Add_0    movf    AccB+0,W    ; Process next byte
    addwf    AccA+0,F
    return


;**********************************************************
;
;    Negate number in AccA (2's complement form)
;

MinusA    comf    AccA+0,f    ; Complement all bits
    comf    AccA+1,f    ; of number
    comf    AccA+2,f
    comf    AccA+3,f
    
    incf    AccA+3,f    ; Add 1
    bne    N_xit
    incf    AccA+2,f
    bne    N_xit
    incf    AccA+1,f
    bne    N_xit
    incf    AccA+0,f

N_xit    return

;**********************************************************
;
;    Divide AccA:4 by 4
;
;**********************************************************

Div4    call    Div2        ; Divide AccA:4 by 4

;**********************************************************
;
;    Divide AccA:4 by 2
;
;**********************************************************

Div2    rrf    AccA+0,f
    rrf    AccA+1,f    
    rrf    AccA+2,f
    rrf    AccA+3,f
    bcf    AccA+0,7    ; Possible bad carry in.
    return

;**********************************************************
;
;    Multiply AccA:4 by 64
;
;**********************************************************

Mul64    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2        ; then fall through
    call    Mul2
    call    Mul2
    
;**********************************************************
;
;    Multiply AccA:4 by 2
;
;**********************************************************

Mul2    rlf    AccA+3,f
    rlf    AccA+2,f    
    rlf    AccA+1,f
    rlf    AccA+0,f
    bcf    AccA+3,0    ; Possible bad carry in.
    return
;**********************************************************
;
;    Print String addressed by W
;    Note: Strings are in program space
;

pmsg    movwf    pmsg_t        ; Temp for pointer

pm1    movf    pmsg_t,W    ; Get current pointer
    call    pmsub
    andlw    0xff        ; Test returned value
    beq    pm_end        ; NULL = All done
    call    DATS
    incf    pmsg_t,F
    goto    pm1

;**********************************************************
;
;    Delay for 1000ms (trimmed for actual clock freq)
;    Check for Timer register roll over and count 'em
;
;    Uses: W, COUUNT1, COUNT2, COUNT3 & others
;
;**********************************************************

MS1000    MOVF    Hold+0,w    ; 100 MS DELAY LOOP        
    MOVWF    COUNT1        ; 4 MHZ XTAL

    MOVF    Hold+1,w    ; Count up
    MOVWF    COUNT2        ; to 24 bit overflow

    MOVF    Hold+2,w
    MOVWF    COUNT3

L3    INCFSZ    COUNT3,F
    GOTO    L3
    
    call    RollOver    ; Check for Timer0 RollOver

    INCFSZ    COUNT2,F
    GOTO    L3

    INCFSZ    COUNT1,F
    GOTO    L3

    RETLW    0

;**********************************************************
;
;    SEND A COMMAND BYTE TO LCD DISPLAY MODULE    
;

STROBE    BCF    RS        ; SELECT COMMAND REGISTER
    GOTO    CM

;**********************************************************
;
;    Put a BCD nybble to display
;

PutNyb    ANDLW    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    ADDLW    0x30        ; Convert BIN to ASCII

;**********************************************************
;
;    Put a data byte to display
;

DATS    movwf    TEMP        ; Save character for LCD
    call    putchr
    movf    TEMP,w
    
    BSF    RS        ; SELECT DATA REGISTER
CM    MOVWF    CHR        ; STORE CHAR TO DISPLAY
    SWAPF    CHR,W        ; SWAP UPPER AND LOWER NIBBLES (4 BIT MODE)

    call    PB_dly

    MOVF    CHR,W        ; GET CHAR AGAIN 

;**********************************************************
;
;    Put 4 bits to LCD & wait (untrimmed)
;

PB_dly    ANDLW    0x0F        ; MASK OFF UPPER 4 BITS
    MOVWF    PORTB        ; SEND DATA TO DISPLAY        
    BSF    ENA        ; ENA HIGH
    NOP            
    BCF    ENA        ; ENA LOW 
                ; Fall into 200us DELAY subroutine

;**********************************************************
;
;    Delay for 200us (untrimmed)
;
;    Uses: W, COUNT1
;
;**********************************************************

D200us
DELAY    MOVLW    0x42        ; DELAY 200us
    MOVWF    COUNT1    

NXT5    DECFSZ    COUNT1,F
    GOTO    NXT5    

    RETLW    0

;**********************************************************
;
;    Delay for 2ms (untrimmed)
;
;    Uses: W, COUNT2, COUNT1
;
;**********************************************************

MS2    MOVLW    0x0A        ; DELAY 2ms
    MOVWF    COUNT2

LP15    call    D200us

    DECFSZ    COUNT2,F
    GOTO    LP15

    RETLW    0        

;**********************************************************
;
;    Delay for 512ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS512    clrw            ; 0 -> 256 loops

;**********************************************************
;
;    Delay for multiples of 2ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS2xW    MOVWF    COUNT3    

LPx15    call    MS2

    DECFSZ    COUNT3,F
    GOTO    LPx15

    RETLW    0        

;******************************************************************
;
;    Convert 32-bit binary number at <AccA:4> into a bcd number
;    at <bcd:5>. Uses Mike Keitz's procedure for handling bcd 
;    adjust. Microchip AN526
;

B2_BCD

b2bcd    movlw    .32        ; 32-bits
    movwf    COUNT        ; make cycle counter

    clrf    bcd+0        ; clear result area
    clrf    bcd+1
    clrf    bcd+2
    clrf    bcd+3
    clrf    bcd+4
    
b2bcd2  movlw    bcd        ; make pointer
    movwf    FSR
    movlw    .5        ; Number of BCD bytes?
    movwf    cnt        ; 2 BCD digits per byte

; Mike's routine:

b2bcd3    movlw    0x33    
        addwf    INDF,f        ; add to both nybbles
        btfsc    INDF,3        ; test if low result > 7
        andlw    0xf0        ; low result >7 so take the 3 out
        btfsc    INDF,7        ; test if high result > 7
        andlw    0x0f        ; high result > 7 so ok
        subwf    INDF,f        ; any results <= 7, subtract back
        incf    FSR,f        ; point to next
        decfsz    cnt,f
        goto    b2bcd3
        
        rlf    AccA+3,f    ; get another bit
        rlf    AccA+2,f
        rlf    AccA+1,f
        rlf    AccA+0,f

        rlf    bcd+4,f        ; put it into bcd
        rlf    bcd+3,f
        rlf    bcd+2,f
        rlf    bcd+1,f
        rlf    bcd+0,f

        decfsz    COUNT,f        ; all done?
        goto    b2bcd2        ; no, loop
        return            ; yes


;*********** INITIALISE LCD MODULE 4 BIT MODE ***********************

LCDINIT    CALL    MS512        ; Wait 0.512 sec for LCD  RESET

    BCF    RS        ; REGISTER SELECT LOW
    BCF    ENA        ; ENABLE LINE LOW
    
    MOVLW    0x03        ; 1
    call    PB_dly
    
    CALL    MS512        ; WAIT FOR DISPLAY TO CATCH UP

    MOVLW    0x03        ; 2
    call    PB_dly

    MOVLW    0x03        ; 3
    call    PB_dly

    MOVLW    0x02        ; Fn set 4 bits
    call    PB_dly
    
    MOVLW    0x28        ; DISPLAY 2 Line , 5x7 Dot's
    CALL    STROBE        ; Suggested by PA0EJH
    CALL    DELAY        
    
    MOVLW    0x0C        ; 0x0C DISPLAY ON
    CALL    STROBE
    CALL    DELAY        
    
    MOVLW    0x06        ; 0x06 ENTRY MODE SET
    CALL    STROBE
    CALL    DELAY

    MOVLW    0x01        ; 0x01 CLEAR DISPLAY
    CALL    STROBE
    CALL    MS2

    RETLW    0


;************ MOVE TO START OF LINE 2 *****************

LINE2    MOVLW    0xC0        ; ADDRESS FOR SECOND LINE OF DISPLAY
    CALL    STROBE
    goto    DELAY


;************ CLEAR DISPLAY ***************************

CLEAR    MOVLW    0x01        ; COMMAND TO CLEAR DISPLAY
    CALL    STROBE
    goto    MS2        ; LONGER DELAY NEEDED WHEN CLEARING DISPLAY


;*********** MOVE TO HOME *****************************

HOME    call    crlf        ; Serial

    MOVLW    0x02        ; COMMAND TO HOME LCD DISPLAY
    CALL    STROBE
    goto    MS2


;********************************************************************
;       Initialise Input & Output devices
;********************************************************************

InitIO    bank1

    movlw    0x37        ; Option register
    movwf    OPTION_REG    ; Port B weak pull-up enabled
                ; INTDEG Don't care
                ; Count RA4/T0CKI
                ; Count on falling edge
                ; Prescale Timer/counter
                ; divide Timer/counter by 256

                ; PORTA:-
    movlw    0x02        ; initialise data direction
                ; 1 = input, 0 = output
                ;
                ; PORTA has 5 pins     4 3 2 1 0
                ; 0x02       =   0 0 0 0 0 0 1 0
                ;
    movwf    TRISA        ; PORTA<0>   = Serial + Debugging Out
                ; PORTA<1>   = FIXIT (input)
                ; PORTA<2>   = LCD "E" Out
                ; PORTA<3>   = LCD "RS" Out
                ; PORTA<4>   = "Input" with pull-down
                ;              Actually an output.
                ; PORTA<5:7> = not implemented in 16F84
                ;
                ; PORTB:-
    movlw    0xf0        ; initialise data direction
                ; PORTB has 8 pins
                ; port pin       7 6 5 4 3 2 1 0
                ; 0xf0       =   1 1 1 1 0 0 0 0
                ;
    movwf    TRISB        ; PORTB<0>   = LCD "DB4"
                ; PORTB<1>   =     "DB5"
                ; PORTB<2>   =     "DB6"
                ; PORTB<3>   =     "DB7"
                ; PORTB<4>   = Input
                ; PORTB<5>   = Input
                ; PORTB<6>   = Input
                ; PORTB<7>   = Input

    bank0

    return    

;**********************************************************
;
;    Measure Frequency. Stash in "AccA:4"
;

Measure    bcf    CLAMP        ; CLOSE GATE for safety

    bsf    PORTB,2        ; For compatibility with
    bsf    PORTB,3        ; Version 1 hardware
    
    bcf    INTCON,T0IF    ; Clear any previous overflow
  
    CLRF    TMR0        ; RESET INTERNAL COUNT (INCLUDING PRESCALER)
                ; See page 27 Section 6.0

    CLRF    AccA+0        ; Ready to receive 32 bit number
    CLRF    AccA+1
    CLRF    AccA+2
    CLRF    AccA+3

    bsf    CLAMP        ; OPEN GATE

    CALL    MS1000        ; 1.0 sec DELAY

    bcf    CLAMP        ; CLOSE GATE (COUNT COMPLETE)
    nop            ; and allow time for
    nop            ; the registers to catch up
    nop
    nop
    nop
    
    call    RollOver    ; Final check, just in case

    MOVF    TMR0,W        
    MOVWF    AccA+2

;    Now empty the prescaler

PSC1    bank1

    bcf    OPTION_REG,T0SE    ; Clock the prescaler
    nop
    bsf    OPTION_REG,T0SE

    bank0
    
    DECF    AccA+3,F    ; Decrement the counter
    
    movf    TMR0,W        ; Has TMR0 changed?
    xorwf    AccA+2,W    ; if unchanged, XOR -> 0

    beq    PSC1
        
; AccA : AccA+1 : AccA+2 : AccA+3 now holds 32 bit result
; Rollover subroutine has set AccA+0 and AccA+1 suitably.

    return

;**********************************************************
;
;    Account for TMR0 overflows when counting
;    Check at regular intervals and handle as
;    necessary.
;
;    Needs to be done at less than 936us (@ 70MHz in)
;    intervals, or else it can lose counts.
;

RollOver

    btfss    INTCON,T0IF    ; Rolled over?
    goto    RO3        ; No

RO1    bcf    INTCON,T0IF    ; Yes. ACK!

    INCF    AccA+1,f    ; Count it
    bne    RO2        ; Overflowed?

    incf    AccA+0,f    ; No need to check

RO2    return

;    Balance path lengths

RO3    nop
    nop
    goto    RO2

;**********************************************************
;
;    Display frequency
;
;    Display contents of AccA+0...AccA+3 on LCD
;    First convert to BCD, Then ASCII (nybble at a time)
;
;    In this version, multiply ACCA:4 by 64 since gate
;    time = 1.0 second and ext prescale=64
;

Display    btfsc    PSC        ; 1 = prescaler active = *64        

    call    Mul64        ; Account for prescaler

    CALL    B2_BCD        ; CONVERT all AccA TO BCD

;    Perform Leading Zero Blanking on first 3 digits

    swapf    bcd+0,W        ; 1000's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB1K

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    movf    bcd+0,W        ; 100's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB100

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    swapf    bcd+1,W        ; 10's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB10

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    goto    NoB1

;    Handle rest of number non blanked

NoB1K    SWAPF    bcd+0,W        ; 1000's of MHz
    CALL    PutNyb

NoB100    MOVF    bcd+0,W        ; 100's of MHz
    CALL    PutNyb

NoB10    SWAPF    bcd+1,W        ; 10's of MHz
    CALL    PutNyb

NoB1    MOVF    bcd+1,W        ; 1's of MHz
    CALL    PutNyb

    MOVLW    '.'        ; Decimal Point
    CALL    DATS

    SWAPF    bcd+2,W        ; 100's of KHz
    CALL    PutNyb

    MOVF    bcd+2,W        ; 10's of KHz
    CALL    PutNyb

    SWAPF    bcd+3,W        ; 1's of KHz
    CALL    PutNyb

;    CALL    LINE2
    
    MOVF    bcd+3,W        ; 100's of Hz
    CALL    PutNyb

    SWAPF    bcd+4,W        ; 10's of Hz
    CALL    PutNyb

    MOVF    bcd+4,W        ; 1's of Hz
    CALL    PutNyb

    movlw    mhz        ; WRITE " Mhz" AT end OF LINE
    goto    pmsg        ; includes RETURN


;********************************************************************
;    Read EEPROM into "AccB"  (AccB must be visible in both
;    W -> memory to read          memory banks 0 & 1)
;********************************************************************    

EE_RD

#ifdef    F628
    bank1
#endif

    MOVWF    EEADR        ; Address to read

#ifdef    F628
    bank0
#endif
    
    XORLW    0x0C        ; Special case (no links)
    BEQ    AVERAGE

    CALL    EE_R
    MOVWF    AccB+0

    CALL    EE_Rinc
    MOVWF    AccB+1

    CALL    EE_Rinc
    MOVWF    AccB+2

    CALL    EE_Rinc
    MOVWF    AccB+3

    RETURN

;--------------------------------------------------------------------

#ifdef F84

EE_Rinc    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    bank0
    MOVF    EEDATA,W    ; W = EEDATA

    RETURN
#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_Rinc    bank1
    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    MOVF    EEDATA,W    ; W = EEDATA
    bank0

    RETURN
#endif

;--------------------------------------------------------------------

AVERAGE    movlw    0x04        ; AM - use avg BFO freq.
    call    EE_RD        ; Read in one BFO freq
    copy    AccB,AccA    ; Into AccA

    movlw    0x08        ; Then second
    call    EE_RD        ; into AccB

    call    AplusB        ; Add 'em
    call    Div2        ; get average in AccA
    copy    AccA,AccB    ; and in AccB
    return
    

;********************************************************************
;    Write EEPROM from "AccB"  (AccB must be visible in both
;    W -> memory to write          memory banks 0 & 1)
;********************************************************************    

#ifdef    F84

EE_WR    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    RETURN

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    bank1
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    BCF    EECON1,EEIF    ; clear interrupts
    bank0

    RETURN    

#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_WR    bank1
    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    bank0
    RETURN

    errorlevel    -302    ; In Bank 2

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    bank0
    BCF    PIR1,EEIF    ; clear interrupts
    bank1
    RETURN    

    errorlevel    +302
#endif


;********************************************************************
;    Testing counter 
;********************************************************************    

ctest    movlw    0xfe        ; MS byte of loop count
    movwf    COUNT3        ; Counted upward till it overflows

    movlw    0x1d
    movwf    COUNT2

    movlw    0xc0
    movwf    COUNT1

cloop    bcf    PUFF        ; Toggle counter input once
    bsf    PUFF

    incfsz    COUNT1,f
    goto    cloop

    incfsz    COUNT2,f
    goto    cloop

    incfsz    COUNT3,f
    goto    cloop

    return

;***********************************************************************
;
;    Debugging Memory & Register dump
;

debug
    MOVWF    D_Wtemp        ; Copy W to temp register,
    SWAPF    STATUS,W    ; Swap status to be saved into W
    MOVWF    D_Stemp        ; Save status to D_Stemp register
    movf    FSR,W        ; Save FSR
    movwf    D_FSR
    
    movlw    0x57        ; W=
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Wtemp,w
    call    hex_2
    
    movlw    0x20        ; 2 spaces, just to be neat
    call    putchr
    movlw    0x20
    call    putchr
    
    movlw    0x53        ; SR=
    call    putchr
    movlw    0x52
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Stemp,w
    call    hex_2
    
    call    crlf        ; Serial

    clrf    FSR        ; Ready for memory dump

D_loop    movf    0,W        ; Read indirect
    call    hex_2
    movlw    0x20
    call    putchr
    incf    FSR,f        ; to next byte

    movf    FSR,w        ; end of line?
    andlw    0x0F
    bne    next_ln

    call    crlf
    bra    chk4end

next_ln    andlw    0x03        ; Groups of 4
    bne    chk4end

    movlw    0x20
    call    putchr

chk4end    movf    FSR,w        ; All done?
    xorlw    0x80
    bne    D_loop

    call    crlf
    call    crlf
    
    movf    D_FSR,W        ; Restore FSR
    movwf    FSR
    
    SWAPF    D_Stemp,W    ; Swap nibbles in D_Stemp register
                ; and place result into W

    MOVWF    STATUS        ; Move W into STATUS register
                ; (sets bank to original state)
    SWAPF    D_Wtemp,F    ; Swap nibbles in D_Wtemp and place result in D_Wtemp
    SWAPF    D_Wtemp,W    ; Swap nibbles in D_Wtemp and place result into W
    
    return

    
;***********************************************************************
;
;    Print CRLF to serial
;

crlf    movlw    0x0d        ; CRLF
    call    putchr
    movlw    0x0a
    goto    putchr

;***********************************************************************
;
;    Print W as 2 Hex digits
;

hex_2    movwf    D_hex
    swapf    D_hex,w        ; Get big bit
    call    hex_3

    movf    D_hex,w        ; Get little bit

hex_3    andlw    0x0f        ; keep bottom 4 bits
    addlw    0xF6
    bcc    hex_4
    addlw    0x07        ; binary A -> ASCII A
hex_4    addlw    0x3A        ; binary 0 -> ASCII 0
;    goto    putchr

;********************************************************
;
;    Output Routines for PIC16F84
;    
;    Clock is 4.0 MHz.
;    ie. 1.0 us per cycle = 4/Fosc.
;
;    9600 Baud  = 104.17 us
;               = 104.17   CPU cycles
;
;********************************************************
;
;    Output the character in W. Assumes Mac is ready.
;       
;    Uses W
;

putchr    movwf    S_Wtemp        ; Character being output

    movlw    0x08        ; Bit count
    movwf    S_count

    bcf    S_out        ; Send a 0 - Start bit

put_clp    movlw    0xE7        ; Delay "104" cycles
txd_0    addlw    0x01
    bne    txd_0

    rrf    S_Wtemp,f    ; Transmit a bit
    bcs    t_0

    bcf    S_out        ; Send a 0
    bra    tx_1

t_0    bsf    S_out        ; Send a 1

tx_1    decfsz    S_count,f    ; Done all bits?
    goto    put_clp

    movlw    0xE7        ; Delay for last data
txd_1    addlw    0x01
    bne    txd_1

    bsf    S_out        ; Transmit two stop bit

    movlw    0xCD
txd_9    addlw    0x01
    bne    txd_9
    
    return
 
;********************************************************************
;    Tail End Charlie
;********************************************************************    
; initialize eeprom locations

        ORG 0x2100

        DE  0x00, 0x00, 0x00, 0x00    ; Unused (reserved for later)
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 1 Low  BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 2 High BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 3 No   BFO -AM-
        DE  0xfa, 0xff, 0x5f, 0x00    ; 4.000 MHz initial calibration

END
Ric.
03/11/2013 #74


Gracias Ric,

No lo podré probar hasta mañana lunes por la tarde ya que estoy fuera de mi domicilio y regresaré mañana.

Un saludo
04/11/2013 #75


Hola de nuevo!

Ya de regreso del “puente” he podido efectuar las pruebas que quería hacer para intentar evitar que los datos de la frecuencia saliesen repartidos en las dos líneas del display.

Como la más cómoda era la de Ric, ya que me había dejado el código con una modificación efectuada, lo he compilado y lo he probado.
Bien, pues ¡Funciona perfectamente! ¡Gracias de nuevo, Ric! Has acertado con tu modificación. El frecuencímetro marca perfectamente y con todos los datos en la primera línea. Para no entender mucho de programación, como dices, ¡a mí me lo has arreglado perfectamente!

Debido a que funciona correctamente, me he animado a subir un nuevo vídeo con las mismas pruebas que efectué anteriormente, pero con el prescaler MB506, a saber:

- con un módulo oscilador de 100,00 Mhz
- con un walkie (de ocho canales) que trabaja en 446 Mhz

Con el módulo oscilador ade 100,00 Mhz no he logrado medir la frecuencia fundamental. Siempre se me ha deslizado a 300,00 Mientras que con el prescaler U664BS y un pequeño condensador en serie no hubo problemas.

Con los walkies ha ido todo muy bien. He puesto los datos que he obtenido en una prueba anterior, en una hoja de cálculo que se ve en el video, para no alargar demasiado la duración del mismo, pero los datos son prácticamente los mismos como se verá en dicho video.

La precisión es realmente buena ya que las desviaciones respecto de las frecuencias por canal detalladas en el manual (y que también se ven en la tercera columna de la hoja de cálculo del video) son del orden de varias diezmillonésimas o lo que es lo mismo, del orden de uno a tres cientos de hercios. Como el prescaler está dividiendo por 256, es aproximadamente esa la desviación. Es decir, mínima, bajo mi punto de vista.

Con esto, queda comprobado perfectamente el funcionamiento del frecuencímetro de Phil Rice sin prescaler (probado por mí hasta 33,3 Mhz), con prescaler U664BS (utilizando el divisor 64) (en 100.00, de 87 a 108 Mhz [emisora de FM] y 446 Mhz), y con el prescaler MB506 utilizando el divisor /256 (a 100,00 con la salvedad indicada, y 446 Mhz).

Me gustaría poder probarlo a frecuencias más elevadas, en particular con el MB506, porque teóricamente llega a 2,4 Ghz, pero no dispongo de fuente con esa frecuencia ya que, aunque creía que detectaría el wifi de un router, he podido leer en varios sitios que emiten muy corto espacio de tiempo a esa frecuencia y además, está muy “desparramada” o no concentrada.

Tampoco dispongo, de momento, de micrófonos inalámbricos que creo que trabajan sobre los 860 Mhz, pero si algún día consigo alguno, lo probaré y lo haré saber aquí.

Por lo demás, iré exponiendo aquí los avances en el montaje definitivo sobre placa, con fotos y videos (el prescaler en “Manhattan”).

Un saludo y, gracias de nuevo a Ric, Miguelus, Fogonazo y resto de foreros.

P.D.: Varias veces he dicho multiplicador en vez de divisor, espero que me disculpéis.

Video:
Archivos Adjuntos
Tipo de Archivo: doc Medidas efectuadas con el frecuencímetro.doc (47,0 KB (Kilobytes), 10 visitas)
04/11/2013 #76


"trifoncar" me alegro que te funcione las modificaciones...ya que vi el video y veo como visualiza en el display los datos te adjunto algo para que pruebes a ver que pasa y si te gusta.
En programación/computación ando desde el '79 y algo por mas "burro" que uno sea aprende, pero es complicado analizar algo echo por otra persona y entenderlo para así modificar lo a nuestro gusto. Desde hace mucho solo uso lenguajes de alto nivel por eso decía que no es mi fuerte el asembler. Mí primer frecuencimetro lo realice por los años 80 y obviamente no era con microprocesador si no en base al 74C926, como prescaler usaba el 74LS90 en baja frecuencia y el 11C90 en alta frecuencia y el método de medición era el descripto por "Miguelus" de "ventana" de 0.1S, 1S y 10S para mediciones mas justas.
Te sugiero para completar este post que en la medida de lo posible subas los esquemáticos de la modificaciones para así serle de utilidad a futuros consultantes.
Suerte con la pasada en limpio del circuito.
Saludos.

Ric.

Código:
;*******************************************************************
;
;    "Digital" Frequency display with /64 prescaler & no offsets
;
;    Crystal freq. = 4.000MHz +/- a bit
;
;*******************************************************************
;
;    First, let us choose our weapon - 16F84 or 16F628
;

;    Comment out the next line [;#define F84] if using a 16F628

#define    F84

#ifndef    F84
    #define    F628
#endif


;*******************************************************************
;
;    Some Testing Stuff(tm)
;

;#define    testing        1    ; Comment out when testing finished

;#define    Two_Line    1    ; Un-comment for two line displays


;************************ REVISION HISTORY *************************
;
;    FM1.000    Originally from FM3/4 9:39pm 14 May 2002
;        As implemented in experimental 3.5MHz receiver
;
;*******************************************************************
;
;    FM1.003    Fixed? major silliness in LO-IF code
;        Re-wrote USB/LSB suffix code
;        Added #defines for crook displays
;        Added #defines for two line displays
;        Wrapped #ifdef ... endif around debugging code
;
;*******************************************************************
;
;    FM1.004    Added code to allow user to fix crook display
;        Deleted #defines for crook displays
;        Pin 18 is now input. 1 = good display, 0 = crook
;
;*******************************************************************
;
;    FM2.000    New Hardware! Deleted external counter & gating
;        Now uses the same scheme as the LC Meter, with the
;        third byte of the count implemented in the PIC.
;        Basically, the "output" of the timer register is
;        counted within the gate timing loop.
;
;*******************************************************************
;
;    FM2.001    Discovered that I don't need to use RA0 as a gate
;        cos RA4 can be used as a timer input, even when
;        defined as an output - all that is required is to
;        set it high to count or low to inhibit.
;        Jeez, Microchip are smart arses.
;        I dunno why I didn't spot this long ago.
;        (Can't be used on the LC Meter, cos its oscillator
;        needs to be clamped HIGH, not low as in this case).
;
;*******************************************************************
;
;    FM2.002    Added 9600 baud serial output via RA0
;
;*******************************************************************
;
;    FM2.003    Rewrote RollOver subroutine to use INTCON,T0IF bit.
;        Incorporated two bits from OvrFlow counter
;        to extend range to over 80MHz.
;
;*******************************************************************
;
;    FM2.004    Changed to 32 bit counting.
;
;*******************************************************************
;
;    FM2.005    Added "Calibrate" mode.
;
;*******************************************************************
;
;    FM2.006    Moved "divide by 4" to increase resolution of
;        the stored IF offsets
;
;*******************************************************************
;
;    FM2.007    Moved "check for rollover" out of the inner MS400
;        timing loop and adjusted loop count appropriately
;        The aim - to improve the resolution of the software
;        calibration by a factor of around 13 to 15 times.
;
;*******************************************************************
;
;    fm2b.007    Ported to 16F628
;    FM2c.007    Introduced macros
;    fm2.008        Renumbered
;
;*******************************************************************
;
;    fm2.009        Cleaned up AM IF Offset calculation
;            Converted some inline code to subroutines
;            Created new 32 bit "copy" macro
;            Adjusted calibration slightly
;            Added a "Processor =" message
;            Removed advertising.
;
;*******************************************************************
;
;    ghzfm.000    Added multiply by 64
;            Rendered offsets ineffective
;            changed display format to
;            xxxx.xxxxxx MHz
;            Gate time now 1.000 Second
;
;
;
;*******************************************************************
;o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o
;*******************************************************************
;
;    Some frequently used code fragments
;    Use macros to make mistreaks consistently.
;
;-------------------------------------------------------------------
;    Select Register Bank 0

bank0    macro
    errorlevel    +302        ; Re-enable bank warning
    bcf        STATUS,RP0    ; Select Bank 0
    endm

;-------------------------------------------------------------------
;    Select Register Bank 1

bank1    macro
    bsf        STATUS,RP0    ; Select Bank 1
    errorlevel    -302        ; disable warning
    endm

;-------------------------------------------------------------------
;    Copy a 32 bit thing from one place to another

copy    macro    from,to

    movf    from+0,W
    movwf    to+0

    movf    from+1,W
    movwf    to+1

    movf    from+2,W
    movwf    to+2

    movf    from+3,W
    movwf    to+3

    endm

;*******************************************************************
;
;    CPU configuration
;

#ifdef    F84
    MESSG        "Processor = 16F84"
    #define     RAMStart    0x0C    ; by VK3BHR
    processor    16f84
    include        <p16f84.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF
#endif

#ifdef    F628
    MESSG        "Processor = 16F628"
    #define     RAMStart    0x20
    processor    16f628
    include        <p16f628.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF & _CP_OFF & _BODEN_ON & _LVP_OFF
#endif

;*******************************************************************
;
;    I/O configuration
;


#define S_out    PORTA,0x00    ; 9600 baud serial out
#define PUFF    PORTA,0x00    ; Testing counter out

;#define    FIXIT    PORTA,0x01    ; 1 = "good display"
                ; 0 = do CRLF at "chr 8"

#define    PSC    PORTA,0x01    ; 1 = multiply by 64
                
#define    ENA    PORTA,0x02    ; Display "E"
#define    RS    PORTA,0x03    ; Display "RS"
#define    CLAMP    PORTA,0x04    ; Pull-down the timer input

#define    Store    PORTB,0x04    ; Pin 10, 0 = Measure BFO
#define    Add_LO    PORTB,0x05    ; Pin 11, 0 = RF := LO + IF
                ;         1 = RF := | LO + (-IF) |
#define    BFO_Lo    PORTB,0x06    ; Pin 12, 0 = BFO on lower freq.
#define    BFO_Hi    PORTB,0x07    ; Pin 13, 0 = BFO on higher freq.

#define    Prg_FLG    FLAGS,0x05
#define    AMflag    FLAGS,0x03    ; 0 = Don't print USB/LSB suffix

#define    beq    bz        ; Motorola syntax branches
#define    BEQ    bz
#define    BNE    bnz
#define    bne    bnz

#define    BCC    bnc
#define    bcc    bnc
#define    BCS    bc
#define    bcs    bc

#define    BRA    goto
#define    bra    goto

;*******************************************************************
;
;    file register declarations: uses only registers in bank0
;    bank 0 file registers begin at 0x20 in the 16F628
;
;*******************************************************************

    cblock    RAMStart

    dbg0:4            ; Debugging stuff
    dbg1:4
    dbg2:4
    dbg3:4
    dbg4:4
    dbg5:4


    bcd:5            ; BCD, MSD first 

    SBflag            ; 0 = Lower BFO frequency
                ; 1 = Higher

    COUNT            ; Bin to BCD convert (bit count)
    cnt            ;                    (BCD BYTES)


    CHR
    TEMP            ; DATS/Putchr temporary
    pmsg_t            ; Used by PMSG

    FLAGS

    S_Wtemp            ; "debug" Variables
    S_count
    D_Wtemp
    D_Stemp
    D_FSR
    D_hex
    
    endc

#ifdef    F84
Part2    equ    D_hex+1        ; Just tack on end
#endif

#ifdef    F628
Part2    equ    0x70        ; $70-7F Visible from all banks
#endif

    cblock    Part2

    COUNT1            ; Used by delay routines
    COUNT2            ; Timing (100ms)
    COUNT3            ; Timing (100ms)
    COUNT4            ; Timing (400ms)

    AccA:4            ; Binary, MSByte first

    AccB:4            ; Intermediate frequency

    Hold:4            ; Used in "cal" mode

    endc

;**********************************************************
;
;    Begin Executable Stuff(tm)
;

    org    0

GO    clrwdt            ; 0 << Reset
    clrf    INTCON        ; 1 No interrupts

#ifdef    F628
    movlw    0x07        ; 2 Comparator off
    movwf    CMCON        ; 3
#endif

    goto    START        ; 4 << Interrupt.

;**********************************************************
;
;    Part of string printer
;

pmsub    movwf    PCL        ; Goto W
    nop            ; Just in case
pm_end    return

;**********************************************************
;
;    Text Strings (stored in RETLWs)
;

mhz    dt    " MHz",0
Spaces    dt    " ",0
USB    dt    "U",0
LSB    dt    "L",0
Prog    dt    "P",0
Cal    dt    "C",0

#ifdef    Two_Line

adv3    dt    "1234567890ABCDEF",0

 endif

;**********************************************************
;
;    Main Program
;

START    call    InitIO        ; INITIALISE PORTS
    CLRF    PORTA
    CLRF    PORTB
    bsf    S_out        ; Serial output to idle
    
    CALL    LCDINIT         ; INITIALIZE LCD MODULE    

;    MOVLW    adv1        ; Sign on
;    call    pmsg

;    btfss    FIXIT        ; Test input 1 = just return
;    CALL    LINE2        ; 0 = fix bad display

;    movlw    adv2
;    call    pmsg
    
;    CALL    MS512        ; Delay for about 1 sec.
;    CALL    MS512        ; 0.512 sec x 2

    CALL    CLEAR

;**********************************************************
;
;    Check if in "Calibrate" mode
;

    btfsc    Store        ; If grounded initially
    goto    newbit        ; then were in "cal"

    MOVLW    0xfa        ; Set initial counter        
    MOVWF    Hold+0        ; value

    MOVLW    0xff        ; 
    MOVWF    Hold+1        ; for a 4 MHZ XTAL

    MOVLW    0x5f
    MOVWF    Hold+2            

    MOVLW    0x00        ; Unused
    MOVWF    Hold+3            

GetCal    call    Measure    
    call    Display
    movlw    Cal        ; Say "we're calibrating"
    call    pmsg
    CALL    HOME

;
;    Adjust Cal value
;

cal_dn    btfsc    BFO_Lo
    goto    cal_up
    
    incf    Hold+2,f    ; Add 1
    bne    inc_xit
    incf    Hold+1,f
    bne    inc_xit
    incf    Hold+0,f
inc_xit    goto    StorCal

cal_up    btfsc    BFO_Hi
    goto    StorCal

;
;    Hold := Hold + (1-)    ; Subtract 1
;

Hadd_2    movlw    0xff        ; Process LS byte
    addwf    Hold+2,F
    bcc    Hadd_1        ; If no carry,do next

    incf    Hold+1,f    ; Else roll over higher
    bne    Hadd_1        ; bytes as appropriate

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_1    movlw    0xff        ; Process next byte
    addwf    Hold+1,F
    bcc    Hadd_0        ; If no carry,do next

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_0    movlw    0xff        ; Process next byte
    addwf    Hold+0,F

;
;    Time to save "Cal" value?
;

StorCal    btfss    Store        ; Ready to store it?
    goto    GetCal

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetCal

    copy    Hold,AccB    ; Write EEPROM from AccB

    movlw    0x10        ; EEADR of Cal value
    call    EE_WR


;**********************************************************
;
;    Begin a new measurement cycle
;

newbit    movlw    0x10        ; EEADR of Cal value
    call    EE_RD        ; in AccB
    
    copy    AccB,Hold    ; Get timing "constant"

    call    HOME        ; Display ready

    clrf    SBflag        ; 0 = Lower BFO frequency
                ; 1 = Higher

    bcf    AMflag        ; 0 = No USB/LSB suffix

    bcf    Prg_FLG

    btfsc    Store        ; Doing "BFO STORE"?
    goto    GetOffs

    call    MS512        ; Delay 0.5 sec

    btfsc    Store        ; De-bounce
    goto    GetOffs

GetIf    call    Measure        ; Get freq in AccA:4

    copy    AccA,AccB    ; For EEPROM Writing

    call    Display        ; Display freq in AccA
    
    movlw    Prog        ; Say "we're programming"
    call    pmsg
    CALL    HOME

    btfss    Store        ; Ready to store it?
    goto    GetIf

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetIf

    bsf    Prg_FLG        ; Flag "to be stored"

GetOffs    btfss    BFO_Hi        ; Which Offset??
    goto    Get2        ; Point @ EEPROM

    btfss    BFO_Lo        ; 4 bytes each
    goto    Ch2        ; BFO low link only
    goto    Ch3        ; No links

Get2    btfss    BFO_Lo
    goto    Ch0        ; Both links
    goto    Ch1        ; BFO high link only

Ch0    movlw    0x00        ; Offset channel 0 (both links fitted)
    goto    EndOff

Ch1    bsf    AMflag        ; We're gunna print
    comf    SBflag,f    ; that BFO is on higher frequency
    movlw    0x04        ; Offset channel 1 (BFO_Hi link fitted)
    goto    EndOff

Ch2    bsf    AMflag        ; We're gunna print
                ; that BFO is on lower frequency
    movlw    0x08        ; Offset channel 2 (BFO_Lo link fitted)
    goto    EndOff

Ch3    movlw    0x0C        ; Offset channel 3 (no links fitted)
;    goto    EndOff

EndOff    btfsc    Prg_FLG        ; Storing Offset?
    goto    Do_St        ; If not, then

    call    EE_RD        ; must be reading.
    goto    Do_Meas

Do_St    call    EE_WR

;
;    Now have IF in AccB
;

Do_Meas    call    Measure        ; Measure Local Osc Freq.

;
;    Now have LO in "AccA"
;        and  IF in "AccB"
;

Add_Sub    btfss    Add_LO        ; Add or Sub LO freq?
    goto    AddLSB        ; Clear = just add

    call    MinusA        ; RF := |IF - LO|
                ; SBflag is OK

AddLSB    call    AplusB

;
;    Fix overflow. If negative then make positive
;

    btfss    AccA+0,7    ; Set? (=Overflow)
    goto    OK2go        ; Clear = OK 2 print
    
    call    MinusA        ; Make positive and
    comf    SBflag,f    ; Swap USB/LSB

;
;    Display resulting number in AccA
;

OK2go    call    Display        ; display result at last

;
;    Print suffix - USB, LSB or nuffin
;    Now disabled

    btfsc    AMflag        ; Do we print at all?
    goto    trySBf

    movlw    Spaces        ; nuffin = spaces
    goto    EndMsg

trySBf    btfsc    SBflag,0    ; Which sideband?
    goto    pLSB

    movlw    USB        ; USB obviously
    goto    EndMsg

pLSB    movlw    LSB        ; LSB
;    goto    EndMsg

EndMsg    call    pmsg        ; Print selected trailer


#ifdef    Two_Line

    CALL    LINE2        ; WRITE second LINE

    movlw    adv3
    call    pmsg
 endif

    goto    newbit        ; Start next measurement


;**********************************************************
;
;    AccA := AccA + AccB
;

AplusB    movf    AccB+3,W    ; Process LSB
    addwf    AccA+3,F
    bcc    Add_2        ; If no carry,do next

    incf    AccA+2,f    ; Else roll over higher
    bne    Add_2        ; bytes as appropriate

    incf    AccA+1,f
    bne    Add_2

    incf    AccA+0,f    ; may roll over MSByte
    
Add_2    movf    AccB+2,W    ; Process next byte
    addwf    AccA+2,F
    bcc    Add_1        ; If no carry,do next

    incf    AccA+1,f    ; Else roll over higher
    bne    Add_1        ; bytes as appropriate

    incf    AccA+0,f    ; may roll over MSByte
        
Add_1    movf    AccB+1,W    ; Process next byte
    addwf    AccA+1,F
    bcc    Add_0        ; If no carry,do next

    incf    AccA+0,f    ; may roll over MSByte
        
Add_0    movf    AccB+0,W    ; Process next byte
    addwf    AccA+0,F
    return


;**********************************************************
;
;    Negate number in AccA (2's complement form)
;

MinusA    comf    AccA+0,f    ; Complement all bits
    comf    AccA+1,f    ; of number
    comf    AccA+2,f
    comf    AccA+3,f
    
    incf    AccA+3,f    ; Add 1
    bne    N_xit
    incf    AccA+2,f
    bne    N_xit
    incf    AccA+1,f
    bne    N_xit
    incf    AccA+0,f

N_xit    return

;**********************************************************
;
;    Divide AccA:4 by 4
;
;**********************************************************

Div4    call    Div2        ; Divide AccA:4 by 4

;**********************************************************
;
;    Divide AccA:4 by 2
;
;**********************************************************

Div2    rrf    AccA+0,f
    rrf    AccA+1,f    
    rrf    AccA+2,f
    rrf    AccA+3,f
    bcf    AccA+0,7    ; Possible bad carry in.
    return

;**********************************************************
;
;    Multiply AccA:4 by 64
;
;**********************************************************

Mul64    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2        ; then fall through
    call    Mul2
    call    Mul2
    
;**********************************************************
;
;    Multiply AccA:4 by 2
;
;**********************************************************

Mul2    rlf    AccA+3,f
    rlf    AccA+2,f    
    rlf    AccA+1,f
    rlf    AccA+0,f
    bcf    AccA+3,0    ; Possible bad carry in.
    return
;**********************************************************
;
;    Print String addressed by W
;    Note: Strings are in program space
;

pmsg    movwf    pmsg_t        ; Temp for pointer

pm1    movf    pmsg_t,W    ; Get current pointer
    call    pmsub
    andlw    0xff        ; Test returned value
    beq    pm_end        ; NULL = All done
    call    DATS
    incf    pmsg_t,F
    goto    pm1

;**********************************************************
;
;    Delay for 1000ms (trimmed for actual clock freq)
;    Check for Timer register roll over and count 'em
;
;    Uses: W, COUUNT1, COUNT2, COUNT3 & others
;
;**********************************************************

MS1000    MOVF    Hold+0,w    ; 100 MS DELAY LOOP        
    MOVWF    COUNT1        ; 4 MHZ XTAL

    MOVF    Hold+1,w    ; Count up
    MOVWF    COUNT2        ; to 24 bit overflow

    MOVF    Hold+2,w
    MOVWF    COUNT3

L3    INCFSZ    COUNT3,F
    GOTO    L3
    
    call    RollOver    ; Check for Timer0 RollOver

    INCFSZ    COUNT2,F
    GOTO    L3

    INCFSZ    COUNT1,F
    GOTO    L3

    RETLW    0

;**********************************************************
;
;    SEND A COMMAND BYTE TO LCD DISPLAY MODULE    
;

STROBE    BCF    RS        ; SELECT COMMAND REGISTER
    GOTO    CM

;**********************************************************
;
;    Put a BCD nybble to display
;

PutNyb    ANDLW    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    ADDLW    0x30        ; Convert BIN to ASCII

;**********************************************************
;
;    Put a data byte to display
;

DATS    movwf    TEMP        ; Save character for LCD
    call    putchr
    movf    TEMP,w
    
    BSF    RS        ; SELECT DATA REGISTER
CM    MOVWF    CHR        ; STORE CHAR TO DISPLAY
    SWAPF    CHR,W        ; SWAP UPPER AND LOWER NIBBLES (4 BIT MODE)

    call    PB_dly

    MOVF    CHR,W        ; GET CHAR AGAIN 

;**********************************************************
;
;    Put 4 bits to LCD & wait (untrimmed)
;

PB_dly    ANDLW    0x0F        ; MASK OFF UPPER 4 BITS
    MOVWF    PORTB        ; SEND DATA TO DISPLAY        
    BSF    ENA        ; ENA HIGH
    NOP            
    BCF    ENA        ; ENA LOW 
                ; Fall into 200us DELAY subroutine

;**********************************************************
;
;    Delay for 200us (untrimmed)
;
;    Uses: W, COUNT1
;
;**********************************************************

D200us
DELAY    MOVLW    0x42        ; DELAY 200us
    MOVWF    COUNT1    

NXT5    DECFSZ    COUNT1,F
    GOTO    NXT5    

    RETLW    0

;**********************************************************
;
;    Delay for 2ms (untrimmed)
;
;    Uses: W, COUNT2, COUNT1
;
;**********************************************************

MS2    MOVLW    0x0A        ; DELAY 2ms
    MOVWF    COUNT2

LP15    call    D200us

    DECFSZ    COUNT2,F
    GOTO    LP15

    RETLW    0        

;**********************************************************
;
;    Delay for 512ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS512    clrw            ; 0 -> 256 loops

;**********************************************************
;
;    Delay for multiples of 2ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS2xW    MOVWF    COUNT3    

LPx15    call    MS2

    DECFSZ    COUNT3,F
    GOTO    LPx15

    RETLW    0        

;******************************************************************
;
;    Convert 32-bit binary number at <AccA:4> into a bcd number
;    at <bcd:5>. Uses Mike Keitz's procedure for handling bcd 
;    adjust. Microchip AN526
;

B2_BCD

b2bcd    movlw    .32        ; 32-bits
    movwf    COUNT        ; make cycle counter

    clrf    bcd+0        ; clear result area
    clrf    bcd+1
    clrf    bcd+2
    clrf    bcd+3
    clrf    bcd+4
    
b2bcd2  movlw    bcd        ; make pointer
    movwf    FSR
    movlw    .5        ; Number of BCD bytes?
    movwf    cnt        ; 2 BCD digits per byte

; Mike's routine:

b2bcd3    movlw    0x33    
        addwf    INDF,f        ; add to both nybbles
        btfsc    INDF,3        ; test if low result > 7
        andlw    0xf0        ; low result >7 so take the 3 out
        btfsc    INDF,7        ; test if high result > 7
        andlw    0x0f        ; high result > 7 so ok
        subwf    INDF,f        ; any results <= 7, subtract back
        incf    FSR,f        ; point to next
        decfsz    cnt,f
        goto    b2bcd3
        
        rlf    AccA+3,f    ; get another bit
        rlf    AccA+2,f
        rlf    AccA+1,f
        rlf    AccA+0,f

        rlf    bcd+4,f        ; put it into bcd
        rlf    bcd+3,f
        rlf    bcd+2,f
        rlf    bcd+1,f
        rlf    bcd+0,f

        decfsz    COUNT,f        ; all done?
        goto    b2bcd2        ; no, loop
        return            ; yes


;*********** INITIALISE LCD MODULE 4 BIT MODE ***********************

LCDINIT    CALL    MS512        ; Wait 0.512 sec for LCD  RESET

    BCF    RS        ; REGISTER SELECT LOW
    BCF    ENA        ; ENABLE LINE LOW
    
    MOVLW    0x03        ; 1
    call    PB_dly
    
    CALL    MS512        ; WAIT FOR DISPLAY TO CATCH UP

    MOVLW    0x03        ; 2
    call    PB_dly

    MOVLW    0x03        ; 3
    call    PB_dly

    MOVLW    0x02        ; Fn set 4 bits
    call    PB_dly
    
    MOVLW    0x28        ; DISPLAY 2 Line , 5x7 Dot's
    CALL    STROBE        ; Suggested by PA0EJH
    CALL    DELAY        
    
    MOVLW    0x0C        ; 0x0C DISPLAY ON
    CALL    STROBE
    CALL    DELAY        
    
    MOVLW    0x06        ; 0x06 ENTRY MODE SET
    CALL    STROBE
    CALL    DELAY

    MOVLW    0x01        ; 0x01 CLEAR DISPLAY
    CALL    STROBE
    CALL    MS2

    RETLW    0


;************ MOVE TO START OF LINE 2 *****************

LINE2    MOVLW    0xC0        ; ADDRESS FOR SECOND LINE OF DISPLAY
    CALL    STROBE
    goto    DELAY


;************ CLEAR DISPLAY ***************************

CLEAR    MOVLW    0x01        ; COMMAND TO CLEAR DISPLAY
    CALL    STROBE
    goto    MS2        ; LONGER DELAY NEEDED WHEN CLEARING DISPLAY


;*********** MOVE TO HOME *****************************

HOME    call    crlf        ; Serial

    MOVLW    0x02        ; COMMAND TO HOME LCD DISPLAY
    CALL    STROBE
    goto    MS2


;********************************************************************
;       Initialise Input & Output devices
;********************************************************************

InitIO    bank1

    movlw    0x37        ; Option register
    movwf    OPTION_REG    ; Port B weak pull-up enabled
                ; INTDEG Don't care
                ; Count RA4/T0CKI
                ; Count on falling edge
                ; Prescale Timer/counter
                ; divide Timer/counter by 256

                ; PORTA:-
    movlw    0x02        ; initialise data direction
                ; 1 = input, 0 = output
                ;
                ; PORTA has 5 pins     4 3 2 1 0
                ; 0x02       =   0 0 0 0 0 0 1 0
                ;
    movwf    TRISA        ; PORTA<0>   = Serial + Debugging Out
                ; PORTA<1>   = FIXIT (input)
                ; PORTA<2>   = LCD "E" Out
                ; PORTA<3>   = LCD "RS" Out
                ; PORTA<4>   = "Input" with pull-down
                ;              Actually an output.
                ; PORTA<5:7> = not implemented in 16F84
                ;
                ; PORTB:-
    movlw    0xf0        ; initialise data direction
                ; PORTB has 8 pins
                ; port pin       7 6 5 4 3 2 1 0
                ; 0xf0       =   1 1 1 1 0 0 0 0
                ;
    movwf    TRISB        ; PORTB<0>   = LCD "DB4"
                ; PORTB<1>   =     "DB5"
                ; PORTB<2>   =     "DB6"
                ; PORTB<3>   =     "DB7"
                ; PORTB<4>   = Input
                ; PORTB<5>   = Input
                ; PORTB<6>   = Input
                ; PORTB<7>   = Input

    bank0

    return    

;**********************************************************
;
;    Measure Frequency. Stash in "AccA:4"
;

Measure    bcf    CLAMP        ; CLOSE GATE for safety

    bsf    PORTB,2        ; For compatibility with
    bsf    PORTB,3        ; Version 1 hardware
    
    bcf    INTCON,T0IF    ; Clear any previous overflow
  
    CLRF    TMR0        ; RESET INTERNAL COUNT (INCLUDING PRESCALER)
                ; See page 27 Section 6.0

    CLRF    AccA+0        ; Ready to receive 32 bit number
    CLRF    AccA+1
    CLRF    AccA+2
    CLRF    AccA+3

    bsf    CLAMP        ; OPEN GATE

    CALL    MS1000        ; 1.0 sec DELAY

    bcf    CLAMP        ; CLOSE GATE (COUNT COMPLETE)
    nop            ; and allow time for
    nop            ; the registers to catch up
    nop
    nop
    nop
    
    call    RollOver    ; Final check, just in case

    MOVF    TMR0,W        
    MOVWF    AccA+2

;    Now empty the prescaler

PSC1    bank1

    bcf    OPTION_REG,T0SE    ; Clock the prescaler
    nop
    bsf    OPTION_REG,T0SE

    bank0
    
    DECF    AccA+3,F    ; Decrement the counter
    
    movf    TMR0,W        ; Has TMR0 changed?
    xorwf    AccA+2,W    ; if unchanged, XOR -> 0

    beq    PSC1
        
; AccA : AccA+1 : AccA+2 : AccA+3 now holds 32 bit result
; Rollover subroutine has set AccA+0 and AccA+1 suitably.

    return

;**********************************************************
;
;    Account for TMR0 overflows when counting
;    Check at regular intervals and handle as
;    necessary.
;
;    Needs to be done at less than 936us (@ 70MHz in)
;    intervals, or else it can lose counts.
;

RollOver

    btfss    INTCON,T0IF    ; Rolled over?
    goto    RO3        ; No

RO1    bcf    INTCON,T0IF    ; Yes. ACK!

    INCF    AccA+1,f    ; Count it
    bne    RO2        ; Overflowed?

    incf    AccA+0,f    ; No need to check

RO2    return

;    Balance path lengths

RO3    nop
    nop
    goto    RO2

;**********************************************************
;
;    Display frequency
;
;    Display contents of AccA+0...AccA+3 on LCD
;    First convert to BCD, Then ASCII (nybble at a time)
;
;    In this version, multiply ACCA:4 by 64 since gate
;    time = 1.0 second and ext prescale=64
;

Display    btfsc    PSC        ; 1 = prescaler active = *64        

    call    Mul64        ; Account for prescaler

    CALL    B2_BCD        ; CONVERT all AccA TO BCD

;    Perform Leading Zero Blanking on first 3 digits

    swapf    bcd+0,W        ; 1000's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB1K

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    movf    bcd+0,W        ; 100's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB100

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    swapf    bcd+1,W        ; 10's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB10

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    goto    NoB1

;    Handle rest of number non blanked

NoB1K    SWAPF    bcd+0,W        ; 1000's of MHz
    CALL    PutNyb

NoB100    MOVF    bcd+0,W        ; 100's of MHz
    CALL    PutNyb

NoB10    SWAPF    bcd+1,W        ; 10's of MHz
    CALL    PutNyb

NoB1    MOVF    bcd+1,W        ; 1's of MHz
    CALL    PutNyb

    MOVLW    '.'        ; Decimal Point
    CALL    DATS

    SWAPF    bcd+2,W        ; 100's of KHz
    CALL    PutNyb

    MOVF    bcd+2,W        ; 10's of KHz
    CALL    PutNyb

    SWAPF    bcd+3,W        ; 1's of KHz
    CALL    PutNyb

;    CALL    LINE2

    MOVLW    ','        ; Decimal Coma 
    CALL    DATS
    
    MOVF    bcd+3,W        ; 100's of Hz
    CALL    PutNyb

    SWAPF    bcd+4,W        ; 10's of Hz
    CALL    PutNyb

    MOVF    bcd+4,W        ; 1's of Hz
    CALL    PutNyb

    movlw    mhz        ; WRITE " Mhz" AT end OF LINE
    goto    pmsg        ; includes RETURN


;********************************************************************
;    Read EEPROM into "AccB"  (AccB must be visible in both
;    W -> memory to read          memory banks 0 & 1)
;********************************************************************    

EE_RD

#ifdef    F628
    bank1
#endif

    MOVWF    EEADR        ; Address to read

#ifdef    F628
    bank0
#endif
    
    XORLW    0x0C        ; Special case (no links)
    BEQ    AVERAGE

    CALL    EE_R
    MOVWF    AccB+0

    CALL    EE_Rinc
    MOVWF    AccB+1

    CALL    EE_Rinc
    MOVWF    AccB+2

    CALL    EE_Rinc
    MOVWF    AccB+3

    RETURN

;--------------------------------------------------------------------

#ifdef F84

EE_Rinc    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    bank0
    MOVF    EEDATA,W    ; W = EEDATA

    RETURN
#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_Rinc    bank1
    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    MOVF    EEDATA,W    ; W = EEDATA
    bank0

    RETURN
#endif

;--------------------------------------------------------------------

AVERAGE    movlw    0x04        ; AM - use avg BFO freq.
    call    EE_RD        ; Read in one BFO freq
    copy    AccB,AccA    ; Into AccA

    movlw    0x08        ; Then second
    call    EE_RD        ; into AccB

    call    AplusB        ; Add 'em
    call    Div2        ; get average in AccA
    copy    AccA,AccB    ; and in AccB
    return
    

;********************************************************************
;    Write EEPROM from "AccB"  (AccB must be visible in both
;    W -> memory to write          memory banks 0 & 1)
;********************************************************************    

#ifdef    F84

EE_WR    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    RETURN

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    bank1
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    BCF    EECON1,EEIF    ; clear interrupts
    bank0

    RETURN    

#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_WR    bank1
    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    bank0
    RETURN

    errorlevel    -302    ; In Bank 2

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    bank0
    BCF    PIR1,EEIF    ; clear interrupts
    bank1
    RETURN    

    errorlevel    +302
#endif


;********************************************************************
;    Testing counter 
;********************************************************************    

ctest    movlw    0xfe        ; MS byte of loop count
    movwf    COUNT3        ; Counted upward till it overflows

    movlw    0x1d
    movwf    COUNT2

    movlw    0xc0
    movwf    COUNT1

cloop    bcf    PUFF        ; Toggle counter input once
    bsf    PUFF

    incfsz    COUNT1,f
    goto    cloop

    incfsz    COUNT2,f
    goto    cloop

    incfsz    COUNT3,f
    goto    cloop

    return

;***********************************************************************
;
;    Debugging Memory & Register dump
;

debug
    MOVWF    D_Wtemp        ; Copy W to temp register,
    SWAPF    STATUS,W    ; Swap status to be saved into W
    MOVWF    D_Stemp        ; Save status to D_Stemp register
    movf    FSR,W        ; Save FSR
    movwf    D_FSR
    
    movlw    0x57        ; W=
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Wtemp,w
    call    hex_2
    
    movlw    0x20        ; 2 spaces, just to be neat
    call    putchr
    movlw    0x20
    call    putchr
    
    movlw    0x53        ; SR=
    call    putchr
    movlw    0x52
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Stemp,w
    call    hex_2
    
    call    crlf        ; Serial

    clrf    FSR        ; Ready for memory dump

D_loop    movf    0,W        ; Read indirect
    call    hex_2
    movlw    0x20
    call    putchr
    incf    FSR,f        ; to next byte

    movf    FSR,w        ; end of line?
    andlw    0x0F
    bne    next_ln

    call    crlf
    bra    chk4end

next_ln    andlw    0x03        ; Groups of 4
    bne    chk4end

    movlw    0x20
    call    putchr

chk4end    movf    FSR,w        ; All done?
    xorlw    0x80
    bne    D_loop

    call    crlf
    call    crlf
    
    movf    D_FSR,W        ; Restore FSR
    movwf    FSR
    
    SWAPF    D_Stemp,W    ; Swap nibbles in D_Stemp register
                ; and place result into W

    MOVWF    STATUS        ; Move W into STATUS register
                ; (sets bank to original state)
    SWAPF    D_Wtemp,F    ; Swap nibbles in D_Wtemp and place result in D_Wtemp
    SWAPF    D_Wtemp,W    ; Swap nibbles in D_Wtemp and place result into W
    
    return

    
;***********************************************************************
;
;    Print CRLF to serial
;

crlf    movlw    0x0d        ; CRLF
    call    putchr
    movlw    0x0a
    goto    putchr

;***********************************************************************
;
;    Print W as 2 Hex digits
;

hex_2    movwf    D_hex
    swapf    D_hex,w        ; Get big bit
    call    hex_3

    movf    D_hex,w        ; Get little bit

hex_3    andlw    0x0f        ; keep bottom 4 bits
    addlw    0xF6
    bcc    hex_4
    addlw    0x07        ; binary A -> ASCII A
hex_4    addlw    0x3A        ; binary 0 -> ASCII 0
;    goto    putchr

;********************************************************
;
;    Output Routines for PIC16F84
;    
;    Clock is 4.0 MHz.
;    ie. 1.0 us per cycle = 4/Fosc.
;
;    9600 Baud  = 104.17 us
;               = 104.17   CPU cycles
;
;********************************************************
;
;    Output the character in W. Assumes Mac is ready.
;       
;    Uses W
;

putchr    movwf    S_Wtemp        ; Character being output

    movlw    0x08        ; Bit count
    movwf    S_count

    bcf    S_out        ; Send a 0 - Start bit

put_clp    movlw    0xE7        ; Delay "104" cycles
txd_0    addlw    0x01
    bne    txd_0

    rrf    S_Wtemp,f    ; Transmit a bit
    bcs    t_0

    bcf    S_out        ; Send a 0
    bra    tx_1

t_0    bsf    S_out        ; Send a 1

tx_1    decfsz    S_count,f    ; Done all bits?
    goto    put_clp

    movlw    0xE7        ; Delay for last data
txd_1    addlw    0x01
    bne    txd_1

    bsf    S_out        ; Transmit two stop bit

    movlw    0xCD
txd_9    addlw    0x01
    bne    txd_9
    
    return
 
;********************************************************************
;    Tail End Charlie
;********************************************************************    
; initialize eeprom locations

        ORG 0x2100

        DE  0x00, 0x00, 0x00, 0x00    ; Unused (reserved for later)
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 1 Low  BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 2 High BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 3 No   BFO -AM-
        DE  0xfa, 0xff, 0x5f, 0x00    ; 4.000 MHz initial calibration

END
04/11/2013 #77

Avatar de miguelus

Buenas noches.

Como comenta ricbevi, es muy difícil modificar un programa hecho por otra persona y más cuando la programación no es lo nuestro.

Estos días de fiesta he estado jugando algo con el Prográmita pero con la versión "simple" sin preescaler.

La razón es que tengo varios Frecuencímetros y el rango hasta los 2,4Ghz lo tengo cubierto.

Pero necesitaba uno para acoplarlo a un oscilador para comprobar Cristales de Cuarzo.

He estado jugando con la versión sin Prescaler, he quitado toda la parte del programa que gestiona la salida RS232 ya que no lo necesitaba.

He hecho una modificación que creo que es muy útil, la modificación gestiona la forma de visualizar la Frecuencia...

00.000000Mhz lo visualiza de otra manera...
00.000.000 - Mhz. Esto produce una visualización más amigable

Por medio de un Puente (luego será un interruptor) la visualización la hace de esta forma...

00.000 - Mhz ya que para muchas medidas es suficiente con tres decimales.

He anulado toda la parte que gestiona USB, LSB, CAL...

Ahora estoy tratando de quitar del programa todas estas Rutinas, pero tengo poco tiempo para estos menesteres

Este Frecuencímetro no es una gran cosa, pero suficiente para muchas aplicaciones en las que se necesita tener un medidor dedicado para medir una frecuencia.

Otra modificación futura será poner una base de tiempo de mejor calidad que un simple Cuarzo

Mis felicitaciones a ricbevi por el magnífico trabajo que ha relalizado en los Post anteriores

Sal U2
04/11/2013 #78


Hola de nuevo!

Ric, he probado tu nuevo código y es mucho más "amigable". Me gusta.
Ya tenía pensado recapitular un poco lo aparecido y modificado hasta ahora, pero antes quería encontrar una explicación al porqué no me aparece la frecuencia fundamental al intentar medir la frecuencia del módulo oscilador de 100,00 Mhz (aparecen 299,990xxx Mhz) que probablemente pueda corregirse con un condensador y alguna resistencia. También quería "redondear" las pruebas con una lectura entre 800 y 2.400 Mhz. antes de decidir los circuitos definitivos, pero bueno, ya veremos.

Miguelus, tu experimentación del fin de semana ha ido por el mismo camino que el de Ric, hacia una más cómoda lectura de la frecuencia. Estoy, también, deseando disponer de ese código
05/11/2013 #79


Hola una vez más,

he logrado solucionar la medición correcta del módulo oscilador de 100,00 Mhz; un día de estos subiré todos los esquemas.

Por cierto, pongo 100,00 Mhz. con dos decimales porque es lo que pone en el módulo, y yo entiendo que su precisión llega -por lo menos- hasta el cero del segundo decimal, por lo que -de ser así- la frecuencia a la que oscilará estará entre 99,995 y 100,005. Si alguien sabe que estoy equivocado, por favor, que me corrija.

De hecho, si calibro el frecuencímetro a la frecuencia exacta del manual del walkie que tengo, al medir la frecuencia del módulo oscilador obtengo 99,994368, que se encuentra justo en la frontera inferior que he indicado (un pelín por debajo, exactamente 632 hz menos, de ese límite inferior de 99,995 Mhz).

Me interesaba mucho solucionar la precisión de la medida del módulo oscilador porque quiero incluirlo en el montaje como referencia de medida para calibrar el frecuencímetro siempre que haga falta.

Una cosa más que se me ha olvidado comentar en el segundo post con vídeo que ya he subido.
El prescaler MB506 toma la señal del walkie sin antena ni cable de ningún tipo estando incluso a un metro de distancia del circuito del prescaler.

Un saludo
05/11/2013 #80


Otra vez por aquí,

iré explicando toda la evolución que estoy experimentando con el montaje que da título a este hilo, incluído el cambio de prescaler (MB506).

En los últimos post he insistido en utilizar la división /256. ¿Alguien se imagina la razón?

Todo el empeño en dividir por 256 provenía de la suposición (falsa) de que para alcanzar el tope de frecuencia (2,4 Ghz) del prescaler debería de utilizar la división máxima.

Bien, en la hoja de especificaciones (datasheet) del MB506 pone que el techo de frecuencia para dicho prescaler es de 2,4 Ghz ...... y eso lo absorbe y lo procesa; y además lo divide por 64, 128 ó 256.

Entonces resulta que 2,4 Ghz son 2.576.980.378 Hz y si lo divido por 256 obtengo 10.066.330 Hz. que es una frecuencia que el pic 16F84A puede procesar sin ningún problema ya que alcanza los 50 Mhz con garantías.
Si divido esos 2,4 Ghz por 128 obtengo 20.132.659 Hz.
Y si lo divido por 64 obtengo 40.265.318 Hz

El pic 16F84A puede procesar hasta los 50 Mhz y ... por lo visto algo más, pero de cualquier forma, suficiente para procesar esos 40.265.318 Hz que se obtienen al dividir los 2,4 Ghz por 64, por lo que no me hace falta dividir por 256, ya que -incluso con 2,4 Ghz de frecuencia de entrada- el 18F84 puede procesar la frecuencia resultante dividida por 64 y además así se obtiene una precisión cuatro veces mayor que si se dividiese por 256.

Por favor, si alguien cree que esta deducción no es correcta, que lo comente.

Si efectivamente es así, volveré al código de /64



Un saludo
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Buscar más temas sobre:
Lupa Circuitos de Radio

Transmisores, Receptores, Antenas...

Cerrar
Foros de Electrónica » Diseño analógico » Circuitos de Radio

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.