📄 an_008.c
字号:
STROBE=0;
for (WordCounter=0;WordCounter<8;WordCounter++)
{
Data=Configuration[WordCounter];
for (BitCounter=0;BitCounter<16;BitCounter++)
{
CLOCK=1;
STROBE=0;
PDATA=MSB;
Data=Data<<1;
CLOCK=0;
if (BitCounter==15)
STROBE=1;
else
STROBE=0;
}
}
CLOCK=1;
STROBE=0;
CLOCK=0;
}
/****************************************************************************/
/* This routine configures the software for RX mode. Also configures the */
/* CC400/CC900 for RX. */
/****************************************************************************/
void ConfigureRX(void)
{
TRISC=0x08; /* Set DIO as input */
ConfigureCCX00(RX_CONFIG);
/* Initialise variables for RX mode */
ShiftReg=0;
An0=0x08;
An1=0x08;
An2=0x08;
Sample=0x00;
Count=0x00;
ResyncEnable=FALSE;
Sync=FALSE;
ALimit=A_LIMIT_VAL;
ALimit2=A_LIMIT_VAL2;
CountLimit=COUNT_LIMIT_VAL;
Mode=RXMODE;
/* Enable TMR0 interrupt */
TMR0=0xFD; /* Set a short time to next interrupt */
OPTION=RATE_RX;
INTCON=0xA8; /* Enable interrupts */
}
/****************************************************************************/
/* This routine configures the software for TX mode. Also configures the */
/* CC400/CC900 for TX. */
/****************************************************************************/
void ConfigureTX(void)
{
TRISC=0x00; /* Set DIO as output */
ConfigureCCX00(TX_CONFIG);
/* Initialise variables for TX mode */
Mode=TXMODE;
Number=0;
PORTB=0x00; /* Clear PORTB */
/* Enable TMR0 interrupt */
TMR0=0xFC; /* Set a short time to next interrupt */
OPTION=RATE_TX;
INTCON=0xA8; /* Enables interrupts */
}
/****************************************************************************/
/* This routine configures the software for PD mode. Also configures the */
/* CC400/CC900 for power-down. Puts the MCU into sleep mode. */
/****************************************************************************/
void ConfigurePD(void)
{
ConfigureCCX00(PD_CONFIG);
CLK_OUT=0;
DATA_OUT=0;
Mode=PDMODE;
INTCON=0x88; /* Enable interrupts */
__sleep(); /* Put MCU to sleep */
}
/****************************************************************************/
/* Determines which mode the MCU should be in by reading the mode pins. */
/****************************************************************************/
void ModeDecision()
{
if (PD) /* PD has higher priority than RX_TX */
ConfigurePD();
else if (RX_TX)
ConfigureRX();
else
ConfigureTX();
}
/****************************************************************************/
/* Logic to resynchonise the MCU to the data stream. See documentation for */
/* details regarding the resynchronisation algorithm. Called by the RX */
/* interrupt routine. */
/****************************************************************************/
void Resync(void)
{
if (An2>=An1) {
if (An1>=An0) {
if (An1>=ALimit) {
if (An2==An1)
Sample++;
else if (An1==An0)
Sample++;
else {
Sample+=2;
ResyncEnable=FALSE;
}
}
else {
ResyncEnable=FALSE;
}
}
else if (Sync) {
Sample++;
ResyncEnable=FALSE;
}
else
ResyncEnable=FALSE;
}
else if (An1>=An0)
Sample++;
else {
if (Sync) {
if (An1>=ALimit)
ResyncEnable=FALSE;
else {
Sample+=2;
ResyncEnable=FALSE;
}
}
else
ResyncEnable=FALSE;
}
}
/****************************************************************************/
/* This routine is called when TMR0 interrupts occur in RX mode. It */
/* oversamples the incoming signal and performs synchronisation and */
/* resynchronisation. */
/****************************************************************************/
void RXInterrupt(void)
{
char OldValue;
char NewValue;
/* Reinitialise timer, this should be done as quickly as possible */
TMR0=TIMING_RX;
/* Store old values of A */
An2=An1;
An1=An0;
OldValue=ShiftReg&0x01;
NewValue=DIO;
/* Shift new sample into shift register */
ShiftReg=ShiftReg>>1 | ((NewValue==0)?0x00:0x80);
/* Invert new middle bit (Manchester coding) */
ShiftReg^=0x08;
/* Update A according to values shifted in and out */
/* (We are really counting the number of 0's in the shift register) */
if ((OldValue==1)&&(NewValue==0))
An0++;
if ((OldValue==0)&&(NewValue==1))
An0--;
if ((ShiftReg&0x08)==0)
An0++;
else
An0--;
/* Update clock at the appropriate time */
if (Sync) {
if (Sample==3)
CLK_OUT=1;
if (Sample==7)
CLK_OUT=0;
}
if (ResyncEnable) {
/* Resync */
Resync();
}
else if (Sample==7)
/* Finished with entire bit */
/* Are we in sync? */
if (Sync) {
/* Check if this is an invalid Manchester bit. If it is, */
/* increase the BitErrors count. If not, clear the count */
if ((An0<=A_SYNC_LIMIT_HI)&&(An0>A_SYNC_LIMIT_LO)) {
BitErrors++;
if (BitErrors==BIT_ERROR_LIMIT) {
Sync=FALSE;
BitErrors=0;
}
}
else
BitErrors=0;
/* Output data */
DATA_OUT=(An0>ALimit);
CLK_OUT=0;
Sample=0;
ResyncEnable=TRUE;
}
else {
/* We are not in sync, synchronise */
Sample=0;
if (An0>=ALimit2) {
if (Count==CountLimit)
Sync=TRUE;
Count++;
ResyncEnable=TRUE;
}
else {
Count=0;
ResyncEnable=TRUE;
}
}
else
/* Ready for next sample */
Sample++;
/* Must clear interrupt flag before returning from interrupt */
T0IF=0;
}
/****************************************************************************/
/* This routine is called when TMR0 interrupts occur in TX mode. It outputs */
/* clock data and converts incoming NRZ data to Manchester format. */
/****************************************************************************/
void TXInterrupt(void)
{
/* Reinitialise timer, this should be done as quickly as possible */
TMR0=TIMING_TX;
if (Number==0) {
/* First baud in bit */
CLK_OUT=1;
Read=DATA_IN;
DIO=Read;
Number=1;
}
else {
/* Second baud in bit */
CLK_OUT=0;
DIO=~Read;
Number=0;
}
/* Must clear interrupt flag before returning from interrupt */
T0IF=0;
}
/****************************************************************************/
/* This code is called every time an interrupt occurs. If a mode pin has */
/* changed status, the software is initialised to the new mode. Otherwise, */
/* a TMR0 interrupt has occured, and the handling routine appropriate to */
/* the current mode is called. */
/****************************************************************************/
#pragma vector=INTERRUPT_VECTOR
__interrupt void InterruptHandler(void)
{
if (RBIF){
/* Mode bits have changed */
RBIF=0;
ModeDecision();
}
else {
/* Must have been the timer interrupt */
switch(Mode) {
case RXMODE : RXInterrupt();
break;
case TXMODE : TXInterrupt();
break;
}
}
}
/****************************************************************************/
/* Main program. The MCU is initialised and put into the correct mode. The */
/* software then goes into an infinite loop. User code will typically be */
/* inserted here. By default, the only thing the software does is indicate */
/* synchronised/not synchronised status on the RC4 pin */
/****************************************************************************/
void main(void)
{
Initialise();
ModeDecision();
while (TRUE) /* Loop forever */
{
/* Main loop of program here */
if(Sync)
SYNC=1;
else
SYNC=0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -