PICoHolic
Joined: 04 Jan 2005 Posts: 224
|
Another RF link over UART (one-way) |
Posted: Tue Jun 30, 2015 7:25 am |
|
|
Hello,
Inspired by: http://www.ccsinfo.com/forum/viewtopic.php?t=22525
(Optimized and Rx timeout added [optional])
File: manchester.h
Code: |
#ifndef _MANCHESTER_H
#define _MANCHESTER_H
///////////////////////////////////////////////////////////////////////////////
#define MAN_PREAMB 0x55 //preamble
#define MAN_SOP 0xFF //Start of payload
///////////////////////////////////////////////////////////////////////////////
#endif
|
File manchester.c
Code: |
#include "manchester.h"
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
char manchester[16]={
0b01010101, //0
0b01010110, //1
0b01011001, //2
0b01011010, //3
0b01100101, //4
0b01100110, //5
0b01101001, //6
0b01101010, //7
0b10010101, //8
0b10010110, //9
0b10011001, //A 10
0b10011010, //B 11
0b10100101, //C 12
0b10100110, //D 13
0b10101001, //E 14
0b10101010}; //F 15
///////////////////////////////////////////////////////////////////////////////
void TxManchester(int8 Dt)
{
putc(manchester[Dt>>4], PORT1); //MSB
putc(manchester[Dt & 0x0F], PORT1); //LSB
}
///////////////////////////////////////////////////////////////////////////////
signed int8 _RxManchester(int8 Dt)
{
int8 i=0;
while ((Dt!=manchester[i]) && (i<16))
i++;
return i<16?i:-1;
}
///////////////////////////////////////////////////////////////////////////////
int1 ManchesterToBinary(int8 msb, int8 lsb, int8 *bin)
{
signed int8 ret1, ret2;
ret1 = _RxManchester(msb);
if (ret1 != -1)
{
ret2 = _RxManchester(lsb);
if (ret2 != -1)
{
*bin = (ret1 << 4) | ret2;
return 1;
}
else
return 0;
}
else
return 0;
}
///////////////////////////////////////////////////////////////////////////////
|
File: Tx.c
Code: |
#include "manchester.c"
///////////////////////////////////////////////////////////////////////////////
void TxData(int8 *DtBuff) //data is being sent inverted
{
int8 i;
int8 len = DtBuff[0]; //1st byte is length
putc(MAN_PREAMB, PORT1);
putc(MAN_PREAMB, PORT1);
putc(MAN_SOP, PORT1);
for (i=0; i<len; i++) //send payload
{
TxManchester(DtBuff[i]); //last byte in DtBuff should be checksum
}
}
///////////////////////////////////////////////////////////////////////////////
|
File Rx.h
Code: |
#ifndef RX_H
#define RX_H
///////////////////////////////////////////////////////////////////////////////
#define MAXRXDATA 16
#define MAXRXDATAMSK MAXRXDATA-1
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#endif
|
File: Rx.c
Code: |
#include "Rx.h"
///////////////////////////////////////////////////////////////////////////////
#include "manchester.c"
///////////////////////////////////////////////////////////////////////////////
int8 RxDataBuff[MAXRXDATA];
int8 RxPrt = 0;
int1 RxDtReady = 0;
int16 MaxBytesTimeout;
///////////////////////////////////////////////////////////////////////////////
#define RxByteTimeout 525 //in cycles = 8.4ms = time for 1 byte to get Rx @ 1200
#define SetUARTTimeOut(n) {MaxBytesTimeout=(RxByteTimeout*n); set_timer0(0xFFFF - MaxBytesTimeout); clear_interrupt(INT_TIMER0); enable_interrupts(INT_TIMER0);}
#define ResetUARTTimeOut() disable_interrupts(INT_TIMER0)
///////////////////////////////////////////////////////////////////////////////
#INT_TIMER0
void TIMER0_isr(void)
{
//Reset all:
RxDtReady = FALSE;
RxPrt = 0;
ResetUARTTimeOut();
}
///////////////////////////////////////////////////////////////////////////////
#INT_RDA2
void RDA2_isr(void)
{
int8 d;
static int8 RxDtPayPrt = 0;
static int8 ExpectedLen;
static int1 msb = 1;
static int8 msb_data;
d = getc(PORT2);
switch (RxPrt)
{
case 0:
case 1:
if (d==MAN_PREAMB)
RxPrt++;
else
RxPrt = 0; //reset
break;
case 2:
if (d==MAN_SOP)
RxPrt++;
else
RxPrt = 0; //reset
break;
case 3:
if (!msb)
{
if (ManchesterToBinary(msb_data, d, &ExpectedLen)) //get binary value
{
RxDataBuff[0] = ExpectedLen;
SetUARTTimeOut((ExpectedLen-1) * 2);
RxDtPayPrt = 1; //move 2nd position
RxPrt++;
}
else
RxPrt = 0; //reset
}
else
{
msb_data = d;
}
msb = !msb;
break;
default:
if (!msb)
{
if (ManchesterToBinary(msb_data, d, &d)) //get binary value
{
RxDataBuff[RxDtPayPrt++ & MAXRXDATAMSK] = d; //copy & move to next position
if (RxDtPayPrt == ExpectedLen)
{
RxPrt = 0; //reset
RxDtReady = 1; //flag
}
}
else
RxPrt = 0; //reset
}
else
{
msb_data = d;
}
msb = !msb;
break;
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
|
Transmit test code:
Code: |
#include "Tx.c"
//...//
Data[0] = 5;
Data[1] = 0;
Data[2] = 1;
Data[3] = 2;
Data[4] = Data[0] ^ Data[1] ^ Data[2] ^ Data[3];
TxData(Data);
|
Receive test code (RDAx interrupt must be enabled)
Code: |
#include "Rx.c"
//...//
setup_timer_0(T0_INTERNAL | T0_DIV_32); //for Rx timeout (525 per Rx byte) XT = 8Mhz
//..//
if (RxDtReady)
{
RxDtReady = 0;
if ((RxDataBuff[0] == 5) && (RxDataBuff[4] == (RxDataBuff[0] ^ RxDataBuff[1] ^ RxDataBuff[2] ^ RxDataBuff[3])))
{
// TO DO:...
}
}
|
Important notes:
1- Baud rate should be selected carefully (should be less than the maximum bit rate supported by the RF transmitter/receiver)
2- Both UART Tx & Rx must be inverted by hardware (1 way is to use transistors or a simple inverter)
Cheers! |
|