1. 程式人生 > 其它 >BLE和2.4G同時執行

BLE和2.4G同時執行

前言

RF_PHY 是wch提供的一個呼叫底層2.4g收發器的一個介面,可以通過此介面實現更為靈活的通訊方式
這種底層,僅僅是BLE的收發器基礎上,這意味著,收發器調製解調引數,包括frequency,deviation,symbol_rate,以及packet_handler(preamble,syncword,length,crc,whitening)都是符合藍芽的底層規範的.
具體的工程可參考官方SDK對應路徑下的工程,如:CH579EVT_2.3\EXAM\BLE\RF_PHY

適用晶片

  • CH577/CH578/CH579
  • CH571/CH573

使用

初始化

 

void RF_Init( void
) { uint8 state; rfConfig_t rfConfig; //註冊一個task,用於使用者排程 taskID = TMOS_ProcessEventRegister( RF_ProcessEvent ); #if defined(CH573) //針對ch573 //這裡的 accessAddress 就是preamble後跟的同步字,用於識別一個新包到來,收發設定成一樣是是收到包的前提 //這個accessAddress 的設定要符合藍芽規範,比如禁止使用0x55555555以及0xAAAAAAAA ( 建議不超過24次位反轉,且不超過連續的6個0或1 )
rfConfig.accessAddress = 0x8E89BED6; //crc24_ble 的初值,這個收發也要相同,否則一定會在接收完成後產生crc24 錯誤 rfConfig.CRCInit = 0x555555; #elif defined(CH579) //針對ch579 rfConfig.TxAccessAddress = 0x8E89BED6; rfConfig.RxAccessAddress = 0x8E89BED6; rfConfig.TxCRCInit = 0x555555; rfConfig.RxCRCInit = 0x555555
; #else #error "You must define CH573 or CH579 first!" #endif //The channel is mapped to ble channel, ble4.x adv at channel 37/38/39 //這裡的通道對映是BLE的通道,如37通道對應2402Mhz,這個值在收發也要相同 rfConfig.Channel = 37; //這裡的工作模式有兩種LLE_MODE_BASIC和LLE_MODE_AUTO //其中LLE_MODE_BASIC 是基本的收發,而LLE_MODE_AUTO 是帶自動回覆的,根據實際場景來選擇 //另外在最近更新的庫裡面 增加了兩個可配置選項LLE_MODE_NON_RSSI和LLE_MODE_EX_CHANNEL(ch57x m0 系列不支援) rfConfig.LLEMode = LLE_MODE_BASIC; //註冊狀態回撥函式,這裡主要是傳送完成,接收到資料之類的會進入這個回撥函式 rfConfig.rfStatusCB = RF_2G4StatusCallBack; state = RF_Config( &rfConfig ); PRINT("rf 2.4g init state for ble adv test: %x\n",state); }

狀態回撥

/這裡的回撥函式是在state = RF_Config( &rfConfig ); 註冊的
void RF_2G4StatusCallBack( uint8 sta, uint8 crc, uint8 *rxBuf ) {
    switch( sta ) {
        case TX_MODE_TX_FINISH://傳送完成,LLE_MODE_BASIC,LLE_MODE_AUTO模式都會產生
            break;
        case TX_MODE_TX_FAIL:  //傳送失敗,LLE_MODE_BASIC,LLE_MODE_AUTO模式都會產生
            break;
        case TX_MODE_RX_DATA:  //LLE_MODE_AUTO模式下,傳送完資料後,接收到了ack訊號
            if( crc == 1 ) {
                PRINT("crc error\n");
            } else if( crc == 2 ) {
                PRINT("match type error\n"); //這裡的match type 就是再發射接收的時候 傳入的match type跟當前接收配置的type對比的結果
            } else {
                uint8 i;
                PRINT("tx recv,rssi:%d\n",(s8)rxBuf[0]);
                PRINT("len:%d-",rxBuf[1]);
                for(i=0; i<rxBuf[1]; i++) PRINT("%x ",rxBuf[i+2]);
                PRINT("\n");
            }
            break;
        case TX_MODE_RX_TIMEOUT: //LLE_MODE_AUTO模式下,傳送完資料後,沒有接收到ack訊號,預設超時是 3 ms
            break;
        case RX_MODE_RX_DATA:    //接收到資料,LLE_MODE_BASIC,LLE_MODE_AUTO模式都會產生
            if( crc == 1 ) {
                PRINT("crc error\n");
            } else if( crc == 2 ) {
                PRINT("match type error\n");
            } else {
                uint8 i;
                //rxBuf[0] 預設情況下是rssi,如果 在LLEMode初始化時同時開啟了LLE_MODE_NON_RSSI,那這裡將會變為PKT_TYPE
                PRINT("rx recv, rssi: %d\n",(s8)rxBuf[0]);
                //我們還可以通過下面方式獲取RSSI,這個不受LLE_MODE_NON_RSSI配置影響:
                PRINT("rssi:%d\r\n",(int8_t)rxBuf[2+((rxBuf[1]+5)&0xffc)]);
                //資料部分
                PRINT("length: %d:",rxBuf[1]);
                for(i=0; i<rxBuf[1]; i++) {
                    PRINT("%02x ",rxBuf[i+2]);
                }
                PRINT("\n");
            }
            break;
        case RX_MODE_TX_FINISH:  //LLE_MODE_AUTO模式下,接收到資料後,自動ack完成
            break;
        case RX_MODE_TX_FAIL:    //LLE_MODE_AUTO模式下,接收到資料後,ack失敗,僅僅只是傳送失敗
            break;
    }
    PRINT("STA: %x\n",sta);
}

 

API說明

//RF_PHY內部初始化必須先執行這個再執行後面的RF_Config
//這個也可以 在ble初始化以後再加入這個,這樣就可以做到2.4g跟ble 同時執行
bStatus_t RF_RoleInit( void );
 
//初始化,按照上面給你的示例說明
bStatus_t RF_Config( rfConfig_t *pConfig );
 
/*******************************************************************************
 * @fn          RF_Rx
 *
 * @brief       rx mode.
 *
 * input parameters
 *
 * @param       txBuf - rx mode tx data
 * @param       txLen - rx mode tx length(0-251)
 * @param       pktRxType - rx mode rx package type
 *                        broadcast type(0xFF):receive all matching types,
 *                        others:receive match type or broadcast type
 * @param       pktTxType - rx mode tx package type(auto mode)
 *                        broadcast type(0xFF):received by all matching types; 
 *                        others:only received by matching type
 *
 * output parameters
 *
 * @param       None.
 *
 * @return      0 - success.
 */
extern bStatus_t RF_Rx( u8 *txBuf, u8 txLen, u8 pktRxType, u8 pktTxType );
 
/*******************************************************************************
 * @fn          RF_Tx
 *
 * @brief       tx mode.
 *
 * input parameters
 *
 * @param       txBuf - tx mode tx data
 * @param       txLen - tx mode tx length(0-251)
 * @param       pktTxType - tx mode tx package type
 *                        broadcast type(0xFF):received by all matching types; 
 *                        others:only received by matching type
 * @param       pktRxType - tx mode rx package type(auto mode)
 *                        broadcast type(0xFF):receive all matching types,
 *                        others:receive match type or broadcast type
 *
 * output parameters
 *
 * @param       None.
 *
 * @return      0 - success.
 */
extern bStatus_t RF_Tx( u8 *txBuf, u8 txLen, u8 pktTxType, u8 pktRxType );
 
//關閉TX/RX模式,不建議在狀態回撥裡呼叫,而是在外面呼叫
bStatus_t RF_Shut( void );
 
//設定RF的通道,這裡的通道對應的是ble的通道,比如37對應2402Mhz
void RF_SetChannel( u8 channel );

 

應用

模擬BLE廣播

說明

  • 有時候,我們的應用很簡單,並不需要建立BLE連線,只需要廣播,比如各種beacon應用,而ble的協議棧是比較龐大的,而用2.4G的方式直接寫,則可以做到非常的輕量.
  • 本文只實現不可連線的廣播,不支援scan_respone的回覆包

初始化

void RF_Init( void ) {
    uint8 state;
    rfConfig_t rfConfig;
    taskID = TMOS_ProcessEventRegister( RF_ProcessEvent );
#if defined(CH573)
    //依據BLE的核心規範,填寫Access Address 和 CRC24 的入值.
    rfConfig.accessAddress = 0x8E89BED6;
    rfConfig.CRCInit = 0x555555;
#elif defined(CH579)
    rfConfig.TxAccessAddress = 0x8E89BED6;
    rfConfig.RxAccessAddress = 0x8E89BED6;
    rfConfig.TxCRCInit = 0x555555;
    rfConfig.RxCRCInit = 0x555555;
#else
    #error "You must define CH573 or CH579 first!"
#endif
    //The channel is mapped to ble channel, ble4.x adv at channel 37/38/39
    rfConfig.Channel = 37;
    rfConfig.LLEMode = LLE_MODE_BASIC;
    rfConfig.rfStatusCB = RF_2G4StatusCallBack;
    state = RF_Config( &rfConfig );
    PRINT("rf 2.4g init state for ble adv test: %x\n",state);
}
 

構造資料

//ble adv data for RF-PHY test
static uint8_t ble_adv_test_data[] = {
                                0x3c,0x10,0x2D, 0xE4, 0xC2, 0x84,      //MAC ADDR
                                9,0x09,'A','D','V','-','T','E','S','T' //ADV data
                              };

傳送

uint8_t ble_adv_tx(void) {
   RF_Shut( );
   //tx type :0X02 for no connected adv
   return RF_Tx( ble_adv_test_data,sizeof(ble_adv_test_data), 0x02, 0xFF );
}

接收BLE廣播

與BLE工程一起跑

BLE的工作特點是間歇性工作,依據廣播間隔/連線間隔協議棧進行定時呼叫收發器工作,其他時間收發器資源都是釋放的,這也是為什麼的BLE可以和WIFI,zigbee,thread等協議共用部分射頻資源動態共存的原因
鑑於BLE的這種工作特點,wch也把RF_PHY 這種模式與ble可以共存執行.
下面在wch 提供的ble的工程裡面加入RF_PHY 工作的初始方式,實際上就是把RF_PHY的初始化函式放在BLE初始化完成後呼叫即可,但是由於BLE 的存在,所以丟包可能是非常普遍, 如,這邊在發射,接收端的射頻被BLE短暫佔用,就會導致接收不到這一包資料,所以一定差錯控制(如ack機制,資料包冗餘機制)在實際的應用中,往往是必要的.

int main( void )  {
#if (defined (DCDC_ENABLE)) && (DCDC_ENABLE == TRUE)
    PWR_DCDCCfg( ENABLE );
#endif
    SetSysClock( CLK_SOURCE_PLL_60MHz );
    GPIOA_ModeCfg( GPIO_Pin_All, GPIO_ModeIN_PU );
    GPIOB_ModeCfg( GPIO_Pin_All, GPIO_ModeIN_PU );
#ifdef DEBUG
    GPIOA_SetBits(bTXD1);
    GPIOA_ModeCfg(bTXD1, GPIO_ModeOut_PP_5mA);
    UART1_DefInit( );
#endif   
    PRINT("%s\n",VER_LIB);
    CH57X_BLEInit( );
    HAL_Init( );
    GAPRole_PeripheralInit( );
    Peripheral_Init( ); 
    //RF_PHY 例程初始化函式
    RF_Init();
    Main_Circulation();
}