Hi!
I am using CC2541 for my own application. Senging of the paket should work using "CMD_TX_FIFO_TEST" command, Receiver using "CMD_RX" command.
For data transmission im using the folowing functions:
uint8 freq = 33;
RFSetDirectFrequency(&freq );
SEND_LLE_CMD(CMD_TX_FIFO_TEST);
(Functiondefinitions:)
#define SEND_LLE_CMD(cmd) st(while(RFST != 0); RFST = (cmd); while(RFST != 0);)
void RFSetDirectFrequency(uint8* frequency) { // frequency in range 1..83
RFDisableRadio(FORCE); // Stop the radio
FREQCTRL = (*frequency) + 21;
RF_RadioChannel = (*frequency);
RFEnableRadio(); // Activate Radio
return;
}//RFSetDirectFrequency
For receiving of the data im using folowing instructions:
uint8 freq = 13;
RFSetFrequency(&freq );
RF_ReceiveStartedHandler (void)
void RFSetFrequency(uint8* frequency) {
RFDisableRadio(FORCE);
PRF_CHAN = (*frequency) + 21;
RF_RadioChannel = (*frequency);
RFEnableRadio(); // Activate Radio
return;
}//RFSetFrequency
void RF_ReceiveStartedHandler (void)
{
RFIRQM1 |= RFIRQF1_RXOK; // Activate "Packet Received Correctly" Interrupt
S1CON = 0; // Clear RF CPU Finterrupt flags
RFIRQF1 = 0x00; // Clear all RF core interrupts Flags
RFIRQF0 = 0x00; // Clear all RF core interrupts Flags
IEN2 |= IEN2_RFIE; // activate Radio Interrupts
SEND_LLE_CMD(CMD_RX); // Start Receive Operation
while (!(LLESTAT& 0x03));
MCUTimer2CompareCC0(RF_ReceiveTimeoutHandler, GetGlobalTimeLow()+RF_MaxReceiveDuration+200);
return;
} // RF_ReceiveStartedHandle
My problem is following:
After the initialisation i can send data without any problems - the frequency passt.
But if Receiver was activated at least once, the next transmission will not met the frequency!
(It will be one or two MHz smaller or greater as it was set).
I can not find what I am doing wrong! It would be great if someone mentions where
can an error be.
Thanks in advance!
In Following I give an essential part of my code for Timer and RF :
Timer:
r
#Finclude "MCUTimer2.h"
__monitor uint8 GetLock(void);
__monitor void ReleaseLock(void);
MCUTimer2_Com_CBF MCUTimer2_Com0_CBF;
MCUTimer2_Com_CBF MCUTimer2_Com1_CBF;
uint8 Lock;
uint16 currenteventmoment = 0;
uint16 SettetTime = 0;
void MCUTimer2_Init(void)
{
//********************************************************************//
EA = 0;
T2CTRL = STOP; //Stop Timer2
T2EVTCFG = 0xFF;// no event
T2MSEL = T2OVF;
T2MOVF0 = 0x00; //Reset OverflowCount 0
T2MOVF1 = 0x00; //Reset OverflowCount 1
T2MOVF2 = 0x00; //Reset OverflowCount 2
//********************************************************************//
T2MSEL = T2_PER; //Set MUX to Overflov Count and Timer Period (timer period)
T2M0 = 0x20; //Set Timer Period to 32 => Overflow after 1us
T2M1 = 0x00; //Set Timer Period to 32 => Overflow after 1us
//********************************************************************//
T2MSEL = T2TIM; //Set MUX to Overflov Count and Timer Value (timer count value)
T2M0 = 0x00; //Reset Timer Value
T2M1 = 0x00; //Reset Timer Value
//********************************************************************//
T2MSEL = T2OVF_PER; //Set MUX to Overflov Count and Timer Period (timer period)
T2MOVF0 = 0xFF; //Reset OverflowCount 0
T2MOVF1 = 0xFF; //Reset OverflowCount 1
T2MOVF2 = 0x00; //Reset OverflowCount 2
T2IRQM = 0x00;
T2IRQM = 0x00; //Disable all Timer2 Interrupt Sources
T2IE = 1;
T2IF = 0;
T2EVTCFG = NO_TIMER_EVENT; // No timer 2 events sent to LLE
EA = 1; //Enable Global Interrupts
return;
}//MCUTimer2_Init
uint16 GetGlobalTimeLow(void)
{
T2MSEL = T2OVF; //Setze Multiplexer für T2MOVF0...T2MOVF2 auf OverflowCounter;
return (T2MOVF0 + (((uint16)T2MOVF1)<<8));
}//GetGlobalTimeLow
void ResetTimer(void) {
if (GetLock()) {
//********************************************************************//
T2CTRL = STOP; //Stop Timer2
T2MSEL = T2OVF;
T2MOVF0 = 0x00; //Reset OverflowCount 0
T2MOVF1 = 0x00; //Reset OverflowCount 1
T2MOVF2 = 0x00; //Reset OverflowCount 2
//********************************************************************//
T2MSEL = T2TIM; //Set MUX to Overflov Count and Timer Value
T2M0 = 0x00; //Reset Timer Value
T2M1 = 0x00; //Reset Timer Value
//********************************************************************//
T2IRQM = 0x00; //Disable all Timer2 Interrupt Sources
T2IRQF = 0; // Clear All Timer2 Interrupt flags.
T2IF = 0;
ReleaseLock();
}
}//ResetTimer
void StartTimer(void) {
if (GetLock()) {
T2IRQM = 0x00; //Disable all Timer2 Interrupt Sources
IRCON &= ~0x04; //Clear Timer2 Interrupt Flag
T2CTRL = RUN; //Start Timer2
ReleaseLock();
}
}//StartTimer
void MCUTimer2CompareCC0(MCUTimer2_Com_CBF com0_cbf, uint16 latch_time)
{
//EA = 0;
if (GetLock()) {
//TimerReceiveTime = latch_time;
T2IF = 0; //Clear Timer2 Interrupt Flag
T2IRQF &= TIMER2_OVF_COMPARE1F; //Clear Timer2 OverflowCompare1 IRQ Flag
T2MSEL = T2OVF_CMP1; //Set MUX to Overflov Compare Value1 and Timer Value
T2MOVF0 = (uint8)(latch_time& 0xFF); //Set OverflowCount 0
T2MOVF1 = (uint8)((latch_time >> 8)& 0xFF); //Set OverflowCount 1
T2MOVF2 = 0x00;
T2IRQM |= TIMER2_OVF_COMPARE1M; //Enable Timer2 OverflowCompare Interrupt 1
T2IE = 1;
MCUTimer2_Com0_CBF = com0_cbf;
ReleaseLock();
}
}//MCUTimer2CompareCC0
void MCUTimer2CompareCC1(MCUTimer2_Com_CBF com1_cbf, uint16 latch_time)
{
if (GetLock()) {
T2IF = 0; //Clear Timer2 Interrupt Flag
T2IRQF &= TIMER2_OVF_COMPARE2F; //Clear Timer2 OverflowCompare1 IRQ Flag
T2MSEL = T2OVF_CMP2; //Set MUX to Overflov Compare Value2 and Timer Value
T2MOVF0 = (uint8)(latch_time & 0xFF); //Set OverflowCount 0
T2MOVF1 = (uint8)((latch_time >> 8) & 0xFF); //Set OverflowCount 1
T2MOVF2 = 0x00;
T2IRQM |= TIMER2_OVF_COMPARE2M; //Enable Timer2 OverflowCompare Interrupt 1
T2IE = 1;
MCUTimer2_Com1_CBF = com1_cbf;
ReleaseLock();
}
}//MCUTimer2CompareCC1
//********************************************************************//
void TimerClearCallBack(void) {
MCUTimer2_Com1_CBF = NULL;
MCUTimer2_Com0_CBF = NULL;
T2IE = 0;
T2IRQM = 0x00; //Disable all Timer2 Interrupt Sources
IRCON &= ~0x04; //Clear Timer2 Interrupt Flag
}//TimerClearCallBack
uint8 status = 0;
#pragma vector=T2_VECTOR
__interrupt void Timer2_isr(void) {
if (GetLock()) {
status = T2IRQF;
T2IRQM = 0x00; // mask interrupts
T2IRQF = 0x00; // clear flags
T2IF = 0;
if(status & TIMER2_OVF_COMPARE1F) { // independent from counter overflow react ob the Overflow counter compare to start the first CALLBACK function
ReleaseLock();
if(MCUTimer2_Com0_CBF != NULL)MCUTimer2_Com0_CBF(); /* NUR Wenn der Funktionzeiger kein leerer Zeiger ist*/
}
if(status & TIMER2_OVF_COMPARE2F) { // If we have received second overflow start the second CALLBACK function
ReleaseLock();
if(MCUTimer2_Com1_CBF != NULL)MCUTimer2_Com1_CBF(); /* NUR Wenn der Funktionzeiger kein leerer Zeiger ist*/
}
}
T2IRQF = 0x00; // clear IRQ CPU flags
T2IF = 0; // clear CPU flags
}
__monitor uint8 GetLock (void)
{
if (Lock == 0) /* ? Ist Lock Semaphore besetzt ?*/
{
Lock = 1; /* Semaphore ist frei -> Semaphore besetzen */
return TRUE;
}
else /* Semaphore ist besetzt */
{
return FALSE;
}
} // RF_GetLock
__monitor void ReleaseLock (void)
{
Lock = 0; /* Semaphore freigeben */
} // RF_ReleaseLock
RF:
#pragma vector=RFERR_VECTOR
__interrupt void RF_ErrorInterrupt(void)
{
RFForceShutdown();
if (RFERRF & TXUNDERF) {
SEND_LLE_CMD(CMD_TXFIFO_RESET); // Reset TX FiFo
}
if (RFERRF & RXTXABO) {
SEND_LLE_CMD(CMD_TXFIFO_RESET); // Reset TX FiFo
SEND_LLE_CMD(CMD_RXFIFO_RESET); // Reset RX FiFo
}
if (RFERRF & RXOVERF) {
SEND_LLE_CMD(CMD_RXFIFO_RESET); // Reset RX FiFo
}
// Deactive Transmitter Imidiately
RFERRF = 0x00;
}
#pragma vector=RF_VECTOR // Transmission complete event do not implemented jet
__interrupt void RF_Interrupt(void) {
if (RFIRQF1 & RFIRQF1_RXOK) {
RF_ReceiveStructPtr->ReceiveTime = GetGlobalTimeLow();
TimerClearCallBack();
RFForceShutdown();
RF_ReceivedPPDUHandler();
}
}
void RFInit(){
/* Clear radio memory.
* The RAM registers don't have a default value set after power on */
memset((void*)RFCORE_RAM_PAGE, 0, RFCORE_RAM_PAGE_SZ);
// Reset RXFIFO and TXFIFO.
SEND_LLE_CMD(CMD_RXFIFO_RESET);
SEND_LLE_CMD(CMD_TXFIFO_RESET);
RFFCFG = 0x33; // Auto Commit TX FIFO and RX FIFO
RFTXFTHRS = 0x10; //TX FIFO Threshold at 16 Bytes
RFRXFTHRS = 0x10; //TX FIFO Threshold at 16 Bytes
RFERRM |= TXUNDERF; // Underflow interrupt for transmitter
//RFIRQM0 = 0x00; // Do not react on transmisson errors; TRANSMITTER ONLY
// Set default output power: 0dBm.
TXPOWER = TXPOWER_0_DBM;
//T2EVTCFG = NO_TIMER_EVENT; // No timer 2 events sent to LLE
return;
}//RFInit
void RFConfig(uint8 modulationSheme, uint8 SyncLength, uint8 usedConfiguration){//, uint8 tx) {
//Eigene Konfiguration
// Change this parameters if needed!
EA = 0;
RFDisableInterrupt(0xFF);
PRF.PKT_CONF.ADDR_LEN = 0x00;//!!(usedConfiguration & PKT_CONF_ADDR);
PRF.PKT_CONF.AGC_EN = 0;
PRF.PKT_CONF.START_TONE = 0;
// Task Config
PRF.TASK_CONF.MODE = 0x00;
PRF.TASK_CONF.REPEAT = 0; // Repeat. // was 1
PRF.TASK_CONF.START_CONF = 0; // Start immediately after command.
PRF.TASK_CONF.STOP_CONF = 0; // Don't stop on timer 2 event 2.
PRF.TASK_CONF.TX_ON_CC_CONF = 1;
PRF.TASK_CONF.REPEAT_CONF = 0;
PRF.FIFO_CONF.AUTOFLUSH_IGN = 0; // No Flush duplicate packets.
PRF.FIFO_CONF.AUTOFLUSH_CRC = 0; // do not Flush packets with CRC error.
PRF.FIFO_CONF.AUTOFLUSH_EMPTY = 0; // do not Flush empty packets.
PRF.FIFO_CONF.RX_STATUS_CONF = 0; // append status information in FIFO.
PRF.FIFO_CONF.RX_ADDR_CONF = 0; // address byte in Rx FIFO.
PRF.FIFO_CONF.TX_ADDR_CONF = 0; // Read address from PRF.ADDR_ENTRY[0].ADDRESS.
PRF.CRC_LEN = 0; // Number of CRC bytes, permitted values are 0..4
PRF.CRC_INIT[0] = 0xFF; // CRC init Byte 0
PRF.CRC_INIT[1] = 0xFF; // CRC init Byte 1
PRF.CRC_INIT[2] = 0xFF; // CRC init Byte 2
PRF.CRC_INIT[3] = 0xFF; // CRC init Byte 3
PRF_CHAN = 0; // Channel 21 = 2400 MHz
PRF_RSSI_LIMIT = 0x7F; //0x00;
PRF_RSSI_COUNT = 0x0000; // 2 bytes
PRF_W_INIT = 0xFF;
PRF_RETRANS_CNT = 0x00;
PRF_TX_DELAY = 0x0000; // 2 bytes
PRF_RETRANS_DELAY = 0x0000; // 2 bytes
PRF_SEARCH_TIME = 0x0000; // 2 bytes
PRF_RX_TX_TIME = 0x0000; // 2 bytes
PRF_TX_RX_TIME = 0x0000; // 2 bytes
PRF.ADDR_ENTRY[0].CONF.ENA0 = 1;
PRF_N_TX = 0x00;
PRF_LAST_RSSI = 0x00;
PRF_RADIO_CONF = 0x00;
PRF_ENDCAUSE = 0x00;
TXCTRL = 0x19; // TX Settings.
TXFILTCFG = 0x03; // Set Tx Filter bandwidth.
IVCTRL = 0x1B; // Analog Control.
FRMCTRL0 = 0x41| (!!(usedConfiguration & PKT_CONF_ADDR)); // Amplitude weight in frequency offset compensation (assuming MSB first).
//MDMCTRL0 = (modulationSheme) | (!!(usedConfiguration & PKT_CONF_PHASE_INV)); // Set Modulation and data rate.
MDMCTRL0 = modulationSheme;// | PKT_CONF_PHASE_INV;
MDMCTRL1 = 0x08; // Correlation threshold.
MDMCTRL2 = 0xA3; //Synch: MSB first, Preamble for Freq.-Offset estimation, Preamble is set to 0101 0101 4 Byte Preamble // Pre inv.to first SyncBit,
// Set RSSI mode to peak detect after sync.
MDMCTRL3 = 0x63; //no ErrorBits in Sync, Ramping of DAC, no Sniff, peak detect after sync.
ADCTEST0 = 0x10; // was 0x66
MDMTEST0 = 0xAC; //RSSI: two 21us Windows Mean, DC-Block 128 Samples, DC-Cancellation enabled
MDMTEST1 = 0x0A; //DC-Delay = 5, IF = 1MHz, Baseband Freq = 0MHz
// Set gain (will set correct gain even for 2 MBPS).
RFSetGain(HAL_RF_GAIN_HIGH);
// Program sync word length and configure single sync word.
// Set Default Sync Word lengths and the sync word itself
RFSetSyncWord(SyncLength, 0x00, 0x3E, 0x94, 0x59, 0x00, 0x3E, 0x94, 0x59);
LLECTRL = 0x00;
RFSetWhitening(0x00);
RFSetWhiteningRegister (0x65);
//Quadrature Skew Setting (see User Guide Table 23-24)
setQuadratureSkew(0x16);
FREQTUNE = 0x0F; //no Freq. Tune
RFERRIE = 1;
EA = 1;
return;
}//RFConfig
uint8 RFReceiveMsg (RFReceiveStructPtr rsp)
{
//uint32 tmp1;
if(RF_State == RF_IDLE_STATE) /* ? Idle ?*/
{
//tmp1 = rsp->ReceiveStartTime - GetGlobalTimeLow();
//if((tmp1 > RECEIVER_STARTUP_TIME) && (tmp1 < 0xF000)) /* ? Reicht die Zeit zum Anschalten des Empfängers ?*/
//{
RF_PSDUPtr = rsp->PSDU; /* Parameterübernahme in die lokalen Variablen */
if((RF_RadioChannel == CONFIG_CHANNEL_1) || (RF_RadioChannel == CONFIG_CHANNEL_2))
{
RXPacketLength = 11; // 88 BITS Config Telegram DSLOT (normal)
}
else
{
RXPacketLength = 15; // 120 Bits, 80 BitPayload + 24 Bits SyncWord + 2Bit UL group + 6 Bit Cell ID (Downlink Telegramm DSLOT Extended)
}
RF_ExecTime = rsp->ReceiveStartTime;
RF_MaxReceiveDuration = rsp->MaxReceiveDuration;
RF_ReceiveStructPtr = rsp;
/* if (OK) {
asm("NOP");
}*/
PRF.ADDR_ENTRY[0].RXLENGTH = RXPacketLength;
RF_ReturnPtr->RF_ErrorType = RF_NO_ERROR;
RF_State = RF_RX_PACKET_STATE;
RF_ReturnPtr->RF_State = RF_RX_PACKET_STATE;
MCUTimer2CompareCC1(RF_ReceiveStartedHandler, (RF_ExecTime - (uint16)RXPREPARETIME));
return TRUE;
}
else /* Radio ist nicht Idle -> Cmd nicht annehmen und State zurückgeben */
{
RF_ReturnPtr->RF_ErrorType = RF_FALSE_STATE;
return FALSE;
}
} // RFReceiveMsg
void RF_ReceiveStartedHandler (void)
{
RFIRQM1 |= RFIRQF1_RXOK; // Activate "Packet Received Correctly" Interrupt
S1CON = 0;
RFIRQF1 = 0x00; // Clear all RF core interrupts Flags
RFIRQF0 = 0x00; // Clear all RF core interrupts Flags
IEN2 |= IEN2_RFIE; // activate Radio Interrupts
SEND_LLE_CMD(CMD_RX); // Start Receive Operation
while (!(LLESTAT& 0x03));
MCUTimer2CompareCC0(RF_ReceiveTimeoutHandler, GetGlobalTimeLow()+RF_MaxReceiveDuration+200);
return;
} // RF_ReceiveStartedHandler
void RF_ReceiveTimeoutHandler(void)
{
if(RF_State == RF_RX_PACKET_STATE)
{
RFForceShutdown();
TimerClearCallBack();
RF_ReceiveStructPtr->ReceivedPacketStatus = RF_RECEIVE_TIMEOUT;
RF_State = RF_IDLE_STATE;
RF_ReturnPtr->RF_State = RF_IDLE_STATE;
RF_ReceiveStructPtr->ReceiveCBF();
} //Ein Packet wurde empfangen befor die Timeout erreicht wurde
}
void RFForceShutdown(void) {
// Send Rx command
// Disable RX interrupts
RFIRQM1 &= ~RFIRQF1_RXOK;
IEN2 &= ~IEN2_RFIE; // RFIE = 0
S1CON = 0;
RFIRQF1 = 0x00; // Clear all RF core interrupts Flags
RFIRQF0 = 0x00; // Clear all RF core interrupts Flags
SEND_LLE_CMD(CMD_SHUTDOWN);
return;
}//RFStartRx