• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Data isn't being read correctly with programmer


Ok so I made this BIG circuit which took me a week:


and this is my PCB


Yes I got it on a single sided board with a couple of jumpers. Most decoupling capacitors are 47nF and the two next to the external regulated power supply are 100uF.

I made my own parts in eagle called "tiny" which are tiny smd pads just to make the autorouter work.

Here is also my test code:

    #include <sys/stat.h>
    #include <sys/types.h>
    #include <sys/io.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>

    #define NIBBLE 6
    #define CMDCLK 3
    #define CMD 2
    #define DATA 0
    #define DATACLK 1

    #define ERASE 0x04
    #define READ 0x10
    #define WRITE 0x1C
    #define NOPROG 0x01
    #define RESET 0x02

    int reset=0;

    void lag(){usleep(100000L);}

    void uCreset(){
      outb(READ | RESET | NOPROG,0x378);outb(CMD,0x37A);lag();
      outb(READ | NOPROG,0x378);lag();

    unsigned char uCread(){
      unsigned char a,b,r;
      outb(READ | NOPROG,0x378);lag();outb(CMD,0x37A);lag();
      printf("A=%X B=%X ",a,b);
      r+=(b & 0x40)/0x40;r<<=1;
      r+=(1-((b & 0x80)/0x80));r<<=1;
      r+=(a & 0x40)/0x40;r<<=1;
      r+=(1-((a & 0x80)/0x80));r<<=1;
      r+=(b & 0x20)/0x20;r<<=1;
      r+=(b & 0x10)/0x10;r<<=1;
      r+=(a & 0x20)/0x20;r<<=1;
      r+=(a & 0x10)/0x10;
      if (reset != 1){uCreset();}
      return r;

    void uCwrite(unsigned char n){
      outb(WRITE | NOPROG,0x378);lag();outb(CMD,0x37A);lag();
      printf("write value: %x\n",n);
      if (reset != 1){uCreset();}
      outb(WRITE | NOPROG,0x378);lag();outb(CMD,0x37A);lag();
      outb(WRITE | NOPROG,0x378);lag();

    void uCerase(){
      outb(ERASE | NOPROG | RESET,0x378);lag();
      outb(ERASE | RESET,0x378);usleep(50000L);
      outb(ERASE | NOPROG | RESET,0x378);usleep(50000L);

    void dotest(){
      unsigned char c;
      unsigned int n;
      for (n=0;n<4;n++){
        uCwrite(n % 256);
      uCreset();int erc=0;
      for (n=0;n<4;n++){
        if (c != (n % 256)){printf("Validate error at byte %x. Got %x\n",n,c);erc++;if (erc > 10){printf("Too many fails\n");break;}}
      printf("Validate done\n");

    int main(int argc, char* argv[]){
      if (ioperm(0x378,8,1) ==-1){printf("ERROR: Access to port hardware denied by PC.\n");return -1;}
      if (argc <= 1){dotest();return 0;}
      unsigned char d,e=argv[1][0],ok=0;
      if (e=='w'){ok=1;if (argc > 1){unsigned char c=strtoll(argv[2],NULL,16);uCwrite(c);}else{printf("Write needs data byte in hex\n");}}
      if (e=='r'){d=uCread();printf("Returned: %X\n",d);ok=1;}
      if (e=='e'){uCerase();printf("Chip Erased\n");ok=1;}
      if (e=='R' || e=='-'){uCreset();printf("Address count reset\n");ok=1;}
      if (ok==0){printf("Valid parameters: w=write char+ inc addr, r= read char + inc addr, e=erase + reset, R or - = reset\n");}
      return 0;
So I run the code with no parameters expecting to program the first 4 bytes of the ROM in the AT89S52 to be values 0, 1, 2, and 3.

After running the program, the returned bytes are FFh in all address locations.

This suggests to me the erase operation is OK.

Now what's weird is that I tried 10 bytes like that and every location returns FFh except one which returns a different incorrect value (of 5).

I also modified my code to include an additional read verify right after erase and before writing to see if I'm day dreaming, but I'm not because the verify right after erase shows all FFh's which is normal so this further suggests the erase operation is OK.

The problem is that with my circuit and code, data isn't correctly being written to the 8051 ROM yet I followed all the instructions set out in the AT89S52 datasheet to the point where my timings are in the order of milliseconds. Why milliseconds? just to test the damn thing.

The only thing I haven't done is include pull-ups or pull-down resistors on the parallel port status lines.

I'm using the port on my laptop that I configured as standard parallel port. and I'm running the tests in Linux.

I want to continue work on my laptop but I feel the only way to continue is to buy an old-fashioned PC with only DOS on it and transfer files back and forth but I need a better approach.

What can I do to make my circuit with modern parallel ports set in SPP mode?


P.S. that mini IC thing close to the parallel port in the schematic is actually 4 resistors next to each other (each multiplexer output connected to each status via 100 ohm resistors)

Latest threads

EE World Online Articles