NUEVOS Cursos de Oficios onLine
 

Programar un PIC en C

Seguir
Hola amigos, soy nuevo en esto, alguien me podria decir como puedo hacer un programador de PICs en lenguaje C ya que es un proyecto para mi clase y pues necesito informarme bien de esto. Ya tengo el circuito, ahora necesito saber si hay algun proyecto por ahi que me puedan informar para bajarlo y poder ver como hacer el mio.
Saludos


2 Soluciones propuestas

SOLUCIÓN ACEPTADA
// NOPPP.C (Revised) - M. Covington 1997, 1998, 1999
// Software for the "No-Parts Pic Programmer"
// Inspired by David Tait's TOPIC; compatible therewith.

// This is Microsoft C.
// Be sure to compile for 8088 (not 286 or 386) for maximum portability.

// Command line arguments:
// None.
// Environment variable:
// PPLPT=n where n=1, 2, or 3 specifies which LPT port to use.

#define BANNER "NOPPP - \"No-Parts\" PIC Programmer"

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

typedef unsigned int word;
typedef unsigned char byte, bit;

// *********************************************************************
// GLOBAL STATUS VARIABLES
// *********************************************************************

int LPT = 0, // which LPT port we're using (1..3)
PORT = 0; // its port address

#define PIC16C84 1
#define PIC16F84 2
#define PIC16F83 3
int DEVICE = 0; // which PIC we're programming

#define PROGRAM 1
#define VERIFY 0 // desired action in main programming loop

char FNAME[255]; // name of file currently loaded

char CHOICE = 0; // user's most recent menu choice

// *********************************************************************
// I/O UTILITIES
// *********************************************************************

#define KBUFSIZE 256

char buf[KBUFSIZE]; // keyboard input buffer

char* cleanctrl(char *s) { // truncates string at first ctrl char,
int i=0; // cleaning up ^M or ^J left behind by fgets
while (s >= ' ') i++;
s = 0;
return s;
}

char* getstring() { // read string
fgets(buf,KBUFSIZE-1,stdin);
cleanctrl(buf);
return buf;
}

int getint() { return atoi(getstring()); }; // read integer

char getchoice(char *s) { // read menu choice
// prints prompt, then reads letters, uppercasing,
// until a letter that is in s is found
printf("\n\nYour choice (%s): ",s);
do {
CHOICE = _getch();
CHOICE = toupper(CHOICE);
// toupper evals arg twice, so arg can't be _getch()
}
while ((CHOICE == ',') || (strchr(s,CHOICE) == NULL));
printf("%c\n",CHOICE);
return CHOICE;
}

void clearscreen() {
__asm {
mov ax,0f00h
int 010h
mov ah,0
int 010h
}
}

void waitkey() {
while (_kbhit()) { _getch(); };
puts("\nPress space bar to continue...");
_getch();
while (_kbhit()) { _getch(); };
}

void errmsg(char *s) {
puts(s);
waitkey();
}

// *********************************************************************
// TIMING
// *********************************************************************

#define IODELAY (_inp(0x61)) // allow time for timer to respond

void delay(int k) {
// Delay at least k microseconds, possibly a good bit more.
// k must be less than 27304.
// Minimum delay on a 25-MHz 386 is about 100 microseconds;
// on a 133-MHz Pentium, about 18 microseconds.

// Uses system timer 2.
// When running in a DOS box under OS/2, set HW_TIMER ON in DOS settings.

unsigned int w;
unsigned char lo,hi;

_outp(0x61, (_inp(0x61) & 0xFD) | 1); // spkr off, tmr 2 gate on
w = (unsigned int)(k*1.2);
_outp(0x43, 0xB0); // tmr 2 mode 0 2-byte load
IODELAY;
_outp(0x42, (unsigned char)w); // low byte
IODELAY;
_outp(0x42, (unsigned char)(w>>); // high byte
IODELAY;
do {
_outp(0x43,0x80); // latch timer count
IODELAY;
lo = _inp(0x42); // discard low byte
IODELAY;
hi = _inp(0x42); // get high byte
IODELAY;
}
while ((hi & 0x80) == 0); // wait for a 1 there, signifying rollover
return;
}

// *********************************************************************
// PARALLEL PORT HARDWARE INTERFACE
// *********************************************************************

// Uses two-wire serial data communication through printer port.
// Pin 1, STROBE, is serial clock;
// Pin 14, AUTOFD, is serial data out to PIC;
// Pin 11, BUSY, is serial data in from PIC;
// Pin 17, SLCTIN, is low when writing, high to provide pull-up when reading;
// Pin 2, D0, is lowered to apply Vpp.

// SLCTIN and BUSY are tied together for pull-up and for hardware detection.
// (In current versions this is done through diodes or gates.)

// SLCTIN is an open-collector output with pull-up.
// If it is pulled down, some printer ports will latch it down.
// Accordingly, it and all the other control bits are asserted
// every time they are needed.

byte BITS = 0x0F;

word portaddr(int n) { // base address of port LPTn
return(*(word far *)(0x00000408+2*n-2));
}

// Procedures to set and clear the data lines

void datawritable() { // SLCTIN, AUTOFD down
BITS |= 0x0A; _outp(PORT+2,BITS);
}
void datareadable() { // SLCTIN, AUTOFD up
BITS &= ~0x0A; _outp(PORT+2,BITS);
}

void datadown() { BITS |= 0x02; _outp(PORT+2, BITS); } // AUTOFD down
void dataup() { BITS &= ~0x02; _outp(PORT+2, BITS); } // AUTOFD up

void clockdown() { BITS |= 0x01; _outp(PORT+2, BITS); } // STROBE down
void clockup() { BITS &= ~0x01; _outp(PORT+2, BITS); } // STROBE up

void vppon() {
BITS &= ~0x04;
_outp(PORT+2, BITS); // INIT down, D0 down
_outp(PORT, 0 );
}

void vppoff() {
BITS |= 0x04;
_outp(PORT+2, BITS); // INIT up, D0 up
_outp(PORT, 1 );
}

bit datain() { return(((~(byte)_inp(PORT+1)) & 0x80) >> 7); }

void allpinslow() {
vppoff();
//datawritable();
//datadown();
//clockdown();
BITS = 0x0F;
_outp(PORT+2, BITS);
}

bit detecthardware() { // True if BUSY and SLCTIN are tied together.
datawritable(); // SLCTIN down
dataup(); // AUTOFD up
delay(10);
if (datain() == 1) return(0);
datareadable(); // SLCTIN up
dataup(); // AUTOFD up
delay(10);
if (datain() == 0) return(0);
return(1);
}

// *********************************************************************
// PIC COMMUNICATION ROUTINES
// *********************************************************************

void sendbit(bit b) { // Sends out 1 bit to PIC
if (b) dataup(); else datadown();
clockup();
delay(1); // tset1
clockdown(); // data is clocked into PIC on this edge
delay(1); // thld1
datadown(); // idle with data line low
}

bit recvbit() { // Receives a bit from PIC
bit b;
clockup();
delay(1); // tdly3
clockdown(); // data is ready just before this
b = datain();
delay(1); // thld1
return b;
}

void sendcmd(byte b) { // Sends 6-bit command from bottom of b
int i;
datawritable();
delay(2); // thld0
for (i=6; i>0; i--) {
sendbit((bit)(b & 1));
b = b >> 1;
}
delay(2); // tdly2
}

void senddata(word w) { // Sends 14-bit word from bottom of w
int i;
datawritable();
delay(2); // thld0
sendbit(0); // one garbage bit
for (i=14; i>0; i--) {
sendbit((bit)(w & 1)); // 14 data bits
w = w >> 1;
}
sendbit(0); // one garbage bit
delay(2); // tdly2
}

word recvdata() { // Receives 14-bit word, lsb first
int i;
bit b;
word w = 0;
datareadable(); // SLCTIN up for pull-up
delay(2); // thld0
recvbit(); // one garbage bit
for (i=0; i<14; i++) {
b = recvbit();
w = w | ((word)b << i); // 14 data bits
}
recvbit(); // another garbage bit;
delay(2); // tdly2
return w;
}

// *********************************************************************
// PIC PROGRAMMING ALGORITHMS
// *********************************************************************

// PIC MEMORY MAP

// The PIC16F84 has four programmable memory areas
// (plus data RAM, which is not programmable).
// Config memory is only 1 byte, but is treated like the others.

#define PBASE 0 // Base address of each memory
#define IBASE 0x2000
#define CBASE 0x2007
#define DBASE 0x2100

#define PSIZEMAX 1024 // Max size of each memory
#define ISIZEMAX 4
#define CSIZEMAX 1
#define DSIZEMAX 64

word PSIZE = PSIZEMAX; // Actual size, can be set lower
word ISIZE = ISIZEMAX; // for particular CPUs
word CSIZE = CSIZEMAX;
word DSIZE = DSIZEMAX;

word PMEM[PSIZEMAX]; // Arrays representing the memories
word IMEM[ISIZEMAX];
word CMEM[CSIZEMAX];
word DMEM[DSIZEMAX];

word PUSED = 0; // Number of valid words in array
word CUSED = 0;
word IUSED = 0;
word DUSED = 0;

#define PMASK 0x3fff // Which bits are used in each word
word CMASK = 0x001f; // (CMASK depends on processor)
#define IMASK 0x3fff
#define DMASK 0x00ff

word DEFAULTCONFIG = 0x1B; // Initialization for config word

void cleararrays () { // Mark the memory arrays as empty
PUSED =
IUSED =
CUSED =
DUSED = 0;
}

bit stuffarray (word address, // Stuff data into a memory array.
word array[], // Returns true if successful.
word base,
word size,
word *used,
word data[],
int count) {
int i;
if (address-base+count-1 > size) {
printf("Invalid address: %04XH\n",address+count-1);
return 0;
}
for (i=0; i<count; i++) {
array = data;
if (*used < address-base+count) *used = address-base+count;
}
return 1;
}

// PIC PROGRAMMING COMMANDS

byte LOADCONFIG = 0;
byte LOADPROGRAM = 2;
byte READPROGRAM = 4;
byte INCREMENTADDRESS = 6;
byte BEGINPROGRAMMING = 8;
byte LOADDATA = 3;
byte READDATA = 5;
byte ERASEPROGRAM = 9;
byte ERASEDATA = 11;

// PROGRAMMING PROCEDURES

void vppreset() { // reset PIC, apply Vpp
vppoff();
datawritable();
datadown();
clockdown();
delay(25000);
vppon();
delay(25000);
}

void progcycle(byte cmd, word arg) { // send a command and an argument,
sendcmd(cmd); // then program EPROM accordingly
senddata(arg);
sendcmd(BEGINPROGRAMMING);
delay(20000); // PIC errata sheet says 10ms is typical, not guaranteed
}

bit programall(
// Program a memory from appropriate array.
// Returns true if successful.
int mode, // program or verify
word mask, // to throw away irrelevant bits
byte writecommand, // command to write this memory
byte readcommand, // command to read this memory,
word array[], // which memory array we're using
word base, // its base address
word used) { // number of valid words in array
word i,w;
switch(mode) {
case PROGRAM: puts("programming..."); break;
case VERIFY: puts("verifying..."); break;
}
for (i=0; i<used; i++) {
printf("%04X\b\b\b\b",i+base); // display addr and backspace
if (mode==PROGRAM)
progcycle(writecommand,(array & mask));
sendcmd(readcommand);
w = (recvdata() & mask);
if (w != (array & mask)) {
printf("Failed at %04X: Expecting %04X, found %04X.\n",
i+base, (array & mask), w);
return 0;
}
sendcmd(INCREMENTADDRESS);
}
return 1;
}


// *********************************************************************
// HEX FILE LOADER
// *********************************************************************

// This is for Intel INHX8M (8-bit merged) hex files only.
// These files use two bytes for each word (low, then high).
// All addresses are doubled, i.e., 0x2001 is encoded as 0x4002,
// so that addresses increment at the same rate as the byte count.

bit validhexline(char *s) { // Gross syntax and checksum check.
byte cksum = 0; // For all HEX formats, not just 8M.
int bytecount;
int i, b;
if (s[0] != ':') return(0); // Initial colon
sscanf(s+1,"%2x",&bytecount);
if (bytecount > 32) return(0); // Valid byte count
cksum = bytecount;
i = 3;
bytecount = bytecount+3;
while (bytecount>0) {
bytecount--;
sscanf(s+i,"%2x",&b);
cksum = cksum+b; // Compute checksum
i = i+2;
}
sscanf(s+i,"%2x",&b);
cksum = -cksum;
if (cksum == b) return 1; // Test checksum
return 0;
}

void loadhexfile(FILE *f) { // Loads a hex file into memory arrays
char s[256];
word i,lo,hi;
word linetype = 0; // 0 for data, 1 for end of file
word wordcount; // number of 16 bit words on this line
word address; // address where they begin
word data[8]; // 16 bytes = 8 words max. per line of hex

cleararrays();

while((!feof(f)) && (linetype != 1)) {
fgets(s,255,f);
cleanctrl(s);

if (!validhexline(s)) { // Syntax check
s[40] = 0; // Truncate invalid line for display
if (s[0] != ':') {
printf("Invalid line (skipped): '%s'...\n",s);
continue;
}
else {
printf("Unable to decode line: '%s'...\n",s);
goto bailout;
}
}

sscanf(s+1,"%2x",&wordcount); // Parse the line - Intel Hex8M
wordcount = wordcount/2; // (double bytes, addresses doubled)
sscanf(s+3,"%4x",&address);
address = address/2;
sscanf(s+7,"%2x",&linetype);

if (linetype==1) goto finished;

for (i=0; i<wordcount; i++) { // Grab the data
sscanf(s+(9+4*i),"%2x%2x",&lo,&hi);
data = (hi << | lo;
}

// Place in appropriate array
if (address >= DBASE) {
if (!stuffarray(address,DMEM,DBASE,DSIZE,&DUSED,data,wordcount))
goto bailout;
}
else if (address >= CBASE) {
if (!stuffarray(address,CMEM,CBASE,CSIZE,&CUSED,data,wordcount))
goto bailout;
}
else if (address >= IBASE) {
if (!stuffarray(address,IMEM,IBASE,ISIZE,&IUSED,data,wordcount))
goto bailout;
}
else {
if (!stuffarray(address,PMEM,PBASE,PSIZE,&PUSED,data,wordcount))
goto bailout;
}
} // while

finished:
printf("Program memory loaded: %5d word(s)\n",PUSED);
printf("Configuration loaded: %5d word(s)\n",CUSED);
printf("ID memory loaded: %5d word(s)\n",IUSED);
printf("Data memory loaded: %5d byte(s)\n",DUSED);
return;

bailout:
cleararrays();
errmsg("Unable to load file.");
FNAME[0] = 0;
return;
}

// *********************************************************************
// USER INTERFACE
// *********************************************************************

void banner() {
clearscreen();
puts("---------------------------------");
puts(BANNER);
puts("Michael A. Covington");
puts("Version of " __DATE__ " " __TIME__);
puts("---------------------------------");
if (LPT > 0) printf("Using LPT%d on %03XH\n",LPT,PORT);
puts("---------------------------------");
switch (DEVICE) {
case PIC16C84: printf("PIC16C84"); break;
case PIC16F84: printf("PIC16F84"); break;
case PIC16F83: printf("PIC16F83"); break;
default: printf(" ");
}
printf(" %s\n",FNAME);
puts("---------------------------------\n");
}

void selectport() {
char c;
c = (getenv("PPLPT"))[0];

if ((c >= '1') && (c <= '3')) {
CHOICE = c;
}
else {
banner();
printf("Which LPT port? ");
getchoice("1,2,3");
puts("\nTo avoid having to make this selection");
puts("every time, you can add the command\n");
printf(" SET PPLPT=%c\n\n",CHOICE);
puts("to your AUTOEXEC.BAT file.");
errmsg(" ");
}
LPT = CHOICE - '0';
PORT = portaddr(LPT);

banner();
puts("Apply power to programmer now.\n");
puts("If your programmer has adjustable Vcc,");
errmsg("set it to 5.0 volts.");

if (!detecthardware()) {
banner();
puts("Caution: Programmer hardware not found!\n\n");
puts("With some versions of the circuit and some");
puts("parallel ports, this may be normal.\n");
puts("If you are sure you have chosen the correct");
puts("parallel port, press space bar to proceed.");
puts("To cancel program, press Ctrl-C.");
errmsg(" ");
}
}

void troubleshoot() {
banner();
puts("Ensure programmer is powered up now,");
puts("with Vcc set to 5.0 V (if adjustable)");
puts("and no PIC in the socket.");
errmsg(" ");

allpinslow();
banner();
puts("TEST A\n");
puts("Connect negative voltmeter lead to pin 5");
puts("of PIC socket and check the following voltages:\n");
puts(" Socket pin 4 < 0.8 V");
puts(" Socket pin 12 < 0.8 V");
puts(" Socket pin 13 < 0.8 V");
puts(" Socket pin 14 4.75 to 5.25 V");
puts(" Junction of");
puts(" D1, D2, and R1 < 0.8 V");
errmsg(" ");

vppon();
clockup();
dataup();
banner();
puts("TEST B\n");
puts("With negative voltmeter lead still");
puts("connected to pin 5 in the PIC socket,");
puts("check the following voltages:\n");
puts(" Socket pin 4 12.0 - 14.0 V");
puts(" Socket pin 12 > 4.0 V");
puts(" Socket pin 13 > 4.0 V");
puts(" Junction of");
puts(" D1, D2, and R1 < 0.8 V");
errmsg(" ");

vppoff();
clockdown();
datareadable(); // AUTOFD, SLCTIN high
//banner();
//puts("TEST 3\n");
//puts("With negative voltmeter lead still");
//puts("connected to pin 5 in the PIC socket,");
//puts("verify that pin 13 > 4.0 V.\n");
//puts("Next, insert a 470-ohm resistor into the socket");
//puts("connecting pin 13 to pin 5 and verify that");
//puts("pin 13 drops to < 2.0 V with the resistor in place.\n");
//errmsg("Then remove the resistor.");

allpinslow();
datawritable(); // SLCTIN down
dataup(); // AUTOFD up
banner();
puts("TEST C\n");
puts("With negative voltmeter lead still");
puts("connected to pin 5 in the PIC socket,");
puts("verify that the junction of D1, D2, and R1");
puts("is < 0.8 V.");
errmsg(" ");

allpinslow();
datareadable(); // SLCTIN up
dataup(); // AUTOFD up
banner();
puts("TEST D\n");
puts("With negative voltmeter lead still");
puts("connected to pin 5 in the PIC socket,");
puts("verify that the junction of D1, D2, and R1");
puts("is now > 4 V.\n");
errmsg(" ");

banner();
puts("This completes the voltage test sequence.\n");
puts("You should also check the cable from PC to programmer.");
puts("It should be relatively short (under 2 feet) and have");
puts("all necessary pins connected (serial cables don't).");
errmsg(" ");

allpinslow();
exit(0);
}


void load() {
FILE *f;
banner();
printf("File to load: ");
strcpy(FNAME,getstring());
f = fopen(FNAME,"rt");
if (f == NULL) {
errmsg("Unable to open file.");
FNAME[0] = 0;
return;
}
loadhexfile(f);
fclose(f);
errmsg("Loading complete.");

if (CUSED == 0) {
banner();
puts("Caution: HEX file did not contain a configuration word.\n");
puts("The following settings will be used:\n");
puts(" RC oscillator");
puts(" Watchdog timer disabled");
puts(" Power-up timer enabled");
puts(" Code not read-protected\n");
errmsg("You can specify other settings in the assembler.");
}
else if (CMEM[0] != (CMEM[0] & CMASK)) {
banner();
puts("Caution: Configuration word appears to contain invalid bits.\n");
puts("Your program may have been assembled for a different");
puts("type of PIC. Check device selection carefully.");
errmsg("");
}

}

void selectdevice() {
banner();
puts("Devices supported:\n");
puts(" C PIC16C84");
puts(" F PIC16F84");
puts(" 3 PIC16F83\n\n");
puts(" T Test the programmer circuit\n");
getchoice("C,F,3,T");
switch(CHOICE) {
case 'C':
DEVICE = PIC16C84;
PSIZE = 1024;
CMASK = 0x001F;
DEFAULTCONFIG = 0x001B;
break;
case 'F':
DEVICE = PIC16F84;
PSIZE = 1024;
CMASK = 0x3FFF;
DEFAULTCONFIG = 0x3FF3;
break;
case '3':
DEVICE = PIC16F83;
PSIZE = 512;
CMASK = 0x3FFF;
DEFAULTCONFIG = 0x3FF3;
break;
case 'T':
troubleshoot();
}
}

void erase() {
int i;
vppreset();
printf("Commanding PIC to erase ID, configuration, ");
sendcmd(LOADCONFIG);
senddata(0x3FFF);
for (i=7; i>0; i--) sendcmd(INCREMENTADDRESS);
sendcmd(1);
sendcmd(7);
sendcmd(BEGINPROGRAMMING);
delay(20000);
sendcmd(1);
sendcmd(7);
printf("program, ");
progcycle(ERASEPROGRAM,0x3FFF); // is the data word necessary?
printf("data...");
progcycle(ERASEDATA,0x3FFF); // is the data word necessary?
allpinslow();
puts(" Done.");
waitkey();
}

void program(int mode) {
word i;
banner();
if (PUSED+IUSED+CUSED+DUSED == 0) {
printf("Load a file first.\n");
goto finish;
}

vppreset();

printf("Program memory: ");
if (!programall(mode,PMASK,LOADPROGRAM,READPROGRAM,PMEM,PBASE,PUSED))
goto finish;

sendcmd(LOADCONFIG); // from here on we're in config/ID memory
senddata(DEFAULTCONFIG); // loadconfig requires an arg, here it is

printf("ID memory: ");
if (!programall(mode,IMASK,LOADPROGRAM,READPROGRAM,IMEM,IBASE,IUSED))
goto finish;

for (i=0; i < CBASE-IBASE-IUSED; i++)
sendcmd(INCREMENTADDRESS); // get to config memory

printf("Configuration memory: ");
if (!programall(mode,CMASK,LOADPROGRAM,READPROGRAM,CMEM,CBASE,CUSED))
goto finish;

vppreset(); // Reset address counter in PIC to 0

printf("Data memory: ");
if (!programall(mode,DMASK,LOADDATA,READDATA,DMEM,DBASE,DUSED))
goto finish;

puts("Programming complete.\n\n");
puts("For production-grade work, you should now verify");
puts("the PIC at the maximum and minimum values of Vcc.");

finish:
allpinslow();
waitkey();
}




void queryexit() {
banner();
allpinslow();
puts("Are you sure you want to exit?");
getchoice("Y,N");
if (CHOICE == 'Y') {
banner();
errmsg("You may remove the PIC from the socket now.");
exit(0);
}
}


void menu() {
allpinslow(); // Clean up after aberrant routines if any
banner();
puts(" L Load HEX file");
puts(" S Select type of PIC");
puts(" E Erase PIC");
puts(" P Program PIC");
puts(" V Verify PIC\n");
puts(" X Exit program");
getchoice("L,S,E,P,V,X");
switch(CHOICE) {
case 'L': load(); break;
case 'S': selectdevice(); break;
case 'E': erase(); break;
case 'P': program(PROGRAM); break;
case 'V': program(VERIFY); break;
case 'X': queryexit();
}
}


main() {

FNAME[0] = 0; // no file is presently loaded

selectport();

allpinslow();
selectdevice(); // mandatory
banner();
puts("You may insert the PIC in the socket now.");
errmsg("Be very careful not to insert it backward.");

while(1) menu();

return 0;
}
Hola Amigo, muchisima gracias. DIsculpa por no haberte respondido pues estuve fuera de circulacion por un buen rato pero ya ando de nuevo por aqui.
Saludos y muchas gracias por la ayuda.
Que tengas un excelente dia