CH585 RF_Basic例程讲解<含单向和双向发送>
CH585_RF基础通讯例程见下图路径:
1、RF初始化参数配置
/*******************************************************************************
* @fn RFRole_Init
*
* @brief RF应用层初始化
*
* @param None.
*
* @return None.
*/
void RFRole_Init(void)
{
rfTaskID = TMOS_ProcessEventRegister( RFRole_ProcessEvent );
{
rfRoleConfig_t conf ={0};
conf.TxPower = LL_TX_POWEER_4_DBM;//配置初始发射功率
conf.rfProcessCB = RF_ProcessCallBack;//注册RF中断回调
conf.processMask = RF_STATE_RX|RF_STATE_RX_CRCERR|RF_STATE_TX_FINISH|RF_STATE_TIMEOUT;//配置RF中断事件
RFRole_BasicInit( &conf );//RF初始化
}
{
gParm.accessAddress = 0x71762345;//配置默认通信地址
gParm.crcInit = 0x555555;//初始化CRC校验和,一般不做修改
// 配置PHY类型
gParm.properties = LLE_MODE_PHY_2M;//配置2M模式
// 配置重传间隔,发送次数大于1时有效,和TxParam.sendCount配合使用
gParm.sendInterval = 1999*2;
// 配置发送稳定时间
gParm.sendTime = 10*2;//gParm.sendTime可在程序中任意时刻修改,不会耗时,注意点:↓↓↓↓↓
//①不包含跳频操作,即调用发送接口时频点保持不变,该值配置时在此例程中不建议低于6*2,即6us,实际需按照下文第5点进行调整;
//②如果此次发送有频点修改,该值配置时最低必须至少是60*2,即60us,如低于这个时间会导致频点切换不稳定,出现接收端收不到数据问题;
RFRole_SetParam( &gParm );
}
}
2、发送方和接收方参数配置
// TX相关参数,全局变量
{
gTxParam.accessAddress = gParm.accessAddress;//配置初始通信地址
gTxParam.crcInit = gParm.crcInit;//配置初始化CRC校验和
gTxParam.properties = gParm.properties;//配置通信模式
gTxParam.sendCount = 1;//配置重传间隔,发送次数大于1时有效,0和1都代表只发一次,无重传
gTxParam.txDMA = (uint32_t)TxBuf;//TxDMA配置
}
// RX相关参数,全局变量
{
gRxParam.accessAddress = gParm.accessAddress;//配置初始通信地址
gRxParam.crcInit = gParm.crcInit;//配置CRC校验初始值
gRxParam.properties = gParm.properties;//配置通信模式
gRxParam.rxDMA = (uint32_t)RxBuf;//RxDMA配置
gRxParam.rxMaxLen = TEST_DATA_LEN;//接收方需配置,虽说接收方接收没有配置超时时间,但是如果在Rx状态下接收到的有效数据长度大于所配置的rxMaxLen,会有概率返回接收超时,原因是不能错过下一次接收窗口,从而影响接收下一包数据
}
PFIC_EnableIRQ( BLEB_IRQn );
PFIC_EnableIRQ( BLEL_IRQn );//使能BLE中断,中断方式接收
PRINT("rf role init.id=%d\n",rfTaskID);
3、定时器中断配置,演示发送方发送数据,为了不影响RF接收数据的响应时间,配置了中断嵌套,允许其他中断打断
TMR0_TimerInit( GetSysClock() / RF_DEVICE_PERIDOC );//4k速率发送,250us进一次中断
TMR0_ITCfg(ENABLE, TMR0_3_IT_CYC_END); // 开启中断
PFIC_SetPriority( TMR0_IRQn, 0x80 );
PFIC_EnableIRQ(TMR0_IRQn);
4、定时器中断函数
__INTERRUPT
__HIGH_CODE
void TMR0_IRQHandler(void) // TMR0 定时中断
{
if(TMR0_GetITFlag(TMR0_3_IT_CYC_END))
{
TMR0_ClearITFlag(TMR0_3_IT_CYC_END); // 清除中断标志
// 初始化发送的数据
#define TEST_DATA_LEN 4
TxBuf[0] = 0x55;//帧头,数据自定义
TxBuf[1] = TEST_DATA_LEN;//数据长度,不包含第一字节和第二字节,用于告知底层数据包整体长度
//TxBuf长度=2+TEST_DATA_LEN
TxBuf[2]++;
TxBuf[3] = gRssi;//RSSI是通过其他地方赋值过来的,不代表这个字节固定代表RSSI
TxBuf[4] = 0;
TxBuf[5] = 0;
rf_tx_start( TxBuf );//启动DMA发送
}
}
5、RF发送函数
/**
* @brief rf发送数据子程序
*
* @param pBuf - 发送的DMA地址
*
* @return None.
*/
__HIGH_CODE
void rf_tx_start( uint8_t *pBuf )
{
RFIP_SetTxStart( );//配置寄存器启动发送,需要一定时间,在此期间可以配置下面的频点和数据准备
// 配置发送的频点
gTxParam.frequency = TEST_FREQUENCY;//配置频点
// 发送的DMA地址
gTxParam.txDMA = (uint32_t)pBuf;
// gTxParam.accessAddress = gParm.accessAddress; // 发送同步字
// gTxParam.sendCount = 1; // 发送次数
RFIP_SetTxParm( &gTxParam );//启动发送
}
6、配置Rx通信频点,配置Rx接收窗口时间
/**
* @brief rf接收数据子程序
*
* @param None.
*
* @return None.
*/
__HIGH_CODE
void rf_rx_start( void )
{
// 配置发送的频点
gRxParam.frequency = TEST_FREQUENCY;
// 配置接收的超时时间,0则无超时
gRxParam.timeOut = 80;//单位1us,库注释有误,单位并非0.5us
//RF发送完切至Rx等待应答时,极限时间为24us+sendtime+(2字节前导码+4字节接入地址+3字节CRC)*4us=60+sendtime,单位us
//建议配置超时时间至少为80us,如果代码处理还有耗时,建议再加上一些余量
// gRxParam.accessAddress = gParm.accessAddress; // 接收同步字
RFIP_SetRx( &gRxParam );//启动接收,打开接收窗口
}
7、发送结束后,会间隔一定时间,在中断里收到此次发送的状态回调,
如果发送成功,则进入RF_STATE_TX_FINISH中断,切换至接收态,打开接收窗口,在打开接收窗口后,根据主动配置的超时时间:
①如果超时,进入RF_STATE_TIMEOUT中断,选择丢包还是重传,重传需主动调用rf_tx_start再次发送
②如果在接收窗口期间内正确接收到了数据包,则进入RF_STATE_RX,用户可选择主动下发下一包数据
/*******************************************************************************
* @fn RF_ProcessCallBack
*
* @brief rf中断处理程序
*
* @param sta - 中断状态.
* id - 保留
*
* @return None.
*/
__HIGH_CODE
void RF_ProcessCallBack( rfRole_States_t sta,uint8_t id )
{
if( sta&RF_STATE_RX )//要么收到数据进RF_STATE_RX,要么没收到数据进入RF_STATE_TIMEOUT,二者进其一
{
rf_rx_process_data();//接收成功,获取完整数据
}
if( sta&RF_STATE_RX_CRCERR )//如果收到对方回复的数据后,校验结果与CRC不符会进入该中断
{
PRINT("nak@crc\n");
}
if( sta&RF_STATE_TX_FINISH )//底层发送成功后,会将发送成功状态通过此中断函数报上来
{
#if( WAIT_ACK )
rf_rx_start( );//发送结束,转为Rx接收,打开接收窗口,等待对方收到数据前导码后回复应答数据
#endif
gTxCount ++;//可统计每秒钟发送成功的数据包数量
}
if( sta&RF_STATE_TIMEOUT )//在打开接收窗口后,超过配置的gRxParam.timeOut时,进入接收超时中断
{
//此处可配置重传
PRINT("timeout\n");
//如果超时,在这里重新发送
}
}