This discussions focuses how to move a design from a 16C84 platform to a 16C55X processor. The 16C55X one time programmable devices (OTP) are typically $2.50.
My students do most of their initial design using the PIC16C84. We have emulators for the 16C84 and when they move on to actually programming a device, the 16C84 is very attractive as it may be reprogrammed.
However, for applications which are to be permanent or for various kits that we have developed where we are programming hundreds of processors, we usually rework the code for either a 16C554 (512 memory), 556 (1024 memory) or 558 (2048 memory) depending on how much program memory is required. The reason is simple economy. These 16C55X one time programmable devices are typically $2.50, considerably less than a 16C84.
We don't have an emulator for the 16C55X series, but have had good fortune in thoroughly developing the design using the 16C84 and then making some minor changes to permit the code to run on a 16C55X.
Comparison of 16C84 and 16C55X.
To my knowledge, the 16C55X instruction set is precisely the same as the 16C84. The operation of the reset, watchdog timer, power on timer and the ability to configure weak pull-up resistors on PORTB all appear the same. The operation of the external interrupt is the same. The operation of the stack appears the same. The pinouts appear to be exactly the same.
I say all of this in a somewhat guarded manner, as one never knows when some anomoly will rear its head, but this is based on my experience in moving many designs from the 16C84 to the 16C55X.
There are minor differences in PORTA. On the 16C84, only RA.4 has a Schmitt Trigger input; all other bits are TTL. On the 16C55X, all five bits on PORTA are Schmitt Trigger Inputs. RA.4 is an open drain when used as an output on both.
PORTB appears to be the same on both.
The 16C55X lacks user EEPROM. Thus, there is no EEDATA, EEADR, EECON1 and EECON2. The 16C55X does have one register that is not present on the 16C84; PCON which consists of a single bit which permits the programmer to distinguish between a power on reset and other causes of a reset.
On the 16C84, user variables may be assigned in the range of 0CH - 2FH (36 locations) and these are also mapped into Bank 1. On the 16C55X this varies depending on the exact device;
16C554 20H - 6FH 80 locations 16C556 20H - 6FH 80 locations 16C558 20H - 7FH and A0H-BFH 128 locations
Thus, there are differences between the 16C84 and the 16C55X. Clearly, if your application requires user EEPROM, the 16C55X is not a candidate. However, all of the other differences are minor, and in my mind, they all come down in favor of the 16C55X; more Schmitt Trigger inputs and more user RAM.
Modifying the Code.
We use a template as shown below to write code for the 16C84 which gives us the ability when the degugging is completed to simply modify one DEFINE statement so as to make the code compatible with the 16C55X.
Note that is _16C84 is defined, the processor is a 16C84 and variables begin at 0CH. If _16C84 is not defined, the processor is a 16C554 and variables begin at 20H.
;#define _16C84 ; uncomment this line for 16C554 IFDEF _16C84 ; 16C84 LIST p=16c84 #include <c:\mplab\p16c84.inc> __CONFIG 11H CONSTANT BASE_VAR=0CH ELSE ; otherwise, it's a 16C554 LIST p=16c554 ; 16C554 #include <c:\mplab\p16c554.inc> __CONFIG 05H CONSTANT BASE_VAR=20H ENDIF COUNTER EQU BASE_VAR+0 ORG 000H GOTO MAIN ORG 004H GOTO INT_SERV MAIN: BSF STATUS, RP0 ; bank 1 MOVLW 1 ... ... ; etc
Minor Difference in Variables.
I recently had a design which was working using the 16C84, but when mapped over to the 16C554 the processor was doing all manner of wierd things. The design involved the use of a lookup table to set one bit on TRISB to an output. A portion of the code is shown.
MOVLW 0 MOVWF INDEX BSF STATUS, RP0 ; switch to bank 1 CALL LOOKUP MOVWF TRISB BCF STATUS, RP0 ; back to bank 0 ... LOOKUP: MOVF INDEX, W ADDWF PCL, F DT FEH, FDH, FBH, F7H, EFH, DFH, BFH, 7FH
Note that when LOOKUP is called, the STATUS register is configured for Bank 1. Unfortunately, variable INDEX is in Bank 0. With the 16C84, INDEX was also mirrored into BANK 1 and the program worked, but with the 16C554 it is not mirrored and the program choked.
This was corrected so as to call LOOKUP while configured for Bank 0.
MOVLW 0 MOVWF INDEX ; in bank 0 CALL LOOKUP ; fetch the value BSF STATUS, RP0 ; switch to bank 1 MOVWF TRISB ; and move the value to trisb BCF STATUS, RP0 ; back to bank 0 ... LOOKUP: MOVF INDEX, W ADDWF PCL, F DT FEH, FDH, FBH, F7H, EFH, DFH, BFH, 7FH
I don't normally use the mirrored variable feature of the 16C84, but in this example, it was the reason that my program was working. That is, INDEX was a location 0CH and also at 8CH.
And, of course when I moved to the 16C554 which doesn't have this feature, the program failed. Without an emulator for the 16C55X, this took a great deal of time to find.
Caution on the Use of CERDIP EEPROM.
Our design process is;
Thus, prior to actually programming one of the one time programmable 16C55X devices, my students usually burn an EEPROM version of the 16C55X. These are fairly expensive; $13, but they may be erased and reused. It is an attractive alternative to programming some 15 OTP devices and still not have a working circuit as I recently did prior to finding the elusive problem described above.
When programming the EEPROM version, DO NOT set the code protect bits. We have accidentally done this a number of times and have been unable to erase the EEPROM after doing so.
Microchip couches their language as "with the EEPROM version, we do not recommend setting the code protect bits." I would be a bit stronger and caution the developer that setting the code protect bits will render the device unusable as it cannot be erased.
The EEPROM and OTP versions of the 16C554 and 558 are available from