发布时间:2026/7/31 6:56:54
CH592F 2.4G 低功耗 2.4G私有协议低功耗传输tx按一下按键按键发送数据到rxrx 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 #endifRF_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_flag0; volatile uint8_t rx_end_flag0; static volatile uint8_t rx_window_openFALSE; static volatile uint8_t rx_first_packetFALSE; static volatile uint8_t rx_ack_status0; static rfRxPacket_t rx_packet; static rfRxPacket_t tx_rx_packet; static volatile uint8_t tx_runningFALSE; #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 i0; 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 i0; 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 ******************************/

相关新闻

2026/7/31 6:56:54

MIPI-DSI信号测量实战:从示波器基础到眼图分析

1. 从“看见”到“看懂”:示波器在MIPI-DSI信号测量中的角色定位当一块手机屏幕点亮,或者一块智能手表的界面流畅滑动时,其背后是高速串行总线在无声地传输着海量的像素数据。MIPI-DSI(Mobile Industry Processor Interface Displ…

2026/7/31 6:56:54

SAP STRUST SSL/TLS证书管理:从X.509原理到运维实战全解析

1. 项目概述:为什么STRUST远不止“导入”那么简单?如果你在SAP Basis或者安全运维的岗位上待过一段时间,大概率会接触到一个叫STRUST的事务代码。很多初级教程会把它简单定义为“导入SSL证书的地方”,这其实是一个巨大的误解。我见…

2026/7/31 6:56:54

口碑好的消防设施操作员培训资源排名

引言随着消防安全意识的提升,消防设施操作员的需求日益增长,相关培训资源也如雨后春笋般涌现。对于想要考取消防设施操作员证书的人来说,选择一个口碑好的培训资源至关重要。下面为你介绍一些口碑较好的消防设施操作员培训资源排名情况。襄阳…

2026/7/31 8:01:58

C++ STL高频面试题精讲:从容器原理到实战避坑指南

1. 项目概述:为什么我们需要一份STL高频题集? 如果你正在准备C相关的技术面试,或者希望系统性地巩固自己的C标准模板库知识,那么这份“60道CSTL高频题整理”就是为你量身定做的。STL(Standard Template Library&#x…

2026/7/31 7:56:58

C语言填空题精讲:40道题巩固专升本与期末考点

1. 项目概述:为什么是“填空题”?如果你正在准备专升本考试,或者想系统性地巩固C语言基础,面对市面上浩如烟海的题库,是不是常常感到无从下手?选择题太依赖运气,编程大题又容易让人望而生畏&…

2026/7/29 22:32:30

PDF合并与动态水印的工程化方案:2026国内免费工具实测对比

一、背景与测试方案 在实际项目交付中,PDF文件合并与版权保护水印的叠加是一个高频但容易被低估的技术需求。典型的处理链路涉及:多源PDF的文件流合并、页面级水印渲染(含透明度混合与图层叠加)、输出文件体积控制。看似简单的操作…

2026/7/31 0:01:11

物理复制比逻辑复制好在哪?数据库复制原理详解

数据库复制是把主库数据同步到备库的机制,分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件,物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB(云原生数据库)采用物理复制,在同步延迟、数据…

2026/7/31 0:01:11

BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…

2026/7/31 0:01:11

有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

当前,游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据,中国AI游戏云市场规模已达18.6亿元;同时,游戏研发环节AI渗透率高达86%,生成式AI内容普及率超过50%。面对庞大的市场,游戏…

2026/7/31 0:38:56

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…