DIY_EFI Digest Saturday, 20 March 1999 Volume 04 : Number 183 In this issue: Re: 02 sensor - temprature compensation. EGR valves HAN (hydroxylammonium nitrate) Re: 02 sensor - temprature compensation. Re: EGR valves Re: EGR valves Somewhat off topic... Engine Diag Software? Re: Somewhat off topic... Engine Diag Software? Re: 8051 programming See the end of the digest for information on subscribing to the DIY_EFI or DIY_EFI-Digest mailing lists. ---------------------------------------------------------------------- From: Wen Yen Chan Date: Sat, 20 Mar 1999 09:36:26 -0500 Subject: Re: 02 sensor - temprature compensation. Hello, Just a thought... Why not use a cheaper 1 wire o2 sensor and monitor its temperature by measuring the sensor's impedence. Wen On Fri, 19 Mar 1999, Bruce Plecan wrote: > > -----Original Message----- > From: Espen Hilde > To: diy_efi@xxx.edu> > Date: Friday, March 19, 1999 5:06 PM > Subject: 02 sensor - temprature compensation. > > Need to have a second sensor, independent of O2 for sensing temp. > Now if you used a heated O2 sensor and used the resistance of the heater as > an indication of the EG temperature, then your cooking. Now that gm has 4 > wire O2s that is something to look at...... 830mv, can be 12.5 to 11.3:1 > depending on EGT. > Bruce > > > >Seems like its difficult to accept that a regular o2 sensor is not accurate > >in > >rich or lean and high temp conditions. > > Making wide band sensor circuit have stranded 2 times......maybe its to > >time consuming or to difficult? > >The wide band sensor is expensive...... > >What about developing a temp compensating circuit for the LM 3914 based > >led meter? > >Is this easy? > >Maybe a led temp meter with it? > >Espen Hilde > > > > ------------------------------ From: bob@xxx.com (Robert Harris) Date: Sat, 20 Mar 1999 16:36:53 GMT Subject: EGR valves Does anyone have a good purchasable reference covering late model electronically controllable EGR valves among other Smoggy Doo? The simple EFI design Dave, myself and a couple of others are working on has progressed to the point where because we are perverse, sick, insane, illegitimate offspring of female dogs we actually have found a legitimate use for EGR in a street EFI. We are looking for a reasonably affordable EGR valve that we can modulate and varying the flow - either in distinct steps or continuously by hopefully pulse width modulation. The previous information about the Ford IAC was very helpful and appreciated. Thanks in advance. 1963 Ford C-600 Prison Bus Conversion "Home" 1971 Lincoln Continental 460 "Christine" 1972 "Whale" Mustang awaiting transplant 1978 Dodge Long Bed Peeek Up "Bundymobile" Habaneros - not just for breakfast anymore ------------------------------ From: bob@xxx.com (Robert Harris) Date: Sat, 20 Mar 1999 17:23:22 GMT Subject: HAN (hydroxylammonium nitrate) For those who think that nitromethane is not just for breakfast anymore and that hydrazine adds a nice kick to your motor - just might want to check out the above chemical (H4 N2 O4) at www.hydrazine.com Water and alcohol dissolvable - might just put a tiger in your tank - developed by the army as a liquid replacement for gunpowder. Its a good thing that Timothy McVay and his government/DNC supervisors were stupid. 1963 Ford C-600 Prison Bus Conversion "Home" 1971 Lincoln Continental 460 "Christine" 1972 "Whale" Mustang awaiting transplant 1978 Dodge Long Bed Peeek Up "Bundymobile" Habaneros - not just for breakfast anymore ------------------------------ From: "Bruce Plecan" Date: Sat, 20 Mar 1999 12:35:00 -0500 Subject: Re: 02 sensor - temprature compensation. - -----Original Message----- From: Wen Yen Chan To: diy_efi@xxx.edu> Date: Saturday, March 20, 1999 9:45 AM Subject: Re: 02 sensor - temprature compensation. The O2 sensor can catch individual cylinder firings way up in the rpm band, and trying to isolate all that noise out of it seems like it would be a whole lot harder then just referencing a temp to current draw of the heater. With the isolated grounds, it would be much easier... Bruce >Just a thought... Why not use a cheaper 1 wire o2 sensor and monitor its >temperature by measuring the sensor's impedence. >Wen >> Subject: 02 sensor - temprature compensation. >> Need to have a second sensor, independent of O2 for sensing temp. >> Now if you used a heated O2 sensor and used the resistance of the heater as >> an indication of the EG temperature, then your cooking. Now that gm has 4 >> wire O2s that is something to look at...... 830mv, can be 12.5 to 11.3:1 >> depending on EGT. >> Bruce >> >Seems like its difficult to accept that a regular o2 sensor is not accurate >> >in >> >rich or lean and high temp conditions. >> > Making wide band sensor circuit have stranded 2 times......maybe its to >> >time consuming or to difficult? >> >The wide band sensor is expensive...... >> >What about developing a temp compensating circuit for the LM 3914 based >> >led meter? >> >Is this easy? >> >Maybe a led temp meter with it? >> >Espen Hilde ------------------------------ From: thergen@xxx.net Date: Sat, 20 Mar 1999 10:34:45 -0800 (PST) Subject: Re: EGR valves GM has some "linear" egr valves. It has pintle position feedback (something like a potentiometer). It is controlled by a pwm signal (I don't know the frequency) from the ecm. One app that used this is a '92 S10 4.3L vin W (not sure about the 4.3L vin Z, and many parts stores don't even list the vin W). There is no vacuum assist on this egr valve. Tom On Sat, 20 Mar 1999, Robert Harris wrote: > Does anyone have a good purchasable reference covering late model > electronically controllable EGR valves among other Smoggy Doo? > > The simple EFI design Dave, myself and a couple of others are working on has > progressed to the point where because we are perverse, sick, insane, > illegitimate offspring of female dogs we actually have found a legitimate use > for EGR in a street EFI. > > We are looking for a reasonably affordable EGR valve that we can modulate and > varying the flow - either in distinct steps or continuously by hopefully pulse > width modulation. > > The previous information about the Ford IAC was very helpful and appreciated. > > Thanks in advance. > > 1963 Ford C-600 Prison Bus Conversion "Home" > 1971 Lincoln Continental 460 "Christine" > 1972 "Whale" Mustang awaiting transplant > 1978 Dodge Long Bed Peeek Up "Bundymobile" > > Habaneros - not just for breakfast anymore > ------------------------------ From: "David A. Cooley" Date: Sat, 20 Mar 1999 14:23:08 -0500 Subject: Re: EGR valves At 10:34 AM 3/20/99 -0800, you wrote: >GM has some "linear" egr valves. It has pintle position feedback >(something like a potentiometer). It is controlled by a pwm signal (I >don't know the frequency) from the ecm. One app that used this is a '92 >S10 4.3L vin W (not sure about the 4.3L vin Z, and many parts stores don't >even list the vin W). There is no vacuum assist on this egr valve. The 94/95 Buick Lesabre VIN L uses the same thing... I think all the newer vehicles went to the linear EGR, as it's more accurate to control than a vacuum operated valve =========================================================== David Cooley N5XMT Internet: N5XMT@xxx.net Packet: N5XMT@xxx. Member #7068 I am Pentium of Borg...division is futile...you will be approximated. =========================================================== ------------------------------ From: "PC Handyman" Date: Sat, 20 Mar 1999 14:51:06 -0500 Subject: Somewhat off topic... Engine Diag Software? Does anyone know where I could find some engine Diagnostic software that will run on the PC and could potentially plug in to various OBD systems, etc.? I have seen the Snap-On one, as well as the Carsoft for BMW/Mercedes, but what I would prefer is something based on a laptop that would still take the OBD plugs, and maybe even have a few sensors... Any Ideas, Experiences? - -Noah ------------------------------ From: "David A. Cooley" Date: Sat, 20 Mar 1999 14:55:22 -0500 Subject: Re: Somewhat off topic... Engine Diag Software? At 02:51 PM 3/20/99 -0500, you wrote: >Does anyone know where I could find some engine Diagnostic software that will >run on the PC and could potentially plug in to various OBD systems, etc.? I >have >seen the Snap-On one, as well as the Carsoft for BMW/Mercedes, but what I would >prefer is something based on a laptop that would still take the OBD plugs, and >maybe even have a few sensors... > Noah, Try http://www.obdii.com/ They have the "autotap" diagnostic cable/software for OBD_II vehicles. I think it's about $250.00 =========================================================== David Cooley N5XMT Internet: N5XMT@xxx.net Packet: N5XMT@xxx. Member #7068 I am Pentium of Borg...division is futile...you will be approximated. =========================================================== ------------------------------ From: Al Lipper Date: Sat, 20 Mar 1999 12:43:47 -0800 Subject: Re: 8051 programming - --=====================_4473098==_ Content-Type: text/plain; charset="us-ascii" Ord, Thanks so much for your interest! I don't think we need too uch assembly programming, but some. Basicially, we've changed over from an Intel 80C51GB (that is no longer made) to a Phillips 80C552. They have similar features, but the capture/compare timers and A/D converter have different register structures, so the old software needs to be modified to work with the philips chip. The other thing we need done is to revise our old flash memory loader to work with a new 5v flash (we used to use a 12v version). All the current code is well commented. I've attached the files that contain it, so perhaps you can look over them and tell me what you think. Al At 02:23 PM 3/20/99 -0500, you wrote: >Al, > >I do a lot of 8051 programming, mostly in assembler (with a little MCS basic >for fun now and then). > >Perhaps I can help you with the ECU6 software. I can not spend too much >time with it, but if you have some specific problems to solve, or algorithms >that you need let me know. > >Ord > > - --=====================_4473098==_ Content-Type: text/plain; charset="us-ascii" Content-Disposition: attachment; filename="Fload.asm" ;******************************************************************** ; 8051 Boot Loader ver 3.0 ; Download standard Intel hex format files ; Assemble using ASM51.EXE by MetaLink Corp. ; Author: Steven J. Merrifield, sjm@xxx.au ; sjm 11 Apr 95 Mike Sullivan ; ; Al Lipper 7/26/97 Implemented for ECU6 ;******************************************************************** ; Using the 87C51GB. $MOD51GB r0b0 equ 00h ; Register R0, Bank0 r1b0 equ 01h ; Register R1, Bank0 r2b0 equ 02h ; Register R2, Bank0 r3b0 equ 03h ; Register R3, Bank0 r4b0 equ 04h ; Register R4, Bank0 cret equ 0dh ; carriage return lf equ 0ah ; linefeed BaudLoad equ -39 ;9600 at 12MHz SMOD equ 00000001b ; Bit to set in PCON for double baud rate ;******************************************************************** ; Interrupt vector table ;******************************************************************** org 0000h ; System reset RST ljmp main org 000bh ; Timer 0 TF0 ljmp wdt_isr ;WDT ISR to keep CPU going ;******************************************************************** ; Main program starts here ;******************************************************************** org 0030h main: lcall wdt_init ; init timer 0 for WDT reset lcall s_init ; init serial port lcall intro ; print welcome message lcall e_prompt ; erase prompt LCALL F_ERASE ; call flash erase routine lcall hexload ; read hex file and save in flash done_main: lcall end_msg ; Display done message sjmp done_main ; loop forever ; Read Intel hex file from serial port and store in flash HEXLOAD: PUSH PSW mov dptr,#p_rxhex ; Print 'Ready for hex file' message lcall outstr ANL PCON,#11110000B ; Clear flag bits SJMP GetHex ; Wait for either ':' (Start), ; CR, or LF. Ck_CR: CJNE A,#CRET,Ck_LF ; Any other chars will set the SJMP WAIT ; error flag. Ck_LF: CJNE A,#LF,Ck_C SJMP WAIT Ck_C: CJNE A,#3,CharErr ; Check for SJMP HEX_DONE CharErr:ORL PCON,#8 ; Set error flag CALL C_OUT SJMP WAIT GetHex: JNB TI,$ CLR TI MOV SBUF,#'>' ; Output pace character WAIT: CALL GetChar ; Wait to receive a character CJNE A,#':',Ck_CR ; Wait for start character ? CALL C_OUT SETB F0 ; --------- THE MAIN ENTRY POINT FOR HEXLOAD -------- MOV R2,#0 ; Start checksum CALL RdByte ; 1) Get record length MOV R0,A ; Save length CALL RdByte ; 2) Get high address MOV DPH,A CALL RdByte ; 3) Get low address MOV DPL,A CALL RdByte ; 4) Get record type JZ GetDat ; 0 if data, 1 if last record CLR F0 ; Clear flag GetDat: MOV A,R0 ; Check record length JZ IsEnd DataIn: CALL RdByte ; 5) Get a byte JNB F0,NoStor ; Store if data record WriteX: ; movx @dptr, a LCALL WR_BYTE ; Write to flash CJNE A, #02h, NoHexErr ; Check for pgm error MOV R4, #02h ; Save code for program error ; SJMP HEX_DONE ; Abort loading & report error NoHexErr: INC DPTR ; Point to next addr. in flash NoStor: DJNZ R0,DataIn ; Get more bytes DEC R0 ; R0 = FF IsEnd: CALL RdByte ; Get checksum byte MOV A,R2 JZ ChkOK ORL PCON,#4 ChkOK: MOV A,#CRET CALL C_OUT MOV A,R0 ; Will be FF for data record JNZ GetHex ; Read another record? MOV A,#0CH ; Now check for any errors ANL A,PCON JZ HEX_DONE ; Checksum Error cs_error: mov dptr,#p_cserror lcall outstr mov R4, #04 ; Save code for Checksum error HEX_DONE: POP PSW RET ; All done so return GetChar:JNB RI,$ ; Character in SBUF ? MOV A,SBUF CLR RI CLR ACC.7 ; Clear parity bit RET ; Get 2 chars & make a 2 digit byte. Return byte in acc. RdByte: SETB PSW.1 DoAgin: MOV R3,A CALL GetChar ; Get a single character CALL C_OUT ; Echo it CLR C SUBB A,#'0' JNC Do_1 ; Not a digit ? (<30H ?) ORL PCON,#8 ; Set error flag CLR F0 ; DO NOT store this record Do_1: SUBB A,#10 ; Test for A-F JC IsNmbr SUBB A,#7 ; Adjust for gap IsNmbr: ADD A,#10 ; Restore ANL A,#0FH JBC PSW.1,DoAgin ; 2nd time ? SWAP A ORL A,R3 SWAP A ; 2 digits in ACC XCH A,R2 ; Get Checksum ADD A,R2 ; Update it and XCH A,R2 ; get byte back. RET C_OUT2: CALL C_OUT ; Send the character twice. C_OUT: JNB TI,$ ; Wait til last character gone. CLR TI ; Clear interrupt flag. MOV SBUF,A ; Write out character. CJNE A,#CRET,CONT ; If it was then follow with . JNB TI,$ CLR TI MOV SBUF,#LF ; Output linefeed. CONT: RET ;******************************************************************** ; Erase prompt message ;******************************************************************** e_prompt: mov dptr,#p_ersprmpt ; print erase prompt lcall outstr lcall inchar ; get char from serial port cjne a,#'e',e_prompt ; if "e" not pressed, loop lcall inchar cjne a,#'r',e_prompt ; if "r" not pressed, loop lcall inchar cjne a,#'a',e_prompt ; if "a" not pressed, loop lcall inchar cjne a,#'s',e_prompt ; if "s" not pressed, loop lcall inchar cjne a,#'e',e_prompt ; if "e" not pressed, loop ret ;******************************************************************** ; Print welcome message ;******************************************************************** intro: mov dptr,#p_intro1 lcall outstr mov dptr,#p_intro2 lcall outstr ret ;******************************************************************** ; Print finished message or error ;******************************************************************** ; NOTE: If more than one error occurs, only the first one will be reported end_msg: mov A, R4 ; Get Error code cjne A, #00h, erase_err ; Check for No Error No_Err: mov dptr,#p_finish lcall outstr sjmp end_exit erase_err: cjne A, #01h, pgm_err ; Check for Erase Error mov dptr,#p_ererror lcall outstr sjmp end_exit pgm_err: cjne A, #02h, zero_err; Check for Zeroing Error mov dptr,#p_pgmerror lcall outstr sjmp end_exit zero_err: cjne A, #03h, cksm_err; Check for Checksum Error mov dptr,#p_zrerror lcall outstr sjmp end_exit cksm_err: cjne A, #04h, inval_err; Check for undefined Error code mov dptr,#p_cserror lcall outstr sjmp end_exit inval_err: mov dptr,#p_iverror lcall outstr end_exit: ret ;******************************************************************** ; Wait until a char is received from the serial port, and return ; that char in the accumulator. ;******************************************************************** inchar: jnb ri,inchar ; wait until ri is set clr ri ; clear interrupt mov a,sbuf ; get character ret ;******************************************************************** ; Wait until tx ready, then send a char out serial port ;******************************************************************** outchar: jnb ti,outchar ; wait until ti is set clr ti ; clear it mov sbuf,a ; send acc to serial buffer ret ;******************************************************************** ; Send a null terminated string out serial port ;******************************************************************** outstr: clr a movc a,@a+dptr ; get character jz exit ; stop if char == null lcall outchar ; else send it inc dptr ; point to next char sjmp outstr exit: ret ;******************************************************************** ; Init serial port ;******************************************************************** ; *** Alternate baud rate init routine for 9600 baud at 12 Mhz (Using Timer2) *** ; Taken from Intel serio2m.asm. ; S_INIT: CLR TR1 MOV SCON,#01011010B ;TI set indicates transmitter ready. ; mode 1,REN MOV T2CON,#00110000B; Initialize Timer 2 as Baud Rate generator orl PCON,#SMOD ; Set to double rate. setb smod mov rcap2h,#High BaudLoad ; Set reload value mov rcap2l,#low Baudload setb tr2 ; start timer. ret ; ck_error: mov dptr,#p_cserror lcall outstr stop: sjmp stop p_intro1: db cret,'ECU Flash Memory Loader v1.1 7/24/97',cret,lf,0 p_intro2: db cret,'(c) 1997 Injection Logic',cret,lf,0 p_ersprmpt: db cret,lf,'Enter to Erase Chip',cret,lf,0 p_finish: db cret,'Finished downloading: Switch Back to Run Mode',cret,lf,0 p_zero: db 'Zeroing...',0 p_erase: db 'Erasing...',0 p_erdone: db 'Erase Completed',cret,lf,0 p_rxhex: db cret,lf,'Ready to receive Intel Hex file',cret,lf,0 ; Error message text. Note R4 will contain error code (or 0 for no error) p_ererror: db cret,lf,'Flash Erase Error',0 ; R4 = 1 p_pgmerror: db cret,'Flash Programming Error during HEXLOAD',cret,lf,0 ; R4 = 2 p_zrerror: db cret,lf,'Erase Zeroing Error',0 ; R4 = 3 p_cserror: db cret,'Serial Data Checksum Error Detected ',cret,lf,0 ; R4 = 4 p_iverror: db cret,'Invalid Error Code Returned ',cret,lf,0 ; R4 > 4 ; ;------------------------------------------------------------------------------ ; Macros ; ; The following macros are used to control assembly options. ;------------------------------------------------------------------------------ WAIT6us MACRO ; wait 6 microseconds @ 12MHz push acc mov acc,#01 djnz acc,$ pop acc ENDM ; ; The 10us time delay ; WAIT10us MACRO ; wait 10 microseconds @ 12MHz push acc mov acc,#03h djnz acc,$ pop acc ENDM ; ; 10 ms time delay ; WAIT10ms MACRO ; wait 10 millisecond @ 12MHz push acc mov acc, #10 W10: push acc mov acc,#249 djnz acc,$ mov acc,#249 djnz acc,$ pop acc djnz acc, W10 pop acc ENDM ;----------------------------------------------------------------------------- ; ; Critical Design Information: ; ; 1. For Flash devices, program/erase timing is extremely important. This ; software uses a busy-wait loop to time the program and erase functions. ; Processor/memory speed is therefore of critical importance to correct ; and reliable programming and erasure. In general, use of this software ; requires tailoring it to the timing of each individual system. ; 2. Programming Flash devices requires a 12.0V power supply. ; Control of Vpp is system dependent. Users must supply one function ; -- VPP -- that will be called to turn Vpp on or off. On entry to VPP, ; the ACC register contains a code specifying the desired operation as ; follows: ; ; ACC = 0 Turn Vpp off ; ACC = 1 Turn Vpp on ; ; ; ; Abstract: ; ; This software is designed to support the In-system programming requirements ; of Intel's Flash memory. ; ; This software module is supplied in source code form. The software is ; written in MSC-51 assembly language using Intel ASM51 assembler. It ; is designed to be assembled and linked with other system and application ; software to form an integrated program. ; ; The following functions are supported: ; ; 1. Erase. Used to erase a single Flash memory before programming. ; 2. Program byte. Used to program single data elements, typically for ; data collection applications. ; ; Function Details: ; ; Overview: ; ; Erase ; This operation erases the Flash memory whose base address is ; contained in the DPTR register. The the base address of the 28F010 ; Flash memory is mapped at 0000h. ; ; Write Byte ; This operation writes a single byte (in ACC) into the Flash memory ; at the address contained in the DPTR register: ; ; ACC Byte data ; DPTR Flash memory address ; ; Hardware Configurations: ; ; This software is designed and implemented for the MCS-51 family. ; ; Language ; ; This software is designed to assemble under the Intel ASM51 Assembler, ; on the IBM PC and compatibles. ;============================================================================== ;------------------------------------------------------------------------------ ; Miscellaneous Definitions ;------------------------------------------------------------------------------ M_ETRIES_LOW equ 0E8H ; 1000 erase tries maximum low byte M_ETRIES_HIGH equ 03H ; 1000 erase tries maximum high byte M_PTRIES equ 25 ; 25 program tries maximum F_BASE_ADDRESS equ 0000H ; Flash base address F_ENDL equ 00H ; flash last address+1 (LSB) - FFFFH is last addr. F_ENDH equ 00H ; flash last address+1 (MSB) ;------------------------------------------------------------------------------ ; Command Definitions ; ; These commands are written to the Flash memory to run the internal state ; machine. ;------------------------------------------------------------------------------ C_ERAS equ 020H ; enter erase state C_PROG equ 040H ; enter program state C_EVER equ 0A0H ; enter erase verify state C_PVER equ 0C0H ; enter program verify state C_READ equ 000H ; enter read state ;------------------------------------------------------------------------------ ; Error Definitions ; ; These error values are used to identify MBM operation errors. ;------------------------------------------------------------------------------ OK equ 0 ; no error E_ERASE equ 1 ; erase operation failed E_PROGRAM equ 2 ; program operation failed ;-------------------------------------------------------------------------- ; This routine is used to erase the content of a 28F010. ; ; Input parameters : ; DPTR = base address of the 28F010 ; Oputput parameters : ; ; Other registers used ; R2,R3 = number of erase pulses (high byte in R3) ; R4 = Code indicating error ;------------------------------------------------------------------------------ f_erase: mov dptr,#p_zero ; print 'Zeroing...' lcall outstr push dph ; save dptr push dpl mov r4, #00h ; Reset error code (0 = no error) ; ; Erase algorithm suggests testing to see if flash is erased before erasing it. This ; step is skipped since flash should not ordinarily be previously erased at this point. ; First set all bytes to 00H in preparation for erase. wr_next_page: mov dptr,#f_base_address ; load the flash base address wr_next: mov a,#00h call wr_byte ; programm 00h cjne a,#e_program,nexta mov R4, #03h ; Save zeroing error code sjmp erase_end ; return Zeroing error nexta: inc dptr ; next address ;Check to see if current address has reached last flash address mov a,dpl ; first check low byte cjne a, #f_endl, wr_next mov a,dph ; then check hi byte cjne a, #f_endh, wr_next ; ; ;-------------- now erase the 28F010 erase: mov dptr,#p_erase ; print 'Erasing...' lcall outstr mov dptr, #f_base_address mov r2, #M_ETRIES_LOW ; max. erase retries low byte mov r3, #M_ETRIES_HIGH ; max. erase retries high byte ; max. erase retries = 1000 era_again: mov a, #c_eras movx @dptr, a ; write E_code to CMD register movx @dptr, a ; write again to confirm wait10ms mov a, #c_ever movx @dptr, a ; stop, enter erase verify wait6us ; for high voltage switch ; Verify that flash is erased (all bytes contain FFh) loop: clr a movx a, @dptr ; read back cjne a, #0ffh, next_pulse inc dptr ; next address ;Check to see if current address has reached last flash address mov a,dpl ; first check low byte cjne a, #f_endl, loop mov a,dph ; then check hi byte cjne a, #f_endh, loop ;erased: mov a, #ok ; return code sjmp erase_end ; Erase attempt failed, try erase again if less than 1000 attempts next_pulse: dec r2 ; increment erase count cjne r2, #0ffh, era_again ; if less than 1000 continue dec r3 cjne r3, #0ffh, era_again mov a, #e_erase ; more than 1000, return error code erase_end: push acc ; save return code mov dptr,#f_base_address ; address to flash mov a,#c_read ; write read code movx @dptr,a pop acc ; restore return code pop dpl pop dph cjne a, #e_erase, ck_pgmerr ; check for erase error mov dptr,#p_ererror ; print 'Erase Error' lcall outstr mov r4, #01h ; Save erase error code sjmp er_exit ; at this point, a programming error is due to flash not zeroing correctly ck_pgmerr: cjne a, #e_program, er_success ; check for zeroing error mov dptr,#p_zrerror ; print 'Zeroing Error' lcall outstr mov r0, #03h ; Save zeroing error code sjmp er_exit er_success: mov dptr,#p_erdone ; print 'Erase Completed' lcall outstr er_exit: ret ;************************************************************************* ; ; NAME: WR_BYTE ; ; ABSTRACT: This routine program a byte of data of a Flash memory ; using Quick Pulse programming algorithm. The address is loaded in ; DPTR register and the data is loaded in the accummulator. ; ; INPUTS: DPTR programmed address ; A data ; ; OUTPUTS: none ; ; REGISTERS MODIFIED: ; R0 save data ; R1 number of programming loops ; ; ERROR: A = 00h programmed without error ; A = 02h failed to program ; ; SUBROUTINES ACCESS DIRECTLY: ; wait10us delay 10us (macro) ; wait6us delay 6us (macro) ; ;************************************************************************* wr_byte: push r0b0 ; save r0 push r1b0 ; save r1 mov r0,a ; save data in acc. mov r1, #m_ptries ; allow 25 prog pulses again: mov a,#c_prog ; load code to program movx @xxx. mov a,r0 ; restore data movx @dptr, a ; write data wait10us ; programming pulse width mov a,#c_pver ; load program verify code movx @xxx., enter verify mode ; switch to program verify mode wait6us ; wait for 6us clr a ; ACC=0 for next instruction movx a,@dptr ; read back clr c subb a, r0 ; compare with programmed data jz wr_done ; next address djnz r1,again ; after 25 loops mov a,#e_program ; return with error code sjmp err_done wr_done: mov a,#ok ; return ok code err_done: push acc ; store return code mov a,#c_read ; write read code movx @dptr,a pop acc ; restore return code pop r1b0 ; restore r1 pop r0b0 ; restore r0 ret ;WDT routines - see Intel appnotes (AB-44) ;Initialize timer 0 for watchdog ISR wdt_init: setb ea setb et0 mov tmod, #01h mov tl0, #7fh mov th0, #0c0h setb tr0 ret ; WDT reset - WDT needs to be reset every 16ms or it will reset the CPU ; Timer 0 is used to call this ISR to do this reset. wdt_isr: ; setb p1.5 ;debug clr tr0 mov wdtrst, #1eh mov wdtrst, #0e1h mov tl0, #7fh mov th0, #0c1h setb tr0 ; clr p1.5 ;debug CPL P1.6 ; Invert Reset IC's (MAX805L) Watchdog timer bit reti end - --=====================_4473098==_ Content-Type: text/plain; charset="us-ascii" Content-Disposition: attachment; filename="EFI02.asm" $NOPAGING ; 6/7/97 - added WDT routines ; efi00.asm 950204RHAL ; ASM routines for Electronic Fuel Injection System. ; Includes ISRs for RPM and injector pulsing. ; Using the 87C51GB. $MOD51GB ;************************************************************************* ; Memory useage, Variable declaration, and Vector tables-- r0b0 equ 00h ; Register R0, Bank0 r1b0 equ 01h ; Register R1, Bank0 ; Variables for use in/with ASM routines. ; Note: Internal bits 00-0F use internal memory locations 20 and 21. ; Internal Bits 00-07 for ASM only flags. ; Internal Bits 08-0F for BASIC/ASM flags. SP_SYNC BIT 008h ; Set when Injector Pulse is to be ; Synchronized with Spark Pulse. ; Written by Main loop. EX_ASYNC ; must be called by main loop when ; this value is changed. ; Direct addresses 18H-21H of Internal RAM for BASIC/ASM variables. ; These addresses are not used by the compiler ; External addresses FFF0-FFFF are used to transfer data to BASIC OLD_CCAP0 DATA 018h ; Previous PCA0 capture value, 2 ; bytes (lo-hi). Used to compute ; Spark Pulse period. Used only ; in ISR (Static Local). PW1 DATA 01Ah ; Injector Pulse Width (count for ; PCA1), 2 bytes (lo-hi). Data is ; passed from Main to ISR here. ; Main loop should clear EC0 when ; when writing these bytes. RPMPW DATA 01Ch ; Spark Pulse period, 2 bytes. Data ; is passed from ISR to Main here. ; Main loop should clear EC0 when ; when reading these bytes. APP DATA 01Eh ; Async Injector Pulse Period. Data ; is passed form Main to ISR here. ; Main loop should clear EC0 when ; when writing these bytes. TICK15 XDATA 0FFF6H ; Two byte counter, incremented ; every 15ms by WDT_ISR: for use by ; BASIC program in timed operations. ; A/D Converter addresses ADC_0 DATA 084h ; A/D Converter channel 0 ADC_1 DATA 094h ; A/D Converter channel 1 ADC_2 DATA 0A4h ; A/D Converter channel 2 ADC_3 DATA 0B4h ; A/D Converter channel 3 ADC_4 DATA 0C4h ; A/D Converter channel 4 ADC_5 DATA 0D4h ; A/D Converter channel 5 ADC_6 DATA 0E4h ; A/D Converter channel 6 ADC_7 DATA 0F4h ; A/D Converter channel 7 ACON DATA 097h ; A/D Converter control register ;A/D Converter uses FFF8-FFFF as mirror locations for the above registers ADC_MIRR XDATA 0FFF8h ; A/D Mirror for transfer to BASIC ; Enter values into Interrupt Vector "Mirror." ORG 0FE00H ; RESET VECTOR JMP WDT_INIT ; INIT TIMER 0 FOR WDT RESET ORG 0FE0Bh ; Timer 0 TF0 LJMP WDT_ISR ; WATCHDOG TIMER (WDT) ISR ORG 0FE33h ; PCA INTERRUPT VECTOR LOCATION LJMP ISR_PCA ; Jump to PCA Interrupt Handler. ;************************************************************************* ; BASIC call vectors-- ORG 0FE50H ; Put at very top of code memory ; (must be decreased if code is expanded) AJMP INIT ; Init routine. AJMP READ_ADC ; Read A/D Converter AJMP EX_ASYNC ; Handle change of SP_SYNC. AJMP IAC_HIGHER ; IAC motor init for higher idle AJMP IAC_LOWER ; IAC motor init for lower idle AJMP IAC_STEP ; Step IAC motor in selected direction AJMP IAC_OFF ; Turn off power to IAC motor (doesn't move) ;************************************************************************* ; Startup routines-- INIT: ; Init stuff for ASM routines. setb p4.0 ;debug MOV IP,#01000010b ; Set PPC and PT0 (PCA0 2nd, Timer0 1st) MOV IE,#11000010b ; Enable global (EA), PCA (EC) and TIMER0 (ET0) ints. MOV CMOD,#00 ; Setup PCA Counter Mode. (f.osc/12) MOV CCON,#01000000b ; Enable PCA counter (CR) MOV CCAPM0,#00100001b ; Set PCA0 Mode: Capture positive ; edge and enable PCA interrupt. SETB SP_SYNC ; Set flag to sync mode initially ACALL EX_ASYNC ; Set sync mode (based on flag) MOV DPTR, #TICK15 ; Clear 2 BASIC counter register MOV A, #00 ; bytes. MOVX @xxx. INC DPTR ; then clear the second byte. MOVX @DPTR, A ; MOV ACON,#00010000b ; Enable A/D Converter ; Setup I/O ports. Inputs must be set to 1 before they will work. ; See "8051 IO Ports.xls" for specific pin functions. SETB P1.0 ; Cranking SETB P1.1 ; Key on SETB P1.3 ; SP in SETB P3.2 ; External Int 0 SETB P3.4 ; A/C on SETB P5.2 ; DIP SW 2 SETB P5.3 ; DIP SW 1 clr p4.0 ;debug RET ;************************************************************************* ; Main Loop subroutines-- ; ASM routine called by BASIC to start or end Async Injection Mode based on ; Async Mode flag, must be called when ever SP_SYNC is changed. EX_ASYNC: ; setb p4.1 ;debug MOV CCAPM3,#0 ; Disable PCA3. JB SP_SYNC,EA_OFF ; Check Sync Mode Flag. ; Startup Async Mode. CLR CCF3 ; Clear any pending IRQ for PCA3. MOV CCAP3L,#0 ; Setup Compare Register with MOV A,CH ; 0.25-0.51 ms from now to start ADD A,#2 ; 1st Async pulse. MOV CCAP3H,A MOV CCAPM3,#01001001b ; Set PCA3 for Compare Mode and ; Enable Interrupt. EA_OFF: ; clr p4.1 ;debug RET ; Done. ; Read AD Converter and store in mirror locations (ADCMIRR..ADCMIRR+7) since ; the internal locations which contain the registers are not accesible from ; from BASIC. READ_ADC: PUSH ACC PUSH DPL PUSH DPH PUSH PSW MOV DPTR,#ADC_MIRR ; Put first mirror address in DPTR MOV A,ADC_0 ; Read A/D Channel 0 MOVX @DPTR,A ; Save channel 0 to mirror location MOV A,ADC_1 ; Read A/D Channel 1 INC DPTR ; Increment mirror address MOVX @DPTR,A ; Save channel 1 to mirror location MOV A,ADC_2 ; Read A/D Channel 2 INC DPTR ; Increment mirror address MOVX @DPTR,A ; Save channel 2 to mirror location MOV A,ADC_3 ; Read A/D Channel 3 INC DPTR ; Increment mirror address MOVX @DPTR,A ; Save channel 3 to mirror location MOV A,ADC_4 ; Read A/D Channel 4 INC DPTR ; Increment mirror address MOVX @DPTR,A ; Save channel 4 to mirror location MOV A,ADC_5 ; Read A/D Channel 5 INC DPTR ; Increment mirror address MOVX @DPTR,A ; Save channel 5 to mirror location MOV A,ADC_6 ; Read A/D Channel 6 INC DPTR ; Increment mirror address MOVX @DPTR,A ; Save channel 6 to mirror location MOV A,ADC_7 ; Read A/D Channel 7 INC DPTR ; Increment mirror address MOVX @DPTR,A ; Save channel 7 to mirror location POP PSW POP DPH POP DPL POP ACC RET ;************************************************************************* ; Interrupt Service Routines-- ; Interrupt Service Routine for all PCA interrupts. Determines which ; PCA generated the int. and jumps to the corresponding routine. ISR_PCA: JBC CCF0,ISR_PCA0 ; Check & clear flag for PCA0. JBC CCF1,ISR_PCA1 ; etc. JBC CCF3,ISR_PCA3 RETI ; Others are not used. ; Interrupt Service Routine for End of Injection Pulse -- PCA 1 (Inj 1). ; PCA 2 (Inj 2) is not currently used as an independent timer, but just as a ; single bit output based on the timer used by inj. 1. ISR_PCA1: MOV CCAPM1,#0 ; Disable PCA Module 1. Turn off inj. #1 CLR P1.5 ; Turn off Inj. #2 RETI ; Return from Interrupt. ; Interrupt Service Routine for Starting Async Injection Pulses -- PCA3. ISR_PCA3: ;setb p4.3 ; debug PUSH PSW ; Save registers. PUSH ACC ACALL SETPW ; Handle Starting Output Pulse. MOV A,APP ; Set up this PCA for the next Async ADD A,CCAP3L ; Pulse. MOV CCAP3L,A ; Add Async period to last time MOV A,APP+1 ; for next time. Also, note ADDC A,CCAP3H ; that PCA Compare is disabled MOV CCAP3H,A ; by hardware between write of ; low and high CAP bytes. ;clr p4.3 ; debug AJMP IP0_RTI ; Done, restore registers and return ; from interrupt. ; Interrupt Service Routine for Spark Timing (RPM) -- PCA 0. Also starts ; Injection Pulse when in Synchronous Mode. ISR_PCA0: PUSH PSW ; Save registers. PUSH ACC setb p4.2 JNB SP_SYNC,IP0_RPM ; If in Async mode, skip output ; pulse. ACALL SETPW ; Handle Starting Output Pulse. IP0_RPM: CLR C ; Compute RPM Pulse Width. MOV A,CCAP0L ; RPMPW = CCAP0 - OLD_CCAP0 SUBB A,OLD_CCAP0 ; (16-bit subtract) MOV RPMPW,A MOV A,CCAP0H ; Do MSB. SUBB A,OLD_CCAP0+1 MOV RPMPW+1,A MOV OLD_CCAP0,CCAP0L ; Save CCAP0 for next time. MOV OLD_CCAP0+1,CCAP0H IP0_RTI: POP ACC ; Restore registers. POP PSW clr p4.2 ; debug RETI ; Return from Interrupt. ; Handle Starting an Output Pulse. Common to ISR_PCA0 & ISR_PCA3. SETPW: ; Test for zero output pulse width. setb p4.4 ; debug MOV A,PW1 ; Get LSB of PW. JNZ SPW_SETPW ; If not zero, setup PW. MOV A,PW1+1 ; Get MSB of PW. JZ SPW_DONE ; If zero, skip PW. MOV A,PW1 ; Get LSB of PW. SPW_SETPW: SETB CEX1 ; Start output pulse. Turn on inj. #1 SETB P1.5 ; Turn on Inj. #2 JNB SP_SYNC,SPW_ASYN ; Handle PW for Sync Mode. SPW_SYNC: ADD A,CCAP0L ; Setup PCA1 for output pulse MOV CCAP1L,A ; width. CCAP1 = CCAP0 + PW1 MOV A,PW1+1 ; (16-bit add) ADDC A,CCAP0H SPW_FIN: MOV CCAP1H,A ; Finish both paths. MOV CCAPM1,#01001101b ; Set PCA1 for High Speed Output ; and enable interrupt. clr p4.4 ;debug SPW_DONE: RET ; Return from Subroutine. SPW_ASYN: ADD A,CCAP3L ; Handle PW for Async Mode. MOV CCAP1L,A ; Setup PCA1 for output pulse MOV A,PW1+1 ; width. CCAP1 = CCAP3 + PW1 ADDC A,CCAP3H ; (16-bit add) AJMP SPW_FIN ; Go finish. IAC_HIGHER: ; IAC motor init for higher idle CLR P5.4 ; Set step output low CLR P5.5 ; Set direction to higher idle SETB P5.6 ; Enable IAC (Turn on) RET IAC_LOWER: ; IAC motor init for lower idle CLR P5.4 ; Set step output low SETB P5.5 ; Set direction to higher idle SETB P5.6 ; Enable IAC (Turn on) RET IAC_STEP: ; Step IAC motor in selected direction SETB P5.4 ; Set step output high NOP ; Delay for 10us NOP ; for step to be initiated (MC3479 - PWCKx) NOP NOP NOP NOP NOP NOP NOP NOP CLR P5.4 ; Set step output low RET IAC_OFF: ; Turn off power to IAC motor (doesn't move) CLR P5.6 ; Disable IAC (Turn off) CLR P5.4 ; Set step output to low (it should already be low) RET ; WDT routines - see Intel appnotes (AB-44) ; Initialize timer 0 for watchdog ISR - see WDT_ISR: ; Note: Each timer 'tick' is osc/12 secs. WDT_INIT: setb p4.5 ;debug SETB EA ; Enable All interrupts SETB ET0 ; Enable Timer0 Int SETB PT0 ; Set Timer0 int to 1st priority (highest) PT0 MOV IPH,#00000010b ; Set PT0H MOV TMOD, #01 ; Set Timer0 mode to 16-bit, no prescale MOV TL0, #67H ; Set the timer to interrupt (hit FFFF) in 15000 ticks MOV TH0, #0C5H ; FFFF-3A98 = C567 (65535-15000 = 50535) SETB TR0 ; Start the timer clr p4.5 ;debug RET ; This ISR has 3 functions: ; 1) To reset the WDT before 16.3667 ms passes (at 12 MHz) ; 2) To check for rapid TPS movement ; 3) To increment a byte for use as a counter for EGO and related routines ; WDT reset - WDT needs to be reset every 16.3667ms or it will reset the CPU ; Timer 0 is used to call this ISR every 15ms to do this reset. WDT_ISR: setb p4.6 ;debug PUSH DPH PUSH DPL PUSH ACC PUSH PSW CLR TR0 ; stop timer 0 MOV WDTRST, #1EH ; clear WDT MOV WDTRST, #0E1H MOV TL0, #67H ; Set the timer to interrupt (hit FFFF) in 15000 ticks MOV TH0, #0C5H ; FFFF-3A98 = C567 (65535-15000 = 50535) SETB TR0 ; restart timer 0 ; Pulse bit for external WDT/reset IC. Inverts every time through. ; This should NOT be kept in the ISR, it needs to be in the main BASIC loop CPL P1.6 ; Invert Reset IC's WDT bit ; Increment BASIC counter bytes MOV DPTR, #TICK15 ; Get counter address MOVX A, @DPTR ; Put the contents of TICK15 in A (LSB) INC A ; Increment it MOVX @DPTR, A ; Put it back in TICK15 JNZ WDT_EXIT ; If it hasn't rolled over to 00, then exit INC DPTR ; Do the MSB MOVX A, @DPTR MOV A, #00 ; MOVX A, @DPTR ; Put the contents of TICK15+1 in A (MSB) INC A ; Increment it MOVX @DPTR, A ; Put it back in TICK15+1 WDT_EXIT: POP PSW POP ACC POP DPL POP DPH clr p4.6 ;debug RETI END - --=====================_4473098==_ Content-Type: text/plain; charset="us-ascii" - --=====================_4473098==_-- ------------------------------ End of DIY_EFI Digest V4 #183 ***************************** To subscribe to DIY_EFI-Digest, send the command: subscribe diy_efi-digest in the body of a message to "Majordomo@xxx. A non-digest (direct mail) version of this list is also available; to subscribe to that instead, replace "diy_efi-digest" in the command above with "diy_efi".