CH592F 2.4G 低功耗

发布时间:2026/11/11 2:22:47

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/11/8 22:46:39

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

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

2026/11/9 15:34:24

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

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

2026/11/7 6:50:23

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

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

2026/11/11 2:22:34

国网一级电工证怎么报名才能一次通过

国网一级电工证怎么报名才能一次通过 怕考不过白交培训费?你不是一个人。很多像你一样的在职建筑工人,一边忙于项目,一边还得抽出时间准备国网一级电工证考试,生怕花了钱又没拿到证,耽误了工作和晋升机会。别急,这篇文章不仅告诉你怎么报名,还会帮你避…

2026/11/11 2:22:34

拿了电工证找不到工作?外省证书能全国通用吗?

拿了电工证找不到工作?外省证书能全国通用吗? 之前考的证在外省能不能转过来?这几乎是每个拿到电工证却找不到工作的朋友最关心的问题。事实上,根据 郑州市应急管理局 的相关规定, 电工证是全国通用的…

2026/11/11 2:22:34

怀化辰溪县电工证怎么考不白交钱?官方报名入口在这里

怀化辰溪县电工证怎么考不白交钱?官方报名入口在这里 怕考不过白交培训费?别急,我这10年搞过上千人考证,给你掏心窝子讲明白。怀化辰溪县电工证考前准备、报名入口、考试避坑全在这篇文章,看完保你稳过。…

2026/11/11 2:22:34

操作证与电工证报名入口与办理流程

电工证过期怎么办?2026河南最新政策告诉你怎么复审 证书过期了不知道怎么复审延期?你不是一个人,特别是2026年河南最新政策出台后,很多人对操作证与电工证的办理和复审流程感到困惑。别慌,本文从济源市政公用工程从业者的视角出发,详细拆解从报…

2026/11/11 2:17:34

河南电工证如何报考良心建议

河南电工证如何报考良心建议 工地太忙根本没时间复习考试,这事儿我懂,我也是从一线干出来的。在郑州金水区的一个中小型施工企业,我们经常面临这样的情况:手头活儿多,人员紧张,谁还有空去复习电工证考试?但问题是,不考电工证,你连进工地都难。所以今…

2026/11/10 8:12:38

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/11 0:02:26

考低压电工证通过率考试真题与备考技巧

低压电工证通过率高不高?学历不高也能考,值不值得考? 你是不是总听说电工证能帮你找高薪工作,但又担心自己学历不够,考不上?其实,低压电工证考试门槛并没有你想象中那么高,关键是方法对不对。这篇文章就告诉你, 考低压电工证通过率到底有多高 ,…

2026/11/11 0:02:26

低压电工证学时千万别踩坑,濮阳毕业生怎么避坑报名

低压电工证学时千万别踩坑,濮阳毕业生怎么避坑报名 你是不是也和我一样,刚毕业就听说低压电工证学时必须达标才能上岗?可一打听,发现报名机构五花八门,价格参差不齐, 不知道去哪报名怕被中介坑…

2026/11/10 20:08:15

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/10 10:29:37

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑