PortB Change Interrupts


Closed Thread
Results 1 to 18 of 18
  1. #1

    Default PortB Change Interrupts

    I have setup my code to get an interrupt when PortB's Pin 1 or Pin 0 gets triggered. I am using DT's Instant Interrupt and I have created and enabled interrupt processor for RBC_INT. The interrupt routine is called when either one of the pin is triggered (contact closure), however I can't tell exactly which pin was triggered. I am doing something like this:

    TRIGGER0 VAR BIT
    TRIGGER1 VAR BIT

    TRIGGER0 = portb.0
    TRIGGER1 = portb.1

    However, both would read 1. Any idea what I am doing wrong?

    Any help would be greatly appreciated.

    P.S. I am a picBasic novice. Please go easy on me.

  2. #2
    Join Date
    Sep 2007
    Posts
    50


    Did you find this post helpful? Yes | No

    Default

    What pic are you using?
    Best Regards,

    Kurt A. Kroh
    KrohTech

    “Goodbye and thanks for all the fish”

  3. #3
    Join Date
    Sep 2007
    Posts
    50


    Did you find this post helpful? Yes | No

    Default

    If I am reading the data sheet correctly, the "input change Interrupts" will fire when anything on the port changes. I do not believe the individual pins can be monitored this way. If you need individual pins you may need to use an "external interrupt" and INT_INT.

    Darrel please correct me if I am wrong
    Best Regards,

    Kurt A. Kroh
    KrohTech

    “Goodbye and thanks for all the fish”

  4. #4


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by krohtech View Post
    What pic are you using?
    I am using 18F66J15

  5. #5
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    RBC_INT only triggers on chages with PORTB<7:4>

    For PORTB.0, you would use INT0_INT
    PORTB.1 is INT1_INT

    Each one should have it's own handler, so it automatically knows which pin triggered.
    <br>
    DT

  6. #6


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Darrel Taylor View Post
    RBC_INT only triggers on chages with PORTB<7:4>

    For PORTB.0, you would use INT0_INT
    PORTB.1 is INT1_INT

    Each one should have it's own handler, so it automatically knows which pin triggered.
    <br>
    Actually, I meant to read from pin 4 and 5. That solves half of the problem.

    I have corrected that in my code, still same problem.

  7. #7
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Keep in mind that any changes on PORTB.6 or 7 will also trigger an interrupt. It's best to Not Use 6 and 7 for anything else.
    Code:
    Old_Bits VAR BYTE
    New_Bits VAR BYTE
    
    INCLUDE "DT_INTS-18.bas"        ' Base Interrupt System
    INCLUDE "ReEnterPBP-18.bas"     ' Include if using PBP interrupts
    
    ASM
    INT_LIST  macro    ; IntSource,         Label,  Type, ResetFlag?
            INT_Handler    RBC_INT,  _RBC_handler,   PBP,  yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
    
    Old_Bits = PORTB
    @    INT_ENABLE   RBC_INT     ;RB Port Change Interrupt
    
    Main:
      Pause 1000
    GOTO Main
    
    '---[RBC - interrupt handler]---------------------------------------------------
    RBC_handler:
        New_Bits = PORTB
        IF (New_Bits.4 <> Old_Bits.4) THEN
            ; -- PORTB.4 has changed -- 
        ENDIF
        IF (New_Bits.5 <> Old_Bits.5) THEN
            ; -- PORTB.5 has changed -- 
        ENDIF
        Old_Bits = New_Bits
    @ INT_RETURN
    DT

  8. #8
    Join Date
    Mar 2009
    Location
    Colorado
    Posts
    378


    Did you find this post helpful? Yes | No

    Default Re: PortB Change Interrupts

    Quote Originally Posted by Darrel Taylor View Post
    RBC_INT only triggers on chages with PORTB<7:4>
    <br>
    Darrel, I know this statement was related to a posting for a 18F66J15, but I am trying to use RBC_INT for PortB.2 and PortB.3 on a 16F886. I had a design going on a 18F2550 that used INT2_INT on PortB2 and worked well. However, for reasons I won't go into here I had to move the design to a 16F886 and continue to use PortB.2 and PortB.3 as interrupt inputs from the alarm pins on a DS1337 RTC. I already have PCBs built originally for the 28-pin 18F2550 and am trying to salvage them without trace changes by substituting a 28-pin 16F886 on the same board layout. My question...is there anyway I can use RBC_INT on the PortB.2 and PortB.3 pins of a 16F886 and monitor which pin actually received the interrupt? I have noted your OLDPORT vs NEWPORT technique to do this kind of interrupt isolation and presume I can do this on my 16F886 if RBC_INT will work ont these ports? Can you help me out here?

  9. #9
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default Re: PortB Change Interrupts

    John,

    On the 16F88x's use IOC_INT (Interrupt On Change).

    Set the pins you want to monitor in the IOCB register.
    DT

  10. #10
    Join Date
    Mar 2009
    Location
    Colorado
    Posts
    378


    Did you find this post helpful? Yes | No

    Default Re: PortB Change Interrupts

    Quote Originally Posted by Darrel Taylor View Post
    John,

    On the 16F88x's use IOC_INT (Interrupt On Change).

    Set the pins you want to monitor in the IOCB register.
    OK, Darrel...I got rid of the On Change interrupt related statements in my code and set up for the IOC_INT per following.
    Code:
    ;--- Setup Interrupts ----------------------------------------------------
    ASM
    INT_LIST  macro      ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler      IOC_INT,       _Alarm,   PBP,  yes
    ;       INT_Handler      LVD_INT,     _VoltLow,   PBP,  yes
            endm
            INT_CREATE               ; Creates the interrupt processor
    ENDASM
    @    INT_ENABLE   IOC_INT      ; enable IOC interrupts
    
    ' Per DT, DT_INTS already takes care of setting registers
    ' but this code doesn't work unles below registers set as indicated:
        IOCB.2= 1           ' ENABLE IOC INERRUPT ON PORTB.2 (RB2) for Alarm1
        TRISB = %00011100   ' RB2 & RB3 set as RTC Alarm1 & Alarm2 inputs
                            ' PORTB.2 is also an interrupt from manual switch GND
                            ' PORTB.4 is set for input as A/D Channel 11
        WPUB = 0            ' DISABLE all PortB pull-ups
        CM1CON0 = 0         ' DISABLE COMPARATORS
        CM2CON0 = 0         ' DISABLE COMPARATORS
    However I get the following assembler errors which made me go into the .lst file to see where the problem was but I can't locate what is causing these errors. Can you tell me?
    Warning[205] C:\PBP26\ELLIS_CODES\RTC\16F886\0SETDS1337CLOCK.AS M 364 : Found directive in column 1. (endm)
    Warning[207] C:\PBP26\ELLIS_CODES\RTC\16F886\0SETDS1337CLOCK.AS M 551 : Found label after column 1. (INT_ENABLE)
    Error[122] C:\PBP26\ELLIS_CODES\RTC\16F886\0SETDS1337CLOCK.AS M 551 : Illegal opcode (IOC_INT)

  11. #11
    Join Date
    Mar 2009
    Location
    Colorado
    Posts
    378


    Did you find this post helpful? Yes | No

    Default Re: PortB Change Interrupts

    Discovered I had forgotten to uncomment the follwoing statements required for using DT_INTS.

    INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
    INCLUDE "ReEnterPBP.bas" ' Include if using PBP high priority interrupts

    However, after fixing that however, I still have the following assembly errors I can't figure out:
    Error[101] C:\PBP26\ELLIS_CODES\RTC\16F886\0SETDS1337CLOCK.AS M 790 : ERROR: ("INT_Handler" - Interrupt Flag ( INTCON,IOCIF ) not found.)
    Error[101] C:\PBP26\ELLIS_CODES\RTC\16F886\0SETDS1337CLOCK.AS M 790 : ERROR: ("INT_ENABLE" - Interrupt Flag ( INTCON,IOCIF ) not found.)

  12. #12
    Join Date
    Mar 2009
    Location
    Colorado
    Posts
    378


    Did you find this post helpful? Yes | No

    Default Re: PortB Change Interrupts

    Looked in .lst file for the above errors and found both.

    This one is strange because it indicates INTERRUPT_handler was not labeled with PBP...it was. Can you tell me from this why the error?
    Code:
                      M         if (PBP  == PBP)                     ; If INT handler is PBP
                              M           ifdef ReEnterUsed
                              M             btfsc  _Vars_Saved
                              M             goto   AfterSave
                              M             GetAddress  AfterSave, _RetAddr  
                              M             L?GOTO  _SavePBP                 ; Save PBP system Vars
                              M             LABEL?L  AfterSave
                              M           else
                              M             error ReEnterPBP must be INCLUDEd to use PBP type interrupts
                              M           endif
                              M         endif
                              M         GetAddress  AfterUserRoutine, _RetAddr   ; save return address
                              M         L?GOTO   _Alarm                      ; goto the users INT handler
                              M         LABEL?L AfterUserRoutine
                              M 
                              M         if (yes   == YES)
                              M           CHK?RP   INTCON
                              M           bcf      INTCON,  IOCIF          ; reset flag (if specified)
                              M         endif
                              M       else
                              M         INT_ERROR  "INT_Handler"
    Error[101]  : ERROR: ("INT_Handler" -  Interrupt Flag ( INTCON,IOCIF ) not found.)
                              M     error "INT_Handler" -  Interrupt Flag ( INTCON,IOCIF ) not found.
                              M       endif
    For this error I can't see why the FlagBit wasn't set. Can you explain this error to me?
    Code:
                          00989     INT_ENABLE   IOC_INT      ; enable IOC interrupts
                              M       ifdef FlagBit
                              M         ifdef INT_ENABLECLEARFIRST
                              M           if (INT_ENABLECLEARFIRST == 1)       ; if specified
                              M             MOVE?CT 0, INTCON,  IOCIF          ;   clear the flag first
                              M           endif
                              M         endif
                              M         MOVE?CT  1, INTCON,    IOCIE           ; enable the INT source
                              M       else
                              M         INT_ERROR  "INT_ENABLE"
    Error[101]  : ERROR: ("INT_ENABLE" -  Interrupt Flag ( INTCON,IOCIF ) not found.)
                              M     error "INT_ENABLE" -  Interrupt Flag ( INTCON,IOCIF ) not found.
                              M       endif

  13. #13
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default Re: PortB Change Interrupts

    Sorry, it is RBC_INT on that chip. But you still use the IOCB register like other chips with IOC_INT.

    Microchip does things different everytime.
    DT

  14. #14
    Join Date
    Mar 2009
    Location
    Colorado
    Posts
    378


    Did you find this post helpful? Yes | No

    Default Re: PortB Change Interrupts

    OK, Darrel... that gets the code to compileasseble, but it runs for 30 seconds with the green heart-beat LED blinking during mainloop and then it apparently receives a RBC_INT because the the red LED blinks 3 times as required in the start of the handler (Alarm). However every two seconds the red LED blinks 3 times again indicating it is continuously receiving RBC_INT interrupts. I know it is never getting back into the mainloop because it never does any of the things in the main loop after the red LED starts blinking. Can you look at my code below and tell me why this is happening?
    [CODE]
    'STATUS: Compiles & assembles OK with CPU @ 8 MHz.
    ' Sets date/time/Alarm1 OK.
    ' Displays initialized date/time continuously (if LCD installed).
    ' On change interrupts from clock _INTA OK but continues forever.
    '< FL_PIC16F886 >' ' First valid PIC found within the first 200 lines will
    ' highlight AND set device.
    ' -----------------------[ Program Description ]--------------------------
    ' PICBASIC PRO program to set RTC & demo operation of a LCD/4-bit mode *
    ' 1) Initializes 2x16 or 2x8 LCD display with EasyPic6. *
    ' 2) Initializes DS1337 Real-time-clock & sets time/date/Alarm1. *
    ' (user must adjust code in SetTimeDate subroutine for desired *
    ' startup time/date/Alarm1 settings) *
    ' 3) This code sets Alarm1 to go off every minute..adjust as needed. *
    ' 4) Alarm1 is used as RBC_INT interrupt by MCU. *
    ' 5) Also displays date/time on LCD every second if LCD installed. *
    ' *
    '************************************************* ************************
    ' -----------------------[ Revision History ]-----------------------------
    ' ------------[ NOTES for use with EasyPic6 development board ]-----------
    ' Make sure that SW6.8 on the EasyPic6 is set to ON position before
    ' powerup for LCD's requiring backlight.
    'For use with 2x16 LCD:
    ' - Turn on Port Expander switches SW6.1, SW6.2, SW6.3, SW6.4 & SW6.5.
    ' - Turn on COG LCD 2x16 switches SW10.1, SW10.2, SW10.3, SW10.4,
    ' SW10.5 & SW10.6.
    'For interface to DS1337 RTC:
    ' - To provide battery backup, place two Shottky diode in or configuration
    ' between the Vdd (pin-8) of the DS1337 and the Vcc source and the
    ' + terminal of the backup battery.
    ' - I2C communication lines should be connected to 4.7K pull-ups.
    ' - INTA & INTB lines should be connected to pull-up resistsors.
    ' - Turn off LEDs connected to I2C communication lines.
    '-----------------[ 16F886 Port/PIN Connections ]------------------
    'I/O pin connections to the 16F886 MCU are as follows:
    'PORTA.0 (02) output to LCD D4 & also multiplexed as input from LM34.
    'PORTA.1 (03) output to LCD D5.
    'PORTA.2 (04) output to LCD D6 & also mulitplexed as Vref+ input.
    'PORTA.3 (05) output to LCD D7.
    'PORTA.4 (06) output to LCD RS.
    'PORTA.5 (07) ouput to LCD E.
    'PORTB.0 (21) output as I2C SDA to DS1337.
    'PORTB.1 (22) output as I2C SCL to DS1337.
    'PORTB.2 (23) input as interrupt on change from pin-3 (_INTA) of DS1337 RTC.
    ' Also senses pushbutton for manual interrupt for RangeFinder.
    'PORTB.3 (24) input from SQW/_INTB pin-7 of DS1337 RTC.
    'PORTB.4 (25) set as A/D Channel 11 for analog input from LM34 output
    'PORTB.5 (26) unconnected
    'PORTB.6 (27) connected as PGC for ICSP connection.
    'PORTB.7 (28) connected as PGD for ICSP connection.
    'PORTC.0 (11) output RC0 to control external power to SRF02 & LM34.
    'PORTC.1 (12) output RC1 to MSEL on WiFi Module
    'PORTC.2 (13) output RC2 to LCD R/W or to _RES_PD on WiFi module
    'PORTC.3 (14) reserved to connect as Vbus to 470 pf capacitor for USB
    'PORTC.4 (15) output RC4 to a Red LED for low voltage warning.
    'PORTC.5 (16) output RC5 to Green LED for routine entry indicator.
    'PORTC.6 (17) output as TX to WiFi module RXD.
    'PORTC.7 (18) output as RX to WiFi module TXD.
    '--------------[ Define EEPROM usage ]-----------------------------------
    '09 = day_cnt ' Most recent day_cnt
    '10 = J ' Index for counting interrupts received
    '11 = hr ' Hour time from RTC after setting RTC
    '12 = MINs ' Minutes time from RTC after setting RTC
    '13 = sec ' Seconds time from RTC after setting RTC
    '14 = A1hr ' Alarm1 hour time from RTC after setting RTC
    '15 = A1MINs ' Alarm1 minutes time from RTC after setting RTC
    '16+J = hr ' Log Hour
    '17+J = MINs ' Log Minutes
    '18+J + sec ' Log Seconds
    '240 = ID(0) ' LSB of device ID
    '241 = ID(1) ' MSB of device ID
    '242 = mon ' Month when clock was set
    '243 = date ' Date when clock was set
    '244 = yr ' Year when clock was set
    'INCLUDE "CodeSize.pbp" 'FOR TEST ONLY
    DEFINE Measure 1
    ;@ StartSize(LOOKUP) 'FOR TEST ONLY
    Pause 10 ' This statement is placed at beginning of code for ICD use
    'Disable Debug
    ' Set configuration fuses for the MCU
    ' To use standard config include file, comment out below statement
    @ __config _CONFIG1, _HS_OSC & _WDT_OFF & _MCLRE_OFF & _LVP_OFF & _CP_OFF
    '--------------[ Define Hardware / Set Registers ]------------------------
    DEFINE OSC 8 ' MCU uses external 8 MHz crystal
    DEFINE I2C_SLOW 1 ' Set i2c to the standard speed
    DEFINE I2C_HOLD 1 ' Enable recieving i2c device to pause communication
    Include "Modedefs.Bas" ' Mode definitions for Debug,Serin/out,
    ' Shiftin/out, Xin/out.
    INCLUDE "ALLDIGITAL.pbp" ' Sets all registers for digital ops.
    ' User must make sure AllDigital.pbp file
    ' is in same or higher directory location as
    ' this source code before compiling.
    'DEFINE SHOWDIGITAL 1 ' When uncommented will show analog settings
    ' in Assembler Results window.
    INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
    INCLUDE "ReEnterPBP.bas" ' Include if using PBP high priority interrupts
    ' Allows re-entry to PBP from a High Priority
    ' ASM interrupt. Must have DT_INTS-14.bas
    ' loaded first.
    TRISA = 0 ' Set all PortA initally to outputs for LCD use
    TRISC = %10000000 ' Set PortC to all outputs except PortC.7 which is
    ' reserved as RX input.
    ' PortC.1 is output for MSEL to WiFi module
    ' PortC.2 is used for the LCD R/W connection when
    ' LCD present..otherwise as _RES_PD to Wifi Module.
    ' PortC.4 is output to LED_RED
    '--- Setup Interrupts ----------------------------------------------------
    ASM
    INT_LIST macro ; IntSource, Label, Type, ResetFlag?
    INT_Handler RBC_INT, _Alarm, PBP, yes
    ; INT_Handler HLVD_INT, _VoltLow, PBP, yes
    endm
    INT_CREATE ; Creates the interrupt processor
    ENDASM
    ' Per DT, DT_INTS already takes care of setting INTCON register
    ' but this code doesn't work unles below registers also set as indicated:
    IOCB.2= 1 ' ENABLE IOC INERRUPT ON PORTB.2 (RB2) for Alarm1
    TRISB = %00010100 ' RB2 set as input from RTC Alarm1
    ' PORTB.2 is also an interrupt from manual switch GND
    ' PORTB.4 is set for input as A/D Channel 11
    WPUB = 0 ' DISABLE all PortB pull-ups
    CM1CON0 = 0 ' DISABLE COMPARATORS
    CM2CON0 = 0 ' DISABLE COMPARATORS
    '--- Variables & Aliases -------------------------------------------------
    CNT VAR BYTE ' Counter for timing
    CNT = 0
    day_cnt VAR BYTE
    D_LAY VAR BYTE ' Stores delay value
    dummy VAR BYTE ' dummy variable for resetting PortB mismatch
    ADR VAR BYTE[9] ' Array stores IP address
    deviceID1 VAR BYTE ' Serial # of MCU (MSB)
    deviceID2 VAR BYTE ' Serial # of MCU (LSB)
    ext_pwr VAR PortC.0 ' MCU Controlled external power to SRF02 & LM34
    I VAR Byte ' Index for loop counters
    ID VAR BYTE[8] ' Array for storing device ID parameters
    J VAR BYTE ' Index to EEPROM address for logging
    LCD_Flag VAR Bit ' Flag when set indicates LCD is installed/used
    LED_RED VAR PortC.4 ' Red LED
    LED_GRN VAR PortC.5 ' Green LED used to indicate Routine entries
    logflag VAR BYTE ' Flag used in ISR to indicate to log time stamp
    LowVolt VAR BIT ' Flag that is set when MCU power source is low volt
    MSEL VAR PORTC.1 ' iChip Mode Select
    _RES_PD VAR PORTC.2 ' iCHIP RESET/Power-Down
    OK VAR BYTE ' Captures K in I/OK FTP return messages for testing
    SCL VAR PORTB.1 ' I2C clock pin
    SDA VAR PORTB.0 ' I2C data pin
    Spare_1 VAR PORTB.7 ' PGD for ICSP & Spare I/O for normal ops
    Spare_2 VAR PORTB.6 ' PGC for ICSP & Spare I/O for normal op
    temp VAR WORD ' Stores measured temperature
    TX VAR PORTC.6 ' Serial interface to iWiFI module
    RX VAR PORTC.7
    VDD VAR WORD ' Used in low voltage detection algorithm
    wsave VAR BYTE $70 SYSTEM ' Required per DT post 108282

    CLEAR ' Clear all RAM (sets all VAR declarations to zero)

    '--- Initialize ----------------------------------------------------------
    ' User must set FLAGS for current configuration
    'LowVolt = 0 ' Initalize low voltage Flag
    LCD_Flag = 0 ' Clear if LCD un-installed; set otherwise

    '--- Read MCU Serial Number is stored in 4 ea device ID Locations
    ' at memory locations Addresses $2000 to $2003 but can't be read at run time
    deviceID1 = ID(0) ' MSB of MCU Device Serial Number
    deviceID2 = ID(1) ' LSB of MCU Device Serial Number
    WRITE 240, ID(0) ' Write fixed values to EEPROM for test
    WRITE 241, ID(1)

    '--- Initialize epoch indexes at time of powerup/reset
    day_cnt = 0
    WRITE 6, day_cnt ' Store new epoch initialized day_count

    '*******************SETUP FOR USING DS1337 Real Time Clock**************
    ' Setup Hardware for uart
    DEFINE HSER_BAUD 115200
    DEFINE HSER_RCSTA 90h
    DEFINE HSER_TXSTA 24h
    DEFINE HSER_CLROERR 1
    ' Aliased Variables for CLock
    Alarm1 VAR PORTB.2 ' Alarm1 input from DS1337 INTA (pin-3)
    'Alarm2 VAR PORTB.3 ' Alarm2 input from DS1337 INTB (pin-7)
    'SCL VAR PORTB.1 ' I2C clock pin
    'SDA VAR PORTB.0 ' I2C data pin
    RTCdevice CON $D0 ' Device write address = %11010000 for RTC
    ' This is a list of allowable clock contrl settings, one which
    ' must be setup in the SetTimeAndDate subroutine for intended use.
    '(see data sheet pgs 9-10 for explanation)
    'contrl CON %00000000 ' Starts oscillar, sets the SQW/OUT to
    ' 1Hz pulse, no Alarm interrupts enabled.
    ' WORKS as intended!!
    'contrl CON %00000001 ' Starts oscillator, sets the SQW/OUT to
    ' 1 HZ pulse, & enables INTA interrupt from
    ' A1F. WORKS as intended!!
    'contrl CON %00000010 ' Starts oscillator, sets the SQW/OUT to
    ' 1 HZ pulse, enables INTA interrupt from
    ' A2F. WORKS AS intended!!
    'contrl CON %00000011 ' Starts the oscillator, sets the SQW/OUT
    ' to 1 Hz, enables INTA interrupt from A1F
    ' or from A2F. WORKS as intended!!
    'contrl CON %000xx100 ' Starts oscillator, no interrupts enabled.
    ' WORKS as intended!
    'contrl CON %000xx101 ' Starts oscillator, enables INTA interrupt
    ' from A1F, INTB/SQW off. WORKS OK!
    'contrl CON %000xx110 ' Starts oscillator, enables INTB interrupt
    ' from A2F. WORKS OK!
    'contrl CON %000xx111 ' Starts oscillator, enables INTA interrupt
    ' from A1F or INTB from A2F. WORKS OK!
    ' Both interrupts staggered 30 secs apart.
    'contrl CON %00011111 ' Starts oscillator, sets RS1 & RS2,
    ' enables INTA interrupt from A1F
    ' or A2F starts 32.768khz on SQW output.
    ' WORKS OK!
    'contrl CON %00011001 ' Starts oscillator, sets RS1 & RS2,
    ' clears INTCN to enable INTA interrupt
    ' from A1F with 32.768kHz on SQW output.
    ' SQW output WORKS OK but INTA doesn't!
    'contrl CON %00011010 ' Starts oscillator, sets RS1 & RS2,
    ' clears INTCN to enable INTA interrupt
    ' from A2F with 32.768kHz on SQW. WORKS OK!
    ' RTC Address definitions
    SecReg CON $00 ' seconds address (00 - 59)
    ' Must set MSB of SecReg to a 0 to enable RTC
    MinReg CON $01 ' minutes address (00 - 59)
    HrReg CON $02 ' hours address (01 - 12) or (00 - 23)
    DayReg CON $03 ' day address (1 - 7)
    DateReg CON $04 ' date address (01 - 28/29, 30, 31)
    MonReg CON $05 ' month address (01 - 12)
    YearReg CON $06 ' year address (00 - 99)
    ' Alarm 1 Address definitions
    Alm1sec CON $07 ' Alarm 1 seconds address (00 - 59)
    Alm1min CON $08 ' Alarm 1 minutes address (00 - 59)
    Alm1hr CON $09 ' Alarm 1 hours address (01 - 12) or (00 - 23)
    Alm1Day CON $0A ' Alarm 1 day address (1 - 7)
    ' Alarm 2 Address definitions..not used in this application
    'Alm2min CON $0B ' Alarm 2 minutes address (00 - 59)
    'Alm2hr CON $0C ' Alarm 2 hours address (01 - 12) or (00 - 23)
    'Alm2Day CON $0D ' Alarm 2 day address (1 - 7)
    ' Alias of Clock register addresses
    ContReg CON $0E ' CONTROL register address
    StatusReg CON $0F ' STATUS register address
    ' Clock Variables
    sec VAR BYTE ' seconds
    MINs VAR BYTE ' minutes
    hr VAR BYTE ' hours
    day VAR BYTE ' day of week (Sunday = 7)
    date VAR BYTE ' date in month
    mon VAR BYTE ' month
    yr VAR BYTE ' year
    ' ALARM1 VARIABLES
    A1sec VAR BYTE ' seconds
    A1MINs VAR BYTE ' minutes
    A1hr VAR BYTE ' hours
    A1day VAR BYTE ' day
    ' ALARM2 VARIABLES..not used in this application
    'A2MINs VAR BYTE ' minutes
    'A2hr VAR BYTE ' hours
    'A2day VAR BYTE ' day

    GOTO JumpPoint ' Jump over all subroutines so they don't execute on powerup

    ' ----------------------[ START SUBROUTINES ]--------------------------
    InitializeDisplay: ' Subroutine to initialize 2X16 or 2x8 LCD display
    '=================
    '--SETUP FOR USING 2x16 or 2x8 LCD INSTALLED on PROTOBOARD IN EASYPIC6--
    ' LCD DEFINES FOR USING 2x16 LCD with PortA in EASYPIC6
    DEFINE LCD_DREG PORTA ' Use PORTA for LCD Data
    DEFINE LCD_DBIT 0 ' Use lower(4) 4 bits of PORTA
    ' PORTA.0 thru PORTA.3 connect to
    ' LCD DB4 thru LCD DB-7 respectively
    DEFINE LCD_RSREG PORTA ' PORTA for RegisterSelect (RS) bit
    DEFINE LCD_RSBIT 4 ' PORTA.4 pin for LCD's RS line
    DEFINE LCD_RWREG PORTC ' LCD read/write port
    DEFINE LCD_RWBIT 2 ' LCD read/write bit
    DEFINE LCD_EREG PORTA ' PORTA for Enable (E) bit
    DEFINE LCD_EBIT 5 ' PORTA.5 pin for LCD's E line
    DEFINE LCD_BITS 4 ' Using 4-bit bus
    DEFINE LCD_LINES 2 ' Using 2 line Display
    DEFINE LCD_COMMANDUS 1500' Command Delay (uS)
    DEFINE LCD_DATAUS 44 ' Data Delay (uS)
    ' DEFINE LCD Control Constants
    Line1 CON 128 ' Point to beginning of line 1 ($80)
    Line2 CON 192 ' Point to beginning of line 2 ($C0)
    ' Test the LCD during initialization
    'IF LCD_Flag = 1 THEN ' Uncomment FOR TESTING ONLY
    'LCDOUT $fe,1:FLAGS=0:PAUSE 250 ' Clear Display
    'LCDOUT $fe,Line1,"LCD TEST" ' Display on 1st line
    'LCDOUT $fe,Line2,"POWER ON" ' Display on 2nd line
    'PAUSE 2000
    'ENDIF
    Return
    SetTimeAndDate: ' Subroutine to set current time, date and alarms
    '==============
    ' Blink LED_GRN 2X times to indicate entered SetTimeAndDate
    FOR I = 0 TO 1
    TOGGLE LED_GRN
    Pause 500
    Toggle LED_GRN
    PAUSE 500
    Next
    ' Initialize the display & clock
    Pause 100 ' Wait for LCD to startup after power on
    ' Initialize clock variables to 0
    yr=0:date =0:mon =0:day=0:hr=0:MINs=0:sec=0
    A1sec=0:A1MINs=0:A1hr=0:A1Day=0
    'A2MINs=0:A2hr=0:A2day=0
    ' The BCD constants below set the RTC to: 15:50:00 on 10-05-2011
    hr=$15
    MINs=$50
    sec=$00
    day=$03
    mon=$10
    date=$05
    yr=$11
    ' Per MAXIM TechSupport, proper sequencing requires setting
    ' INTCN = 1, & A2IE=A1IE=0 before setting alarms.
    I2CWRITE SDA, SCL, RTCdevice, ContReg,[%00000100]
    PAUSE 10
    'Define ALARM1 FOR 15:51:30 & to alarm 1/min
    ' For 1/min requires A1M1=0 and A1M2=A1M3=A1M4=1
    ' For 1/hr requires A1M1=A1M2=0 and A1M3=A1M4=1
    ' (A1xxx + $80 or A1xxx + 128d sets bit 7 as A1Mx = 1)
    A1hr = %10010101 '$15 + $80 = %10010101, for A1M3 = 1
    'Bit6 must be 0 for 24 hour clock
    A1MINs = %11010001 '$51 = %11010001, for A1M2 = 1
    A1sec = %00110000 '$30 = %00110000, for A1M1 = 0
    A1day = %10000111 '$07 + $80 = $10000111, for A1M4 = 1
    'DY/_DT Bit6 = 0 for using Day of month alarm
    'Define ALARM2 FOR 12:01:00 & to alarm once per minute (00 secs)
    'Disabled in this application
    ' This requires A2M2 = A2M3 = A2M4 = 1
    ' (A2xxx + $80 or A2xxx + 128d sets bit 7 as A2Mx = 1)
    'A2hr = $12 + $80 '$12 + $80 = %10010010, for A2M3 = 1
    'Bit6 must be 0 for 24 hour clock
    'A2MINs = $01 + $80 '$01 + $80 = %10000001, for A2M2 = 1
    'A2day = $07 + $80 '$07 + $80 = $10000111, for A2M4 = 1
    'DY/_DT Bit6 = 0 for using Day of month alarm
    ' Per MAXIM TechSupport, reset control register for desired Alarm
    ' after setting alarms.
    I2CWrite SDA, SCL, RTCdevice, ContReg,[%00000101]
    PAUSE 10
    'Set the main Time
    I2CWrite SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day,date,mon,yr]
    PAUSE 10
    'Set the Alarm1 Time
    I2CWrite SDA, SCL, RTCdevice, Alm1sec,[A1sec,A1MINs,A1hr,A1day]
    PAUSE 10
    'Set the Alarm2 Time ' Alarm2 disabled for this application
    'I2CWrite SDA, SCL, RTCdevice, Alm2min,[A2MINs,A2hr,A2day]
    'PAUSE 10
    'IF LCD_Flag = 1 THEN ' Uncomment FOR TESTING ONLY
    'Test to see if Time set correctly by displaying on LCD
    'I2CREAD SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day,date,mon,yr]
    'LCDOut $fe,1 ' Clear Display
    'LCDOUT $fe,Line1,"SetTime"
    'LCDOUT $FE,LINE2,hex2 hr,":",hex2 MINs,":",hex2 sec
    'PAUSE 3000 ' Delay so user can view display
    'Test if Alarm1 set correctly by displaying stored Alarm1 time
    'I2CREAD SDA,SCL,RTCdevice,Alm1sec,[A1sec,A1MINs,A1hr,A1day]
    'LCDOut $fe,1 ' Clear Display
    'LCDOUT $fe,Line1,"SetAlm1"
    'LCDOut $FE,line2,hex2 A1hr,":",hex2 A1MINs,":",hex2 A1sec
    'PAUSE 3000 ' Delay so user can view display
    'ENDIF
    ' Clear STATUS and set CONTROL registers
    I2CWrite SDA, SCL, RTCdevice, StatusReg,[$00]
    PAUSE 10
    I2CWrite SDA, SCL, RTCdevice, ContReg,[%00000101]
    ' Starts oscillator, no interrupts enabled.
    ' WORKS as intended!!
    Pause 10
    RETURN
    ISR:
    ' Put code here for actions to take due to RTC Alarm1 interrupt
    IF logflag = 1 THEN 'RTC interrupt has occured..start ISR
    'LOW LED_GRN
    ' Blink the RED LED 3x
    FOR I = 0 TO 2
    TOGGLE LED_RED
    PAUSE 500
    TOGGLE LED_RED
    PAUSE 500
    NEXT
    PAUSE 1000
    IF J > 220 THEN ' If logging space is full start over with logging
    J = 0 ' Reset logging index to start of logging space
    ' Logging space covers time stamps for 220 interrupts
    ENDIF
    ' Read current time/date..display if LCD installed
    'DISABLE ' Disable PortB interrupts during I2C bus use
    I2CREAD SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day,date,mon,yr]
    'ENABLE
    PAUSE 20
    'IF LCD_Flag = 1 THEN ' Uncomment FOR TESTING ONLY
    'LCDOUT $fe,1 ' Clear Display
    'LCDOUT $FE,LINE2,hex2 hr,":",hex2 MINs,":",hex2 sec
    'PAUSE 1000
    'ENDIF
    'Put code here to log time of interrupt
    WRITE 16+J, hr ' Log timestamp for Alarm1 to EEPROM
    WRITE 17+J, MINs
    WRITE 18+J, sec
    WRITE 19+J, logflag
    J = J+4
    'LOW LED_RED
    logflag = 0 ' Reset logflag
    ENDIF
    RETURN
    ' ----------------------[ END OF SUBROUTINES ]--------------------------
    JumpPoint:
    'Setup for starting Main Program
    IF LCD_Flag = 1 Then GOSUB InitializeDisplay ' Initialize LCD before
    ' starting mainloop
    GOSUB SetTimeAndDate ' Set RTC time/date before starting mainloop
    'IF LCD_Flag = 1 THEN ' This code block FOR TESTING ONLY
    'LCDOut $fe,1' Clear Display
    'LCDOUT $fe,Line1,"Entered"
    'LCDOUT $fe,Line2,"JumpPoint"
    'Pause 2000
    'ENDIF
    'Initialize epoch indexes at time of powerup/reset
    day_cnt = date
    WRITE 6, day_cnt ' Store new epoch initialized day_count
    Pause 20
    J = 0 ' Initialize EEPROM logging index
    ' Log program start date/time/Alarm1
    WRITE 7,mon
    WRITE 8,date
    WRITE 9,yr
    WRITE 11,hr
    WRITE 12,MINs
    WRITE 13,sec
    WRITE 14,A1hr
    WRITE 15,A1MINs
    'Initialize LEDs to off before mainloop
    LOW LED_GRN
    LOW LED_RED
    logflag = 0 ' Clear logflag before mainloop
    ' Enable the interrupts that are to be active during main loop.
    @ INT_ENABLE RBC_INT ; enable RBC interrupts
    '--------------------[ Begin Main Program Loop ]-------------------------
    ;@ StartSize(MainLoop) ; FOR TEST ONLY
    mainloop:
    ' Blink Green LED 1x at start of mainloop...Uncomment FOR TEST ONLY
    TOGGLE LED_GRN
    PAUSE 250
    TOGGLE LED_GRN
    PAUSE 2000
    'Check to see if Alarm1 Interrupt occured and service if it did
    DISABLE 'Disable PortB interrupts during ISR routine
    GOSUB ISR
    ENABLE
    ' Display current Date/Time if LCD installed
    IF LCD_Flag = 1 THEN
    LCDOUT $fe,1 ' Clear Display
    LCDOUT $fe,Line1,HEX2 mon,"/",HEX2 date,"/", HEX2 yr
    LCDOUT $FE,Line2,HEX2 hr,":",HEX2 MINs,":",HEX2 sec
    PAUSE 250
    ENDIF
    WRITE 255,9 'Test if executing to this location
    GOTO mainloop
    ;@ EndSize(MainLoop) ; Uncomment FOR TEST ONLY

    '--------------------[ Begin Interrupt Handlers ]------------------------
    Alarm:
    ' Blink Red LED 3x at start of Alarm interrupt...Uncomment FOR TEST ONLY
    FOR I = 0 TO 2
    TOGGLE LED_RED
    PAUSE 250
    Toggle LED_RED
    PAUSE 250
    NEXT
    PAUSE 2000
    logflag = 1 ' Set flag to log this RB2 interrupt in mainloop
    ' Resume Main Program where Interrupt happened
    @ INT_RETURN
    '------------------{ End of Interrupt Handlers }-------------------------
    END ' Safety measure to insure program stops if reaches here
    ;@ EndSize(LOOKUP) ; FOR TEST ONLY
    ;@ LibrarySize ; FOR TEST ONLY
    ;@ UserSize ; FOR TEST ONLY
    ;@ TotalSize ; FOR TEST ONLY

    {/CODE]

  15. #15
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default Re: PortB Change Interrupts

    You need to read PORTB to clear the mismatch condition before exiting the ISR.

    Code:
    R0 = PORTB
    DT

  16. #16
    Join Date
    Mar 2009
    Location
    Colorado
    Posts
    378


    Did you find this post helpful? Yes | No

    Default Re: PortB Change Interrupts

    Reading the PORTB stopped the continuous interrupts, but I still see two happening on each Alarm rather than one. I suspect that is because the DS1337 clock alarm pulls the RB2 pin low on the interrupt and then forces it back to Vcc after the interrupt....hence two changes occuring within a few millisecs of each other. How do I make the RBC_INT only recognize one of these?

  17. #17
    Join Date
    Mar 2009
    Location
    Colorado
    Posts
    378


    Did you find this post helpful? Yes | No

    Default CORRECTION: Re: PortB Change Interrupts

    CORRECTION TO MY LAST POST: It was only doing one interrupt on the falling edge of the signal from the DS1337 Alarm1. I was mistaking the 2nd one because I had a red LED blink 3x also in the beginning of the routine that was doing the logging of the interrupt, which I thought was another RBC_INT on the rising edge. So the RBC_INT is recognizing just the first change (falling edge) of the signal.
    However, solving this question uncovered another problem. Now I notice that the Alarm1 signal from the DS1337 doesn't reset to High after the alarm as it should. This is strange to me because signal line has a 10K pullup resistor on it to Vcc, which should force it back to High after the DS1337 resets the Alarm1 signal after the interrupt. I have put a voltmeter on this line and I see it is high during the normal mainloop and goes low as it should when the Alarm1 time occurs. However it then stays at 21 millivolts forever after and never goes back to high. And as a result no more Alarm1 signals are detected when they should be. I can't figure out why my MCU is holding the line Low after the 1st interrupt. The circuit is one I have used before so it must somehow being caused by my code which I am posting below. Can anyone tell me why?
    Code:
    'STATUS: Compiles & assembles OK with CPU @ 8 MHz.
    '        Sets date/time/Alarm1 OK.
    '        Displays initialized date/time continuously (if LCD installed).
    '        On change interrupts from clock _INTA OK
    '        Logs time stamps for 1st interrupt into EEPROM.
    '        However no more _INTA interrupts are recognized and a voltmeter
    '        reveals the MCU pin connected to _INTA stays low thereafter with no
    '        more RBC_INT recognition.
    '< FL_PIC16F886 >' ' First valid PIC found within the first 200 lines will
                       ' highlight AND set device.
    '***********************************************************************
    ' -----------------------[ Program Description ]----------------------------------------
    '  PICBASIC PRO program to set RTC & demo operation of a LCD/4-bit mode  *
    '    1)  Initializes 2x16 or 2x8 LCD display with EasyPic6.                             *
    '    2)  Initializes DS1337 Real-time-clock & sets time/date/Alarm1.              *
    '        (user must adjust code in SetTimeDate subroutine for desired             *
    '        startup time/date/Alarm1 settings)                                                  *
    '    3)  This code sets Alarm1 to go off every minute..adjust as needed.         *
    '    4)  Alarm1 is used as RBC_INT interrupt by MCU.                                   *
    '    5)  Also displays date/time on LCD every second.                                   *
    '                                                                                                           *
    '*************************************************************************
    '-----------------[ 16F886 Port/PIN Connections ]------------------
    'I/O pin connections to the 16F886 MCU are as follows:
    'PORTA.0 (02) output to LCD D4 & also multiplexed as input from LM34.
    'PORTA.1 (03) output to LCD D5.
    'PORTA.2 (04) output to LCD D6 & also mulitplexed as Vref+ input.
    'PORTA.3 (05) output to LCD D7.
    'PORTA.4 (06) output to LCD RS.
    'PORTA.5 (07) ouput to LCD E.
    'PORTB.0 (21) output as I2C SDA to DS1337.
    'PORTB.1 (22) output as I2C SCL to DS1337.
    'PORTB.2 (23) input as interrupt on change from pin-3 (_INTA) of DS1337 RTC.
                  ' Also senses pushbutton for manual interrupt for RangeFinder.
    'PORTB.3 (24) input from SQW/_INTB pin-7 of DS1337 RTC.
    'PORTB.4 (25) set as A/D Channel 11 for analog input from LM34 output
    'PORTB.5 (26) unconnected
    'PORTB.6 (27) connected as PGC for ICSP connection.
    'PORTB.7 (28) connected as PGD for ICSP connection.
    'PORTC.0 (11) output RC0 to control external power to SRF02 & LM34.
    'PORTC.1 (12) output RC1 to MSEL on WiFi Module
    'PORTC.2 (13) output RC2 to LCD R/W or to _RES_PD on WiFi module
    'PORTC.3 (14) reserved to connect as Vbus to 470 pf capacitor for USB
    'PORTC.4 (15) output RC4 to a Red LED for low voltage warning.
    'PORTC.5 (16) output RC5 to Green LED for routine entry indicator.
    'PORTC.6 (17) output as TX to WiFi module RXD.
    'PORTC.7 (18) output as RX to WiFi module TXD.
    '--------------[ Define EEPROM usage ]-----------------------------------
       '09  = day_cnt  ' Most recent day_cnt
       '10  = J        ' Index for counting interrupts received
       '11  = hr       ' Hour time from RTC after setting RTC
       '12  = MINs     ' Minutes time from RTC after setting RTC
       '13  = sec      ' Seconds time from RTC after setting RTC
       '14  = A1hr     ' Alarm1 hour time from RTC after setting RTC
       '15  = A1MINs   ' Alarm1 minutes time from RTC after setting RTC
       '16+J = hr      ' Log Hour
       '17+J = MINs    ' Log Minutes
       '18+J + sec     ' Log Seconds
       '240 = ID(0)    ' LSB of device ID
       '241 = ID(1)    ' MSB of device ID
       '242 = mon      ' Month when clock was set
       '243 = date     ' Date when clock was set
       '244 = yr       ' Year when clock was set
    'INCLUDE "CodeSize.pbp"     'FOR TEST ONLY
    DEFINE Measure 1
    ;@ StartSize(LOOKUP)        'FOR TEST ONLY
    Pause 10     ' This statement is placed at beginning of code for ICD use
    'Disable Debug
    ' Set configuration fuses for the MCU
    ' To use standard config include file, comment out below statement
    @ __config   _CONFIG1, _HS_OSC & _WDT_OFF & _MCLRE_OFF & _LVP_OFF & _CP_OFF
    '--------------[ Define Hardware / Set Registers ]------------------------
        DEFINE OSC 8        ' MCU uses external 8 MHz crystal
        DEFINE I2C_SLOW 1   ' Set i2c to the standard speed
        DEFINE I2C_HOLD 1   ' Enable recieving i2c device to pause communication
        Include "Modedefs.Bas" ' Mode definitions for Debug,Serin/out,
                               ' Shiftin/out, Xin/out.
        INCLUDE "ALLDIGITAL.pbp"  ' Sets all registers for digital ops.
                                  ' User must make sure AllDigital.pbp file
                                  ' is in same or higher directory location as
                                  ' this source code before compiling.
            'DEFINE SHOWDIGITAL 1 ' When uncommented will show analog settings
                                  ' in Assembler Results window.
        INCLUDE "DT_INTS-14.bas"  ' Base Interrupt System
        INCLUDE "ReEnterPBP.bas"  ' Include if using PBP high priority interrupts
                                  ' Allows re-entry to PBP from a High Priority
                                  ' ASM interrupt. Must have DT_INTS-14.bas
                                  ' loaded first.
        TRISA = 0           ' Set all PortA initally to outputs for LCD use
        TRISC = %10000000   ' Set PortC to all outputs except PortC.7 which is
                            ' reserved as RX input.
                            ' PortC.1 is output for MSEL to WiFi module
                            ' PortC.2 is used for the LCD R/W connection when
                            ' LCD present..otherwise as _RES_PD to Wifi Module.
                            ' PortC.4 is output to LED_RED
    '****************** SETUP PORTB for RBC_INT Interupt *************
    '--- Setup Interrupts ----------------------------------------------------
    ASM
    INT_LIST  macro      ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler      RBC_INT,       _Alarm,   PBP,  yes
    ;        INT_Handler   HLVD_INT,       _VoltLow,   PBP,  yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
    ' Per DT, DT_INTS already takes care of setting INTCON register
    ' but this code doesn't work unles below registers also set as indicated:
        IOCB.2= 1           ' ENABLE IOC INERRUPT ON PORTB.2 (RB2) for Alarm1
        TRISB = %00010100   ' RB2 set as input from RTC Alarm1
                            ' PORTB.2 is also an interrupt from manual switch GND
                            ' PORTB.4 is set for input as A/D Channel 11
        WPUB = 0            ' DISABLE all PortB pull-ups
        CM1CON0 = 0         ' DISABLE COMPARATORS
        CM2CON0 = 0         ' DISABLE COMPARATORS
    '--- Variables & Aliases -------------------------------------------------
    CNT         VAR BYTE      ' Counter for timing
    CNT = 0
    day_cnt     VAR BYTE
    D_LAY       VAR BYTE      ' Stores delay value
    dummy       VAR BYTE      ' dummy variable for resetting PortB mismatch
    ADR         VAR BYTE[9]   ' Array stores IP address
    deviceID1   VAR BYTE      ' Serial # of MCU (MSB)
    deviceID2   VAR BYTE      ' Serial # of MCU (LSB)
    ext_pwr     VAR PortC.0   ' MCU Controlled external power to SRF02 & LM34
    I           VAR Byte      ' Index for loop counters
    ID          VAR BYTE[8]   ' Array for storing device ID parameters
    J           VAR BYTE      ' Index to EEPROM address for logging
    LCD_Flag    VAR Bit       ' Flag when set indicates LCD is installed/used
    LED_RED     VAR PortC.4   ' Red LED
    LED_GRN     VAR PortC.5   ' Green LED used to indicate Routine entries
    logflag     VAR BYTE      ' Flag used in ISR to indicate to log time stamp
    LowVolt     VAR BIT       ' Flag that is set when MCU power source is low volt
    MSEL        VAR PORTC.1   ' iChip Mode Select
    _RES_PD     VAR PORTC.2   ' iCHIP RESET/Power-Down
    OK          VAR BYTE      ' Captures K in I/OK FTP return messages for testing
    SCL         VAR PORTB.1   ' I2C clock pin
    SDA         VAR PORTB.0   ' I2C data pin
    Spare_1     VAR PORTB.7   ' PGD for ICSP & Spare I/O for normal ops
    Spare_2     VAR PORTB.6   ' PGC for ICSP & Spare I/O for normal op
    temp        VAR WORD      ' Stores measured temperature
    TX          VAR PORTC.6   ' Serial interface to iWiFI module
    RX          VAR PORTC.7
    VDD         VAR WORD      ' Used in low voltage detection algorithm
    wsave       VAR BYTE  $70  SYSTEM  ' Required per DT post 108282
    CLEAR                     ' Clear all RAM (sets all VAR declarations to zero)
    'ENABLE DEBUG
    '--- Initialize ----------------------------------------------------------
        ' User must set FLAGS for current configuration
            'LowVolt = 0       ' Initalize low voltage Flag
            LCD_Flag = 0      ' Clear if LCD un-installed; set otherwise
    '--- Read MCU Serial Number is stored in 4 ea device ID Locations
    ' at memory locations Addresses $2000 to $2003 but can't be read at run time
        deviceID1 = ID(0)           ' MSB of MCU Device Serial Number
        deviceID2 = ID(1)           ' LSB of MCU Device Serial Number
        WRITE 240, ID(0)            ' Write fixed values to EEPROM for test
        WRITE 241, ID(1)
    '--- Initialize epoch indexes at time of powerup/reset
        day_cnt = 0
        WRITE 6, day_cnt     ' Store new epoch initialized day_count
    '*******************SETUP FOR USING DS1337 Real Time Clock**************
        ' Setup Hardware for uart
            DEFINE HSER_BAUD 115200
            DEFINE HSER_RCSTA 90h
            DEFINE HSER_TXSTA 24h
            DEFINE HSER_CLROERR 1
        ' Aliased Variables for CLock
            Alarm1     VAR PORTB.2     ' Alarm1 input from DS1337 INTA (pin-3)
            'Alarm2     VAR PORTB.3     ' Alarm2 input from DS1337 INTB (pin-7)
            'SCL        VAR PORTB.1     ' I2C clock pin
            'SDA        VAR PORTB.0     ' I2C data pin
            RTCdevice CON $D0  ' Device write address = %11010000 for RTC
            ' This is a list of allowable clock contrl settings, one which
            ' must be setup in the SetTimeAndDate subroutine for intended use.
            '(see data sheet pgs 9-10 for explanation)
            'contrl   CON %00000000 ' Starts oscillar, sets the SQW/OUT to
                                    ' 1Hz pulse, no Alarm interrupts enabled.
                                    ' WORKS as intended!!
            'contrl   CON %00000001 ' Starts oscillator, sets the SQW/OUT to
                                    ' 1 HZ pulse, & enables INTA interrupt from
                                    ' A1F.  WORKS as intended!!
            'contrl   CON %00000010 ' Starts oscillator, sets the SQW/OUT to
                                    ' 1 HZ pulse, enables INTA interrupt from
                                    ' A2F. WORKS AS intended!!
            'contrl   CON %00000011 ' Starts the oscillator, sets the SQW/OUT
                                    ' to 1 Hz, enables INTA interrupt from A1F
                                    ' or from A2F.  WORKS as intended!!
            'contrl   CON %000xx100 ' Starts oscillator, no interrupts enabled.
                                      ' WORKS as intended!
            'contrl   CON %000xx101 ' Starts oscillator, enables INTA interrupt
                                    ' from A1F, INTB/SQW off. WORKS OK!
            'contrl   CON %000xx110 ' Starts oscillator, enables INTB interrupt
                                    ' from A2F. WORKS OK!
            'contrl   CON %000xx111 ' Starts oscillator, enables INTA interrupt
                                    ' from A1F or INTB from A2F. WORKS OK!
                                    ' Both interrupts staggered 30 secs apart.
            'contrl   CON %00011111 ' Starts oscillator, sets RS1 & RS2,
                                    ' enables INTA interrupt from A1F
                                    ' or A2F starts 32.768khz on SQW output.
                                    ' WORKS OK!
            'contrl   CON %00011001 ' Starts oscillator, sets RS1 & RS2,
                                    ' clears INTCN to enable INTA interrupt
                                    ' from A1F with 32.768kHz on SQW output.
                                    ' SQW output WORKS OK but INTA doesn't!
            'contrl   CON %00011010 ' Starts oscillator, sets RS1 & RS2,
                                    ' clears INTCN to enable INTA interrupt
                                    ' from A2F with 32.768kHz on SQW. WORKS OK!
        ' RTC Address definitions
            SecReg      CON $00   ' seconds address (00 - 59)
                                  ' Must set MSB of SecReg to a 0 to enable RTC
            MinReg      CON $01   ' minutes address (00 - 59)
            HrReg       CON $02   ' hours address (01 - 12) or (00 - 23)
            DayReg      CON $03   ' day address (1 - 7)
            DateReg     CON $04   ' date address (01 - 28/29, 30, 31)
            MonReg      CON $05   ' month address (01 - 12)
            YearReg     CON $06   ' year address (00 - 99)
        ' Alarm 1 Address definitions
            Alm1sec     CON $07  ' Alarm 1 seconds address (00 - 59)
            Alm1min     CON $08  ' Alarm 1 minutes address (00 - 59)
            Alm1hr      CON $09  ' Alarm 1 hours address (01 - 12) or (00 - 23)
            Alm1Day     CON $0A  ' Alarm 1 day address (1 - 7)
        ' Alarm 2 Address definitions..not used in this application
            'Alm2min     CON $0B  ' Alarm 2 minutes address (00 - 59)
            'Alm2hr      CON $0C  ' Alarm 2 hours address (01 - 12) or (00 - 23)
            'Alm2Day     CON $0D  ' Alarm 2 day address (1 - 7)
        ' Alias of Clock register addresses
           ContReg     CON $0E    ' CONTROL register address
           StatusReg   CON $0F    ' STATUS register address
        ' Clock Variables
            sec         VAR BYTE  ' seconds
            MINs        VAR BYTE  ' minutes
            hr          VAR BYTE  ' hours
            day         VAR BYTE  ' day of week (Sunday = 7)
            date        VAR BYTE  ' date in month
            mon         VAR BYTE  ' month
            yr          VAR BYTE  ' year
        ' ALARM1 VARIABLES
            A1sec       VAR BYTE  ' seconds
            A1MINs      VAR BYTE  ' minutes
            A1hr        VAR BYTE  ' hours
            A1day       VAR BYTE  ' day
        ' ALARM2 VARIABLES..not used in this application
            'A2MINs      VAR BYTE  ' minutes
            'A2hr        VAR BYTE  ' hours
            'A2day       VAR BYTE  ' day
    
    GOTO JumpPoint ' Jump over all subroutines so they don't execute on powerup
    
    ' ----------------------[ START SUBROUTINES ]--------------------------
    InitializeDisplay:  ' Subroutine to initialize 2X16 or 2x8 LCD display
    '==========
      '--SETUP FOR USING 2x16 or 2x8 LCD INSTALLED on PROTOBOARD IN EASYPIC6--
         ' LCD DEFINES FOR USING 2x16 LCD with PortA in EASYPIC6
               DEFINE LCD_DREG PORTA    ' Use PORTA for LCD Data
               DEFINE LCD_DBIT 0        ' Use lower(4) 4 bits of PORTA
                                          ' PORTA.0 thru PORTA.3 connect to
                                          ' LCD DB4 thru LCD DB-7 respectively
               DEFINE LCD_RSREG PORTA   ' PORTA for RegisterSelect (RS) bit
               DEFINE LCD_RSBIT 4       ' PORTA.4 pin for LCD's RS line
               DEFINE LCD_RWREG PORTC   ' LCD read/write port
               DEFINE LCD_RWBIT 2       ' LCD read/write bit
               DEFINE LCD_EREG PORTA    ' PORTA for Enable (E) bit
               DEFINE LCD_EBIT 5        ' PORTA.5 pin for LCD's E line
               DEFINE LCD_BITS 4        ' Using 4-bit bus
               DEFINE LCD_LINES 2       ' Using 2 line Display
               DEFINE LCD_COMMANDUS 1500' Command Delay (uS)
               DEFINE LCD_DATAUS 44     ' Data Delay (uS)
        ' DEFINE LCD Control Constants
               Line1   CON 128          ' Point to beginning of line 1 ($80)
               Line2   CON 192          ' Point to beginning of line 2 ($C0)
        ' Test the LCD during initialization
               'IF LCD_Flag = 1 THEN ' Uncomment FOR TESTING ONLY
                  'LCDOUT $fe,1:FLAGS=0:PAUSE 250    ' Clear Display
                  'LCDOUT $fe,Line1,"LCD TEST"       ' Display on 1st line
                  'LCDOUT $fe,Line2,"POWER ON"       ' Display on 2nd line
                  'PAUSE 2000
               'ENDIF
    Return
    SetTimeAndDate:  ' Subroutine to set current time, date and alarms
    '==========
        ' Blink LED_GRN 2X times to indicate entered SetTimeAndDate
               FOR I = 0 TO 1
                   TOGGLE LED_GRN
                   Pause 500
                   Toggle LED_GRN
                   PAUSE 500
               Next
        ' Initialize the display & clock
            Pause 100           ' Wait for LCD to startup after power on
            ' Initialize clock variables to 0
                yr=0:date =0:mon =0:day=0:hr=0:MINs=0:sec=0
                A1sec=0:A1MINs=0:A1hr=0:A1Day=0
                'A2MINs=0:A2hr=0:A2day=0
            ' The BCD constants below set the RTC to: 18:22:00 on 10-06-2011
                hr=$18
                MINs=$22
                sec=$00
                day=$05
                mon=$10
                date=$06
                yr=$11
            ' Per MAXIM TechSupport, proper sequencing requires setting
            ' INTCN = 1, & A2IE=A1IE=0 in controle register before setting alarms.
                I2CWRITE SDA, SCL, RTCdevice, ContReg,[%00000100]
                PAUSE 10
            'Define ALARM1 FOR 18:21:00 & to alarm 1/min
                    ' For 1/min requires A1M1=0 and A1M2=A1M3=A1M4=1
                    ' For 1/hr requires A1M1=A1M2=0 and A1M3=A1M4=1
                ' (A1xxx + $80 or A1xxx + 128d sets bit 7 as A1Mx = 1)
                  A1hr   = %10011000  '$18 + $80 = %10011000, for A1M3 = 1
                            'Bit6 must be 0 for 24 hour clock
                  A1MINs = %10100001  '$23 = %10100011, for A1M2 = 1
                  A1sec  = %00000000  '$00 = %00000000, for A1M1 = 0
                  A1day  = %10000101  '$05 + $80 = %10000101, for A1M4 = 1
                                    'DY/_DT Bit6 = 0 for using Day of month alarm
            'Define ALARM2 FOR 12:01:00 & to alarm once per minute (00 secs)
            'Disabled in this application
                ' This requires A2M2 = A2M3 = A2M4 = 1
                ' (A2xxx + $80 or A2xxx + 128d sets bit 7 as A2Mx = 1)
                'A2hr   = $12 + $80  '$12  + $80 = %10010010, for A2M3 = 1
                                     'Bit6 must be 0 for 24 hour clock
                'A2MINs = $01 + $80  '$01 + $80 = %10000001, for A2M2 = 1
                'A2day  = $07 + $80  '$07 + $80 = $10000111, for A2M4 = 1
                                    'DY/_DT Bit6 = 0 for using Day of month alarm
            ' Per MAXIM TechSupport, reset control register for desired Alarm
            ' after setting alarms.
                I2CWrite SDA, SCL, RTCdevice, ContReg,[%00000101]
                PAUSE 10
            'Set the main Time
                I2CWrite SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day,date,mon,yr]
                PAUSE 10
            'Set the Alarm1 Time
                I2CWrite SDA, SCL, RTCdevice, Alm1sec,[A1sec,A1MINs,A1hr,A1day]
                PAUSE 10
            'Set the Alarm2 Time  ' Alarm2 disabled for this application
                'I2CWrite SDA, SCL, RTCdevice, Alm2min,[A2MINs,A2hr,A2day]
                'PAUSE 10
            'IF LCD_Flag = 1 THEN ' Uncomment FOR TESTING ONLY
               'Test to see if Time set correctly by displaying on LCD
                    'I2CREAD SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day,date,mon,yr]
                    'LCDOut $fe,1 ' Clear Display
                    'LCDOUT $fe,Line1,"SetTime"
                    'LCDOUT $FE,LINE2,hex2 hr,":",hex2 MINs,":",hex2 sec
                    'PAUSE 3000    ' Delay so user can view display
                'Test if Alarm1 set correctly by displaying stored Alarm1 time
                    'I2CREAD SDA,SCL,RTCdevice,Alm1sec,[A1sec,A1MINs,A1hr,A1day]
                    'LCDOut $fe,1 ' Clear Display
                    'LCDOUT $fe,Line1,"SetAlm1"
                    'LCDOut $FE,line2,hex2 A1hr,":",hex2 A1MINs,":",hex2 A1sec
                    'PAUSE 3000    ' Delay so user can view display
            'ENDIF
            ' Clear STATUS and set CONTROL registers
                I2CWrite SDA, SCL, RTCdevice, StatusReg,[$00]
                PAUSE 10
                I2CWrite SDA, SCL, RTCdevice, ContReg,[%00000101]
                              ' Starts oscillator, no interrupts enabled.
                              ' WORKS as intended!!
                Pause 10
    RETURN
    ISR:
         ' Put code here for actions to take due to RTC Alarm1 interrupt
            IF logflag = 1 THEN   'RTC interrupt has occured..start ISR
               'LOW LED_GRN
               ' Blink the RED LED 1 sec 3x
                 FOR I = 0 TO 2
                     TOGGLE LED_RED
                     PAUSE 1000
                     TOGGLE LED_RED
                     PAUSE 1000
                 NEXT
                 PAUSE 1000
                IF J > 220 THEN  ' If logging space is full start over with logging
                   J = 0     ' Reset logging index to start of logging space
                             ' Logging space covers time stamps for 220 interrupts
                ENDIF
                ' Read current time/date..display if LCD installed
                'DISABLE            ' Disable PortB interrupts during I2C bus use
                I2CREAD SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day,date,mon,yr]
                'ENABLE
                PAUSE 20
                'IF LCD_Flag = 1 THEN ' Uncomment FOR TESTING ONLY
                     'LCDOUT $fe,1 ' Clear Display
                     'LCDOUT $FE,LINE2,hex2 hr,":",hex2 MINs,":",hex2 sec
                     'PAUSE 1000
                'ENDIF
                'Put code here to log time of interrupt
                     WRITE 16+J, hr    ' Log timestamp for Alarm1 to EEPROM
                     WRITE 17+J, MINs
                     WRITE 18+J, sec
                     WRITE 19+J, logflag
                     J = J+4
                'LOW LED_RED
                logflag = 0      ' Reset logflag
           ENDIF
    RETURN
    ' ----------------------[ END OF SUBROUTINES ]--------------------------
    JumpPoint:
        'Setup for starting Main Program
        IF LCD_Flag = 1 Then GOSUB InitializeDisplay  ' Initialize LCD before
                                                      ' starting mainloop
        GOSUB SetTimeAndDate  ' Set RTC time/date before starting mainloop
        'IF LCD_Flag = 1 THEN ' This code block FOR TESTING ONLY
            'LCDOut $fe,1' Clear Display
            'LCDOUT $fe,Line1,"Entered"
            'LCDOUT $fe,Line2,"JumpPoint"
            'Pause 2000
        'ENDIF
        'Initialize epoch indexes at time of powerup/reset
            day_cnt = date
            WRITE 6, day_cnt     ' Store new epoch initialized day_count
            Pause 20
            J = 0                ' Initialize EEPROM logging index
        ' Log program start date/time/Alarm1
            WRITE 7,mon
            WRITE 8,date
            WRITE 9,yr
            WRITE 11,hr
            WRITE 12,MINs
            WRITE 13,sec
            WRITE 14,A1hr
            WRITE 15,A1MINs
        'Initialize LEDs to off before mainloop
            LOW LED_GRN
            LOW LED_RED
        logflag = 0          ' Clear logflag before mainloop
        ' Enable the interrupts that are to be active during main loop.
    @    INT_ENABLE   RBC_INT      ; enable RBC interrupts
    ;@    INT_ENABLE   LVD_INT      ; enable LVD interrupt
    '--------------------[ Begin Main Program Loop ]-------------------------
    ;@ StartSize(MainLoop)    ; FOR TEST ONLY
    mainloop:
        ' Blink Green LED 1x at start of mainloop...Uncomment FOR TEST ONLY
                TOGGLE LED_GRN
                PAUSE 250
                TOGGLE LED_GRN
                PAUSE 2000
        'Check to see if Alarm1 Interrupt occured and service if it did
               DISABLE   'Disable PortB interrupts during ISR routine
               GOSUB ISR
               ENABLE
        ' Display current Date/Time if LCD installed
            IF LCD_Flag = 1 THEN
                LCDOUT $fe,1 ' Clear Display
                LCDOUT $fe,Line1,HEX2 mon,"/",HEX2 date,"/", HEX2 yr
                LCDOUT $FE,Line2,HEX2 hr,":",HEX2 MINs,":",HEX2 sec
                PAUSE 250
            ENDIF
    WRITE 255,9    'Test if executing to this location
    GOTO mainloop
    ;@ EndSize(MainLoop)    ; Uncomment FOR TEST ONLY
    '--------------------[ Begin Interrupt Handlers ]------------------------
    Alarm:
          ' Blink Red LED 3x at start of Alarm interrupt...Uncomment FOR TEST ONLY
                FOR I = 0 TO 2
                    TOGGLE LED_RED
                    PAUSE 250
                    Toggle LED_RED
                    PAUSE 250
                NEXT
                PAUSE 2000
           logflag = 1    ' Set flag to log this RB2 interrupt in mainloop
           dummy = PORTB  ' Read PortB to eliminate mismatch on interrupt
           ' Resume Main Program where Interrupt happened
    @ INT_RETURN
    '------------------{ End of Interrupt Handlers }-------------------------
    END     ' Safety measure to insure program stops if reaches here

  18. #18
    Join Date
    Mar 2009
    Location
    Colorado
    Posts
    378


    Did you find this post helpful? Yes | No

    Default Re: PortB Change Interrupts

    PROBLEM SOLVED! I forgot to clear the RTC's Alarm1 flag to be ready for next RTC interrupt. Had to add these statement to end of ISR:

    ' Reset Alarm1 (_INTA) interrupt by clearing STATUS register
    I2CWRITE SDA, SCL, RTCdevice, StatusReg,[$00]

    Thanks for your patience, Darrel. Sometimes it is the obvious things that are missed

Similar Threads

  1. PICs can do more if use others than delays instructions
    By hardcore in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 24th February 2010, 19:52
  2. Returning from Int on PortB change
    By sheryl in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 11th December 2008, 18:09
  3. shifting problem
    By helmut in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 31st August 2007, 06:11
  4. Output PIC module
    By freelancebee in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 12th September 2005, 20:10
  5. Can anyone help a beginner in a struggle?
    By douglasjam in forum mel PIC BASIC
    Replies: 1
    Last Post: - 5th May 2005, 23:29

Members who have read this thread : 2

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts