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

[Help me] Problem with RDA interrupts in 16F877A.

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Delfy_Coltech



Joined: 25 Nov 2009
Posts: 27
Location: Vietnam

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

[Help me] Problem with RDA interrupts in 16F877A.
PostPosted: Sun Dec 27, 2009 1:08 pm     Reply with quote

Hi all!
I am trying to get the "idnumber" from RFID tags by using TLM-20(ID-20) reader.

But I have some problems. Plz help me solve them!
Here is my code:
Code:
#include <16F877A.h>
#include <def_877a.h>
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=ID20)// ID20 Communication
#use rs232(baud=9600,parity=N,xmit=PIN_B6,rcv=PIN_B7,bits=8,stream=PC,ERRORS) // PC Communication

#include <lcd_lib_4bit.c> // 4 bit LCD Library
#define start_byte    0x0A
#define end_byte   0x0D

//II. Main Program
// 1. Variable Setting
 int8 string[20];
 int8 byte1,byte2,byte3,byte4,len;
 char c;
 int32 idnumber;
 int8 max=20;
 
 // 2. Display 32bit integer on LCD
               
 VOID int32_display(int32 number)
   {
      int8 i;
      int32 temp,exp10;
      unsigned char a[10];
     
      temp=number;
      exp10=1000000000;
      for (i=9;i>=2;i--)
       {
          a[i]=temp/exp10;
          temp=temp%exp10;
          exp10=exp10/10;
       }
      a[1]=temp/10;
      a[0]=temp%10;

      for (i=9;i>=1;i--)
         {
          if (a[i]>0)
          {
             LCD_putchar(a[i]+48);
             //delay_us(10);
          }
        }
      LCD_putchar(a[0]+48);
     // delay_us(10);
   }
// 3. ID20 Communication
     
#INT_RDA
    VOID RDA_ISR()
      {               
          //Wait for start byte
            do
                 {
                   c = fgetc(ID20);
                 } while (c != start_byte);
 
           // Receive data until END byte is received or buffer full
              len=0;
            while ((c != end_byte) && (len < max))
                 {
                  c = fgetc(ID20);
                  string[len++] = c;
                  // Get 4 good bytes
                  byte1=string[8];
                  byte2=string[9];
                  byte3=string[10];
                  byte4=string[11];
                 }
            //Making the ID_number     
              idnumber=make32(byte1,byte2,byte3,byte4);
              fprintf(PC,"%lu\n\r",idnumber); // Sent to PC.
            // Create interrupts
              OUTPUT_HIGH(PIN_A0);
              OUTPUT_LOW(PIN_A0);
            // Clear interrupts flag.
           
     }
//4. Main program

VOID main()

    TRISA=0X00;
    PORTA=0XFF;
    enable_interrupts(INT_RDA);
    enable_interrupts(GLOBAL);
   
    LCD_init();
    Printf(LCD_putchar,"START...");
    //delay_ms(500);
    LCD_putcmd(0x80);
    Printf(LCD_putchar,"RFID PATIENT MNG");
    //delay_ms(500);
 
// if  Put enable_interrupts() here. I have to reset PIC

      do   
        {
          LCD_putcmd(0xC0);
          Printf(LCD_putchar,"ID: ");
          int32_display((int32) idnumber);
        }while(true);
 }


1. When I put enable_interrupts(INT_RDA) after LCD_init()
I have to reset PIC so the program can run. if not it isn't run.

--> Can U show me why?

2. But when I put enable_interrupts(INT_RDA) in front of LCD_init() like above. The interrupts only occurs at the second time. (In the first time, when I take the tag over the reader, there is nothing transmitting into PC!)
And the LCD can not show anything???


I hope someone can help me!
Thanks alot!
_________________
-------------------------------------------------
Mechatronics Department, Coltech, VNUH
Hanoi, Vietnam.
-------------------------------------------------
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Dec 27, 2009 1:54 pm     Reply with quote

Quote:

VOID int32_display(int32 number)
{
int8 i;
int32 temp,exp10;
unsigned char a[10];
.
.
.

}

Why do you have this large routine ?
You can do it like this, with one line of code:
Code:

printf(lcd_putchar, "%lu", idnumber);


Also, I don't see any reason why your program needs to use #int_rda.
You can do everything that is inside the #int_rda routine, inside main(),
instead. You don't need rda interrupts in your program.

In other words, don't make your code complicated. Make it simple.
It's easier to understand and debug simple code.
Ttelmah
Guest







PostPosted: Sun Dec 27, 2009 3:48 pm     Reply with quote

Also, if you do want to use interrupts, _keep the handler as fast and as small as possible_.
The interrupt, implies there is just _one_ character to receive. Your current code, sits inside the interrupt, waiting for the entire string, then still inside the interrupt, prints the message, using software serial. The LCD print routine, is used in the main code, and in the interrupt, so this immediately implies that interrupts _will_ be disabled in the external code, for the display routine, and all the stuff it contains (like delays etc..). Now, the 16F877A, only has one hardware serial port,on C6/C7. Your serial setup, has an 'errors' statement on the software serial (which does no good at all), but does not have one on the hardware serial (where it is needed). This implies, that if data arrives while the processor is in one of the sections that have interrupts disabled, because of your bad use of interrupts, the UART _will_ hang, and when eventually the interrupt is called, the software will be completely locked up.....

Either use code entirely in the main, or use the interrupts properly. Look at EX_SISR, for an example of how to receive serial data usng the interrupts.

Best Wishes
Delfy_Coltech



Joined: 25 Nov 2009
Posts: 27
Location: Vietnam

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

Continue with my problem...
PostPosted: Sun Dec 27, 2009 10:08 pm     Reply with quote

Thank you very much! PCM programmer and Ttelmah, two professional programmers.

I'm a newbie, so I don't know clearly about interrupts of PIC.
I am surprising that I can receive data from ID-20 reader without using #INT_RDA. Very Happy

Now, my code like below:
Code:

#include <16F877A.h>
#include <def_877a.h>
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=ID20)// ID20 Communication
#use rs232(baud=9600,parity=N,xmit=PIN_B6,rcv=PIN_B7,bits=8,stream=PC) // PC Communication

#include <lcd_lib_4bit.c> // 4 bit LCD Library
#define start_byte    0x0A
#define end_byte   0x0D

//II. Main Program
// 1. Variable Setting
 int8 string[20];
 int8 byte1,byte2,byte3,byte4,len;
 char c;
 int32 idnumber;
 int8 max=20;

// 2. ID20 Communication
     
    VOID READ_TAG()
      {               
          //Wait for start byte
            do
                 {
                   c = fgetc(ID20);
                 } while (c != start_byte);
 
           // Receive data until END byte is received or buffer full
              len=0;
            while ((c != end_byte) && (len < max))
                 {
                  c = fgetc(ID20);
                  string[len++] = c;
                  // Get 4 good bytes
                  byte1=string[8];
                  byte2=string[9];
                  byte3=string[10];
                  byte4=string[11];
                 }
            //Making the ID_number     
              idnumber=make32(byte1,byte2,byte3,byte4);             
              fprintf(PC,"%lu\n\r",idnumber); // Sent to PC.
            // Create interrupts
              OUTPUT_HIGH(PIN_A0);
              OUTPUT_LOW(PIN_A0); 
     }
//3. Main program

VOID main()

        PORTA=0XFF;
        LCD_init();
        Printf(LCD_putchar,"START...");
        delay_ms(500);
        LCD_putcmd(0x80);
        Printf(LCD_putchar,"RFID PATIENT MNG");
        delay_ms(500);
   
         DO {         
                READ_TAG();
                LCD_putcmd(0xC0);
                Printf(LCD_putchar,"ID: ");
                printf(LCD_putchar,"%lu",idnumber);           
            } WHILE(TRUE); 
 }

But there is a small problem that I can only receive "idnumber" at the second scan.
I don't know why? I think it take some seconds for PIC to init. So I waited some seconds and then scan the tag. But there is nothing in the first time.

Can U help me? Thank again! PCM programmer and Ttelmah.
_________________
-------------------------------------------------
Mechatronics Department, Coltech, VNUH
Hanoi, Vietnam.
-------------------------------------------------
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Dec 27, 2009 11:18 pm     Reply with quote

Post a link to a document that describes the protocol for the reader.
It should provide a description of all the bytes that are sent by the
reader.

Also post a link to a detailed data sheet for the reader. On their website,
I only saw short "brochure" style documents. I didn't see any technical
data sheets.
dyeatman



Joined: 06 Sep 2003
Posts: 1912
Location: Norman, OK

View user's profile Send private message

PostPosted: Mon Dec 28, 2009 7:33 am     Reply with quote

I suspect a big part of the problem are the start (0x0A) and end (0x0D) bytes
that are defined. I have never encountered a reader that started a data
stream with x0A. Most of the ones I have seen end the data stream with
CR/LF. As PCM says, we need to see the data sheet to know for sure.
_________________
Google and Forum Search are some of your best tools!!!!
Delfy_Coltech



Joined: 25 Nov 2009
Posts: 27
Location: Vietnam

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

ID20 Datasheet
PostPosted: Mon Dec 28, 2009 8:20 am     Reply with quote

Thanks! The datasheet can be downloaded here:

http://www.soselectronic.com/?str=371&artnum=54215

I also have only that!
Follow it, the data structrure is:

STX(02h) + Data (10 ASCII) + Checksum (2 ASCII) + CL+RF+EXT(03h)
_________________
-------------------------------------------------
Mechatronics Department, Coltech, VNUH
Hanoi, Vietnam.
-------------------------------------------------
dyeatman



Joined: 06 Sep 2003
Posts: 1912
Location: Norman, OK

View user's profile Send private message

PostPosted: Mon Dec 28, 2009 9:06 am     Reply with quote

The start byte is Start of Text (STX) 02h
followed by 10 ASCII characters (NOT an ASCII 10).
then 2 bytes containing 2 ASCII digits as the exclusive OR checksum.
then 0Dh (CR)
then 0Ah (LF)
the last byte is End of Text (ETX) byte of 03h.

This means your start byte is 02h and the end byte is 03h. You must
change your code to fit the above format. The data sheet says the
checksum is the Exclusive OR of the 10 ASCII data characters.

Note the total length of the data packet is 16 bytes not 20 so you will
have to modify your data stream length and you will have to unpack each
byte to get the ASCII characters in each nibble.

Also, make sure pin 7 is grounded for the ASCII format.
_________________
Google and Forum Search are some of your best tools!!!!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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