CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

rs232 missed characters
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
BOB_SANTANA



Joined: 16 Oct 2006
Posts: 110
Location: HOVE, EAST SUSSEX

View user's profile Send private message

rs232 missed characters
PostPosted: Mon Dec 04, 2006 11:03 am     Reply with quote

Hello Everyone

I have being pulling my hair (Whats left of it for 2 days now) trying to fine the problem with my program.
All i am trying to do is to use my pc to control 16 relays connected to my pic.
The address of my Pic is AD1 then the next 4 characters form a 16bits
number that i then convert to hex then binary before it outputed to my relays
those seems to got ok but its the communition part that plays up some time
The pic receives the messages ok but sometimes WHEN I TYPE A MESSAGE ON HYPERTHERM it justs sits there until i type the same message again.
the fomats of my messages are AD1FFFF , AD1F023
sometimes 4 times before it decides to work.
i thinks its something to do with the buffer ,but my c is still in baby stage
Here is my code below
Code:



#if defined(__PCM__)
#include <16F877.h>
#ORG 0x1F00,0x1FFF {} // use boot loader for the 8k 16F877
#fuses XT,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,ERRORS)  // Jumpers: 8 to 11, 7 to 1

#include <LCD_File.c>   

///////////////////////////////////////////////
// We want to be able to write a byte value to the following spare pins.
// RA0,RA1,RA2,RA3,RD0,RD1,RD2,RD3
#byte PortA = 0x05  // For 16F877
#byte PortB = 0x06  // For 16F877
#byte PortD = 0x08  // For 16F877
#bit RD4 = 8.4//LSB
#bit RD5 = 8.5
#bit RD6 = 8.6
#bit RD7 = 8.7
#bit RA3 = 5.3
#bit RA2 = 5.2
#bit RA1 = 5.1
#bit RA0 = 5.0
#bit RB0 = 6.0
#bit RB1 = 6.1
#bit RB2 = 6.2
#bit RB3 = 6.3
#bit RB4 = 6.4
#bit RB5 = 6.5
#bit RB6 = 6.6
#bit RB7 = 6.7 //MSB

// The following macro defines the "setPorts()" function.
// This will be implemented by the compiler as 16 sequential
// BSF or BCF instructions.
#define SetPorts(x) \
RD4 = x & 1;        \
RD5 = (x >> 1) & 1; \
RD6 = (x >> 2) & 1; \
RD7 = (x >> 3) & 1; \
RA3 = (x >> 4) & 1; \
RA2 = (x >> 5) & 1; \
RA1 = (x >> 6) & 1; \
RA0 = (x >> 7) & 1; \
RB0 = (x >> 8) & 1; \     
RB1 = (x >> 9) & 1; \
RB2 = (x >> 10) & 1; \
RB3 = (x >> 11) & 1; \
RB4 = (x >> 12) & 1; \
RB5 = (x >> 13) & 1; \
RB6 = (x >> 14) & 1; \
RB7 = (x >> 15) & 1;\
///////////////////////////////////////////////
///////////////////////////////////////////////
#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
BYTE Flag = 0;
char data[8];
int Rxdata[4];

/// This Function loads the Received Characters to the Circular buffer //
#int_rda
void serial_isr() {
   int t;

   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!
}

#define bkbhit (next_in!=next_out)
#define pointer (next_out-8)
/* Defines */
#define LENGTH_OF_SHORT 16u

/////////////////////////////////////////////////////////////////////////
/// This Function gets the Received Characters from buffer //
/// Its pointer to the received chars is Next_Out                     
/////////////////////////////////////////////////////////////////////////
BYTE bgetc()                                                           
{                                               
   BYTE c;                                            
                                                                     
   while(!bkbhit) ;                                                 
   c=buffer[next_out];                                               
   next_out=(next_out+1) % BUFFER_SIZE;                           
   flag = 1;                                                           
   return(c);                                                       
}                                                                     
/////////////////////////////////////////////////////////////////////////


BYTE MyFunction()
{  BYTE r=0;
   
   int i;
   int j=0;
       
   for (i=pointer ;i<next_out;i++)  // pointer has-8 offset to pointer
    {
    data[j]=buffer[i];                   // copy from buffer the data array
    j++;
    }
 
     if (data[0]=='A')
        {  r++; 
           if  (data[1]=='D')
                r++;
                if  (data[2]=='1')
               r++;
               
        }
 if ((data[0]=='A')&& (data[1]=='D')&& (data[2]=='1')&& (r==3)&&(data[7]==13))
            {
                 r=100;
                 flag = 0;              // Clear flag
                return (r);           // tell main data is ok     
                                       
            }
 else
            {
                                       
           r++;
           return (r);
            }

}

///////////////////////////////////////////////////////
/// This Function checks the 4 character locations Data[3]to Data[6]
/// Has the values 0 - F
 int CheckData ()
{
  int i,Checker,Result;
 
  Result = 0;
  for (i=3; i<7; i++)
   {
      Checker = Data[i];
      if (( Checker >=48 && Checker <= 57 )||( Checker >=65 && Checker <= 70 ))
             {
           
               Result++;
            }
     else
             {
              Result--;
             }
    }
   
   return(Result);
}
///////////////////////////////////////////////////////
// This converts the ascii to hex
int ConvertData(int Rxd )

{
 
     if((Rxd>=48)&&(Rxd<= 57 ))
             {
               Rxd=Rxd-48;
             }
             else
                 if((Rxd>=65) &&(Rxd<= 70 ))
                   {
                    Rxd=Rxd-55;
                   }
                   
                 
   return (Rxd);
}
                                   
///////////////////////////////////////////////////////
/// coverts the final value to binary 16bits
void PrintAsBinary ( int16 value )
{   char display[16];
    int i;
    int binaryValue;
    for ( i = 0; i < LENGTH_OF_SHORT; i++ )
    {
        /* Check MSB against 1 */
        if ( 0x8000 == ( value & 0x8000 ) )
        {
            binaryValue = 1;
            display[i]='1';
        }
        else
        {
            binaryValue = 0;
             display[i]='x';
        }
        /* Print the binary value */
        lcd_gotoxy(5+i, 2);  // Go to end of first line.
         printf(lcd_putc,"%c",display[i] );
        /* Shift next bit into mask position */
        value = value << 1;
    }
}


///////////////////////////////////////////////////////////
void main()
{


  int16 updateLcd;       
  int8 test,counter,D,i,result[4];

set_tris_a(0b00000000);
set_tris_b(0b00000000);
set_tris_d(0b00000000);
setup_adc_ports(NO_ANALOGS);
   enable_interrupts(global);
   enable_interrupts(int_rda);

  lcd_init();

    printf(lcd_putc, "\f"); // Clear the LCD.
    delay_ms(500);

    //Display 1st Default Startup Lcd Message
   //-----------------------------------------     
   printf(lcd_putc, "\f       Start Up Test    "); // Clear Screen & Write To Line 1.
   printf(lcd_putc, "\n 16 Port HV Switch"); // Write to "Line 2.
 
   delay_ms(3000);
   lcd_gotoxy(20, 2);             // Go to End of 2nd Line
   for(i = 0; i < 20; i++)         // Backspace over 2nd line.
      {
       printf(lcd_putc," \b\b");
       delay_ms(150);
      }               
     lcd_gotoxy(20, 1);         // Go to end of first line.       
 
   for(i = 0; i < 20; i++)      // Backspace over first line.
      {
       printf(lcd_putc," \b\b");
       delay_ms(150);
      }

    //Display 2nd Default Startup Lcd Message
   //----------------------------------------
   printf(lcd_putc, "\fPT: 0123456789ABCDEF"); // Clear Screen & Write To Line 1.
   printf(lcd_putc, "\nAD1:0000000000000000"); // Write to "Line 2.
   delay_ms(1000);                             // 1 Seconds Delay in mSeconds       

   do {
      delay_ms(5000);
     
      while(bkbhit)       
        {
          bgetc();
          if (flag !=0)
             {
              test = myFunction();
             }
          if (test==100)              // test for valid for valid Address
              {
           D = CheckData ();            // test for valid for valid Data Range 0- F
                 if ( D ==4)
                      {
                       counter=0;
                        lcd_gotoxy(20, 2);               // Go to 2nd digit of   2nd line.
                     for(i = 1; i < 20; i++)              // Backspace over 2nd line.
                     {
                      printf(lcd_putc," \b\b");     // clears msg on line 2
                      delay_ms(5);
                     }
                          printf(lcd_putc,"AD1:");          //new msg on line 2
                   
                                  for(counter=3;counter < 7;counter++)
                           {
                                    lcd_gotoxy(6+counter, 2);                     
                                    printf(lcd_putc,"%c",data[counter] );   
/////////////////////////////////////////////////////////////////////////////////////////////////////
                    ///     copy positions data[3]-data[6]
                                    Rxdata[0]=data[3];
                                    Rxdata[1]=data[4];
                                    Rxdata[2]=data[5];
                                    Rxdata[3]=data[6];

                                    for (i = 0; i < 4; i++)
                                          {   // Converts ASCII Range 0-F
                                             result[i] = ConvertData(Rxdata[i]);
                                          }                                     
                                       
////////////////////////////////////////////////////////////////////////////////////////////////////
updateLcd = ((int16)result[0]<<12) + ((int16)result[1]<<8) + (result[2]<<4) + (result[3]);
               SetPorts(updateLcd);                             // Sets 16 Bits output port
                PrintAsBinary (updateLcd);                 //Update LCD Display with binary value           
                 test=false;                    // reset data test
                        }
                                    printf("\r\nOk\n ");                    // Ack for saved msg
                       }
                    else
                       {
                         printf("\r\nAddr or Data Error\n ");
                          test=false;
                        }
               }
               
         }
 
      D=0;
 
   } while (TRUE);

}


Regards
_________________
BOB_Santana Smile


Last edited by BOB_SANTANA on Tue Dec 05, 2006 3:46 am; edited 3 times in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Dec 04, 2006 11:12 am     Reply with quote

You have to disable HTML when posting code. It's essential.
Look at this line in your post. It's messed up:
Quote:
for (i=3; i<7>=48 && Checker <57>=65 && Checker <70>=48)&&(Rxd<57>=65) &&(Rxd<= 70 ))

Please EDIT your post, delete the existing code and paste in a fresh
copy of the code. And then, this time, select the box below the posting
window to disable HTML. It looks like this:
Quote:
x Disable HTML in this post
BOB_SANTANA



Joined: 16 Oct 2006
Posts: 110
Location: HOVE, EAST SUSSEX

View user's profile Send private message

PostPosted: Tue Dec 05, 2006 3:47 am     Reply with quote

Thanks PCM Pro

I have just managed to edit the post
i know now next time

Best Regards
_________________
BOB_Santana Smile
Ttelmah
Guest







PostPosted: Tue Dec 05, 2006 5:29 am     Reply with quote

The code you have posted, is so complex, that I haven't bothered to try to understand it!.
However let me suggest a totally different way of doing this type of scan on data:
Code:

#define hextoval(x) (x<='9')?(x-'0'):((toupper(x)-'A')+10)

int16 find_message(void) {
   int8 state=0;
   int16 ctr=20000;
   int8 chr;
   int16 val=0;
   int16 dig=0;
   while (true) {
      while (!bkbhit) {
         //timeout if a command is not completed in perhaps 10 seconds
         if (--ctr)==0)) return 0;
         delay_ms(5);
      }
      //Here I have a character
      chr=bgetc();
      switch (state) {
      case 0:
         if (chr=='A') {
            //legitimate first char
            state=1;   
            //Reset timeout
            ctr=20000;
        }
        //go back to waiting
        break;
     case 1:
         if (chr=='D') {
            //legitimate second char
            state=2;   
            //Reset timeout
            ctr=20000;
        }
        //Otherwise start looking for the first character again
        else if (chr!='A') state=0;
        //go back to waiting
        break;
      case 2:
         if (chr=='1') {
            //legitimate third char
            state=3;   
            //Reset timeout
            ctr=20000;
        }
        //Otherwise start looking for the first character again
        else if (chr!='A') state=0;
        else state=1;
        //go back to waiting
        break;
     case 3:
        //Now you have seen 'AD1'
        //Decode the digits
        val=(val*16)+hextoval(x);
        if (++dig >=4) return val;
        break;
    }
  }
}

Now this is completely untested, but shows how to use a 'state machine', to walk through the arriving characters. It doesn't test everything (it should test that the digits are legitimate), but also shows how to implement a crude 'timeout', if there is a long gap in the incoming data (which would reflect a possible error). It does handle certain types of data error (so for instance, AAD1FFFF will be correctly handled). It returns '0' in the event of a timeout.
I'd suspect your problem, is actually quite simple. My 'guess' would be that you are not handling the extra characters present in the hyperterminal output it will normally send both line feed, and carriage return for an 'enter'), so the code gets out of sync from the incoming data.

Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Dec 05, 2006 5:40 am     Reply with quote

You said you're missing commands that are typed in. Your main loop
has got large delays in it. There's one delay of 5 seconds and there
are other delays in for(;;) loops. While those delays are executing,
the PIC can't check the buffer to see if chars are available. I don't
know if the delays are really the problem, because the code is
formatted so poorly that it's just too painful to read it.

I noticed that you took some of the demo code from the 20x4 LCD
driver that I posted in the Code Library. You're using it to clear
lines. It was never intended for that purpose. You're using code
that was intended to demonstrate the Backspace command. It runs
slowly, on purpose, so the user can see that the demo is working.

If you want to clear a line, use the lcd_gotoxy() function to set the
cursor to the start of a line, and then just printf 20 spaces to it
(using the redirection feature to send it to lcd_putc ).
Or do a for(;;) loop and send 20 spaces to it that way. But get
rid of that demo code.
BOB_SANTANA



Joined: 16 Oct 2006
Posts: 110
Location: HOVE, EAST SUSSEX

View user's profile Send private message

PostPosted: Tue Dec 05, 2006 7:13 am     Reply with quote

Thanks guys
I am taking this all on board and learning the hard way
which is good for me.
I did removed the delays before posting and it didn't make much difference .
As for the formatting i would only learn as i go and with all your help
i would also try everything that you suggested

Thanks for All Your Help
_________________
BOB_Santana Smile
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Dec 05, 2006 9:25 am     Reply with quote

Does your serial data come in "word" and then a little idle time. If so I would
say you should try an irq reception read into a buffer. set a timmer when start rx of serial(reset it on every char rx)
then when timer is 0 you are in the idle time.
Then check the data in the buffer.

This allows you to do other things without missing a RX char.

If you describe a little about how your project works, people will try to help you make programming decisions, and why, and still at your
learning curve level.
BOB_SANTANA



Joined: 16 Oct 2006
Posts: 110
Location: HOVE, EAST SUSSEX

View user's profile Send private message

PostPosted: Tue Dec 05, 2006 10:19 am     Reply with quote

treitmey

Sorry for not describing the project in details and ( of cause the programming layout)

All i am trying to do is capture 7 characters example AD1FFFF using the
the serial interupt (int_rda).
the first 3 characters is the address of my Pic (Like a header) while the
next 4 characters are converter from ascii to hex limiting if to the range
0000 - FFFF .
Anything out of that range would be and error.
i then use the accepted range and send it to the out output of my pic
which is made up as follows
(This is an old piece of harware so i cant change it .if it were a new design i would have used 2 shift regs)

RB7 = MSB
RB6
RB5
RB4
RB3
RB2
RB1
RB0
RA0
RA1
RA2
RA3
RD0
RD1
RD2
RD3 = LSB


The rest of the time the pic is just running in a loop until the outputs need to be update through the pc

Its a simple project but its me that make it dificult

Regards
_________________
BOB_Santana Smile
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Dec 05, 2006 10:42 am     Reply with quote

Is there idle time after the 7 char but before the next 7??

a few ms would do.
BOB_SANTANA



Joined: 16 Oct 2006
Posts: 110
Location: HOVE, EAST SUSSEX

View user's profile Send private message

PostPosted: Tue Dec 05, 2006 1:06 pm     Reply with quote

yes i suppose
i am typing in on hyperterm and i also created text files with some different combination and send it to my pic as text file via hypertem
Now just to ask and please don't take it the wrong way i just want your professional opinion
When using the curly brackets with C which way is better

Code:


 Type A                                          Type B

 if (condition) {                            if (condition)
          do this;                                 {
        }                                             do this; 

                                                    } 

_________________
BOB_Santana Smile
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Dec 05, 2006 1:13 pm     Reply with quote

I flip/flop. Right now I use option A. I like to see as much code as possible.
and I've gotten use to it

But... I've also done option B as it lines up the curlies nice and its the way c# does it by default.

I'd say do it the way ttelma or pcm programmer does it. : )
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Dec 05, 2006 1:15 pm     Reply with quote

The complaints about formatting are not really about the braces.
It's about your indentation. Look at your code above. There's a
section where almost every line is indented more than the previous line.
It makes the code hard to read.
BOB_SANTANA



Joined: 16 Oct 2006
Posts: 110
Location: HOVE, EAST SUSSEX

View user's profile Send private message

PostPosted: Tue Dec 05, 2006 3:26 pm     Reply with quote

Thats Ok
Its back to the drawing board for me.
I have to get it right and i am in the right company
learning from you guys
Thank you for being honest no matter what, it can only help me.

Best Regards
_________________
BOB_Santana Smile
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Dec 05, 2006 3:39 pm     Reply with quote

New post
http://www.ccsinfo.com/forum/viewtopic.php?t=29092
davekelly



Joined: 04 Oct 2006
Posts: 53
Location: Berkshire, England

View user's profile Send private message

PostPosted: Wed Dec 06, 2006 1:56 am     Reply with quote

For the formatting problem, get yourself a decent code editor.

The one I use for the CCS code is Notepad++ http://notepad-plus.sourceforge.net/uk/site.htm

This has a plugin (automatically installed) which can reformat your code (Plugins, TextFx Edit, Reindent C++ code).
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group