| View previous topic :: View next topic | 
	
	
		| Author | Message | 
	
		| BOB_SANTANA 
 
 
 Joined: 16 Oct 2006
 Posts: 110
 Location: HOVE, EAST SUSSEX
 
 
			    
 
 | 
			
				| rs232 missed characters |  
				|  Posted: Mon Dec 04, 2006 11:03 am |   |  
				| 
 |  
				| 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
  
 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
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Dec 04, 2006 11:12 am |   |  
				| 
 |  
				| 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Dec 05, 2006 3:47 am |   |  
				| 
 |  
				| Thanks PCM Pro 
 I have just managed to edit the post
 i know now next time
 
 Best Regards
 _________________
 BOB_Santana
  |  | 
	
		|  | 
	
		| Ttelmah Guest
 
 
 
 
 
 
 
			
			
			
			
			
			
			
			
			
 
 | 
			
				|  |  
				|  Posted: Tue Dec 05, 2006 5:29 am |   |  
				| 
 |  
				| 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
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Dec 05, 2006 5:40 am |   |  
				| 
 |  
				| 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Dec 05, 2006 7:13 am |   |  
				| 
 |  
				| 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
  |  | 
	
		|  | 
	
		| treitmey 
 
 
 Joined: 23 Jan 2004
 Posts: 1094
 Location: Appleton,WI   USA
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Tue Dec 05, 2006 9:25 am |   |  
				| 
 |  
				| 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Dec 05, 2006 10:19 am |   |  
				| 
 |  
				| 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
  |  | 
	
		|  | 
	
		| treitmey 
 
 
 Joined: 23 Jan 2004
 Posts: 1094
 Location: Appleton,WI   USA
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Tue Dec 05, 2006 10:42 am |   |  
				| 
 |  
				| 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Dec 05, 2006 1:06 pm |   |  
				| 
 |  
				| 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
  |  | 
	
		|  | 
	
		| treitmey 
 
 
 Joined: 23 Jan 2004
 Posts: 1094
 Location: Appleton,WI   USA
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Tue Dec 05, 2006 1:13 pm |   |  
				| 
 |  
				| 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
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Dec 05, 2006 1:15 pm |   |  
				| 
 |  
				| 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Dec 05, 2006 3:26 pm |   |  
				| 
 |  
				| 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
  |  | 
	
		|  | 
	
		| treitmey 
 
 
 Joined: 23 Jan 2004
 Posts: 1094
 Location: Appleton,WI   USA
 
 
			      
 
 |  | 
	
		|  | 
	
		| davekelly 
 
 
 Joined: 04 Oct 2006
 Posts: 53
 Location: Berkshire, England
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Dec 06, 2006 1:56 am |   |  
				| 
 |  
				| 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).
 |  | 
	
		|  | 
	
		|  |