??? 05/25/05 02:18 Read: times |
#93854 - movx a,@dptr! |
Hi Guys,
I have been trying to figure out a problem with a small program that I am doing. I am fairly new with 8051 so please bear with me. I have built an eeprom I2C programmer using an old Dallas 5000FP that I received in the development kit a few years back. The program uses any terminal program and runs at 9600 baud. It will read eeproms 24C16 to 24C256 and dump the code to the terminal screen. You can also send a file you want programmed in the eeprom through the terminal program. The data to be programmed (sent through the terminal program) is stored in the Dallas's NVRAM temporarily, then it is written to the eeprom afterwards. I have tested the I2C routines, all are working both read and write. The problem I have is that the first byte from every line is being written to the entire line, its as if the dptr is not being incremented while trying to fetch a byte from the RAM. I tried a debug routine that would print the bytes being written to the terminal and everything is working perfect. The data to be written is being stored in the NVRAM at addr 4000h (partitioned the chip @4000 while programming). I am sure of this because i read the contents of the DALLAS at addr 4000 and the file being sent from the terminal program is there, every byte, So the problem is when the byte is being fetched from the RAM, it is the first byte of every line continually written 10 times. The next line, same thing. I have been trying everything and the code seems perfect. I simply do not know what is happening (and I think I am tired of pulling my hair out) Here is an example: send this file through the terminal: :10000000800075A800758170787FE4F6D8FD120431 :10001000B71202E39004BD120461790F1202E3D912 :10002000FB120487B43103020071B432030200BE34 will be written like this: :10000000808080808080808080808080808080808000 :10001000B7B7B7B7B7B7B7B7B7B7B7B7B7B7B700 :10002000FBFBFBFBFBFBFBFBFBFBFBFBFBFB00 I have no idea why this simple thing is giving me trouble. I have attached my source code and would appreciate any help from the pros. This is just a learning thing for me and there is absolutely no profit involved. As far as I can tell it should work! Maybe I overlooked a something simple. The problem lies in the Prog_eep routine. The code still needs to be cleaned up a bit but it is fully functional with the exception of the one problem above. thanks CT Here is the source: ;******************************************************************** ; 8051 Boot Loader ver 3.0 ; Download standard Intel hex format files ; uses DALLAS 5000 NV RAM for temporary storage of file sent through terminal ; @9600 baud. ; when loading set partition at 4000 ;******************************************************************** $mod51 ; symbol definitions DYTA equ 10H ; data byte to be written filesizeH equ 23h ;to measure length of file being downloaded filesizeL equ 22h ;so we know how many bytes to write addrhi equ 21h ;used for writing eeprom addrlo equ 20h ;used for writing eeprom CKSUM equ 1Fh ; Intel Hex Checksum Reg count equ 1Eh ; byte counter progcntr EQU 1Dh ; progress bar counter to slow down symbols L_SIZE EQU 1Ch ; eeprom size low byte H_SIZE EQU 1Bh ; eeprom size high byte SCL BIT p1.2 ; serial clock SDA BIT p1.3 ; serial data LF EQU 0Ah ; Line Feed character. CR EQU 0Dh ; Carriage Return character. ESC EQU 1Bh ; Escape character. StartChar EQU ':' ; Line start character for hex file. space equ 020h ; ascii space Ser_RX equ p3.0 ; Serial RX Ser_TX equ p3.1 ; Serial TX BITTIM equ 45 ;9600 Baud (@ 11.0592MHZ) ;******************************************************************** ; Interrupt vector table ;******************************************************************** org 0 ; System reset RST sjmp Start org 3 ; External 0 IE0 not used reti org 0bh ; Timer 0 TF0 not used reti org 13h ; External 1 IE1 not used reti org 1bh ; Timer 1 TF1 not used reti org 23h ; Serial port TI or RI not used reti org 2bh ; Timer 2 TF2 or EXF2 not used reti ;******************************************************************** ; Main program starts here ;******************************************************************** org 30h Start: MOV IE,#0 ; Turn off all interrupts. MOV SP,#07h ; Start stack near top of '51 RAM. mov r0,#7fh ; clear RAM clr a ; Start1: mov @r0,a ; djnz r0,Start1 ; lcall Delay ; Main: lcall ClrScreen lcall Newline lcall intro ; print welcome message mov r1,#00Fh ; Main2: lcall newline ; djnz r1,Main2 ; Main3: lcall Inchar ;Get a cmd to work with cjne a,#031h,Main4 ; ljmp dump_eep ;user pressed '1' Read Eeprom Main4: cjne a,#032h,Main5 ;user pressed '2' Program Eeprom ljmp Prog_eep Main5: sjmp Main3 ;didn't get selection, try again ;*********************************************************** dump_eep: lcall Chk_Dev ; MOV DPTR,#0000H dump: mov count,#010h mov R0,#030h dump1: LCALL EEPROM_READ MOV A,DYTA ;read byte in DYTA mov @R0,a inc R0 djnz count,dump1 lcall PrintLine mov a, dpl ; check low byte mov b,L_SIZE ; cjne a,b,dump ; mov a, dph ; check high byte mov b,H_SIZE ; cjne a,b,dump ; jump if not last DMP_Done: MOV A,#CR ; LCALL outchar ; START ON A NEW LINE MOV A,#LF ; LCALL outchar ; MOV DPTR,#ENDREC ; ADDRESS OF INTEL HEX END RECORD LCALL outstr ; PUT OUT THE STRING lcall Inchar ljmp Main ENDREC: DB ':00000001FF',CR,LF,0 ret ;*********************************************************** Prog_eep: mov dptr,#File_str lcall outstr ; lcall load1 ; get Chars, convert to hex, store in NVRam mov dptr,#Prog_str lcall outstr ; mov dptr,#4000h mov addrhi,#0 mov addrlo,#0 Prog_Loop: movx a,@dptr ;get data byte mov dyta,a inc dptr ;we have addrhi, addrlo, & data set up,write it LCALL EEPROM_WRITE2 ;write one byte ;here we check dptr against last addr previously loaded to NVRAM ;last addr = filesizeH, filesizeL mov a, dpl ; check low byte mov b,filesizeL ; cjne a,b,Prog_Loop1 ; a<>b? keep programming mov a, dph ; a = b? check high byte mov b,filesizeH ; cjne a,b,Prog_Loop1 ; a<>b? keep programming sjmp Prog_End ; end program Prog_Loop1: inc addrlo mov a,addrlo jnz Prog_Loop inc addrhi sjmp Prog_Loop Prog_End: mov dptr,#Success_str lcall outstr lcall Inchar ;wait for keypress ljmp Main ;====================================================================== ;get Chars, convert to hex, store in Ram load1: lcall inchar cjne a,#1ah,skip1 ; end of file? sjmp Done skip1: cjne a,#':',load1 ; each record begins with ':' mov r1,#0 ; init checksum to zero lcall gethex ; get byte from serial port mov b,a ; use b as byte counter jz done ; if b = 0 load2: inc b lcall gethex ; get address high byte mov dph,a mov a,dph add a,#040h ;DS5000 partition @4000h mov dph,a lcall gethex ; get address low byte mov dpl,a lcall gethex ; get record type (ignore this) load4: acall gethex ; get data byte movx @dptr,a ; store in ext. ram inc dptr dec b ; repeat until count = 0 mov a,b jnz load4 mov a,r1 ; checksum should be zero jz load1 ; if so, then get next record ljmp error ; if not, stop download Done: mov filesizeH,dph ;save filesize high byte mov filesizeL,dpl ;save filesize low byte ret ;************************************************************************* Chk_Dev: lcall ClrScreen mov dptr,#Device_str ; lcall outstr ; ChkInp: lcall Inchar ;Get a cmd to work with cjne a,#031h,ChkInp1 ;if its a 1 select 24C16 mov L_SIZE,#000h mov H_SIZE,#008h ret ChkInp1: cjne a,#032h,ChkInp2 ;if its a 2 then select 24C32 mov L_SIZE,#000h mov H_SIZE,#010h ret ChkInp2: cjne a,#033h,ChkInp3 ;if its a 3 then select 24C64 mov L_SIZE,#000h mov H_SIZE,#020h ret ChkInp3: cjne a,#034h,ChkInp4 ;if its a 4 then select 24C128 mov L_SIZE,#000h mov H_SIZE,#040h ret ChkInp4: cjne a,#035h,ChkInp5 ;if its a 5 then select 24C256 mov L_SIZE,#000h mov H_SIZE,#080h ret ChkInp5: ljmp ChkInp ;none of the above, check again ;******************************************************************** ; Get two characters from serial port and form a hex byte. Also add ; byte to checksum in r1. ;******************************************************************** gethex: lcall inchar ; get first character lcall atoh ; convert to hex swap a ; put in upper nibble mov r0,a ; save it lcall inchar ; get second character lcall atoh ; convert to hex orl a,r0 ; or with first nibble mov r2,a ; save byte add a,r1 ; add byte to checksum mov r1,a ; restore checkum in r1 mov a,r2 ; retrieve byte ret ;******************************************************************** ; ASCII to hex - enter with ascii code in acc. (assume hex char 0-F) ; exit with hex nibble in A.0-A.3 ;******************************************************************** atoh: clr acc.7 ; ensure parity bit is off cjne a,#3ah,next ; ?? this just sets carry bit ?? next: jc atoh2 add a,#9 ; no, adjust for range A-F atoh2: anl a,#0fh ; yes, convert directly ret ;******************************************************************** ; Print welcome message ;******************************************************************** intro: mov dptr,#intro_str lcall outstr 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 ;================================================================== error: mov dptr,#error_str lcall outstr ret ;--------------Clear Terminal Screen---------- ClrScreen: mov dptr,#cls ; call outstr ; ret ;================================================================== ; NewLine - output a carriage return / line feed pair to the serial port. NewLine: MOV A,#CR CALL OutChar MOV A,#LF CALL OutChar RET ;=================================================================== Init_Buffer: mov R0,#030h ret ;************************************************************ ;reading 8 bits from i2c device I2C_READ: MOV R7,#8 GFD: SETB SDA SETB SCL MOV C,SDA RLC A CLR SCL DJNZ R7,GFD MOV DYTA,A RET ;************************************************************ ;writing 8 bits in to i2c device I2C_WRITE: MOV R7,#8 WRITING: RLC A MOV SDA,C LCALL CLOCK DJNZ R7,WRITING RET ;************************************************************ ;start of i2c routine I2C_START: SETB SCL SETB SDA CLR SDA CLR SCL RET ;************************************************************ ;end of i2c routine I2C_STOP: SETB SCL CLR SDA SETB SDA CLR SCL RET ;************************************************************ ;synchronizing clock CLOCK: SETB SCL NOP NOP CLR SCL RET ;************************************************************ ;acknowledge from transmitter or receiver ACK: CLR SDA SETB SCL CLR SCL RET ;************************************************************ ;no acknowledge from transmitter or receiver NO_ACK: SETB SDA SETB SCL CLR SCL RET ;************************************************************ ;SERIAL EEPROM PACKAGE ;write one byte to eeprom EEPROM_WRITE: LCALL I2C_START LCALL EEPROM_WRITE_ADDR LCALL ACK MOV A,DPH LCALL I2C_WRITE LCALL ACK MOV A,DPL LCALL I2C_WRITE LCALL ACK MOV A,DYTA LCALL I2C_WRITE LCALL ACK LCALL I2C_STOP LCALL DELAY_STOP RET ;************************************************************ EEPROM_WRITE2: LCALL I2C_START LCALL EEPROM_WRITE_ADDR LCALL ACK ;MOV A,DPH mov a,addrhi LCALL I2C_WRITE LCALL ACK ;MOV A,DPL mov a,addrlo LCALL I2C_WRITE LCALL ACK MOV A,DYTA LCALL I2C_WRITE LCALL ACK LCALL I2C_STOP LCALL DELAY_STOP RET ;************************************************************ ;read from eeprom EEPROM_READ: LCALL I2C_START LCALL EEPROM_WRITE_ADDR LCALL ACK MOV A,DPH LCALL I2C_WRITE LCALL ACK MOV A,DPL LCALL I2C_WRITE LCALL ACK LCALL I2C_START LCALL EEPROM_READ_ADDR LCALL ACK LCALL I2C_READ LCALL NO_ACK LCALL I2C_STOP RET ;************************************************************ EEPROM_READ_ADDR: ;A2,A1,A0 are aero MOV A,#10100001B LCALL I2C_WRITE RET ;************************************************************ EEPROM_WRITE_ADDR: ;A2,A1,A0 are aero MOV A,#10100000B LCALL I2C_WRITE RET ;************************************************************ Delay: mov r2,#0FFh ; djnz r2,$ ; ret ; ;************************************************************ ;terminating write process DELAY_STOP: MOV R5,#95 ;was 85 DELAY_STOP1: DJNZ R5,DELAY_STOP1 ret ;*********************************************************** ;---- Print out 10h bytes to Terminal in Intel Hex ---- PrintLine: mov R0,#030h ; point to buffer DMPHEX: CLR C ; DMP_B: MOV r1,#010H ; LEN := 16 DMP_C: MOV CKSUM,#0 ; CKSUM := 0 MOV A,#CR ; LCALL outchar ; START RECORD ON A NEW LINE MOV A,#LF ; LCALL outchar ; MOV A,#':' ; LCALL outchar ; HEADER CHARACTER MOV A,r1 ; LCALL HOUT ; LENGTH mov a,dph LCALL HOUT ; ADDRESS (HI BYTE) mov a,dpl LCALL HOUT ; ADDRESS (LOW BYTE) NoBump: CLR A ; LCALL HOUT ;RECORD TYPE DMP_D: MOV A,@R0 ;REPEAT A := MEM[DPTR] INC R0 LCALL HOUT ;WRITE IT OUT INC DPTR ;++INDEX DJNZ r1,DMP_D ;UNTIL (LEN = 0); MOV A,CKSUM ;DO A TWO'S COMPLEMENT OF CKSUM BY CPL A ;COMPLEMENTING INC A ;AND ADDING ONE LCALL HOUT ;CKSUM ret ;************************************************************** ;calculate the checksum, convert to ascii and print to screen HOUT: PUSH ACC ADD A,CKSUM MOV CKSUM,A POP ACC PUSH ACC SWAP A LCALL PHEX1 POP ACC LCALL PHEX1 RET ;********************************************************** ;same as the hex2ascii routine (HexAsc) PHEX1: ANL A,#0FH ADD A,#4 MOVC A,@A+PC LCALL outchar RET DB '0123456789ABCDEF' ;---------------- PC SIO Subroutines --------------------- ; Receive a character from the PC RXD line and return in A InChar: getc: JB Ser_RX,$ ;Wait for start bit MOV R2,#BITTIM/2 ;Wait 1/2 bit-time DJNZ R2,$ ;To sample in middle JB Ser_RX,getc ;Insure valid MOV R3,#8 ;Read 8 bits getc1: MOV R2,#BITTIM ;Wait full bit-time DJNZ R2,$ ;For DATA bit MOV C,Ser_RX ;Read bit RRC A ;Shift it into ACC DJNZ R3,getc1 ;read 8 bits CLR C ; RET ;go home ;---------------------------------------------------------; ;Transmit character in A via PC TXD line OutChar: putc: CLR Ser_TX ;Drop line for start bit MOV R2,#BITTIM ;Wait full bit-time DJNZ R2,$ ;For START bit MOV R3,#8 ;Send 8 bits putc1: RRC A ;Move next bit into carry MOV Ser_TX,C ;Write next bit MOV R2,#BITTIM ;Wait full bit-time DJNZ R2,$ ;For DATA bit DJNZ R3,putc1 ;write 8 bits SETB Ser_TX ;Set line high RRC A ;Restore ACC contents MOV R2,#BITTIM ;Wait full bit-time DJNZ R2,$ ;For STOP bit RET ; ;---------------------------------------------------------; ;data tables and strings ; ;---------------------------------------------------------; intro_str: db ' 24CXX Programmer ',cr,lf, db 'Select: (1) Read Eeprom',cr,lf, db ' (2) Program Eeprom',cr,lf,0 File_str: db 'Send File Now',cr,lf,0 Prog_str: db 'Programming Eeprom, PLEASE WAIT...',cr,lf,0 Done_str: db cr,'Programming Success!',cr,lf,0 Cls: db esc,'[','H',esc,'[','J',0 ;---------------------------------------------------------------- device_str: db ' Select Device ',cr,lf, db ' (1) 24C16',cr,lf, db ' (2) 24C32',cr,lf, db ' (3) 24C64',cr,lf, db ' (4) 24C128',cr,lf, db ' (5) 24C256',cr,lf,cr,lf,lf,lf,lf,lf,0 ;---------------------------------------------------------------- error_str: db 'Download Failed',cr,lf,0 Success_str: db 'Upload Success!',cr,lf,0 end |
Topic | Author | Date |
movx a,@dptr! | 01/01/70 00:00 | |
I think your problem is... | 01/01/70 00:00 | |
No Michael | 01/01/70 00:00 | |
DYTA EQU 10H? | 01/01/70 00:00 | |
movx a,@dptr | 01/01/70 00:00 | |
code format | 01/01/70 00:00 | |
WHICH EEPROM | 01/01/70 00:00 | |
the error... | 01/01/70 00:00 | |
movx a,@dptr![]() | 01/01/70 00:00 |