>First, I am using PSIM v 2.42 , PASM v2.3, and DS30015I data sheet for the >PIC16c56. > I just wrote some code to do a BCD to binary coversion (the hard way, a 10X >loop of ADDWF) and I had to redo some of the code and I don't really have a >good grasp of why. John Payson and I have been looking at the BCD conversion problem. He had some really good ideas that I haven't fully explored yet. Here's my routine, which is probably a little faster, though by no means optimal: cvBCD ; Converts a binary number (known to be less than 100) to packed BCD. ; Process: Trial-subtractions of 80, 40, 20, and 10 are done. If the ; number is greater than these, the corresponding bit in the high BCD ; digit is set. The remainder forms the low BCD digit. ; Input: Binary number in W. ; Output: Packed BCD number in bcd0 ; RAM: tmp, tmp+1, bcd0 (stores result) cvBCD movwf tmp ;Store number being converted. clrf bcd0 ;Clear result. movlw .80 ; 80 decimal is 01010000. movwf tmp+1 cvBCDl movfw tmp+1 ;Get base (80, 40, 20, or 10) subwf tmp,0 ;form number - current base. skpnc ;If less, don't restore. movwf tmp ;It was more. Store adjusted value. rlf bcd0,1 ;Rotate result into bcd0 (brings 0 out C) rrf tmp+1,1 ;Reduce base number by half. btfss tmp+1,0 ;Is base number 5 yet? goto cvBCDl ;No, do another bit in MS digit. ; Now we have the low 4 bits of BCD0 being the high digit, and the low 4 ; bits of tmp being the low digit (known to be less than 10). swapf bcd0,1 ;Put high digit in place. movfw tmp ;Get the low digit. iorwf bcd0,1 ;OR in the low digit. This is untested as well, and is also about an order of magnitude below what John sent me privately (I will await his permission before posting). But it's something to think about. The really fast way (6 instruction cycles) is of course a table of 100 entries. Not unfeasible if you don't need the space for anything else. > >This piece of code always resulted in a skip, even if carry was set > BTFSC STATUS,C > but this worked > BTFSC STATUS,0 I thought C was a predefined equate? With MPALC (the only one I'm familar with), you need an include file with the standard names of all the special-purpose stuff. (It is possible that STATUS is not a predefined equate either) However, MPALC includes the pre-defined psuedo-instructions SKPC (skip if C set), and SKPNC (skip if C not set), which assemble to BTFSS 3,0 etc. Look at your .LST file and decode what was actually assembled. > > > in a single call jump/return > RETLW TEMP W didn't contain the variable TEMP, I had to > do a MOVF TEMP,W after the return. This is a flawed concept. It is not possible to return a variable in W with the 16C5x series, other than with multiple RETLWs. The RETLW loads a constant from ROM (what you ended up with in your case was always the *address* of TMP in W). Since this is the only way to return on the 5x, any value left in W by the subroutine will be lost. One work-around if you have only a few possible values to return is to end your subroutine with a table: ; return 0, 1, or 2 in W. Will crash if W>2. Must execute from first half of ; a program page. addwf PC,1 ;Skip to apropriate location in table retlw 0 retlw 1 retlw 2 The ADDWF will affect C, DC, and Z though. In most cases keeping the result in RAM and loading it after return is the best way to do it. > > This statement didn't move the value TEMP to W > MOVF TEMP but this did > MOVF TEMP,W If the destination register is not given, I thought > it would put the contents in W. The default in MPALC is F. I always specify it explicitly either way to avoid confusion. MPALC also has the psuedo-instruction MOVFW which makes it clearer what is going on. > > Same thing with ADDWF, This didn't put the result into W > ADDWF TEMP but this did > ADDWF TEMP,0 could I have typed in ADDWF TEMP,W? Same problem, same solution. The default is F. Generally I use 0 and 1 rather than W and F but I think most assemblers would be smart enough to handle either. The binary opcodes in the instruction table will help you figure out exactly what your assembler is doing by examining the resultant opcode in the .LST file. -Mike