2.4G私有协议低功耗传输,tx按一下按键按键发送数据到rx,rx 1s内启动10ms接收窗口进行接收。
代码从github上拉取官方的代码:GitHub - openwch/ch592: The SDK and HDK for RISC-V Bluetooth LE BLE5.4 CH591/CH592 · GitHub
例程是ch592\EVT\EXAM\BLE\RF_PHY
配置开启 HAL_SLEEP

然后替换下面3个文件:
RF_PHY.h
/********************************** (C) COPYRIGHT *******************************
* File Name : rf_phy.h
* Author : WCH
* Version : V1.0
* Date : 2018/11/12
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef CENTRAL_H
#define CENTRAL_H
#ifdef __cplusplus
extern "C" {
#endif
#define SBP_RF_RX_OPEN_EVT 0x0001 // 打开RX并启动接收窗口
#define SBP_RF_RX_CLOSE_EVT 0x0002 // 关闭RX并进入低功耗等待
#define SBP_RF_RX_RESTART_EVT 0x0004 // 基本模式收包后重新启动RX
#define SBP_RF_TX_SEND_EVT 0x0008 // 发送一包TX数据
#define SBP_RF_TX_RX_DATA_EVT 0x0010 // 在TMOS任务中处理并打印应答数据
#define SBP_RF_KEY_IRQ_EVT 0x0020 // PA4下降沿中断投递事件
#define SBP_RF_KEY_CHECK_EVT 0x0040 // 延时10ms后检查按键电平
#define SBP_RF_TX_TIMEOUT_EVT 0x0080 // 连续发送3秒仍无应答则停止
#define LLE_MODE_ORIGINAL_RX (0x80) //如果配置LLEMODE时加上此宏,则接收第一字节为原始数据(原来为RSSI)
extern void RF_Init(void);
#ifdef __cplusplus
}
#endif
#endif
RF_main.c
/********************************** (C) COPYRIGHT *******************************
* File Name : main.c
* Author : WCH
* Version : V1.0
* Date : 2020/08/06
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/******************************************************************************/
/* 头文件包含 */
#include "CONFIG.h"
#include "HAL.h"
#include "RF_PHY.h"
/*********************************************************************
* GLOBAL TYPEDEFS
*/
__attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
#if(defined(BLE_MAC)) && (BLE_MAC == TRUE)
const uint8_t MacAddr[6] = {0x84, 0xC2, 0xE4, 0x03, 0x02, 0x02};
#endif
/*********************************************************************
* @fn Main_Circulation
*
* @brief 主循环
*
* @return none
*/
__HIGH_CODE
__attribute__((noinline))
void Main_Circulation()
{
while(1)
{
TMOS_SystemProcess();
}
}
/*********************************************************************
* @fn main
*
* @brief 主函数
*
* @return none
*/
int main(void)
{
#if(defined(DCDC_ENABLE)) && (DCDC_ENABLE == TRUE)
PWR_DCDCCfg(ENABLE);
#endif
SetSysClock(CLK_SOURCE_PLL_60MHz);
#if(defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE)
GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
GPIOB_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
#endif
#ifdef DEBUG
GPIOA_SetBits(bTXD1);
GPIOA_ModeCfg(bTXD1, GPIO_ModeOut_PP_5mA);
UART1_DefInit();
#endif
PRINT("start.\n");
PRINT("%s\n", VER_LIB);
CH59x_BLEInit();
HAL_Init();
RF_RoleInit();
RF_Init();
Main_Circulation();
}
/******************************** endfile @ main ******************************/
RF_PHY.c
/********************************** (C) COPYRIGHT *******************************
* File Name : main.c
* Author : WCH
* Version : V1.0
* Date : 2020/08/06
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/******************************************************************************/
/* 头文件包含 */
#include "CONFIG.h"
#include "RF_PHY.h"
#define RF_DEVICE_ROLE_RX 0
#define RF_DEVICE_ROLE_TX 1
#define RF_DEVICE_ROLE RF_DEVICE_ROLE_TX
#if(RF_DEVICE_ROLE != RF_DEVICE_ROLE_RX) && \
(RF_DEVICE_ROLE != RF_DEVICE_ROLE_TX)
#error "Invalid RF_DEVICE_ROLE"
#endif
/*********************************************************************
* GLOBAL TYPEDEFS
*/
#define RF_AUTO_MODE_EXAM 1
#define RF_RX_PERIOD MS1_TO_SYSTEM_TIME(1000)
#define RF_RX_WINDOW MS1_TO_SYSTEM_TIME(10)
#define RF_KEY_DEBOUNCE_TIME MS1_TO_SYSTEM_TIME(10)
#define RF_TX_TIMEOUT_TIME MS1_TO_SYSTEM_TIME(3000)
#define RF_KEY_PIN GPIO_Pin_4
typedef struct
{
int8_t rssi;
uint8_t len;
uint8_t data[251];
} rfRxPacket_t;
uint8_t taskID;
uint8_t ACK_DATA[2] = {'o', 'k'};
uint8_t TX_DATA[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
volatile uint8_t tx_end_flag=0;
volatile uint8_t rx_end_flag=0;
static volatile uint8_t rx_window_open=FALSE;
static volatile uint8_t rx_first_packet=FALSE;
static volatile uint8_t rx_ack_status=0;
static rfRxPacket_t rx_packet;
static rfRxPacket_t tx_rx_packet;
static volatile uint8_t tx_running=FALSE;
#if(RF_DEVICE_ROLE == RF_DEVICE_ROLE_TX)
/*********************************************************************
* @fn HAL_KeyIrqInit
*
* @brief 配置PA4上拉输入、下降沿中断和睡眠唤醒
*/
void HAL_KeyIrqInit(void)
{
GPIOA_ModeCfg(RF_KEY_PIN, GPIO_ModeIN_PU);
GPIOA_ITModeCfg(RF_KEY_PIN, GPIO_ITMode_FallEdge);
GPIOA_ClearITFlagBit(RF_KEY_PIN);
PFIC_EnableIRQ(GPIO_A_IRQn);
PWR_PeriphWakeUpCfg(ENABLE, RB_SLP_GPIO_WAKE, Long_Delay);
}
/*********************************************************************
* @fn HAL_KeyIrqGet
*
* @return 0-按下,非0-释放
*/
uint32_t HAL_KeyIrqGet(void)
{
return GPIOA_ReadPortPin(RF_KEY_PIN);
}
/*********************************************************************
* @fn GPIOA_IRQHandler
*
* @brief PA4下降沿中断,只投递事件,不在中断中消抖
*/
__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
void GPIOA_IRQHandler(void)
{
uint16_t flag = R16_PA_INT_IF;
if(flag & RF_KEY_PIN)
{
GPIOA_ClearITFlagBit(RF_KEY_PIN);
tmos_set_event(taskID, SBP_RF_KEY_IRQ_EVT);
}
}
#endif
/*********************************************************************
* @fn RF_Wait_Tx_End
*
* @brief 手动模式等待发送完成,自动模式等待发送-接收完成,必须在RAM中等待,等待时可以执行用户代码,但需要注意执行的代码必须运行在RAM中,否则影响发送
*
* @return none
*/
__HIGH_CODE
__attribute__((noinline))
void RF_Wait_Tx_End()
{
uint32_t i=0;
while(!tx_end_flag)
{
i++;
__nop();
__nop();
// 约5ms超时
if(i>(FREQ_SYS/1000))
{
tx_end_flag = TRUE;
}
}
}
/*********************************************************************
* @fn RF_Wait_Rx_End
*
* @brief 自动模式等待应答发送完成,必须在RAM中等待,等待时可以执行用户代码,但需要注意执行的代码必须运行在RAM中,否则影响发送
*
* @return none
*/
__HIGH_CODE
__attribute__((noinline))
void RF_Wait_Rx_End()
{
uint32_t i=0;
while(!rx_end_flag)
{
i++;
__nop();
__nop();
// 约5ms超时
if(i>(FREQ_SYS/1000))
{
rx_end_flag = TRUE;
}
}
}
/*********************************************************************
* @fn RF_2G4StatusCallBack
*
* @brief RF 状态回调,此函数在中断中调用。注意:不可在此函数中直接调用RF接收或者发送API,需要使用事件的方式调用
* 在此回调中直接使用或调用函数涉及到的变量需注意,此函数在中断中调用。
*
* @param sta - 状态类型
* @param crc - crc校验结果
* @param rxBuf - 数据buf指针
*
* @return none
*/
void RF_2G4StatusCallBack(uint8_t sta, uint8_t crc, uint8_t *rxBuf)
{
switch(sta)
{
case TX_MODE_TX_FINISH:
{
#if(!RF_AUTO_MODE_EXAM)
tx_end_flag = TRUE;
#endif
break;
}
case TX_MODE_TX_FAIL:
{
tx_end_flag = TRUE;
#if(RF_DEVICE_ROLE == RF_DEVICE_ROLE_TX)
if(tx_running)
{
tmos_set_event(taskID, SBP_RF_TX_SEND_EVT);
}
#endif
break;
}
case TX_MODE_RX_DATA:
{
#if(RF_AUTO_MODE_EXAM)
tx_end_flag = TRUE;
#if(RF_DEVICE_ROLE == RF_DEVICE_ROLE_TX)
if((crc == 0) &&
(rxBuf[1] == sizeof(ACK_DATA)) &&
(rxBuf[2] == ACK_DATA[0]) &&
(rxBuf[3] == ACK_DATA[1]))
{
uint8_t rx_len;
tx_rx_packet.rssi = (int8_t)rxBuf[0];
rx_len = rxBuf[1];
if(rx_len > sizeof(tx_rx_packet.data))
{
rx_len = sizeof(tx_rx_packet.data);
}
tmos_memcpy(tx_rx_packet.data, &rxBuf[2], rx_len);
tx_rx_packet.len = rx_len;
tmos_set_event(taskID, SBP_RF_TX_RX_DATA_EVT);
}
else
{
if(tx_running)
{
tmos_set_event(taskID, SBP_RF_TX_SEND_EVT);
}
}
#endif
#endif
break;
}
case TX_MODE_RX_TIMEOUT: // Timeout is about 200us
{
#if(RF_AUTO_MODE_EXAM)
tx_end_flag = TRUE;
#if(RF_DEVICE_ROLE == RF_DEVICE_ROLE_TX)
if(tx_running)
{
tmos_set_event(taskID, SBP_RF_TX_SEND_EVT);
}
#endif
#endif
break;
}
case RX_MODE_RX_DATA:
{
if((crc == 0) && rx_window_open && !rx_first_packet)
{
uint8_t rx_len;
rx_first_packet = TRUE;
rx_packet.rssi = (int8_t)rxBuf[0];
rx_len = rxBuf[1];
if(rx_len > sizeof(rx_packet.data))
{
rx_len = sizeof(rx_packet.data);
}
tmos_memcpy(rx_packet.data, &rxBuf[2], rx_len);
rx_packet.len = rx_len;
#if(RF_AUTO_MODE_EXAM)
RF_Wait_Rx_End();
#endif
}
#if(!RF_AUTO_MODE_EXAM)
if(rx_window_open)
{
tmos_set_event(taskID, SBP_RF_RX_RESTART_EVT);
}
#endif
break;
}
case RX_MODE_TX_FINISH:
{
#if(RF_AUTO_MODE_EXAM)
rx_end_flag = TRUE;
if(rx_first_packet)
{
rx_ack_status = 1;
tmos_set_event(taskID, SBP_RF_RX_CLOSE_EVT);
}
#endif
break;
}
case RX_MODE_TX_FAIL:
{
#if(RF_AUTO_MODE_EXAM)
rx_end_flag = TRUE;
if(rx_first_packet)
{
rx_ack_status = 2;
tmos_set_event(taskID, SBP_RF_RX_CLOSE_EVT);
}
#endif
break;
}
}
}
/*********************************************************************
* @fn RF_ProcessEvent
*
* @brief RF 事件处理
*
* @param task_id - 任务ID
* @param events - 事件标志
*
* @return 未完成事件
*/
uint16_t RF_ProcessEvent(uint8_t task_id, uint16_t events)
{
if(events & SYS_EVENT_MSG)
{
uint8_t *pMsg;
if((pMsg = tmos_msg_receive(task_id)) != NULL)
{
// Release the TMOS message
tmos_msg_deallocate(pMsg);
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
#if(RF_DEVICE_ROLE == RF_DEVICE_ROLE_TX)
if(events & SBP_RF_KEY_IRQ_EVT)
{
tmos_stop_task(taskID, SBP_RF_KEY_CHECK_EVT);
tmos_start_task(taskID, SBP_RF_KEY_CHECK_EVT,
RF_KEY_DEBOUNCE_TIME);
return events ^ SBP_RF_KEY_IRQ_EVT;
}
if(events & SBP_RF_KEY_CHECK_EVT)
{
if(HAL_KeyIrqGet() == 0)
{
PRINT("PA4 key pressed\n");
if(!tx_running)
{
tx_running = TRUE;
tmos_start_task(taskID, SBP_RF_TX_TIMEOUT_EVT,
RF_TX_TIMEOUT_TIME);
tmos_set_event(taskID, SBP_RF_TX_SEND_EVT);
}
}
return events ^ SBP_RF_KEY_CHECK_EVT;
}
if(events & SBP_RF_TX_TIMEOUT_EVT)
{
tx_running = FALSE;
RF_Shut();
tx_rx_packet.len = 0;
tmos_clear_event(taskID, SBP_RF_TX_SEND_EVT |
SBP_RF_TX_RX_DATA_EVT);
PRINT("TX timeout, no ACK in 3s\n");
return events & ~(SBP_RF_TX_TIMEOUT_EVT |
SBP_RF_TX_SEND_EVT |
SBP_RF_TX_RX_DATA_EVT);
}
if(events & SBP_RF_TX_RX_DATA_EVT)
{
uint8_t i;
if(tx_rx_packet.len)
{
PRINT("tx recv ACK, rssi: %d\n", tx_rx_packet.rssi);
PRINT("len:%d-", tx_rx_packet.len);
for(i = 0; i < tx_rx_packet.len; i++)
{
PRINT("%x ", tx_rx_packet.data[i]);
}
PRINT("\n");
tx_rx_packet.len = 0;
}
tx_running = FALSE;
tmos_stop_task(taskID, SBP_RF_TX_TIMEOUT_EVT);
RF_Shut();
PRINT("TX success, ACK received\n");
return events ^ SBP_RF_TX_RX_DATA_EVT;
}
if(events & SBP_RF_TX_SEND_EVT)
{
uint8_t state;
if(!tx_running)
{
return events ^ SBP_RF_TX_SEND_EVT;
}
RF_Shut();
tx_end_flag = FALSE;
state = RF_Tx(TX_DATA, sizeof(TX_DATA), 0xFF, 0xFF);
if(state != SUCCESS)
{
PRINT("TX start failed.state = %x\n", state);
tmos_start_task(taskID, SBP_RF_TX_SEND_EVT,
MS1_TO_SYSTEM_TIME(1));
}
return events ^ SBP_RF_TX_SEND_EVT;
}
#else
/* Close RX first if close and restart events arrive together. */
if(events & SBP_RF_RX_CLOSE_EVT)
{
uint8_t i;
rx_window_open = FALSE;
tmos_stop_task(taskID, SBP_RF_RX_CLOSE_EVT);
RF_Shut();
if(rx_packet.len)
{
PRINT("rx recv, rssi: %d\n", rx_packet.rssi);
PRINT("len:%d-", rx_packet.len);
for(i = 0; i < rx_packet.len; i++)
{
PRINT("%x ", rx_packet.data[i]);
}
PRINT("\n");
rx_packet.len = 0;
}
if(rx_ack_status == 1)
{
PRINT("ACK sent, RX closed early\n");
}
else if(rx_ack_status == 2)
{
PRINT("ACK failed, RX closed early\n");
}
return events ^ SBP_RF_RX_CLOSE_EVT;
}
if(events & SBP_RF_RX_OPEN_EVT)
{
uint8_t state;
rx_window_open = TRUE;
rx_first_packet = FALSE;
rx_ack_status = 0;
rx_packet.len = 0;
rx_end_flag = FALSE;
RF_Shut();
state = RF_Rx(ACK_DATA, sizeof(ACK_DATA), 0xFF, 0xFF);
PRINT("RX window open.state = %x\n", state);
tmos_start_task(taskID, SBP_RF_RX_CLOSE_EVT, RF_RX_WINDOW);
tmos_start_task(taskID, SBP_RF_RX_OPEN_EVT, RF_RX_PERIOD);
return events ^ SBP_RF_RX_OPEN_EVT;
}
#endif
return 0;
}
/*********************************************************************
* @fn RF_Init
*
* @brief RF 初始化
*
* @return none
*/
void RF_Init(void)
{
uint8_t state;
rfConfig_t rf_Config;
tmos_memset(&rf_Config, 0, sizeof(rfConfig_t));
taskID = TMOS_ProcessEventRegister(RF_ProcessEvent);
rf_Config.accessAddress = 0x71764129; // 禁止使用0x55555555以及0xAAAAAAAA ( 建议不超过24次位反转,且不超过连续的6个0或1 )
rf_Config.CRCInit = 0x555555;
rf_Config.Channel = 39;
rf_Config.Frequency = 2480000;
#if(RF_AUTO_MODE_EXAM)
rf_Config.LLEMode = LLE_MODE_AUTO;
#else
rf_Config.LLEMode = LLE_MODE_BASIC | LLE_MODE_EX_CHANNEL; // 使能 LLE_MODE_EX_CHANNEL 表示 选择 rf_Config.Frequency 作为通信频点
#endif
rf_Config.rfStatusCB = RF_2G4StatusCallBack;
rf_Config.RxMaxlen = 251;
state = RF_Config(&rf_Config);
PRINT("rf 2.4g init: %x\n", state);
#if(RF_DEVICE_ROLE == RF_DEVICE_ROLE_TX)
tx_rx_packet.len = 0;
tx_running = FALSE;
HAL_KeyIrqInit();
#else
rx_window_open = FALSE;
tmos_set_event(taskID, SBP_RF_RX_OPEN_EVT);
#endif
}
/******************************** endfile @ main ******************************/