|
|
View previous topic :: View next topic |
Author |
Message |
Delfy_Coltech
Joined: 25 Nov 2009 Posts: 27 Location: Vietnam
|
[Help me] Problem with RDA interrupts in 16F877A. |
Posted: Sun Dec 27, 2009 1:08 pm |
|
|
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
|
|
Posted: Sun Dec 27, 2009 1:54 pm |
|
|
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
|
|
Posted: Sun Dec 27, 2009 3:48 pm |
|
|
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
|
Continue with my problem... |
Posted: Sun Dec 27, 2009 10:08 pm |
|
|
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.
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
|
|
Posted: Sun Dec 27, 2009 11:18 pm |
|
|
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: 1933 Location: Norman, OK
|
|
Posted: Mon Dec 28, 2009 7:33 am |
|
|
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
|
ID20 Datasheet |
Posted: Mon Dec 28, 2009 8:20 am |
|
|
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: 1933 Location: Norman, OK
|
|
Posted: Mon Dec 28, 2009 9:06 am |
|
|
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!!!! |
|
|
|
|
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
|