This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Problems with serial communication

Hello,

I have two AT89C52 in a simplex connection,
I'm having problems with my receiver.
I've tried like 5 different ways of receiving data
but it looks like I'm getting the wrong data in SBUF
and it receives like 20% packets that are actually sent.
I used an osciloscope to see if the packets are sent,
and it looks fine. no noises and such.

I tried putting the 2 processors on a matrice to check
them with a simple program and it works, so I guess
it has something to do with the bigger program.

This is a LED Matrice project (with scanning) so the
extra stuff is related to it.
It would be very helpful if someone could comment
and maybe find what I'm doing wrong

#include <reg52.h>
#include <intrins.h>

// prototypes
char set_font(unsigned int row, unsigned int letter);
///char pow(char num, char pow);
//bit is_effect(char DATA);

sbit CLK_COL = P3^1;
sbit ROW0 = P1^0;
sbit ROW1 = P1^1;
sbit ROW2 = P1^2;
sbit ROW3 = P1^3;
sbit OE_ROW = P1^4;
sbit OE_COL = P1^5;
sbit OE_COL_D = P3^4;
sbit LE = P1^6;
sbit SER = P1^7;

// global variables
//xdata char my_string[] = {6,4,14,17,6,4,36,17,20,1,8,13,36,14,22,13,25,36,24,14,20,17,36,0,18,18,36,36,36,36};
//xdata char str_len=30;
xdata char output[7][48] = {{0}};
xdata unsigned char my_string[] = {22,4,11,2,14,12,4,36,36,36,36};
xdata unsigned char str_len=11,border;
xdata char timer0_c=0;
xdata unsigned char tmp_sbuf=0;
bit shift_flag=0,data_ready=0,clean_flag=0;

char set_font(unsigned int row, unsigned int letter)
// returns wanted code for font according to wanted row
{
 ....
}

void SER_ISR() interrupt 4
{
  if(RI)
  {
        RI = 0;
        my_string[str_len++] = SBUF;
  }
}
void INT0_ISR() interrupt 0
{
  SCON = 0x50; // Mode 1, No Parity, Receive Enable
  TMOD &= 0x0F;
  TMOD |= 0x20; // T1 Mode 2 (auto reload - baud gen).
  TH1 = -52; // 1200 baud rate
  TR1 = 1;

  IE &= 0xef;
  IE |= 0x10; // Enable SER ISR

  str_len = 0;
  data_ready = 1;
}

void timer0_ISR() interrupt 1
{
  TH0 = ~(50000/256);
  TL0 = -(50000%256);
  if(timer0_c<=2)
  {
        timer0_c++;
  }
  else
  {
    timer0_c = 0;
    shift_flag = 1;
  }
}

void main(void)
{
  xdata char carry[48]={0};
  xdata char i=0,j,cor_order,tmp,cur_row=5;

  border = (str_len>=4) ? str_len : 4;

  IE = 0x83; // Timer 0 (rotation). INT0 (serial transmission)
  IT0 = 1; // Using FF

  SCON = 0x50; // Mode 1, No Parity, Receive Enable
  TMOD = 0x21; //  T0 Mode 1 (rotate counter). T1 Mode 2 (baud rate generator)
  TH1 = -52; // 1200 baud rate
  TR1 = 1;

  T2CON = 0x01; // T2 Capture Mode
  TH0 = ~(50000/256);
  TL0 = -(50000%256);
  TR0 = 1;

  // populate output(array) with font data
  for(i=0; i<7; i++)
        for(j=str_len-1,cor_order=0; j>=0; j--,cor_order++)
          output[cor_order] = set_font(i,my_string[j]);

  while(1)
  {
    if(data_ready)
        {
          data_ready = 0;
          if(my_string[str_len--] == 0xaa)
          {
            str_len-=2;
            // Fill font array with new data
        for(i=0; i<7; i++)
              for(j=str_len-1,cor_order=0; j>=0; j--,cor_order++)
                    output[cor_order] = set_font(i,my_string[j]);
            border = (str_len>=4) ? str_len : 4; // Set new borders
            //IE &= 0xef; // Disable SER ISR
            clean_flag = 0;
          }
        }
    // RESET BEFORE SHOW
        LE = 0;
        OE_COL_D = 0;
        OE_COL = 1;
        OE_ROW = 1;

    ROW0=cur_row%2;
        ROW1=(cur_row>>1)%2;
        ROW2=(cur_row>>2)%2;
        ROW3=(cur_row>>3)%2;

        // shift data left when needed
        if(shift_flag)
        {
          // i = index, j = row
          for(j=0; j<7; j++)
          {
            // save msb
            for(i=0; i<border; i++)
              carry = _crol_ (output[j]&0x80,1);
            // shift
            for(i=0; i<border; i++)
              output[j] = output[j]<<1;
                // get msb(new lsb) from next cell
            for(i=0; i<border; i++)
            {
              if(i==0) output[j][0] += carry[border-1];
                  else output[j] += carry[i-1];
            }
          }
          shift_flag = 0;
        }

        // output fonts to SER
        for(j=0; j<4; j++)
        {
          tmp = ~output[cur_row-5][j];
          for(i=0; i<8; i++)
          {
            SER = tmp%2;
                tmp=tmp>>1;
            CLK_COL = 1;
            CLK_COL = 0;
          }
        }

        LE = 1;
        OE_COL_D = 1;
        OE_COL = 0;
        OE_ROW = 0;

    if(cur_row==11) cur_row=5;
        else cur_row++;

        TH2 = ~(500/256);
        TL2 = -(500%256);
        TR2=1;
        while(!TF2);
        TR2=0;
        TF2=0;
  }
}

It should work in the following way:
1) I receive an INT0 when a new batch of packets is coming (text)
2) in the INT0 ISR I set all necessary registers for serial commmunication
3) I receive data using SER ISR
4) When finished receiving data I process it (in the main program)

Thanks in advance..

  • Why not have the receive interrupt enabled all the time?

    If you have too slow interrupt response times, you will not have time to enable the UART before you have lost the first byte of the packet.

    There are really no reason to turn on/off the UART. It doesn't consume any processing power when no data is sent. And it doesn't affect the power consumption, since you are not developing a tiny battery-driven device that has to survive on a button cell.

    You are just complicating your life.

  • I guess you're right.

    It doesn't help when I leave it enabled all the time too, so I guess it's not really the problem.