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

ex_sisr sample code problem
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
wordizlife



Joined: 08 Mar 2012
Posts: 38
Location: Canada

View user's profile Send private message

ex_sisr sample code problem
PostPosted: Thu Apr 19, 2012 5:19 pm     Reply with quote

Hey guys,
I am using the CCS ex_sisr example file as a model to receive serial data through my RX port and display it on an LCD.
My code works fine and the data is displayed as expected on the LCD.
My problem is that my program seems to freeze as soon as the data is received and displayed on the LCD, it will not continue through to the next function.
How would I have to modify my function to exit the do loop once the data has been received?

Here is my main function:
Code:

void main()
{
   enable_interrupts(int_rda);
   #if defined(__PCD__)
   enable_interrupts(intr_global);
   #else
   enable_interrupts(global);
   #endif

LCD_init(); // Initialize LCD
   
lcd_putc("\f*****\n");   
lcd_putc("Project 2 - 2012");
delay_ms(5000); // wait 5 seconds

/********** Turn ELM327 On **********/
TRISA = 0x00; // Set Pot D as outputs
A5 = 1; // Turns on ELM327

/********** Display ELM Version **********/
lcd_init();
lcd_putc("\fOBD Reader\n");
read_buffer();  // THIS IS WHERE THECODE STAYS STUCK!

delay_ms(2000);
reset_elm();
}

void read_buffer(void)
{
   do { 
    while(bkbhit)
    lcd_putc( bgetc() );
    }while(1);
}

void reset_elm(void)
{
   lcd_init();
   delay_ms(1000);
   printf("ATZ");
   lcd_putc("\fReset OBD\n");
   delay_ms(1000);
   read_buffer();
}


Thanks!

EDIT:
I just realised that the while(1) at the end of the do loop is the end condition. I'm guessing I will have do modify this to have the loop end when I want it to..?


Last edited by wordizlife on Thu Apr 19, 2012 5:28 pm; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 19, 2012 5:26 pm     Reply with quote

Quote:
void read_buffer(void)
{
do {
while(bkbhit)
lcd_putc( bgetc() );
}while(1);
}

How do you propose to exit the do-while loop when you're done ?
Your while(test) at the end is a "forever" loop. And you don't
have any test inside the loop that will execute a "break".
So, you're stuck in it forever.
wordizlife



Joined: 08 Mar 2012
Posts: 38
Location: Canada

View user's profile Send private message

PostPosted: Thu Apr 19, 2012 5:39 pm     Reply with quote

Ok so I just have to figure out how to write this function so that it stops when all the data has been received.
Question is how am I supposed to know when all the data has been received?

EDIT:
My concern is that all the data might be received but the buffer might not be full, so I cannot set my condition to next_in != next_out... Perhaps some sort of count function would work?
For example:
Code:

void read_buffer(void)
{
   count = 0;
   do { 
    while(bkbhit)
    lcd_putc( bgetc() );
    count = count++;
    }while(count<=32);
}


I tested this without any luck...

Here is my full code:

Code:

/********** Included Files ***********/
#include <main.h>
#include "D:\Winter_2012\Project_2\flex_lcd.c"

/********** Required Registers **********/
#byte TRISA = 0x85
#byte PORTA = 0x05
#byte TRISB = 0x86
#byte PORTB = 0x06

/********** Required Bits **********/
#bit A5 = 0x5.5 // Used to power on ELM323

/********** Declared Functions **********/

void read_buffer(void);
void reset_elm(void);

#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)

BYTE bgetc() {
   BYTE c;
   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}

void main()
{
   enable_interrupts(int_rda);
   #if defined(__PCD__)
   enable_interrupts(intr_global);
   #else
   enable_interrupts(global);
   #endif

LCD_init(); // Initialize LCD
   
lcd_putc("\f*****\n");   
lcd_putc("Project 2 - 2012");
delay_ms(5000); // wait 5 seconds

/********** Turn ELM327 On **********/
TRISA = 0x00; // Set Pot D as outputs
A5 = 1; // Turns on ELM327

/********** Display ELM Version **********/
lcd_init();
lcd_putc("\fOBD Reader\n");
read_buffer();  // THIS IS WHERE THECODE STAYS STUCK!

lcd_init();
delay_ms(2000);
reset_elm();
}

void read_buffer(void)
{
   do { 
    while(bkbhit)
    lcd_putc( bgetc() );
    }while(1);
}

void reset_elm(void)
{
   lcd_init();
   delay_ms(1000);
   printf("ATZ");
   lcd_putc("\fReset OBD\n");
   delay_ms(1000);
   read_buffer();
}
[/code]
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 19, 2012 7:21 pm     Reply with quote

Quote:

Question is how am I supposed to know when all the data has been received?

If the data is in some specified protocol, then it probably has an
end-of-message marker byte, such as a CR, or maybe CR and LF bytes.
Look for those. But, also add some method of exiting the loop if you
don't receive a full message, so that you don't hang up in the loop
forever. Also have the read_buffer() routine return a status byte,
instead of declaring it as void. If it returns TRUE, then you got a
full message. If it returns FALSE, then it means you timed out in the loop,
while waiting for a message that didn't arrive.
wordizlife



Joined: 08 Mar 2012
Posts: 38
Location: Canada

View user's profile Send private message

PostPosted: Thu Apr 19, 2012 7:45 pm     Reply with quote

Thanks for mentioning that. I am communicating between two pics. When my main pic receives this ">" (0x3e) it means that the device is in idle state and no more data will be transmitted.
So I modified my function to look like this:

Code:

void read_buffer(void)
{
   int c;
   
   do { 
    while(bkbhit)
    c = bgetc();
    lcd_putc( c );
    }while(c != 0x3e); //0x3e = >
}


Now the problem is the data being displayed is somewhat erratic, it repeats certain characters, for example instead of displaying Patrick, it displays PPPPATTTRRIICCCCKKKKK.
Why would it be doing this?
Should I modify the code to this?:
Code:

void read_buffer(void)
{
   do { 
    while(bkbhit)
    lcd_putc( bgetc() );
    }while(bgetc() != 0x3e); //0x3e = >
}


At least now it exits the loop correctly Smile
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 19, 2012 7:54 pm     Reply with quote

Post the main.h code.
wordizlife



Joined: 08 Mar 2012
Posts: 38
Location: Canada

View user's profile Send private message

PostPosted: Thu Apr 19, 2012 9:17 pm     Reply with quote

Code:

#if defined(__PCM__)
#include <16F877A.h>
#device adc=16


#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOPROTECT

#use delay(clock=20000000)
#use rs232(baud=38400,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,ERRORS)

#endif

#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 19, 2012 9:26 pm     Reply with quote

As an experiment, add the lines shown in bold below:
Quote:

void read_buffer(void)
{
int c;

do {
while(bkbhit)
c = bgetc();
disable_interrupts(GLOBAL);
lcd_putc( c );
enable_interrupts(GLOBAL);
}while(c != 0x3e); //0x3e = >
}
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Fri Apr 20, 2012 2:27 am     Reply with quote

It's possible the problem occurs whilst you're getting the next character, (the int routine and bgetc() both trying to manipulate next_in and next_out at the same time).

Try this variation on PCM's code.

Quote:

void read_buffer(void)
{
int c;

do {
while(bkbhit)
disable_interrupts(GLOBAL);
c = bgetc();
enable_interrupts(GLOBAL);
lcd_putc( c );
}while(c != 0x3e); //0x3e = >
}

Mike
jeremiah



Joined: 20 Jul 2010
Posts: 1351

View user's profile Send private message

PostPosted: Fri Apr 20, 2012 6:49 am     Reply with quote

I was looking at that, but can't see a conflict. The ISR only changes next_in and can't be interrupted, so looking at bgetc(), it only affects next_out, and it does so in a single instruction, which should be atomic? Can interrupts stop a BYTE MOV instruction or does it finish the instruction and then jump? The "while(!bkbhit)" should be ok too since the ISR won't take values out of the buffer.

What part is weak to synchronization? I know I must be missing something simple.
Ttelmah



Joined: 11 Mar 2010
Posts: 19529

View user's profile Send private message

PostPosted: Fri Apr 20, 2012 7:53 am     Reply with quote

Code:

void read_buffer(void)
{
   int c;
   
   do {
    while(bkbhit)
       c = bgetc(); //This is the line that gets executed while 'bkbhit'....
    lcd_putc( c );
    }while(c != 0x3e); //0x3e = > //Keeps looping and redisplaying....
}


Code:

void read_buffer(void) {
   int tempc;
   do {
       if (bkbhit) {
          c=bgetc();
          lcd_putc(c);
          if (c==0x3E)
            return;
      }
   } while (TRUE);
}


This now loops, until a character is available.
When it is, it reads it, displays it, and then tests if it is the end of message marker. If so, it exits.

Best Wishes
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Fri Apr 20, 2012 8:02 am     Reply with quote

You're getting regular problems with the repeat characters.

That suggests that you've got a conflict during something which takes a fair time to execute.

For that reason it's the timing which make me dubious about your problem being in the bgetc() routine.

So little time is spent there, that there's little opportunity for a clash.

PCM's suggestion of the problem being with the lcd_putc() offers a much bigger time window for a clash to occur.

Mike
wordizlife



Joined: 08 Mar 2012
Posts: 38
Location: Canada

View user's profile Send private message

PostPosted: Fri Apr 20, 2012 4:16 pm     Reply with quote

Ttelmah that configuration worked like a charm!

I can't thank you guys enough, you guys are great help! Smile

Would anyone be aware if CCS also provides example files to send data through the TX pin of a PIC16F877A?

I am not sure if this is correct or not but I tried this:

I modified my read_buffer() function to return the tempc value so it can be used by other functions. I am not sure if this is correct or not. I also changed tempc to a global variable.
Code:

read_buffer(void) {
   do {
       if (bkbhit) {
          tempc=bgetc();
          lcd_putc(tempc);
          if (tempc==0x3E)
            return tempc;
      }
   } while (TRUE);
}

I tried two different way's without any luck to send data through the TX pin:
Code:

void reset_elm(void)
{
   lcd_init();
   delay_ms(500);
   putc(0x41);//A
   putc(0x54);//T
   putc(0x5a);//Z
   delay_ms(500);
   lcd_putc("\fElm Reset\n");
   if (tempc==0x3E);
   read_buffer();
}

Code:

void reset_elm(void)
{
   lcd_init();
   delay_ms(500);
   printf("ATZ")
   delay_ms(500);
   lcd_putc("\fElm Reset\n");
   if (tempc==0x3E);
   read_buffer();
}
temtronic



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

View user's profile Send private message

PostPosted: Fri Apr 20, 2012 6:45 pm     Reply with quote

oopsy...

if (tempc==0x3E);
read_buffer();

...think you do NOT want the semicolon at the end of the if(tempc..line
wordizlife



Joined: 08 Mar 2012
Posts: 38
Location: Canada

View user's profile Send private message

PostPosted: Sat Apr 21, 2012 9:52 am     Reply with quote

That was a stupid mistake... But even if I fix it I am getting no life from the TX pin.
I must be missing something simple here..?
Would I possibly have to set the TRIS to have TX as output and RX as input or is this done automatically with the #use RS232 ?
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