Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

USART C18 Issued(RFID)

Status
Not open for further replies.
thanks i setup another 18F2525 i have (btw i have 3 altogether (PIC18LF2525)) but they are running on 5v @ 20 Mhz.

I setup the buttons to :

1. RB0/INT0/FLT0/AN12
2. RB1/INT1/AN10

So i can try the buttons (which are pulled low). I will try to have the HIGH and LOW priority on this way i can differentiate from the two. Also it will hopefully teach me about that #pragma stuff.
 
thanks i setup another 18F2525 i have (btw i have 3 altogether (PIC18LF2525)) but they are running on 5v @ 20 Mhz.

I setup the buttons to :

1. RB0/INT0/FLT0/AN12
2. RB1/INT1/AN10

So i can try the buttons (which are pulled low). I will try to have the HIGH and LOW priority on this way i can differentiate from the two. Also it will hopefully teach me about that #pragma stuff.
If you're not running bunches of interrupts, forget prioritization. Just do it the old fashioned way and set it to use high only (or is it low only? I forget what that setting does). Worry about high and low priority later.
 
ok... If im using only high the i have to read the port to determine which pin changed right?
Its high interrupt only when IPEN is cleared.

When the IPEN bit is cleared (default state), the
interrupt priority feature is disabled and interrupts are
compatible with PIC® mid-range devices.
In
Compatibility mode, the interrupt priority bits for each
source have no effect. INTCON<6> is the PEIE bit,
which enables/disables all peripheral interrupt sources.
INTCON<7> is the GIE bit, which enables/disables all
interrupt sources. All interrupts branch to address
0008h in Compatibility mode
.
 
Last edited:
ok... If im using only high the i have to read the port to determine which pin changed right?
Its high interrupt only when IPEN is cleared.
I believe so. Memory full error.. fkjsdji08387237@$%5 RESET

My memory isn't as good as it could be. Unless I do it often it's gone. :D It's still there, but not in the index anymore.

With an interrupt on change for PortB I think you'd have to read the port no matter whether the interrupt is high or low. It's only one interrupt for the whole port. What I mean is that there's not one for each bit/pin. Someone correct me if I'm wrong!
 
Last edited:
i think thats the case for RB4:7

An input change on PORTB<7:4> sets flag bit, RBIF
(INTCON<0>). The interrupt can be enabled/disabled
by setting/clearing enable bit, RBIE (INTCON<3>).
Interrupt priority for PORTB interrupt-on-change is
determined by the value contained in the interrupt
priority bit, RBIP (INTCON2<0>).
 
Yay i think i understand the button interrupt now. Some code to show... and many comments to explain it all. lol
Code:
#include <p18f2525.h>
#include <stdio.h>
#include <delays.h>

#pragma config WDT = OFF, LVP = OFF, OSC = HS

/************************************
Prototypes
*************************************/
void main(void);
void high_isr(void);
/************************************
Variables AND Defines
*************************************/
#define BtnAT TRISBbits.TRISB0
#define BtnBT TRISBbits.TRISB1

#define BtnA INTCONbits.INT0IF
#define BtnB INTCON3bits.INT1IF

//VARIABLES
char temp[2];
/************************************
                Main
*************************************/
void main(void){
    BtnAT = BtnBT = 1;      //Make Buttons Input
    ADCON1 = 0x0F;          //All Digital
    RCON = 0x00;            //Compatibility mode
    INTCON3 = 0b01001000;   //INT1IP is High, INT1IE is enabled
    INTCON2 = 0b11100000;   //INTEDG0,INTEDG1 is Rising Edge
    INTCON = 0b11010000;    //GIE, PEIE, INT0IE = 1(ON)

    while(1);               //Main Loop 
}
/************************************
            INTERRUPT STUFF
*************************************/
#pragma code high_vector=0x08       //High Priority
void interrupt_at_high_vector(void)
{
  _asm GOTO high_isr _endasm
}
#pragma code /* return to the default code section */
/************************************
            INTERRUPT STUFF(2)
*************************************/
#pragma interrupt high_isr
void high_isr (void)
{
    if(BtnA == 1){          //Check if its INTOIF
        temp[1] = 'A';      //If so put A in temp[1](ButtonA)
        BtnA = 0;           //Clear the flag.
    }

    if(BtnB == 1){          //Check if its INT1IF
        temp[1] = 'B';      //If so put B in temp[1](ButtonB)
        BtnB = 0;           //Clear the flag.
    }

    temp[0] = PORTB;        //Save PORTB value for testing
}

Only edited to correct typo in comment lol
 
Last edited:
Yes, another interesting thread Atom. :) Since I don't have much time on here these days, I want to know when the thread is updated, so will throw in my 2 cents. :D

If i am right what it should do is on interrupt add to the buffer and when full it starts at the beginning again.

on interrupt you should set a flag which tells you that data is waiting to be read. Then in your main code add the data to the buffer.

So if i have a buffer size of 4 bytes it goes


BUFFER [0] [1] [2] [3]
DATA A B C D

So if i have 1 more byte come in it looks like:

BUFFER [0] [1] [2] [3]
DATA E B C D
almost, but like this:

DATA B C D E

or if i have 4 more bytes come in it looks like

BUFFER [0] [1] [2] [3]
DATA E F G H

correct?
yep.

If so then i would have to read the first one 1st then the rest of the 12 i need. and just clear the buffer when im done as so i wont get invalid data or double data.

I see how this would save space. But i doubt it would help in getting data correctly.
I think the interrupt alone could solve the issue of the overrun error and would eliminate the delays in place.
Why not just do it right in the first place. You have overrun and framing errors because you can't process the data quick enough. Add a fifo and all your errors will disappear.

Mike.

Pommie is correct on this one; it will help to get your data correctly. Using the interrupt frees up your program to do other tasks, instead of poling the receive buffer of the UART. Since you want interrupts to be as fast as possible, you just read the UART; don't do any processing of data in the interrupt, just set a flag ie: DATA_RECEIVED = true; then back to your mainline. In your mainline:
if (DATA_RECEIVED == true) { addDataToBuffer();}



Since i would capture all data in interrups and only keep the first 12 anyway. Then after the 12 are in a variable i can compare it with new incoming data and if the same just skip them.

Then when back to running normal non-interrupt code i can clear the buffer.


Yes, but do all this in your mainline, not in the interrupt.
 
Beebop wouldnt the below make this a Byte Left Shift?:
almost, but like this:
DATA B C D E

If i use interrupts to capture the data as fast as possible then load the new data in a buffer then the buffer would get overwritten with a FIFO somewhat. If i have my FIFO buffer at the size of 12 Bytes then it will write the 12 bytes in and then jump to the start (or shift if beebop is right) and i loose data.

I cant just store data after a interrupt like:
if (DATA_RECEIVED == true) { addDataToBuffer();}

then if i do i loose data because remember sometimes it reads a card 2-3 times and may get cut off in the middle hence the error. (overrun) So that means my data gets written over and over even with the bad data.

I lose myself sometimes lol
 
The buffer which gets overrun is the UART buffer, which is only 2 bytes, so you need to empty it before another byte comes in. If you process the data as you receive it, then the chance of overrunning the 2 byte buffer is greater. So your interrupt just reads the UART, empties the 2 byte buffer, and sets a flag to tell you there is new data. Your main line code handles that data when it has time, and if a new interrupt occures, your mainline stops, and the important 2 byte buffer is emptied.

Since the first byte received was A, then it is A which is first emptied from the ring buffer. The next byte recieved was B, so that will be the next byte out....

I hope I'm making sense for you; I think it is time for more coffee for me. :p
 
The FIFO is just a little reservoir in the data "pipe" to give your program a bit of extra time to get it read or written. The data doesn't stay in there. If you're losing stuff in the FIFO then you're going too fast for it and need a bigger buffer.

Or am I off topic? :p Been elsewhere - just came back.
 
The FIFO is just a little reservoir in the data "pipe" to give your program a bit of extra time to get it read or written. The data doesn't stay in there. If you're losing stuff in the FIFO then you're going too fast for it and need a bigger buffer.

Or am I off topic? :p Been elsewhere - just came back.

No, I don't think so; that is well said.

If anyone is off, it is me. :p My computer won't boot :( so I'm working on my media PC - no toolchain installed, and feel far away from microcontrollers at the moment.)
 
ok ok im going to try this interrupt stuff with the RX now. If i use the same code it will go to the HIGH ISR i believe. With that said i just have to check if the interrupt was indeed the RX and if so get the data from its register and place the data into a buffer.

Once i can do that i will try that FIFO ok.
 
If anyone is off, it is me. :p My computer won't boot :( so I'm working on my media PC - no toolchain installed, and feel far away from microcontrollers at the moment.)
It's going around. :p I have two harshly busted machines in for repair right now. One was SO badly pwned! Totally zombied and pumping out spam. Idiot IE browser was hijacked 16 different ways. The malware was banging into each other there was so much of it. What a mess! Rootkits, keyloggers, dozens of trojans. Aaaarrrrggghhh!!! Stupid (ok, ignorant) users didn't protect themselves at all. Sigh...
 
Last edited:
heh pommie ... i repair my own pc. Ive done it so many times its not funny. The thing is antivirus and other programs tend to slow me down alot so i dont use them...

main topic...
I just tried the interrupt for RX and works well! i can get a full ID and overwrite my buffer over and over with new data from same card. Now ill try to re-read the older post about using FIFO but bad news is i have to go out in about 1hr to the movies (pre screening of Bride Wars) my wife got tickets for free from her job.

So ill try my best to jump into the FIFO stuff till then. Here is my code please comment on it.
Code:
#include <p18f2525.h>
#include <stdio.h>
#include <delays.h>
#include <usart.h>

#pragma config WDT = OFF, LVP = OFF, OSC = HS

/************************************
Prototypes
*************************************/
void main(void);
void high_isr(void);
/************************************
Variables AND Defines
*************************************/
#define RxT TRISBbits.TRISB7
#define RxD PIR1bits.RCIF

//VARIABLES
char temp[2];
char buff[12];
char pntr;
/************************************
                Main
*************************************/
void main(void){
    RxT = 1;                //Make Rx Pin INPUT
    ADCON1 = 0x0F;          //All Digital

    RCON = 0x00;            //Compatibility mode
    PIR1 = 0x00;            //RCIF is what i care about
    PIE1 = 0b00100000;      //RCIE - Enabled
    INTCON3 = 0x00;         
    INTCON2 = 0x00;         
    INTCON = 0b11000000;    //GIE, PEIE
    RCSTA = 0b10010000;     //SPEN, CREN - Enabled (worry: FERR,OERR)
    

    OpenUSART(  USART_TX_INT_OFF  &
                USART_RX_INT_ON  &
                USART_ASYNCH_MODE &
                USART_EIGHT_BIT   &
                USART_CONT_RX     &
                USART_BRGH_LOW,129);

    pntr = 0;
    while(1){
        if(temp[0] == 1){
            buff[pntr++] = temp[1];
            temp[0] = 0;
        }
        if(pntr == 12) pntr = 0;
    }
}
/************************************
            INTERRUPT STUFF
*************************************/
#pragma code high_vector=0x08       //High Priotrity
void interrupt_at_high_vector(void)
{
  _asm GOTO high_isr _endasm
}
#pragma code /* return to the default code section */
/************************************
            INTERRUPT STUFF(2)
*************************************/
#pragma interrupt high_isr
void high_isr (void)
{
    //Is it the Receive Flag?
    if(RxD == 1){
        RxD = 0;           //Clear the flag.
        if (RCSTAbits.OERR) //is it a overrun error
        {
            RCSTA = 0;              // disable the reciever
            RCSTA = 0b10010000;     // reenable the reciever
        }
    
        if (RCSTAbits.FERR)         //is it a framing error
        {
            temp[1] = RCREG;           //read to clear
        }

        temp[1] = RCREG;      //If so put A in temp[1](ButtonA)
    }

    temp[0] = 1;        //Save PORTB value for testing
}
 
im stuck Mike (Pommie) im lost now i implemented the code and can see the fifo buffer full with the data. But how can i tell my program to get just the just bytes i need? Or in fact how do i tell the program that data has finished being processed and i can process the buffer now.

1. Get Data into FIFO - DONE!
2. Determine if data acquisition is complete. - HELP ME?
3. When done getting data do something with it. - I CAN DO IT.

hope you understand.

Code:
#include <p18f2525.h>
#include <stdio.h>
#include <delays.h>
#include <usart.h>

#pragma config WDT = OFF, LVP = OFF, OSC = HS

/************************************
        Prototypes
*************************************/
void main(void);
void high_isr(void);


void InitFifo(void);
void PutFifo(unsigned char chr);
unsigned char GetFifo(void);
unsigned char FifoCount(void);
/************************************
        Variables AND Defines
*************************************/
#define RxT TRISBbits.TRISB7
#define RxD PIR1bits.RCIF

//VARIABLES
char temp[2];
char tmp;
char buff[12];

unsigned char FifoBuffer[12];
unsigned char *FifoStart;
unsigned char *FifoEnd;
/************************************
                Main
*************************************/
void main(void){
    RxT = 1;                //Make Rx Pin INPUT
    ADCON1 = 0x0F;          //All Digital

    RCON = 0x00;            //Compatibility mode
    PIR1 = 0x00;            //RCIF is what i care about
    PIE1 = 0b00100000;      //RCIE - Enabled
    INTCON3 = 0x00;         
    INTCON2 = 0x00;         
    INTCON = 0b11000000;    //GIE, PEIE
    RCSTA = 0b10010000;     //SPEN, CREN - Enabled (worry: FERR,OERR)
    

    OpenUSART(  USART_TX_INT_OFF  &
                USART_RX_INT_ON  &
                USART_ASYNCH_MODE &
                USART_EIGHT_BIT   &
                USART_CONT_RX     &
                USART_BRGH_LOW,129);

    InitFifo();

    while(1){
     
    }
}
/************************************
            INTERRUPT STUFF
*************************************/
#pragma code high_vector=0x08       //High Priotrity
void interrupt_at_high_vector(void)
{
  _asm GOTO high_isr _endasm
}
#pragma code /* return to the default code section */
/************************************
            INTERRUPT STUFF(2)
*************************************/
#pragma interrupt high_isr
void high_isr (void)
{
    //Is it the Receive Flag?
    if(RxD == 1){
        RxD = 0;           //Clear the flag.
        if (RCSTAbits.OERR) //is it a overrun error
        {
            RCSTA = 0;              // disable the reciever
            RCSTA = 0b10010000;     // reenable the reciever
        }
    
        if (RCSTAbits.FERR)         //is it a framing error
        {
            temp[1] = RCREG;           //read to clear
        }

        temp[1] = RCREG;      //If so put A in temp[1](rx)
        PutFifo(temp[1]);
    }

    temp[0] = 1;        //Save PORTB value for testing
}
/************************************
        FIFO
*************************************/
void InitFifo(void){
    FifoStart=FifoBuffer;
    FifoEnd=FifoBuffer;
}

void PutFifo(unsigned char chr){
    *FifoEnd++=chr;
    if(FifoEnd==FifoBuffer+12)      //reached end
        FifoEnd=FifoBuffer;         //yes so wrap
    if(FifoStart==FifoEnd){         //is head eating tail?
        //fifo full so deal with it!!
    }
}

unsigned char GetFifo(void){
unsigned char chr;
    while(FifoStart==FifoEnd);      //if fifo empty then wait
    chr=*FifoStart++;
    if(FifoStart==FifoBuffer+12)    //wrapped?
        FifoStart=FifoBuffer;       //yes
    return(chr);
}

unsigned char FifoCount(void){
    return((FifoEnd-FifoStart)&11);
}

How would i use: FifoCount would i use that to determine if 12 bytes have been recieved? But then even if i clear the buffer how do i know when its done? Should i keep 1 card id in temp and compare if the same?
 
Last edited:
In your main code you use GetFifo instead of reading RCREG. The fifo just allows you time to process the data, in this case (assuming 2400 baud) 66mS which is long enough to search a data base of existing cards.

Mike.
 
the issue is that i need something to set that the data is recived in full but if i get the data in 2 1/2 times if wont be full . I will set the Done Flag the first 2 times then clear it the 3rd(1/2) time.

Can you explain more in detail on how to do this?
 
I would do it something like,
Code:
void GetRFID(char *buffer){
  char i;                           // Length counter
    while(GetFifo()!=0x0a);         //wait for start of ID
    *buffer++=0x0a;
    for(i=0;i<11;i++)               //retrieve 11 characters
    {
        *buffer = GetFifo();
        buffer++;                   // Increment the string pointer
    }    
}
The buffer will then contain 0x0a, 10 char ID, 0x0d.

I suspect that the card actually sends an ID followed by 0x0d,0x0a (crlf). But the way you're doing it works.

Mike.
 
I would do it something like,
Code:
void GetRFID(char *buffer){
  char i;                           // Length counter
    while(GetFifo()!=0x0a);         //wait for start of ID
    *buffer++=0x0a;
    for(i=0;i<11;i++)               //retrieve 11 characters
    {
        *buffer = GetFifo();
        buffer++;                   // Increment the string pointer
    }    
}
The buffer will then contain 0x0a, 10 char ID, 0x0d.

I suspect that the card actually sends an ID followed by 0x0d,0x0a (crlf). But the way you're doing it works.

Mike.

Its actually 0x0A...ID....0x0D.
Ill try that code now... by the way look at the image attached.
 

Attachments

  • RFIDinfo.png
    RFIDinfo.png
    126.7 KB · Views: 186
  • RFID.pdf
    397.8 KB · Views: 316
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top