Machine Independent PIC Programmer (MIPP) by Erik Hermann Ok, let's discuss this schematic. First question: What is this part good for ? Answer: It can be used to program a PIC 16C84 via every RS232. After the initial program is loaded, the PIC takes control over the serial communication and can be used (with some extenders) to program other Pic's, EPROM, Flash, etc. Why did I use so many parts ? Answer: Yes, I could have used the two spare inverters of the Max232 instead of the 4093. (This works, really! I've tested it.) But adjusting this is very tricky, even with an oszilloscope. How does this work ? Answer: The host computer sends only 'FFh' or '00h' to the RS232. The trailing edge of the stop bit is used to clock the data bit into the 16C84. Bit detection is done by the monoflop around IC2B/C8/D2/R3. A 'FFh' is detected as 0 and a '00h' is detected as 1. This simple mechanism can be used to shift commands and data into the Pic. All the host has to do is sending at the correct baud rate. The time between the sended bytes doesn't matter. (great for multitasking systems). JP 4 connects to a ON-OFF-ON switch and is used to change between programming und run mode. What is this Flipflop (IC2C/IC2D) good for ? Answer: It acts as a programming indicator and as a very easy trimming indicator. When finished building the programmer, all You have to do is starting a program that sends 'FFh's and '00h's to the port. (With some pause between). Then adjust R3 until the LED blinks. That's all ! No preprogrammed PIC, no extensive adjusting !. Why this extensive power supply ? Answer: I've planned to use the whole part as an interface to a (production quality) programmer. Therefore I need various voltages. If this method is used only to bootload a 16C84, Vpp can be 'borrowed' from the Max232 (only 10V, but should be enough). (Not testet). I think I've solved the 'Chicken and Egg' problem. The programmer works, but isn't really finished yet. Comments ? -!------------------------------------------------------------------------ Some software: Simple program in Turbo Pascal that sends 'FFh' and '00h' to the RS232. Can be used to adjust R3. -!----------------------- program serbin1; uses dos, crt; Procedure initcom; var regs : registers; Begin With regs do Begin ah := 0; dx := 0; ax := 163; {<== 110:3, 9600: 227, 2400:163} intr($14,regs); {Set to Your favorit baud rate} End; End; Procedure send1; var regs : registers; Begin With regs do Begin dx := 0; ah := 1; al := 255; intr($14,regs); End; End; Procedure send0; var regs : registers; Begin With regs do Begin dx := 0; ah := 1; al := 0; intr($14,regs); End; End; Begin {main} clrscr; initcom; While keypressed do readkey; repeat send1; gotoxy(1,24); write ('##############'); delay (1000); send0; gotoxy(1,24); write (' '); delay (1000); until keypressed; End. {The blinking sign corresponds to the LED} -!--------------------------------------------------------------------- {Complete programming software (no data memory yet)} {Not very smart, but it works} program serprog7; Uses Crt, Code, Dos; CONST com1 = $3F8; com2 = $2F8; com3 = $2EB; com4 = $2E0; {' 16C84 serial programming commands} LdConf = 0; LdProg = 2; RdProg = 4; IncAdd = 6; BegPrg = 8; LdData = 3; RdData = 5; ProgMem = 0; DataMem = 1; ProgSize = 1024; DataSize = 64; CP = 16; PWRTE = 8; WDTE = 4; RC = 3; HS = 2; XT = 1; LP = 0; INHX16 = 16; INHX8M = 8; Var ProgBuf : Array [0 .. ProgSize - 1] of Word; DataBuf : Array [0 .. DataSize - 1] of Word; SerPort, Check, HexType, Fuses : integer; Buffer, Buffer2 : String; Value, pos, CodeSize : Word; ValueLo, ValueHi : Word; InFile : Text; Ended, Good : Boolean; NumBytes, Address : Word; i, j : integer; BitPos : Byte; Procedure initcom; var regs : registers; Begin With regs do Begin ah := 0; dx := 0; ax := 227; {227;} intr($14,regs); End; End; Procedure send1; var regs : registers; Begin With regs do Begin dx := 0; ah := 1; al := 0; intr($14,regs); End; End; Procedure send0; var regs : registers; Begin With regs do Begin dx := 0; ah := 1; al := 255; intr($14,regs); End; End; Procedure VppDly; Begin Delay (100); End; Procedure PrgDly; Begin Delay (5); End; Procedure Command (Cmd : Byte); Begin BitPos := 1; WHILE BitPos <= 32 Do Begin IF (Cmd AND BitPos) = BitPos THEN Send1 ELSE Send0; BitPos := BitPos * 2; End; END; Procedure OutWord (Value : Word); var BitPos : Word; Begin Send0; BitPos := 1; WHILE BitPos <= 8192 Do Begin IF (Value AND BitPos) = BitPos THEN Send1 ELSE Send0; BitPos := BitPos * 2; End; Send0; END; Procedure Programm; var n, i, v, w, mask, ldcmd, rdcmd, j : Word; Begin n := 64; Mask := $3FFF; {ProgMode;} FOR i := 0 to progsize - 1 Do Begin if i <= codesize+2 then Begin Command (LdProg); v := ProgBuf[i]; OutWord (v); Command (BegPrg); PrgDly; Command (IncAdd); End; If (i mod 64) = 0 Then Write ('#'); if i > codesize+2 then for j := 1 to 1000 Do; End; END; Procedure Config; var f : Word; Begin {ProgMode;} Command (LdConf); OutWord (Fuses); FOR i := 1 TO 7 Do Command (IncAdd); Command (LdProg); OutWord (Fuses); Command (BegPrg); PrgDly; END; Procedure LoadProgramFile; Begin for i := 0 to progsize do ProgBuf[Address] := $3FFF; CodeSize := 0; Ended := false; While (not EOF(Infile)) And Not Ended Do Begin pos := 1; Readln (Infile, Buffer); If Buffer[pos] <> ':' Then Halt(1); inc (pos); Buffer2 := Buffer[pos]; inc (pos); Buffer2 := Buffer2 + Buffer[pos]; NumBytes := ByteHex (Buffer2) * 2; inc (pos); Buffer2 := Buffer[pos]; inc (pos); Buffer2 := Buffer2 + Buffer[pos]; inc (pos); Buffer2 := Buffer2 + Buffer[pos]; inc (pos); Buffer2 := Buffer2 + Buffer[pos]; Address := WordHex (Buffer2) div 2; If Address > 1024 Then Ended := true; inc (pos); Buffer2 := Buffer[pos]; If Buffer2 <> '0' Then Ended := True; If not Ended Then Begin pos := 9; While pos <= (Length (Buffer) - 4) Do Begin inc (pos); Buffer2 := Buffer[pos]; inc (pos); Buffer2 := Buffer2 + Buffer[pos]; ValueHi := ByteHex(Buffer2); inc (pos); Buffer2 := Buffer[pos]; inc (pos); Buffer2 := Buffer2 + Buffer[pos]; ValueLo := ByteHex(Buffer2); Value := 256 * ValueLo + ValueHi; ProgBuf[Address] := Value; write (HexWord(ProgBuf[Address]),','); inc (Address); If Address > ProgSize Then Ended := true; inc (Codesize); End; End; End; Writeln; Writeln ('Program size : ', CodeSize, ' Words'); End; Procedure EraseAll; Begin {ProgMode;} Command (9); Command (2); OutWord ($3FFF); Command (8); End; Begin {Main} Fuses := xt + cp; Check := 0; SerPort := Com1; InitCom; ClrScr; Writeln; Assign (Infile, ParamStr(1)); Reset(Infile); Writeln; Writeln ('Loading Objectfile ==> '); LoadProgramFile; Writeln; Writeln ('Switch to Programming Mode !'); while keypressed do readkey; repeat until keypressed; writeln; Write ('Erasing memory '); EraseAll; Writeln (' ==> OK '); Writeln; Write ('Programming ................'); GotoXY (WhereX-16,WhereY); Programm; Writeln; writeln; Write ('Blowing Fuses to 0x', HEXword(Fuses), ' ....'); Config; Writeln (' ==> OK '); Writeln; Write ('Shutting down'); Writeln (' ==> OK '); End. -!------------------------------------------------------------------------