This module demonstrates the use of the Microchip MRF49XA sub-GHz RF transceiver IC. The MRF49XA is a fully integrated transceiver IC which supports the use of the 433, 868, & 915 MHz ISM frequency bands. Its transmitter is capable of +7 dBm.

The module is written to support transmit and receive operations via interrupts as much as possible. The idea behind this is to try to allow the main program to sleep as much as possible, only waking briefly to update the MRF IC, or deal with complete messages as necessary. This should make the module suitable for use in low powered, battery constrained operations such as sensors or dataloggers.


You can download the files from here.


The module code was adapted from the AVR code posted by William Dillon here, and the Microchip AN1252 App Note. It contains the Swordfish CRC16 implementation by Thomas D. Estes.


The example program is configured to run on a PIC18F87J50 FS USB Plug-in Module, running on a PICDEM HPC Explorer or PICDEM PIC18 Explorer board using the MRF49XA PICtail Daughter board (433Mhz). Please note the MRF49XA PICtail board is 3.3V only!

For this demonstration program, you will require two sets of Explorer boards and two Daughter boards. If you order the AC164137 demo kit, you will receive two Daughter boards.


Connect the USB to power the FS USB Plug-in Module boards. The Swordfish USBCDC should then enumerate and you can communicate with the boards using a terminal program such as the Swordfish Serial Communicator for debugging and testing. When the board is ready (LED RE0 is lit on each board), you should be able to send a message from one communicator window, with the other one showing the received packet. RE1 should light as the message is sent and received on each board.


The actual work of transmitting and receiving bytes from the MFR49XA IC is designed to mostly run on the INT3 interrupt from the IC. This interrupt line fires whenever the IC recieves or requires data. By using the interrupt to do our work, we can sleep most of the time whilst the MRF49XA gets on with actually transmitting or waiting for data (the example program doesn't because it uses USB for communication). This technique lends itself well to battery powered devices and the MRF49XA hardware supports this as well.

I implemented a very simple packet structure for the radio messages. The structure contains the preamble, sync word, payload length, data and CRC word(Cyclic Redundancy Check). This allows the receiving device to know when the complete message has been received. It also contains a checksum to allow the receiving device to check whether the message is corrupted or not. The synchonous pattern recogniser occasionally fires on random noise and the CRC is helpful for weeding out these false messages. A more robust error detection/correction method may be of advantage in RF noisy environments, but I have found this simple mechanism to be adequate.

Size (in bytes)ContentPurpose
1PreambleAllow the RX to lock
2Sync WordSyncronisation word - if incorrect the MRF will ignore any further bytes
1LengthLength of the Payload section
nPayloadActual data
2CRCCRC integrity check word
4Lead OutLead out to allow the transmitter to finish

Sending Data

To send data across the RF link, the Transmit Packet structure needs to be filled with the appropriate data. TransmitPacket.Payload is an array which contains the actual data, TransmitPacket.Length should indicate the size of the payload data. Once these have been set, call SendPacket(). SendPacket calculates the CRC, adds the headers and fires off the interrupt. The packet will now be sent automatically, with the ISR being called to update TX buffer as necessary. SendPacket can be called again immediately, but will block until the current transmission is complete.

Receiving Data

When not transmitting data, the transciever is kept in receive mode. In this mode the MRF49XA will be waiting for the Preamble and Sync word. Once these are recieved, the MRF49XA will start calling the INT3 interrupt to pass on the data. Once the ISR has a complete packet, the data is copied to a holding memory (FinishedPacket) and the HasPacket Flag is set, ready for the main program to start action and to free up the receiver to start to receive the next message. Note that it does not check for validity at this stage. It is up to the main application to check (this allows the false or malformed messages to be seen and acted upon eg. retry request).


The CRC is performed upon the Payload section of the packet only. Inital CRC state is $0000.

Module Options

The module is designed to be very flexible and allow the changing of the MRF49XA parameters to suit. The following allow for different hardware configurations to be used. As default, they should work with the MRF49XA PICtail Daughter board.

#option MRF_CS = PORTC.2			// SPI CS To MRF CS 
#option MRF_DI = PORTC.4					 
#option MRF_CLK = PORTC.3					 
#option MRF_DO = PORTC.5					 
#option MRF_IRO = PORTC.4			// Interrupt out from MRF Should be on INT3
#option MRF_FSEL = PORTD.4			// FIFO Select line 
#option MRF_RESET = PORTB.5			// Reset line 
#option MRF_MSSP = 1				// For PICs with 2 MSSP ports, choose 1 or 2 to select port to use
#option MRF_SPI_SPEED = spiOscDiv64		// Use when MRF_SPI = MSSP - valid speeds are spiOscDiv4, spiOscDiv16 and spiOscDiv64

The following can be modified to allow larger packets, however memory consumption will increase by 4 times whatever is set.

#option MRF_MAX_PAYLOAD = 40			// Maximum packet Payload size

The remaining options change the default configuration of the MRF49XA. Except fot MRF_DEFAULT_FREQ, MRF_BAND and MRF_TXPOWER you will need to check the datasheet before modifying any of these options.

#option MRF_LCS	= 3				// Programmable crystal load capacitance value (from Table 3-1: 3 = 10pF)
#option MRF_DRPV_VALUE = 286			
#option MRF_DEFAULT_FREQ = 433.747						
#option MRF_BAND = 434
#option MRF_RX_BANDWIDTH = 67k
#option MRF_MOD_BANDWIDTH = 30k
#option MRF_TXPOWER = 0dB