This is a multi-part message in MIME format. --------------070506010708030508000901 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Two additional items of information: To 'fix' the circuit, I disconnect the battery and wait a while before re-connecting it. I can unplug the magnetic switch entirely leaving the circuit open and it is still 'broken'. Also, one test showed that when working fine, with the switch disconnected, it still later 'broke'. Thanks again I can supply the source code too... actually, it is attached. Rolf Rolf wrote: > Hi all. > > Attached is the schematic for my current project. It is a wireless > garage door monitor. It uses two magnetic switches to monitor two > garage doors, and wirelessly transmits the door state and battery > state to a receiver. > > The basic concept is simple. The PIC puts all pins as input except AN0 > which is used to monitor the battery health. It then sleeps for about > 2.5 seconds, wakes up, checks the battery state, checks the door > states, and then activates the transmitter, and transmits a 24 bit > data stream (ID, state, checksum). > > The problem is that, after a number of hours (about 5) of continuously > correct operation, it starts transmitting that the one door is 'open'. > > First though, some details. > > The batteries are 2xAA Lithium 1.5V > IC1 is a PIC12F675 with MCLR off (pin is used as digital input). The > PIC is the DIP version and is socketed, pulled for programming, and > then re-socketed. No need for ICSP. > U1 is a 1.25V reference - REF3312 from Texas Instruments - it has a > 5uA quiescent current. > U2 is a TXM-418-LR from Linx which has 5nA drain when /PDN is pulled low. > > The momentary switch is only used to generate a new ID for the > transmitter. If the switch is closed then the unit powers up (resets), > the PIC will simply run a timer until the button is released. Whatever > the value in the (8-bit) timer is when the button is released will > become the devices new ID. The button will do nothing else while the > system operates. > > The door that is indicated to be open is always the one that is sensed > through GP1 (pin 6). The door sensed through GP3 is never sensed wrong > (yet). > > When the system runs correctly, I measure the following values at the > various pins (using a DMM all measurements on 2000mV range except pin > 1 on 20V range, all measurements to ground): > 1 3.29 > 2 0.000 > 3 0.000 > 4 0.000 > 5 0.002 > 6 0.010 and 3.28 with the magnetic switch closed. > 7 1.249 > 8 0.000 > > > When the system is 'broken', I have the following measurements: > 1 3.31 > 2 0.000 > 3 0.000 > 4 0.000 > 5 0.000 > 6 1.250 and 1.318 with the magnetic switch 'closed' > 7 1.249 > 8 0.000 > > The actual values for the 'broken' situation are suspiciously similar > between pin 6 and 7... but, it is weird that it rises to 1.318V when > the switch is closed..... > > I am at a loss as to what to check, what may be broken, or where the > design may be wrong. > > I have tried the circuit numerous times, and have 5 different > PIC12F675's, and at least two of them have shown this 'broken' behaviour. > > The trace from R9 to GP1 (the door sense trace) runs underneath both > C1 and R1 which are 1206 footprint parts. I initially suspected that > there was a solder bridge from one of these pads to the trace, but, > that appears not to be the case, and, it would be a consistent > problem, rather than the delayed/intermittent one. > > About the only thing I can believe to be happening is that there is a > short of some sort between pin AN0 and GP1 causing the 1.25V reference > voltage to appear on the GP1 pin. The REF3312 is able to sink current > to maintain 1.25V, so, with the effective 2K impedance 3.3V source > when the sensor circuit is closed, and with the 1K between pin AN0 and > the REF3312, I do some math, and determine.... > > IF the pins have a resistance bridge between them somewhere, the 1M > pull down resistor R3 is not enough to drop the voltage at pin GP1, > but, when the door is open (the switch is closed), the 3.3V source > with 2K impedance is enough to pull the 1.25V to 1.32, or to raise it > 0.7V .... but, it makes no sense that AN0 does not change....... > > Finally, before I got so stuck in to the problem, I decided that the > 1M pull-down was not 'strong' enough, so, I decided that it may be a > 'capacitive' build up on pin GP1 that was causing the problem. To > 'resolve' this perceived issue, I decided to set the GP1 as an output, > and output low for 50us before setting the pin back to an input for > another 200us or so before reading the pin's state through GPIO. I > figured this would be enough to drain any 'spurrious' charges on the > pins. > > But, it was not successful.... > > Anyone have any ideas? > > Anyone suggest another avenue to explore? > > Thanks in advance > > Rolf --------------070506010708030508000901 Content-Type: text/plain; name="tx.asm" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="tx.asm" ;****************************************************************************** ; This file is a basic code template for object module code * ; generation on the PIC12F675. This file contains the * ; basic code building blocks to build upon. * ; * ; Refer to the MPASM User's Guide for additional information on * ; features of the assembler and linker (Document DS33014). * ; * ; Refer to the respective PIC data sheet for additional * ; information on the instruction set. * ; * ;****************************************************************************** ; * ; Filename: tx.asm * ; Date: 22 May 2008 * ; File Version: 0.9 * ; * ; Author: Rolf Lear * ; Company: tuis.net * ; * ; * ;****************************************************************************** ; * ; Files required: P12F675.INC * ; 12f675.lkr * ; * ; * ;****************************************************************************** ; * ; Notes: * ; * ; This program will broadcast the A/D voltage based on a 1.25V reference * ; as well as the state of 2 digital inputs over a data link to an RF TX * ; it is designed to work with the Linx TXM series... * ; * ; * ;****************************************************************************** ;------------------------------------------------------------------------------ ; PROCESSOR DECLARATION ;------------------------------------------------------------------------------ LIST P=12F675 ; list directive to define processor #INCLUDE ; processor specific variable definitions radix dec errorlevel -302 ;errorlevel +302 ;------------------------------------------------------------------------------ ;***** Convenient defines ;------------------------------------------------------------------------------ ; The button is used to set an ID for the chip. ; connect it to the MCLR pin (which is set as digital input). ; Don't press the button while programming! #define BUTTONIO 2 ; garage A io pin. #define GAIO 1 ; garage B io pin #define GBIO 3 ; output pin for the LED. It is shared with the data pin of the TX #define LEDIO 4 ; The data pin on the TX. The LED goes on when transmitting data too. #define DATAIO 4 ; the power down pin for the TX module. Uses 5nA when powered down. #define PDNIO 5 ; where in EEPROM to store the ID for the device. #define IDADDRESS 0x00 ; which bit in the flags is used for the next data state. #define BCTOGGLE 0 ; whether the bit has been set in the ISR. #define BCISR 1 ; the set happens 18 instructions after the timer resets... and, ; with 2 idle instructions after setting TMR0, plus the set instruction itself ; we need to set the timer for: 256 - (us - 21) where 'us' is the time we want in microseconds #define TMRSYNC 256 - (160 - 21) #define TMRSHRT 256 - (120 - 21) #define TMRLONG 256 - (200 - 21) ;------------------------------------------------------------------------------ ; ; CONFIGURATION WORD SETUP ; ; The 'CONFIG' directive is used to embed the configuration word within the ; .asm file. The lables following the directive are located in the respective ; .inc file. See the data sheet for additional information on configuration ; word settings. ; ;------------------------------------------------------------------------------ __CONFIG _CP_ON & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_ON & _PWRTE_ON & _INTRC_OSC_NOCLKOUT ; read the specified EEPROM address, and put the value in W. read_eeprom macro ee_address bsf STATUS,RP0 movlw ee_address movwf EEADR bsf EECON1,RD movf EEDATA,w bcf STATUS,RP0 endm ; write_eeprom will write the value in W to the ee-prom address 'ee_address' write_eeprom macro ee_address clrwdt bsf STATUS,RP0 movwf EEDATA movlw ee_address movwf EEADR bcf PIR1,EEIF ; ensure the ee-prom interrupt is not set. ; adapted from datasheet. bsf EECON1,WREN ; Enable write bcf INTCON,GIE ; Disable INTs movlw 0x55 ; Unlock write movwf EECON2 ; movlw 0xAA ; movwf EECON2 ; bsf EECON1,WR ; Start the write ;back to bank 0 bcf STATUS,RP0 bsf INTCON,GIE ; Enable INTS clrwdt ; btfss PIR1,EEIF ; Wait till write completes. goto $-2 ; endm setio_high macro pin bsf latio,pin movf latio,w movwf GPIO endm setio_low macro pin bcf latio,pin movf latio,w movwf GPIO endm ad_calc macro offset,value movlw offset subwf adtmp,f btfss STATUS,C retlw value endm ;------------------------------------------------------------------------------ ; VARIABLE DEFINITIONS ;------------------------------------------------------------------------------ ; example of using Shared Uninitialized Data Section INT_VAR UDATA_SHR 0x20 W_TEMP RES 1 ; variable used for context saving STATUS_TEMP RES 1 ; variable used for context saving latio res 1 ; latch for GPIO id res 1 ; our ID state res 1 ; our state - battery and door... txc res 1 ; the tx count. tock res 1 ; used for a timer..... tick res 1 ; used for a timer..... bcnext res 1 ; the value to load in to the timer next. bcflags res 1 ; a bitmask for the t0 state.. bcxmit res 1 ; the byte value to transmit adtmp res 1 ; used for A/D calculations bctmp res 1 ; used for broadcast things ;------------------------------------------------------------------------------ ; EEPROM INITIALIZATION ; ; The 12F675 has 128 bytes of non-volatile EEPROM, starting at address 0x2100 ; ;------------------------------------------------------------------------------ DATAEE CODE 0x2100 DE " Garage V1.0" ; Place Text string in EE-PROM DATAWWW CODE 0x2140 DE "(c) Rolf Lear. rolf@tuis.net" ;------------------------------------------------------------------------------ ; OSCILLATOR CALIBRATION VALUE ;------------------------------------------------------------------------------ OSC CODE 0x03FF ; Internal RC calibration value is placed at location 0x3FF by Microchip as ; a 0xADDLW K instruction, where the K is a literal value to be loaded into ; the OSCCAL register. ;------------------------------------------------------------------------------ ; RESET VECTOR ;------------------------------------------------------------------------------ RESET_VECTOR CODE 0x0000 ; processor reset vector GOTO START ; go to beginning of program ;------------------------------------------------------------------------------ ; INTERRUPT SERVICE ROUTINE ;------------------------------------------------------------------------------ INT_VECTOR CODE 0x0004 ; interrupt vector location MOVWF W_TEMP ; save off current W register contents MOVF STATUS,w ; move status register into W register MOVWF STATUS_TEMP ; save off contents of STATUS register ; isr code can go here or be located as a call subroutine elsewhere clrwdt ; Deal with TMR0 i_tmr0 btfss INTCON,T0IE goto i_ad btfss INTCON,T0IF goto i_ad bcf INTCON,T0IF ; right, the timer 0 interrupt is set. ; this is used to toggle the DATA line to the radio. ; So, toggle it to the state in bcflags,BCTOGGLE ; this sequence is guaranteed to take 6 instructions ; regardless of whether it is to be toggled on or off. bcf latio,DATAIO ; 1 btfss bcflags,BCTOGGLE ; 2 or 2/3 goto $+2 ; 3/4 bsf latio,DATAIO ; 4 movf latio,w ; 5 movwf GPIO ; 6 movf bcnext,w ; now, move the next value to the timer... movwf TMR0 ; this will cost some ticks on the timer too. bsf bcflags,BCISR ; record the fact that we have been to the ISR... i_ad ; in the event of a A/D interrupt, the only time we call A/D is ; followed by a sleep. We can ignore the situation in the ISR ; because the handler will be the instruction after the sleep. ; really, the only reason we have the A/D interrupt is to wake ; from sleep..... btfss PIR1,ADIF goto i_end bcf PIR1,ADIF i_end MOVF STATUS_TEMP,w ; retrieve copy of STATUS register MOVWF STATUS ; restore pre-isr STATUS register contents SWAPF W_TEMP,f SWAPF W_TEMP,w ; restore pre-isr W register contents RETFIE ; return from interrupt ;------------------------------------------------------------------------------ ; MAIN PROGRAM ;------------------------------------------------------------------------------ MAIN_PROG CODE START ;------------------------------------------------------------------------------ ; OSCCAL RESTORE (not required if internal OSC is not used) ;------------------------------------------------------------------------------ BSF STATUS,RP0 ; set file register bank to 1 CALL 0x3FF ; retrieve factory calibration value MOVWF OSCCAL ; update register with factory cal value ; BCF STATUS,RP0 ; set file register bank to 0 ;------------------------------------------------------------------------------ ; PLACE USER PROGRAM HERE ; First, do some initialization. ;------------------------------------------------------------------------------ movlw b'10001111' ; set up the option register. movwf OPTION_REG ; pull-ups off, T0 from clock, and 1:64 prescalar on WDT (about 1152ms). movlw b'01000000' ; set up peripheral interupts. movwf PIE1 ; so that only ADIE is enabled. movlw b'00110001' ; Set up AN0 as analog, other pins as digital. movwf ANSEL ; and the A/D unit to use internal dediated 500kHz RC clock... bcf STATUS,RP0 ; set file register bank to 0 clrf latio ; make latio and clrf GPIO ; make all outputs low. clrf PIR1 ; clear all peripheral Interrupt flags... movlw b'11000000' ; set up the INTCON for enable GIE and PIE. movwf INTCON movlw b'00000001' ; Set up the A/D unit. Start with it on, set to AN0 as input. movwf ADCON0 ; The AD module takes almost nothing to have on.... ; numbers are ambiguous on Datasheet, but probably less than 1uA movlw b'00000111' ; turn off comparator. This is a power hog if on. movwf CMCON ; Check status of 'data' input line. It will be high if we need to randomize our ID. btfsc GPIO,BUTTONIO; call fn_new_id clrwdt ; Right, let's read our id.... from EEPROM... read_eeprom IDADDRESS movwf id ; OK, to the business of monitoring the garage doors. ; The WDT is enabled, and will timeout every 1.1s or so. ; the routine is to sleep until the WDT expires, then to ; broadcast our state. then to sleep all over again. main_loop ; sleep will go for a second while the WDT expires. nop sleep ;clrf tock ;clrwdt ;decfsz tock ;goto $-2 nop nop call fn_get_state clrf latio clrf GPIO ; set the output pins as output bsf STATUS,RP0 bcf TRISIO,PDNIO bcf TRISIO,DATAIO bcf STATUS,RP0 clrf GPIO ; double-check the pins are low... ; enable the TX module. setio_high PDNIO ; set up the timer clrf TMR0 bcf INTCON,T0IF bsf INTCON,T0IE ; 0. 2ms wait (or close enough....) is 2000 cycles. ; do 14 150us loops instead (2100ms). movlw 8 movwf bctmp movlw TMRSYNC call fn_send_bit_high decfsz bctmp,f goto $-3 movlw 8 movwf bctmp movlw TMRSYNC call fn_send_bit_low decfsz bctmp,f goto $-3 ; broadcast twice clrf txc call fn_broadcast bsf txc,0 call fn_broadcast ; set the output pins back to input (saves power). ; first, pull pins hard to ground. setio_low DATAIO setio_low PDNIO ; then set the IO's as input.... bsf STATUS,RP0 bsf TRISIO,PDNIO bsf TRISIO,DATAIO bcf STATUS,RP0 goto main_loop ; ----------------------------------------- ; Function that broadcasts our ID and State ; to anyone who cares to listen ; ----------------------------------------- fn_broadcast ; right, the broadcast is a predefined sequence. ; 0. Neaten up the broadcast period to a nice round number.... ; 1. send a series of sync bits (31). ; 2. send a low then high bit to help lock on. ; 3. send the ID ; 4. send the state ; 5. send the XOR of the ID and state for validation.... ; 6. send a transmit ID, short for the first cycle, long for the second. ; 7. send a single bit to clock out the receiver. ; 0. now, set the next timer interrupt for something reasonable ; and neat... exactly 20ms from the start of one broadcast ; to the start of the next..... clrf bcnext ; set up the next interval... bsf bcflags,BCTOGGLE clrwdt btfss bcflags,BCISR ; wait for the ISR to run. goto $-2 bcf bcflags,BCISR ; indicate that we have come out of the wait for ISR ; then a low pulse. clrf bcnext ; set up the next interval... bcf bcflags,BCTOGGLE clrwdt btfss bcflags,BCISR ; wait for the ISR to run. goto $-2 bcf bcflags,BCISR ; indicate that we have come out of the wait for ISR movlw 33 ; this is the tweak constant to make the cycle 20ms. movwf bcnext; btfss bcflags,BCISR ; wait for the ISR to run. goto $-2 bcf bcflags,BCISR ; indicate that we have come out of the wait for ISR ; 1. send 32 sync bits. ; each bit is 50/50 duty cycle, with rate of about 7.5kBaud. ; this makes each part about 150us. ; the trick with this code is to use the instruction time to ; keep constant bit-rate. movlw 32 movwf bctmp movlw TMRSYNC call fn_send_bit_high movlw TMRSYNC call fn_send_bit_low decfsz bctmp,f goto $-5 ; 2. send a short bit for reference.... ; followed by a long bit. call fn_send_data_low call fn_send_data_high ; 3. now, send the ID movf id,w call fn_send_w ; 4. now, send the state movf state,w call fn_send_w ; 5. now send the XOR movf state,w xorwf id,w call fn_send_w ; 6. now send an ID pulse. ; send a short pulse if we are the first transmission, ; send a long pulse if we are the second. btfss txc,0 call fn_send_data_low btfsc txc,0 call fn_send_data_high ; 7. now send a single pulse to clock out the receiver. call fn_send_data_low retlw 0 ; ----------------------------------------- ; Function that reads W, and sends the bits ; over the air.... ; ----------------------------------------- fn_send_w movwf bcxmit movlw 8 movwf bctmp rlf bcxmit,f btfss STATUS,C goto $+3 call fn_send_data_high goto $+2 call fn_send_data_low decfsz bctmp,f goto $-7 retlw 0 fn_send_data_low movlw TMRSHRT call fn_send_bit_high movlw TMRLONG call fn_send_bit_low retlw 0 fn_send_data_high movlw TMRLONG call fn_send_bit_high movlw TMRSHRT call fn_send_bit_low retlw 0 ; function that schedules a high value ; to be broadcast next for the time period in W fn_send_bit_high movwf bcnext ; set up the next interval... bsf bcflags,BCTOGGLE clrwdt btfss bcflags,BCISR ; wait for the ISR to run. goto $-2 bcf bcflags,BCISR ; indicate that we have come out of the wait for ISR retlw 0 ; function that schedules a high value ; to be broadcast next for the time period in W fn_send_bit_low movwf bcnext ; set up the next interval... bcf bcflags,BCTOGGLE clrwdt btfss bcflags,BCISR ; wait for the ISR to run. goto $-2 bcf bcflags,BCISR ; indicate that we have come out of the wait for ISR retlw 0 ; --------------------------------------- ; Function that reads the Battery voltage ; and converts it in to an 0.05V offset ; from 2.20V with 32 battery levels. ; --------------------------------------- fn_get_state bsf ADCON0,GO sleep nop ; double-check... clrwdt btfsc ADCON0,GO goto $-2 ; for debug purposes let's make the ADRESH = 150 ; movlw 150 ; movwf ADRESH bcf latio,GAIO bcf latio,GBIO ; set the door sense pins as output ; we set the door pins to ground to clear any capacitive charges. bsf STATUS,RP0 bcf TRISIO,GAIO bcf TRISIO,GBIO bcf STATUS,RP0 ; Set the input pins as 0V to clear capacitance... movf latio,W movwf GPIO ; wait 30 or so us to ensure the pin is grounded... movlw 10 movwf tick decfsz tick,f goto $-1 ; set the door sense pins back as input ; the door pins were connected to ground to clear any capacitive charges. ; now we set them back to input. ; and give it a short while to settle. bsf STATUS,RP0 bsf TRISIO,GAIO bsf TRISIO,GBIO bcf STATUS,RP0 ; Right, let's do some math.... ; the objective is to get a scaled value of the voltage to 0.05V ; increments on a scale of 0-32 where 0 indicates 2.0V and 40 indicates ; 4.0 v. We do this with table lookups.... ; we set up the A/D to be left justified. We expect values ; between 319 and 640 (correspond to 4.0 and 2.0V) ; with the high-byte left-formatted in ADRESH, this is about 79 and 160 ; respectively. ; do some sanity checking.... movf ADRESH,w sublw 79 ; W is subtracted from 79. We expect a negative result. btfsc STATUS,C ; which would make C = 0. goto _fn_get_state_error ; good, now check for values more than 160... movf ADRESH,w sublw 160 ; W is subtracted from 160. We expect a value <= 160, btfss STATUS,C ; so, the result should be >= 0 goto _fn_get_state_error ; OK, we are in the batt-voltage ball-park. ; we need to subtract 256 from the 10-bit A/D value, which means subtracting ; 64 from the high byte.... movlw 64 subwf ADRESH,w movwf adtmp ; now, we need to halve the 10bit value, but, we do this by shifting the Most- ; significant bit of the ADRESL value in to the high byte. We are certain that the high-byte will ; be less than 128 because, at worst, the high byte started at 160 (640/4), and we subtracted 64 bsf STATUS,RP0 rlf ADRESL,w ; put the high-bit in to STATUS,C bcf STATUS,RP0 rlf adtmp,f ; move STATUS,C in to adtmp after shifting it.... ; our value in adtmp will be between 31 and 191 for voltages between 4.0 and 2.0V respectively. ; lets make it easier to digest... subtract the value from 191 giving a value from 0 to 160 for 2.0V to 4.0V movf adtmp,w sublw 191 movwf adtmp ; now, we have an 8-bit value which is relatively scaled according to the Vbatt. ; we need to check our lookup table to get an idea of where the actual voltage is... ; the lookup function will return the voltage as a number of 0.05V offsets from 2.0V call fn_vbatt_lookup movwf state btfsc GPIO,GAIO bsf state,7 btfsc GPIO, GBIO bsf state,6 clrwdt retlw 0; _fn_get_state_error movlw 0x01 movwf state btfsc GPIO,GAIO bsf state,7 btfsc GPIO, GBIO bsf state,6 retlw 0 fn_vbatt_lookup ; this is a series of 'sieve' fall throughs. ; we keep subtracting a pre-calculated value from adtmp ; until it breaks through zero. at which point we return ; the 0.05V offset from 2.0V ; the ad_calc macro will subtract the first argument, and, ; if the result is less than zero, it will return the second argument. ; i.e. if adtmp starts at 5, it will subtract 8, which results ; in a negative value, so we will return the constant 0 ; the table looks like: ; adtmp V ret Off-set ; 0 2.00 0 ad_calc 8,0 ; 8 2.05 1 8 ad_calc 7,1 ; 15 2.10 2 7 ad_calc 7,2 ; 22 2.15 3 7 ad_calc 7,3 ; 29 2.20 4 7 ad_calc 6,4 ; 35 2.25 5 6 ad_calc 7,5 ; 42 2.30 6 7 ad_calc 5,6 ; 47 2.35 7 5 ad_calc 6,7 ; 53 2.40 8 6 ad_calc 6,8 ; 59 2.45 9 6 ad_calc 5,9 ; 64 2.50 10 5 ad_calc 5,10 ; 69 2.55 11 5 ad_calc 5,11 ; 74 2.60 12 5 ad_calc 4,12 ; 78 2.65 13 4 ad_calc 5,13 ; 83 2.70 14 5 ad_calc 4,14 ; 87 2.75 15 4 ad_calc 4,15 ; 91 2.80 16 4 ad_calc 4,16 ; 95 2.85 17 4 ad_calc 4,17 ; 99 2.90 18 4 ad_calc 4,18 ; 103 2.95 19 4 ad_calc 3,19 ; 106 3.00 20 3 ad_calc 4,20 ; 110 3.05 21 4 ad_calc 3,21 ; 113 3.10 22 3 ad_calc 4,22 ; 117 3.15 23 4 ad_calc 3,23 ; 120 3.20 24 3 ad_calc 3,24 ; 123 3.25 25 3 ad_calc 3,25 ; 126 3.30 26 3 ad_calc 3,26 ; 129 3.35 27 3 ad_calc 2,27 ; 131 3.40 28 2 ad_calc 3,28 ; 134 3.45 29 3 ad_calc 3,29 ; 137 3.50 30 3 ad_calc 2,30 ; 139 3.55 31 2 ad_calc 3,31 ; 142 3.60 32 3 ad_calc 2,32 ; 144 3.65 33 2 ad_calc 3,33 ; 147 3.70 34 3 ad_calc 2,34 ; 149 3.75 35 2 ad_calc 2,35 ; 151 3.80 36 2 ad_calc 2,36 ; 153 3.85 37 2 ad_calc 3,37 ; 156 3.90 38 3 ad_calc 2,38 ; 158 3.95 39 2 ad_calc 2,39 ; 160 4.00 40 2 retlw 40 ; -------------------------------- ; Function to create new ID for TX ; -------------------------------- fn_new_id ; we come here if the button is pressed when the chip resets. ; we start the timer, and let it run until the button is no longer pressed. ; then we use the value in the timer to produce a new ID, and store the ID in EEPROM. ; TMR0 runs continuously. We don't really care what the value is. ; make the LED output bsf STATUS,RP0 bcf TRISIO,LEDIO bcf STATUS,RP0 setio_high LEDIO btfsc GPIO, BUTTONIO ; do a tight loop to get release-point goto $-1 ; for when user lets go of button. ; right, the user has released the button. ; because the loop is 3 instructions long, it could cause funny gaps in possible numbers. ; but, when it wraps around it will be a different sequence. movfw TMR0 write_eeprom IDADDRESS ; OK, the value is written to EEPROM. setio_low LEDIO ; turn the LED back to input. bsf STATUS,RP0 bsf TRISIO,LEDIO bcf STATUS,RP0 retlw 0 END ; directive 'end of program' --------------070506010708030508000901 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist --------------070506010708030508000901--