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 CCS Technical Support

rs232 pass through in both directions
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
cerr



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

rs232 pass through in both directions
PostPosted: Tue Mar 22, 2011 5:39 pm     Reply with quote

Hi There,

I'm trying to realize a pass through of rs232 data through my 18f87k22. On one side theres a PC and on the other side a 16F883.
For some reason I can't deliver data properly from the 16F back to the PC. I came up with below sample app to show the problem.
Does anyone see where the fluke in my code is?
Thank you!
Code:
#include <18F87K22.h>
#device ICD=TRUE, HIGH_INTS=TRUE, adc=16

#FUSES NOWDT                      //No Watch Dog Timer
#FUSES WDT128                     //Watch Dog Timer uses 1:128 Postscale
#FUSES HSM                        //Hi-Speed crystal oscillator
#FUSES NOBROWNOUT                 //No brownout reset
#FUSES NOPLLEN                    //No PLL enabled
#FUSES BBSIZ1K                    //1K words Boot Block size
#FUSES NOXINST                    //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(clock=10000000)
#use rs232(baud=9600,parity=N,xmit=PIN_G1,rcv=PIN_G2,stream=MCU1, ERRORS)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=DEBUG, ERRORS)
#bit RC1IE = getenv("bit:RC1IE")    // Get the receive interrupt enable bit from USART1

int32 outBrec=0;
int32 Brec=0;
int32 outBSnt=0;
int32 BSnt=0;
int8 outcnt=0;
int8 incnt=0;
int8 outbuf[100]={0};
int8 inbuf[100]={0};
void main(void)
{
  enable_interrupts(INT_RDA);
  enable_interrupts(GLOBAL);
  while(RC1IE){
    if(incnt){
     fputc(inbuf[--incnt],MCU1);
     inbuf[incnt]=0x00;
     BSnt++;
   }
   if(outcnt){
     fputc(outbuf[--outcnt],DEBUG);
     outbuf[outcnt]=0x00;
     outBSnt++;
    }
  }   
}
#int_rda
void RDA_isr()
{
static int16 first_esc=0;

int8 ch,outch;
static int8 tmpbuf[3]={0};
  if (kbhit(DEBUG)){
   BRec++;
   ch=fgetc(DEBUG);
   if (ch==0x1b){                // check for first byte of HOME (HOME key sends 4 Bytes, 0x1b 0x5b 0x31 0x7e
     tmpbuf[0]=0x1b;
   } else if(ch==0x5b && tmpbuf[0]==0x1b){// check for 2nd HOME Byte
     tmpbuf[1]=0x5b;
   } else if(ch==0x31 && tmpbuf[1]==0x5b && tmpbuf[0]==0x1b){//check for 3rd HOME Byte
     tmpbuf[2]=0x31;
   } else if(ch==0x7e && tmpbuf[2]==0x31 && tmpbuf[1]==0x5b && tmpbuf[0]==0x1b){
     if (first_esc){            // has the first home key already been received completely?
      disable_interrupts(INT_RDA);// disable interrupt on incoming serial data
       tmpbuf[0]=0;
       tmpbuf[1]=0;      
      first_esc=0;
     }
     else
       first_esc=BRec;            // set the flag that we have received the first HOME key seq
                              // to the no of Bytes received so we can expect the next reception within 100bytes
     BRec=BRec-4;
     return;
   }else{
     if (first_esc){
       if(BRec-first_esc>100){
        tmpbuf[0]=0;
         tmpbuf[1]=0;      
         first_esc=0;
      }   
     }
     if (incnt>=100){
       fprintf(DEBUG,"Variable Overflow inbuf!\r\n");
       return;
       }
     inbuf[incnt++]=ch;
    }
  }
  if (kbhit(MCU1)){
    outch=fgetc(MCU1);
    outBrec++;
   if (outcnt>=100){
     fprintf(DEBUG,"Variable Overflow outbuf!\r\n");
     return;
   }
    outbuf[outcnt++]=outch;
  }
}    
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Tue Mar 22, 2011 8:34 pm     Reply with quote

Are you using one hardware UART and one software?

For an application like that, I would recommend 2 hardware UART's being fed by RCV ISR's for each UART.

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Mar 23, 2011 6:49 am     Reply with quote

While it might no matter, using 'DEBUG' as a stream name, might confuse the compiler as DEBUG should be considered a 'reserved word' ?
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Wed Mar 23, 2011 8:42 am     Reply with quote

temtronic wrote:
While it might no matter, using 'DEBUG' as a stream name, might confuse the compiler as DEBUG should be considered a 'reserved word' ?


I don't know - I used #define DEBUG all the time as it's not already in use.

But I would agree that "DEBUG" is sort of an unofficial reserved word.

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
cerr



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

PostPosted: Wed Mar 23, 2011 9:59 am     Reply with quote

bkamen wrote:
temtronic wrote:
While it might no matter, using 'DEBUG' as a stream name, might confuse the compiler as DEBUG should be considered a 'reserved word' ?

But I would agree that "DEBUG" is sort of an unofficial reserved word.

Fair enough, I've replaced DEBUG with PC it however didn't change the (not) behavior of my application... :(
cerr



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

PostPosted: Wed Mar 23, 2011 12:15 pm     Reply with quote

Ok, my test app now looks like below and it seems to work well as long as I have my oscilloscope probes connected - so I might have a capacitive issue with my dev assembly - i'll have to see if this disappears once we get our first sample... I just talked to our hardware designer and he thinks it shouldn't be a problem once we have the hardware in our hands...

the code:

Code:
#include <18F87K22.h>
#device ICD=TRUE, HIGH_INTS=TRUE, adc=16

#FUSES NOWDT                      //No Watch Dog Timer
#FUSES WDT128                     //Watch Dog Timer uses 1:128 Postscale
#FUSES HSM                        //Hi-Speed crystal oscillator
#FUSES NOBROWNOUT                 //No brownout reset
#FUSES NOPLLEN                    //No PLL enabled
#FUSES BBSIZ1K                    //1K words Boot Block size
#FUSES NOXINST                    //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(clock=10000000)
#use rs232(baud=9600,parity=N,xmit=PIN_G1,rcv=PIN_G2,stream=MCU1, ERRORS)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PC, ERRORS)
#bit RC1IE = getenv("bit:RC1IE")    // Get the receive interrupt enable bit from USART1

int32 outBrec=0;
int32 Brec=0;
int32 outBSnt=0;
int32 BSnt=0;
int8 outcnt=0;
int8 incnt=0;
int8 outbuf[100]={0};
int8 inbuf[100]={0};
void main(void)
{
  enable_interrupts(INT_RDA);
  enable_interrupts(INT_RDA2);
  enable_interrupts(GLOBAL);
  while(RC1IE){
    if(incnt){
     fputc(inbuf[--incnt],MCU1);
     inbuf[incnt]=0x00;
     BSnt++;
   }
   if(outcnt){
     fputc(outbuf[--outcnt],PC);
     outbuf[outcnt]=0x00;
     outBSnt++;
    }
  }   
}
//--------------------------------------------------------------

#int_rda
void RDA_isr()
{
static int16 first_esc=0;

int8 ch;
static int8 tmpbuf[3]={0};
  if (kbhit(PC)){
   BRec++;
   ch=fgetc(PC);
   if (ch==0x1b){                // check for first byte of HOME (HOME key sends 4 Bytes, 0x1b 0x5b 0x31 0x7e
     tmpbuf[0]=0x1b;
   } else if(ch==0x5b && tmpbuf[0]==0x1b){// check for 2nd HOME Byte
     tmpbuf[1]=0x5b;
   } else if(ch==0x31 && tmpbuf[1]==0x5b && tmpbuf[0]==0x1b){//check for 3rd HOME Byte
     tmpbuf[2]=0x31;
   } else if(ch==0x7e && tmpbuf[2]==0x31 && tmpbuf[1]==0x5b && tmpbuf[0]==0x1b){
     if (first_esc){            // has the first home key already been received completely?
      disable_interrupts(INT_RDA);// disable interrupt on incoming serial data
       tmpbuf[0]=0;
       tmpbuf[1]=0;      
      first_esc=0;
     }
     else
       first_esc=BRec;            // set the flag that we have received the first HOME key seq
                              // to the no of Bytes received so we can expect the next reception within 100bytes
     BRec=BRec-4;
     return;
   }else{
     if (first_esc){
       if(BRec-first_esc>100){
        tmpbuf[0]=0;
         tmpbuf[1]=0;      
         first_esc=0;
      }   
     }
     if (incnt>=100){
       fprintf(PC,"Variable Overflow inbuf!\r\n");
       return;
       }
     inbuf[incnt++]=ch;
    }
  }
}
//--------------------------------------------------------------

#int_rda2
void RDA2_isr()
{
int8 ch=0;
  if (kbhit(MCU1)){
    ch=fgetc(MCU1);
    outBrec++;
   if (outcnt>=100){
     fprintf(PC,"Variable Overflow outbuf!\r\n");
     return;
   }
    outbuf[outcnt]=ch;
    outcnt++;
  }
}   
cerr



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

PostPosted: Wed Mar 23, 2011 12:43 pm     Reply with quote

Well, that euphoria was too early. I realized that I'm "only" able to connect to with the bootloader up to my 16F883 PIC but I'm actually not able to send through any data... :( Read and Write both keep timing out... :(
Well, read worked once after a few tries but... Shocked am unable to explain that, been trying to make sense of what i'm seeing on my scope but... Sad
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Mar 23, 2011 1:25 pm     Reply with quote

Hmm...
do you have a GOOD ground ? Most scope probes are at least 10Meg imp..

I see you have ICD=true, that may cause problems...silly things like pins you thought were 'yours' don't act right....

If code was cut using MPLAB have you compiled with build configuryion set to release and NOT the default of 'debug' ? The default will do 'strange' things to your code....
like adding debug code in your code...
cerr



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

PostPosted: Wed Mar 23, 2011 1:51 pm     Reply with quote

GND was my first thought too but I have the two boards powered from the same power source, GNDs are directly connected, GNDs of the RS232 interfaces are connected too thus that shouldn't be the issue.
I however set MPLAB to Release and removed the ICD=TRUE directive and it seems to connect now even when the probes are disconnected. But looks like I can read with the bootloader app from AN1310 only once right after I connected the bootloader-app to the target but I never get to write anything succesfully :( Any clues there maybe Question Question
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Mar 25, 2011 8:46 am     Reply with quote

I might not have the solution to your problem but here are a few tips to improve your code:

*1*
Code:
  if (kbhit(PC)){
Inside the ISR you don't have to test for a character being present. You got here because there is a character waiting to be processed. Removing this test makes the code easier to read and faster to execute.
Also remove the similar test from the other ISR.

*2*
A serious problem is that you are using variables in the main function that are also modified by the interrupts. This is a disaster waiting to happen. For example this piece of code in main:
Code:
     fputc(inbuf[--incnt],MCU1);
     inbuf[incnt]=0x00;
If now in between these two lines a interrupt is triggered, then the variable incnt will be increased and you are setting the wrong offset in inbuf[] to zero.
The normal solution is to temporarily disable the interrupts. Take care to do this around as short pieces of code as possible.
Code:

    if(incnt){
     disable_interrupts(GLOBAL);  // Temporarily disable to protect incnt variable
     fputc(inbuf[--incnt],MCU1);
     inbuf[incnt]=0x00;
     enable_interrupts(GLOBAL);
     BSnt++;
   }
Note: because the fputc function can take some time when another byte is waiting to be sent, it is better to store the new value in a temp variable and call fputc outside the disable/enable section.

*3*
Code:
static int8 tmpbuf[3]={0};
This only initialises the first element of the array. Correct would be to write:
Code:
static int8 tmpbuf[3]={0,0,0};
But because static variables are by definition initialised to zero the whole initialisation can be omitted.

*4*
Your test for the HOME sequence will also accept sequences like:
0x1b 0x1b 0x5b 0x5b 0x31 0x31 0x7e
0x1b 0x5b 0x5b 0x5b 0x31 0x7e
0x1b 0x5b 0x31 0x5b 0x1b 0x7e
etc.
You could improve this by using a state counter, for example:
Code:
int8 CodeState=0;

ch=fgetc(PC);
switch (CodeState)
{
  case 0: ch == 0x1b ? CodeState++ : CodeState=0; break;
  case 1: ch == 0x5b ? CodeState++ : CodeState=0; break;
  case 2: ch == 0x31 ? CodeState++ : CodeState=0; break;
  case 3: ch == 0x7e ? CodeState++ : CodeState=0; break;
  default: CodeState = 0;
}

if (CodeState == 4)
{
  // HOME code was received. Do your processing here.
}
cerr



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

PostPosted: Fri Mar 25, 2011 11:00 am     Reply with quote

Yep,

Great tips! Thank you very much! Esp. *2*!!! For this case, I just removed
Code:
inbuf[incnt]=0x00;
as I don't check for this again anyways. I also implemented a counter as shown in *4* - makes it look a lot nicer!
Thank you for these hints, thety're very much appreciated!
Regarding *3*
to initialize an array you would need to do
Code:
int array[1024]={0,0,0,0,...,0}
I agree but most compiler fill all the missing elements with 0 thus
Code:
int array[1024]={0}
initializes the array with 0 with most compilers (at least GCC & Borland, M$ probably too, not sure). Thus my initialization should be fine but I agree static variables are initialized with 0 already, thus i just removed it.
*4* I think CCS sadly doesn'tsupports the "short if form"
Code:
 like x==1 ? x++ : x--;
I just looked at that yesterday and couldn't find it anywhere thus i had to break this up in
Code:
if (bla) blah; else blahblah;
- however, works fine! And as mentioned above, looks much nicer!
Thanks pal!
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Fri Mar 25, 2011 11:13 am     Reply with quote

CCS does support what you call the "short if form". They call it the "Conditional Expression Operator". It is in the Operators table of my CCS manual and I have been using it for years in trivial IF expressions.

I don't use it in complex expressions because it can make things confusing if someone else has to read my code.
_________________
The search for better is endless. Instead simply find very good and get the job done.
cerr



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

PostPosted: Fri Mar 25, 2011 11:19 am     Reply with quote

SherpaDoug wrote:
CCS does support what you call the "short if form". They call it the "Conditional Expression Operator". It is in the Operators table of my CCS manual and I have been using it for years in trivial IF expressions.

But this doesn't compile for me, I'm getting Expecting LVALUE such as a variable name or * expression Sad
I'm using 4.119
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Fri Mar 25, 2011 11:59 am     Reply with quote

cerr wrote:
SherpaDoug wrote:
CCS does support what you call the "short if form". They call it the "Conditional Expression Operator". It is in the Operators table of my CCS manual and I have been using it for years in trivial IF expressions.

But this doesn't compile for me, I'm getting Expecting LVALUE such as a variable name or * expression Sad
I'm using 4.119




I think the normal format of this type of expression is:


( test )? DoIfTrue: DoIfFalse;

I always put in parentheses around my test.

Maybe that's what your missing?

As for your "if" example, you have
Code:

if (bla) blah; else blahblah;

which also seems sloppy.

I would write as
Code:
 
if (test) {
   do this;
} else {
   do this;
}


Although is it legal to write it as:
Code:

if (test)
  Do this;
else
  do this;


The difference is that in my braced example, I can add extra lines of resulting commands without the need to add braces where without them, any extra commands would require braces or cause a compiler error.

Code should be READABLE. Not superneatoconfusingandextravagant.
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
cerr



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

PostPosted: Fri Mar 25, 2011 1:12 pm     Reply with quote

Well, I didn't get the conditional expression operator working - even when I added brackets but I think below doesn't look two bad either:
Code:
  // test for two consecutive HOME buttons
  switch (CodeState)
  {
    case 0: if(ch == 0x1b) CodeState++; else CodeState=0; break;
    case 1: if(ch == 0x5b) CodeState++; else CodeState=0; break;
    case 2: if(ch == 0x31) CodeState++; else CodeState=0; break;
    case 3: if(ch == 0x7e) CodeState++; else CodeState=0; break;
    case 4: if(ch == 0x1b) CodeState++; else CodeState=0; break;
    case 5: if(ch == 0x5b) CodeState++; else CodeState=0; break;
    case 6: if(ch == 0x31) CodeState++; else CodeState=0; break;
    case 7: if(ch == 0x7e) CodeState++; else CodeState=0; break;     
    default: CodeState = 0;
  }

if (CodeState == 8)
{
  // 2 HOMEs were received, leave here!
  fprintf(PC,"HOME!\r\n");
  CodeState = 0;
  return;
}
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