The datasheet for the RFID module lists the operating current as <50 mA, which is high enough that I want to be able to turn the module on and off from the PIC instead of just leaving it on all the time. To do this, I used a 2N3906 PNP transistor in between the board 5V supply and the RFID 5V supply, with the base connected to a GPIO with a 1k resistor. Turning the GPIO high turns the RFID module on; setting it low turns the RFID module off. Using the transistor dropped the supply from 5V to 4.87V, but this is still within the +/-5% of 5V listed on the datasheet spec, and it appears to be working just fine. I also added a resistor divider to the UART TX line of the RFID module to bring the 5V output down below 3.3V. The following two pictures show a circuit diagram of this, and then what it looks like soldered onto my development board (some parts/wires were soldered underneath the RFID module).
The PIC C18 compiler comes with a set of peripheral libraries, including one for the USART, which made it very easy to configure the USART and had a good example of using it to send and receive data. Once I verified that I could receive a single card's data, I set up a demo with three RFID tags programmed into the PIC so that it would toggle an LED based on which card was swiped. I initially tried to use the "gets1USART" function to read a 14 characters off of the USART, but every once and a while the RFID unit spits out a random bad character (sometimes at power up) that was causing me issues. Instead, the USART reception is handled using an interrupt service routine, and I pulled the basic setup for it from an Example #6 in an older copy of the C18 Getting Started Guide. The code is below, followed by a video of the demo. Note that the code assumes a 16 Mhz clock speed, like my previous post. You'll need to adjust the USART initialization line and delay line if you're using a different clock speed.
#include <p18lf26j11.h>
#include <delays.h>
#include <usart.h>
#include <string.h>
#pragma config OSC = HS //High speed crystal
#pragma config WDTEN = OFF //Disable watchdog timer
#pragma config XINST = OFF //Disable Extended CPU mode
//LED Pin Configuration
#define LED1Pin LATAbits.LATA0
#define LED1Tris TRISAbits.TRISA0
#define LED2Pin LATAbits.LATA1
#define LED2Tris TRISAbits.TRISA1
#define LED3Pin LATAbits.LATA2
#define LED3Tris TRISAbits.TRISA2
#define RFIDVCCPin LATBbits.LATB4 //Define RFIDVCCPin as PORT B Pin 4
#define RFIDVCCTris TRISBbits.TRISB4 //Define RFIDVCCTris as TRISB Pin 4
//Flags & Data Reception Variables
volatile char tagRecdFlag;
volatile char tagComingFlag;
volatile char tagCounter;
volatile char tagRX[14] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
//RFID Tag IDs
char rfidTag1[14] = {0x02, 0x30, 0x35, 0x30, 0x30, 0x41, 0x44, 0x44, 0x38, 0x46, 0x46, 0x43, 0x3f, 0x03};
char rfidTag2[14] = {0x02, 0x30, 0x35, 0x30, 0x30, 0x41, 0x44, 0x42, 0x46, 0x35, 0x37, 0x36, 0x30, 0x03};
char rfidTag3[14] = {0x02, 0x30, 0x35, 0x30, 0x30, 0x41, 0x45, 0x33, 0x46, 0x36, 0x35, 0x44, 0x33, 0x03};
//Function Prototypes
void rx_handler(void);
//Function Prototypes
#pragma code rx_interrupt = 0x8
void rx_int(void)
{
_asm goto rx_handler _endasm
}
#pragma code
#pragma interrupt rx_handler
void rx_handler(void)
{
unsigned char rxByte;
rxByte = RCREG1; //Read character received from USART
if (tagComingFlag == 0 && rxByte == 0x02)
{
tagRX[tagCounter] = rxByte;
tagComingFlag = 1;
tagCounter++;
} else if (tagComingFlag == 1)
{
tagRX[tagCounter] = rxByte;
tagCounter++;
if (tagCounter == 14)
{
tagCounter = 0;
tagComingFlag = 0;
tagRecdFlag = 1;
}
} else
{
tagComingFlag = 0;
tagCounter = 0;
}
PIR1bits.RCIF = 0; //Clear interrupt flag
}
void main()
{
//Set LED Pins data direction to OUTPUT
LED1Tris = 0;
LED2Tris = 0;
LED3Tris = 0;
//Set LED Pins to OFF
LED1Pin = 0;
LED2Pin = 0;
LED3Pin = 0;
tagRecdFlag = 0; //Set in ISR if new RFID tag has been read
tagComingFlag = 0; //Indicates if a tag is partially received
tagCounter = 0; //Counts byte index
//USART1 Initialization
Open1USART(USART_TX_INT_OFF & USART_RX_INT_ON & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW, 25);
//Interrupts
RCONbits.IPEN = 1; //Enable interrupt priority
IPR1bits.RC1IP = 1; //Make receive interrupt high priority
INTCONbits.GIEH = 1; //Enable all high priority interrupts
//Turn on RFID Module
RFIDVCCTris = 0; //Set to output
RFIDVCCPin = 1; //Turn on RFID Module
while(1)
{
if (tagRecdFlag)
{
//Toggle LED corresponding to which card was read
if (memcmp(tagRX, rfidTag1, 14) == 0)
{
LED1Pin = ~LED1Pin;
}
if (memcmp(tagRX, rfidTag2, 14) == 0)
{
LED2Pin = ~LED2Pin;
}
if (memcmp(tagRX, rfidTag3, 14) == 0)
{
LED3Pin = ~LED3Pin;
}
//Delay 1/2 sec & clear flags to prevent repeated card read
Delay10KTCYx(200);
tagRecdFlag = 0;
tagComingFlag = 0;
tagCounter = 0;
}
}
}