Menu

Comparator driver 16f87x with vref control

Santiago
2009-01-25
2013-05-30
  • Santiago

    Santiago - 2009-01-25

    As i adapted this driver to gcbasic, here are the code if useful for someone, there is an example of use following driver:

    '________________________________________________________________________________
    '
    '           COMPARATORS LIBRARY FOR PIC16F87X FAMILY AND COMPATIBLES
    '
    '                              (optimized asm)
    '
    '                     Original driver name: comp_87X.h
    '________________________________________________________________________________
    '
    '
    '    This library is free software; you can redistribute it and/or

    '    modify it under the terms of the GNU Lesser General Public

    '    License as published by the Free Software Foundation; either

    '    version 2.1 of the License, or (at your option) any later version.

    '    This library is distributed in the hope that it will be useful,

    '    but WITHOUT ANY WARRANTY; without even the implied warranty of

    '    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU

    '    Lesser General Public License for more details.

    '    You should have received a copy of the GNU Lesser General Public

    '    License along with this library; if not, write to the Free Software

    '    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    '
    '________________________________________________________________________________
    '
    '                      AVAILABLE FUNCTIONS (examples):
    '________________________________________________________________________________
    '
    '
    'IMPORTANT: ANY CHANGE ON COMPARATORS CONFIGURATION WILL DISABLE COMPARATORS INTERRUPT
    '           YOU WILL HAVE TO RE-ENABLE IT AFTER OPERATION.
    '
    '
    'Set comparator's mode to two comparators with internal Vref:
    '
    '       comp_conf TWO_COMP_VREF
    '
    '
    'Set multiplexed channels to RA0 RA1:
    '
    '       comp_mpl RA0_RA1
    '
    '
    'Set Vref to 60% of Vdd:
    '
    '       comp_vref  VREF_60
    '
    '
    'Invert comparator1 output:
    '
    '       comp_inv  C1_INV
    '
    '
    'read comparator1
    '
    '       value = comp1_read
    '
    '
    'read comparator2
    '
    '       value2 = comp2_read
    '
    '
    'Disable comparators
    '
    '       comp_off
    '
    '________________________________________________________________________________
    '
    '                     DEFINITIONS (available options)
    '________________________________________________________________________________
    '

    ' Configuración de comparadores

    #define COMP_RESET           0X00
    #define COMP1_OUT            0X01
    #define TWO_COMP             0X02
    #define TWO_COMP_OUT         0X03
    #define TWO_COMP_COMREF      0X04
    #define TWO_COMP_COMREF_OUT  0X05
    #define TWO_COMP_VREF        0x06
    #define COMP_OFF             0X07

    ' Multiplexor: usados bits 0-3

    #define RA0_RA1         0X00
    #define RA2_RA3         0X08

    ' Invertir salidas: usados bits 4-5 = CMCON.C1INV-C2INV

    #define NO_INV         0X00
    #define C1_INV         0X10
    #define C2_INV       0X20
    #define C1_C2_INV    0X30

    ' Definiciones Vref, voltajes aproximados para Vpp=5v

    #define VREF_0    0X20    'V = 0,000
    #define VREF_5    0X21    'V = 0,208
    #define VREF_6    0X21    'V = 0,208
    #define VREF_7    0X22    'V = 0,417
    #define VREF_8    0X22    'V = 0,417
    #define VREF_9    0X22    'V = 0,417
    #define VREF_10   0X22    'V = 0,417
    #define VREF_11   0X23    'V = 0,625
    #define VREF_12   0X23    'V = 0,625
    #define VREF_13   0X23    'V = 0,625
    #define VREF_14   0X23    'V = 0,625
    #define VREF_15   0X24    'V = 0,833
    #define VREF_16   0X24    'V = 0,833
    #define VREF_17   0X24    'V = 0,833
    #define VREF_18   0X24    'V = 0,833
    #define VREF_19   0X25    'V = 1,042
    #define VREF_20   0X25    'V = 1,042
    #define VREF_21   0X25    'V = 1,042
    #define VREF_22   0X25    'V = 1,042
    #define VREF_23   0X26    'V = 1,250
    #define VREF_24   0X26    'V = 1,250
    #define VREF_25   0X26    'V = 1,250
    #define VREF_26   0X26    'V = 1,250
    #define VREF_27   0X01    'V = 1,406
    #define VREF_28   0X01    'V = 1,406
    #define VREF_29   0X27    'V = 1,458
    #define VREF_30   0X27    'V = 1,458
    #define VREF_31   0X02    'V = 1,562
    #define VREF_32   0X02    'V = 1,562
    #define VREF_33   0X28    'V = 1,667
    #define VREF_34   0X03    'V = 1,719
    #define VREF_35   0X03    'V = 1,719
    #define VREF_36   0X04    'V = 1,875
    #define VREF_37   0X04    'V = 1,875
    #define VREF_38   0X04    'V = 1,875
    #define VREF_39   0X04    'V = 1,875
    #define VREF_40   0X05    'V = 2,031
    #define VREF_41   0X05    'V = 2,031
    #define VREF_42   0X2A    'V = 2,083
    #define VREF_43   0X06    'V = 2,188
    #define VREF_44   0X06    'V = 2,188
    #define VREF_45   0X2B    'V = 2,292
    #define VREF_46   0X2B    'V = 2,292
    #define VREF_47   0X07    'V = 2,344
    #define VREF_48   0X07    'V = 2,344
    #define VREF_49   0X08    'V = 2,500
    #define VREF_50   0X08    'V = 2,500
    #define VREF_51   0X08    'V = 2,500
    #define VREF_52   0X09    'V = 2,656
    #define VREF_53   0X09    'V = 2,656
    #define VREF_54   0X2D    'V = 2,708
    #define VREF_55   0X2D    'V = 2,708
    #define VREF_56   0X0A    'V = 2,812
    #define VREF_57   0X0A    'V = 2,812
    #define VREF_58   0X2E    'V = 2,917
    #define VREF_59   0X0B    'V = 2,969
    #define VREF_60   0X0B    'V = 2,969
    #define VREF_61   0X0C    'V = 3,125
    #define VREF_62   0X0C    'V = 3,125
    #define VREF_63   0X0C    'V = 3,125
    #define VREF_64   0X0C    'V = 3,125
    #define VREF_65   0X0D    'V = 3,281
    #define VREF_66   0X0D    'V = 3,281
    #define VREF_67   0X0D    'V = 3,281
    #define VREF_68   0X0E    'V = 3,438
    #define VREF_69   0X0E    'V = 3,438
    #define VREF_70   0X0E    'V = 3,438
    #define VREF_71   0X0F    'V = 3,594
    #define VREF_72   0X0F    'V = 3,594
    #define VREF_73   0X0F    'V = 3,594
    #define VREF_74   0X0F    'V = 3,594
    #define VREF_75   0X0F    'V = 3,594

    #define comp1_read CMCON.C1OUT
    #define comp2_read CMCON.C2OUT

    '________________________________________________________________________________
    '
    '                               FUNCTIONS
    '________________________________________________________________________________

    sub comp_conf(set_config) #NR

       

        BCF PIE2,CMIE             ; Desactiva interrupciones comparadores

        BCF PIR1,CMIF             ; Borra flag interrupciones comparadores
        MOVF set_config,W       
        MOVWF   CMCON             ; Establece modo de operación

    end sub

    sub comp_mpl(set_switch) #NR

        BCF PIE2,CMIE             ; Desactiva interrupciones comparadores

        BCF PIR1,CMIF             ; Borra flag interrupciones comparadores

        MOVF set_switch,W
        BCF CMCON,CIS             ; Borra anteriores selecciones
        IORWF CMCON,F             ; Establece canales multiplexados
       
    end sub

    sub comp_vref(set_cvr) #NR
       
        MOVF set_cvr,W       
        MOVWF   CVRCON            ; Establece valor de Vref
        BSF   CVRCON,7            ; Habilita módulo Vref

    end sub

    sub comp_inv(set_inv) #NR

        BCF PIE2,CMIE           ; Desactiva interrupciones comparadores

        BCF PIR1,CMIF           ; Borra flag interrupciones comparadores

        MOVF set_inv,W
        BCF   CMCON,4           ; Borra anteriores selecciones
        BCF   CMCON,5

        IORWF CMCON,F           ; Establece canales invertidos

    end sub

    sub comp_off

        BCF PIE2,CMIE             ; Desactiva interrupciones comparadores   

        BCF PIR1,CMIF             ; Borra flag interrupciones comparadores   
        MOVLW    0x07   
        MOVWF   CMCON             ; Establece modo off = 111
        MOVLW    0x00   
        MOVWF  CVRCON             ; Deshabilita modulo Vref

    end sub

    '*******************************************************************************
    ' END OF DRIVER
    '*******************************************************************************

    'EXAMPLE:

    '________________________________________________________________________________
    '
    '               Example to be used with adc-87X.h driver
    '
    '
    ' A led attached to PORTB.7 will light when Volt. level at PORTA.0 < 60% Vdd
    '
    '________________________________________________________________________________
    '

    'General hardware configuration

    #chip 16F876A, 20

    #config HS_OSC, WDT_OFF, LVP_OFF, PWRTE_ON

    #include <comp-87X.h>  

    'driver must be in "iclude" dir or provide full path

    #define LED1   PORTB.7

    '________________________________________________________________________________

    DIR A0 IN

    DIR B7 OUT

    comp_conf TWO_COMP_VREF

    comp_mpl RA0_RA1

    comp_vref  VREF_60

    do while true

        LED1 = comp1_read

    loop

    '________________________________________________________________________________

     
    • Nobody/Anonymous

      I think this driver is useful with many other pics, just tested with 16f87X/87Xa and 16f62X/62Xa.

      To use with other than 87X/87Xa  just config this way:

        comp_conf 0x02

      or:

        comp_conf b'010'

      or:

      comp_conf 2

       
  • Nobody/Anonymous

    I found a simpler and more direct way to set up the comparator in GCBasic.  Though the library is comprehensive, it seems daunting for basic comparator use.  The datasheet notes only 2 registers are used to set up polled usage, and reading the datasheet for your particular chip is the best way to be sure each bit is chosen properly.  I like to set the registers in binary so it matches closely with the datasheet decriptions.  My test code:

    #chip 16F627, 4

    CMCON = b'00011010' ' Comparator 1 input RA3, internal reference, C1 inverted
    VRCON = b'10101100' ' Reference voltage to 2.5V (3:0 / 24 * VDD, here 12/24*5 = 2.5V)

    #define ANALOGIN CMCON.C1OUT ' Comparator C1 output bit
    #define LED PORTB.1                  ' test LED

    dir LED out

    Main:
        IF ANALOGIN = 0 THEN
    LED = 1
        ELSE
    LED = 0
        END IF
    Goto Main              

    It's that simple.  Long live the Great Cow
    -Norbert

     
  • Santiago

    Santiago - 2010-02-08

    Hi nobody. Thanks for the feedback.

    Norbert, you are right, it's simple when you know how comp registers works, but you have to calculate Vref, and is not that easy as you said when you want max resolution, the correct calculations are these:

    bit 5
          CVRR: Comparator VREF Range Selection bit

          1 = 0 to 0.75 CVRSRC, with CVRSRC/24 step size
          0 = 0.25 CVRSRC to 0.75 CVRSRC, with CVRSRC/32 step size

    bit 3-0
            CVR3:CVR0: Comparator VREF Value Selection bits 0 ≤ VR3:VR0 ≤ 15

            When CVRR = 1:
            CVREF = (VR<3:0>/ 24) • (CVRSRC)

            When CVRR = 0:
            CVREF = 1/4 • (CVRSRC) + (VR3:VR0/ 32) • (CVRSRC)

    And when you want to deal with multiplexed and/or inverted channels, it takes some time to determine wich bits you have to set or clear.

    Then that's why a driver: you don't have to deal with all those stuffs.

    Regards

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.