list p=PIC16F84A #include ; Version 0002 ; 2003-09-14 ; ; (c) 2003 Sugihara Toshio. ; All rights reserved. ; ; PIC16F84A ; Clock=4MHz 1M orders/s ; WDT=off, StartTimer=on ; Protect=off, Oscllator=XT ; System version code VERH equ H'00' ;Higher byte VERL equ H'02' ;Lower byte ; Memory Allocation ;232 Output sbuf equ H'0c' ;I/O buffer to send scount equ H'0d' ;counter to rotate bits serror equ H'0e' ;error of communication ;For Sendhex hbuf equ H'0f' ;Hex buffer hout equ H'10' ;Hex output buffer ;Wait timer(General use) wait1 equ H'12' wait2 equ H'13' ;Timer value timeval equ H'14' ;16 per 1.04sec timenum equ H'15' ;time near second(1.048576s) ;1024 EEPROM address cpth equ H'16' ;Current end address(H,L) cptl equ H'17' rpth equ H'18' ;Address to read(H,L) rptl equ H'19' ;rpt are changed by writing writeh equ H'1a' ;Data to write(H,L) writel equ H'1b' readh equ H'1c' ;Data from EEPROM(H,L) readl equ H'1d' wrtmp equ H'1e' ;temp data to read or write wrlop equ H'1f' ;write loop counter(0 or 1) ;card cardh equ H'20' ;card id(upper 8bit) cardl equ H'21' ;casr id(lower 8bit) iscard equ H'22' ;card loaded=H'ff' other=0 ;Sending status sending equ H'23' ;0=not sending other=sending spth equ H'24' ;Sending pointer h sptl equ H'25' ;Sending pointer l sloop equ H'26' ;sending loop variable ;Other timer tmled equ H'27' ;timer for LED ligeting time tmign equ H'28' ;timer for ROM Disabling time ignore equ H'29' ;switch for ROM Disabling ;IC TAG data icd1 equ H'2a' ;Must be A'S' icd2 equ H'2b' ;Upper 8 bits icd3 equ H'2c' ;Lower 8 bits icd4 equ H'2d' ;Must be A'E' ; ;--Program start ; org H'00' Boot goto Start org H'04' Warikomi goto Start Start ;Select Bank1 movlw H'38' movwf STATUS StopInt ;Stop interrupt clrf INTCON btfsc INTCON,7 goto StopInt ;Option Setting movlw B'10000111' movwf OPTION_REG ;Port Setting movlw B'00010001';232: 2=Pwr,1=RxD,0=RTS(in) movwf TRISA ;INROM: 3=CK, 4=D(in) movlw B'00010000';OUTROM: 4=DO(IN),5=DI,6=SK,7=CS movwf TRISB ;0=LED 1,2,3=NC bcf STATUS,5 ;Select Bank0 movlw B'00000100';232 Power off movwf PORTA movlw B'00000000';All bits are low. movwf PORTB ; ; Setup current cpt address ; Find cpt where read data is H'ffff'. ; or H'0000' becomes the cpt. movlw D'100' ;Wait for 100ms for EEPROM startup call Waitxms clrf cpth ;init cpt address clrf cptl call E1024init ;init device Initcpt1 ;copy cpt into rpt movf cpth,W movwf rpth movf cptl,W movwf rptl ;read and check the value if it is ffff call E1024Read incf readh,W btfss STATUS,2 ;readh == ff ? goto Initcpt2 ;No. try next ;Yes. incf readl,W btfsc STATUS,2 ;readl == ff? goto Initcpt3 ;Yes. It's the cpt to use. ;No. try next Initcpt2 ;Here *cpt is not ffff ;Increment address incf cptl,F btfss STATUS,2 ;cptl becomes 0? goto Initcpt1 ;No. Try again. ;Yes incf cpth,F btfss STATUS,2 ;cpth becomes 0? goto Initcpt1 ;No. Try again. ;Yes. Here cpt is 0000 again. Initcpt3 ;Write reboot signal=H'fffe' into 1024 ROM movlw H'ff' movwf writeh movlw H'fe' movwf writel call E1024Write ;initialize Valiable clrf TMR0 ;clear timer setting bcf INTCON,2 clrf timeval clrf timenum clrf sending ;Not in sending mode clrf ignore ;Not in ignoring mode ; ; Main loop ; Mainloop call Chtmr0 ;timer check clrf iscard ;Not a card is default movf sending,F btfss STATUS,2 ;sending is 0? goto Mainlp1 ;No. ;Yes. wait for a while. movlw D'50' call Waitxms ;Wait to save battery ;Check if time >= 32 sec Mainlp1 movlw B'11100000' andwf timenum,W btfss STATUS,2 ;timenum>=32? goto Timepass ;Yes. ;No. ;Check if card is loaded ;tmled check movf tmled,W sublw D'15' btfss STATUS,0 ;tmled >= 16? bcf PORTB,0 ;Yes. Turn off LED ;No. ;tmign check movf tmign,W sublw D'15' btfss STATUS,0 ;tmign >= 16? clrf ignore ;Yes. Stop ignoring ;No. ;Read 4 bytes from E3EEPROM movlw H'00' call E3Read movf readh,W movwf icd1 movf readl,W movwf icd2 movlw H'01' call E3Read movf readh,W movwf icd3 movf readl,W movwf icd4 ;Verify Read data call Chtmr0 ;Check TMR0 movlw H'00' call E3Read movf readh,W subwf icd1,W btfss STATUS,2 ;icd1 == readh ? goto Sendstep ;No. Read failed. ;Yes. Continue. movf readl,W subwf icd2,W btfss STATUS,2 ;icd2 == readl? goto Sendstep ;No. Read failed. ;Yes. Continue. movlw H'01' call E3Read movf readh,W subwf icd3,W btfss STATUS,2 ;icd3 == readh ? goto Sendstep ;No. Read failed. ;Yes. Continue. movf readl,W subwf icd4,W btfss STATUS,2 ;icd4 == readl ? goto Sendstep ;No. Read failed. ;Yes. Continue. ;Verify format movf icd1,W sublw H'53' btfss STATUS,2 ;icd1 == A'S' ? goto Sendstep ;No. Format is not right. ;Yes. Continue. movf icd4,W sublw H'45' btfss STATUS,2 ;icd4 == A'E' ? goto Sendstep ;No. Format is not right. ;Yes. Continue. btfsc icd2,7 ;ID's bit 15 is 0? goto Sendstep ;No. Format is not right. ;Yes. This is the IC TAG. ;Ignore mode check btfss ignore,0 ;In ignore mode ? goto Ictagfound ;No. Save IC Tag DATA ;Yes. Read operation is invalid. clrf tmign ;ignore time is reset here. goto Sendstep Ictagfound ;Turn on LED bsf PORTB,0 clrf tmled ;Turn on Ignore mode bsf ignore,0 ;set ignore mode clrf tmign ;Set IC TAG value movf icd2,W movwf cardh movf icd3,W movwf cardl ;Go to Cardload goto Cardload ; If it is in writing mode, ; Write no more than 8 words. Sendstep movf sending,F btfsc STATUS,2 ;sending is 0? goto Mainloop ;Yes. Go back to main ;No. ;loop is 8 times movlw D'8' movwf sloop Sendmdp2 ;Send mode point 2 ;decrement spt address decf sptl,F incf sptl,W btfsc STATUS,2 decf spth,F ;Read data from E1024 ROM movf spth,W movwf rpth movf sptl,W movwf rptl call E1024Read ;readh,readl are obtained. ;Send data to EIA-574 movf readh,W call Sendhex movf readl,W call Sendhex movlw H'0a' call Sendbyte ;Check if all sending are done. ; H'7fff' or H'ffff' is stop code movlw B'10000000' iorwf readh,F incf readh,F btfss STATUS,2 ;upper 8 bit is 7f or ff? goto Sendmdp1 ;No. ;Yes. incf readl,F btfss STATUS,2 ;lower 8bit is ff? goto Sendmdp1 ;No. ;Yes. ;Final output ;Output sending address movlw A'P' call Sendbyte movlw A'=' call Sendbyte movf spth,W call Sendhex movf sptl,W call Sendhex movlw H'0a' call Sendbyte ;Output "END" movlw A'E' call Sendbyte movlw A'N' call Sendbyte movlw A'D' call Sendbyte movlw H'0a' call Sendbyte ;Turn off ADM232 movlw D'100' ;Wait for 100ms before using EIA-574 call Waitxms Call Off232 ;clear sending mode clrf sending goto Mainloop Sendmdp1 ;send mode point 1 decf sloop,F btfss STATUS,2 ;sloop becomes 0? goto Sendmdp2 ;No. Send next. goto Mainloop ;Yes. Go back to Mainloop. ;Card id = cardh,cardl Cardload decf iscard,F ;Card loaded sign ;Record time passed if timenum>0 Timepass movf timenum,W btfsc STATUS,2 ;timenum==0? goto Putsensor ;Yes. Record not required. ;No. record required. movlw H'fe' movwf writeh movf timenum,W movwf writel call E1024Write clrf timenum ;Record data from the sensor. Putsensor ;There is no sensor now. ;So, it is possible to add code here ;if sensors are implemented. ;Record card id if iscard != 0 Putcard movf iscard,F btfsc STATUS,2 ;iscard==0? goto Mainloop ;Yes. Go back to Mainloop ;No. Card loaded to record. ;There are already card id as cardh,cardl movf cardh,W andlw B'01111111' ;Card ID starts with 0 movwf writeh movf cardl,W movwf writel call E1024Write ;Check if it is "THE SEND" card(H'7ffe') movlw H'7f' subwf cardh,W btfss STATUS,2 ;cardh is 0x7f? goto Mainloop ;No. Go back to mainloop. ;Yes. movlw H'fe' subwf cardl,W btfss STATUS,2 ;cardl is 0xfe? goto Mainloop ;No. Go back to mainloop ;Yes. movf sending,F btfss STATUS,2 ;sending is 0? goto Mainloop ;No. Already sending. Go back. ;Yes. ;Start sending to EIA-574 ;device open call On232 ;Turn on ADM232A movlw D'100' ;Wait for 100ms before using EIA-574 call Waitxms clrf serror ;Clear serial output error ;Set sending status decf sending,F ;Set starting address movf cpth,W movwf spth movf cptl,W movwf sptl ;Send Header message movlw H'0a' call Sendbyte movlw H'0a' call Sendbyte movlw A'H' call Sendbyte movlw A'E' call Sendbyte movlw A'L' call Sendbyte movlw A'O' call Sendbyte movlw H'0a' call Sendbyte ;Send version code movlw A'V' call Sendbyte movlw A'=' call Sendbyte movlw VERH call Sendhex movlw VERL call Sendhex movlw H'0a' call Sendbyte ;Send current stop address movlw A'A' call Sendbyte movlw A'=' call Sendbyte movf spth,W call Sendhex movf sptl,W call Sendhex movlw H'0a' call Sendbyte ;This means data begins from here movlw A'D' call Sendbyte movlw H'0a' call Sendbyte goto Mainloop ;Change number into 2 HEX charactears ;Outputs are directly into EIA574 ;Higher 4bits are sent first. ;A byte is set in W register Sendhex movwf hbuf ;Upper 4bits swapf hbuf,W andlw H'0f' ;Upper 4 bits are obtained. movwf hout sublw D'9' movlw A'0' btfss STATUS,0 movlw H'57' ;upper 4 bits >= 10 addwf hout,W ;W is now a HEX char call Sendbyte ;Send upper HEX char ;Lower 4bits movf hbuf,W andlw H'0f' ;Lower 4bits are obtained. movwf hout sublw D'9' movlw A'0' btfss STATUS,0 movlw H'57' ;lower 4 bits >= 10 addwf hout,W ;W is now a HEX char call Sendbyte ;Send lower HEX char return ;EIA 574 Only 1ch output routine ;38400bps if OSC=4MHz ;Start bit = 1bit ;Stop bit = 1bit ;Parity = None ;Flow control added ;Turn on ADM232A On232 bsf PORTA,1 ;Data bcf PORTA,2 ;Power return ;Turn off ADM232A Off232 bsf PORTA,2 ;Power bcf PORTA,1 ;Data return ;Send a byte to 232 interface ;A byte is set in W register ;Loop for flow control added. ;serror has to be 0 before this routine ;Wait for 8sec makes error Sendbyte movwf sbuf ;Save value to send Sbtry ;Time increment check call Chtmr0 ;Error check movf serror,F btfss STATUS,2 return ;error != 0 ;Check RTS is 0(Ready) btfss PORTA,0 goto Sendnormal ;Time over check movf timenum,W sublw D'7' btfss STATUS,0 decf serror,F ;timenum >= 8 makes error goto Sbtry Sendnormal bcf PORTA, 1 ;Send a start bit nop ;;4x+1cycle wait start movlw D'4' ;17cycles wait movwf wait1 Sbp2 decf wait1,F btfss STATUS,2 goto Sbp2 ;;4x+1cycle wait end goto Sbp3 Sbp3 movlw D'8' movwf scount ;Rotate counter Sendnextbit btfss sbuf,0 goto Sendzero Sendone nop bsf PORTA,1 ;Send "1"= -12V nop goto Sbp1 Sbp1 ;;4x+1cycle wait start movlw D'3' ;13cycles wait movwf wait1 Sbp4 decf wait1,F btfss STATUS,2 goto Sbp4 ;;4x+1cycle wait end nop rrf sbuf,F ;Rotate for the next bit decf scount,F ;Count remaining bits btfss STATUS,2 goto Sendnextbit ;Go to the next bit ;Wait before the stop bit goto Sbp5 Sbp5 goto Sbp6 Sbp6 bsf PORTA,1 ;Send a stop bit ;;4x+1cycle wait start movlw D'6' ;25cycles wait movwf wait1 Sbp7 decf wait1,F btfss STATUS,2 goto Sbp7 ;;4x+1cycle wait end return Sendzero bcf PORTA,1 ;Send "0"=+12V nop goto Sbp1 ; Wait for W (ms) ; Input is set in W register Waitxms movwf wait1 Waitp1 goto Waitp3 Waitp3 ;;4x+1cycle wait start movlw D'247' ;989cycles wait movwf wait2 Waitp2 decf wait2,F btfss STATUS,2 goto Waitp2 ;;4x+1cycle wait end call Chtmr0 decf wait1,F btfss STATUS,2 goto Waitp1 return ;Check TMR0 ;Increment timeval if TMR0 is overflow Chtmr0 btfss INTCON,2 return bcf INTCON,2 incf timeval,F ;timeval increment incf tmled,F ;LED time increment incf tmign,F ;Ignore time increment Chtmr0p1 ;increment timenum if timeval>=16 movlw H'f0' andwf timeval,W btfsc STATUS,2 ;timeval>=16? return ;No. timeval <= 15 ;Yes.timeval >= 16 incf timenum,F movlw D'16' subwf timeval,F ;timeval -= 16 goto Chtmr0p1 ;Read from 1024 EEPROM ;rpth: Upper 8 bit address ;rptl: Lower 8 bit address ;readh, readl data read from EEPROM ;This routine doesn't init the device E1024rp1 ;init if device does't respond call E1024init E1024Read ;start call E1024start ;Create device address movlw B'10100000' btfsc rpth,7 iorlw B'00000010' call E1024Writeone ;Ckeck ACK btfsc wrtmp,0 ;ACK found? goto E1024rp1 ;No. Try again ;Yes. ;Create upper address rlf rpth,W andlw H'fe' btfsc rptl,7 iorlw H'01' call E1024Writeone ;Create lower address rlf rptl,W andlw H'fe' call E1024Writeone ;Send start call E1024start ;Create device address again movlw B'10100001' btfsc rpth,7 iorlw B'00000010' call E1024Writeone ;Read first byte from 1024 device call E1024Readone movf wrtmp,W movwf readh call E1024ack ;Send ACK ;Read second byte from 1024 device call E1024Readone movf wrtmp,W movwf readl call E1024noack ;Send NOACK call E1024stop return ;Write to 1024 EEPROM ;cpth: Upper 8bit address written first ;cptl: Lower 8bit address written later ;treat as 16 x 64k ;writeh, writel is data to write E1024Write ;clear the wrlop clrf wrlop ;create next address and save it to rpt movf cpth,W movwf rpth incf cptl,W movwf rptl btfsc STATUS,2 incf rpth,F E1024wp1 ;init call E1024init ;start call E1024start ;Create device address movlw B'10100000' btfsc rpth,7 iorlw B'00000010' call E1024Writeone ;Check ACK btfsc wrtmp,0 goto E1024wp1 ;ACK not found ;ACK found ;Create upper address rlf rpth,W andlw H'fe' btfsc rptl,7 iorlw H'01' call E1024Writeone ;Create lower address rlf rptl,W andlw H'fe' btfsc wrlop,0 iorlw H'01' call E1024Writeone ;Create data wrtmr=0,1:0xff tmr=2:writeh tmr=3:writel movlw H'ff' ;this value is for wrlop=0 or 1 btfss wrlop,1 goto E1024wp2 ;wrlop=0 or 1 ;wrlop=2 or 3 movf writel,W ;this value is for wrlop=3 btfss wrlop,0 movf writeh,W ;wrlop = 2 E1024wp2 call E1024Writeone ;stop call E1024stop ;wait movlw D'12' ;10ms are required. 2ms are margin. call Waitxms ;prepare for next byte incf wrlop,F ;Here, wrote wrlop bytes. movlw D'2' subwf wrlop,W btfss STATUS,2 ;wrlop == 2? goto E1024wp3 ;No. ;Yes. ;Verify if H'ffff' is written proprely. ;create next address movf cpth,W movwf rpth movf cptl,W movwf rptl incf rptl,F btfsc STATUS,2 incf rpth,F ;Read and verify. call E1024Read incfsz readh,W ;Higher byte is ff? goto E1024Write ;No. Write again. ;Yes. incfsz readl,W ;Lower byte is ff? goto E1024Write ;No. Write again. ;Yes. H'ffff' is written properly. ;rpt <= cpt movf cpth,W movwf rpth movf cptl,W movwf rptl ;Check if 4 bytes were written E1024wp3 movlw D'4' subwf wrlop,W btfss STATUS,2 ;wrote 4 bytes? goto E1024wp1 ;No. write next byte ;Yes. ;Vefiry wrote data ;[cpth,cptl] must be [writeh,writel] movf cpth,W movwf rpth movf cptl,W movwf rptl call E1024Read movf writeh,W xorwf readh,W btfss STATUS,2 ;Is writeh==readh ? goto E1024Dagain ;No. Write [writeh, writel] again. ;Yes. movf writel,W xorwf readl,W btfss STATUS,2 ;Is writel==readl ? goto E1024Dagain ;No. Write [writeh, writel] again. ;Yes. ;[writeh,writel] are written properly. ;increment current end address incf cptl,F btfsc STATUS,2 incf cpth,F return ;Write [writeh, writel] again E1024Dagain ;Set address movf cpth,W movwf rpth movf cptl,W movwf rptl ;Set count movlw D'2' movwf wrlop goto E1024wp1 ;Reset 1024 EEPROM ;this routine HALT if ROM is broken E1024init ;wait for read data is H'ffff' call E1024Readone incf wrtmp,F btfss STATUS,2 ;readdata == 0? goto E1024init ;No do it again. call E1024Readone incf wrtmp,F btfss STATUS,2 ;readdata == 0? goto E1024init ;No do it again. return ;Make a start ;A4 is read mode ;A3=0 and A4=Z E1024start bsf PORTA,3 ;CLK UP bsf STATUS,5 ;select bank 1 bcf TRISA,4 ;A4 is write mode bcf STATUS,5 ;select bank 0 bcf PORTA,4 ;set SDA=0 bcf PORTA,3 ;clk down bsf STATUS,5 ;select bank 1 bsf TRISA,4 ;A4 is read mode bcf STATUS,5 ;select bank 0 return ;Make a stop ;A4 is read mode ;A3=0 and A4=Z E1024stop bsf STATUS,5 ;select bank 1 bcf TRISA,4 ;A4 is write mode bcf STATUS,5 ;select bank 0 bcf PORTA,4 ;set SDA=0 bsf PORTA,3 ;CLK UP bsf STATUS,5 ;select bank 1 bsf TRISA,4 ;A4 is read mode bcf STATUS,5 ;select bank 0 bcf PORTA,3 ;CLK down return ;Send ACK from PIC to 1024EEPROM ;A3=0 and A4=Z E1024ack bsf STATUS,5 ;select bank 1 bcf TRISA,4 ;A4 is write mode bcf STATUS,5 ;select bank 0 bcf PORTA,4 ;set SDA=0 bsf PORTA,3 ;CLK UP goto E1024ackp1 E1024ackp1 bcf PORTA,3 ;CLK DOWN bsf STATUS,5 ;select bank 1 bsf TRISA,4 ;A4 is read mode bcf STATUS,5 ;select bank 0 return ;Send NOACK from PIC to 1024EEPROM ;A3=0 and A4=Z E1024noack bsf PORTA,3 ;CLK UP goto E1024noackp1 E1024noackp1 bcf PORTA,3 ;CLK DOWN return ;Read 1byte ;A4 is read mode ;A3=0 and A4=Z ;ACK is not created with this routine ;data is in wrtmp E1024Readone movlw D'8' movwf wait1 E1024Readonenext bsf PORTA,3 ;CLK UP RLF wrtmp,F ;shift left(MSB first) bcf wrtmp,0 ;initial value to read btfsc PORTA,4 ;DAT is 1? bsf wrtmp,0 ;Yes. ;No. bcf PORTA,3 ;CLK DOWN decf wait1,F btfss STATUS,2 ;Receive 8 bits? goto E1024Readonenext ;No. get next bit ;Yes. return ;Write 1byte ;A4 is read mode ;A3=0 and A4=Z ;ACK is not verified but time is consumed ;while receiving ACK ;data is in W register ;Return: wrtmp:ACK=0x00 NOACK=0xff E1024Writeone movwf wrtmp bsf STATUS,5 ;select bank 1 bcf TRISA,4 ;A4 is write mode bcf STATUS,5 ;select bank 0 movlw D'8' movwf wait1 E1024Writeonenext btfss wrtmp,7 goto E1024WOT1 bsf PORTA,4 E1024WOT2 bsf PORTA,3 ;CLK UP rlf wrtmp,F ;shift left goto E1024WOT3 ;wait for a while E1024WOT3 bcf PORTA,3 ;CLK DOWN decf wait1,F btfss STATUS,2 ;All 8bit sent? goto E1024Writeonenext ;No send next bit ;Yes bsf STATUS,5 ;select bank 1 bsf TRISA,4 ;A4 is read mode bcf STATUS,5 ;select bank 0 ;Receiving ACK bsf PORTA,3 ;CLK UP clrf wrtmp btfsc PORTA,4 decf wrtmp,F bcf PORTA,3 ;CLK DOWN return E1024WOT1 bcf PORTA,4 goto E1024WOT2 ;Read 2bytes from 3 wire EEPROM ;W reg is input as adress(0x00 - 0x3f) ;rptl and wait1 are used as temp data. ;readh and readl are obtained from EEPROM ;readh is first, readl is second E3Read ;Save address movwf rptl ;Init I/O port bcf PORTB,5 bcf PORTB,6 bcf PORTB,7 ;Enter Read mode bsf PORTB,7 ;Chip Select UP bsf PORTB,5 ;DI UP bsf PORTB,6 ;Out 1 bcf PORTB,6 ; bsf PORTB,6 ;Out 1 bcf PORTB,6 ; bcf PORTB,5 ;DI DOWN bsf PORTB,6 ;OUT 0 bcf PORTB,6 ; ;Send address information movlw D'6' movwf wait1 E3readnext btfss rptl,5 goto E3adr0 bsf PORTB,5 ;DI UP goto E3rp1 E3rp1 bsf PORTB,6 ;Out Ai bcf PORTB,6 ; rlf rptl,F ;Left shift decf wait1,F btfss STATUS,2 ;6 bits are sent? goto E3readnext ;No. send next bit ;Yes. ;Read 16 bits from device bcf PORTB,5 ;DI DOWN ;Now DO must be 0 ;Read first 8 bits movlw D'8' movwf wait1 E3rp2 bsf PORTB,6 bcf PORTB,6 rlf readh,F ;Left shift bsf readh,0 ;readh,0 = PORTB,4 btfss PORTB,4 bcf readh,0 decf wait1,F btfss STATUS,2 goto E3rp2 ;Read second 8 bits movlw D'8' movwf wait1 E3rp3 bsf PORTB,6 bcf PORTB,6 rlf readl,F ;Left shift bsf readl,0 ;readl,0 = PORTB,4 btfss PORTB,4 bcf readl,0 decf wait1,F btfss STATUS,2 goto E3rp3 ;Reading is done. bcf PORTB,7 ;Chip Select down return E3adr0 bcf PORTB,5 ;DI DOWN goto E3rp1 end