/* ********************************************************************************************************* * IAR Development Kits * on the * * M451 * * Filename : uart_RFGateway.h * Version : V1.00 * Programmer(s) : Qian Xianghong ********************************************************************************************************* */ /* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* */ #include "includes.h" extern IWDG_HandleTypeDef hiwdg; const uint8_t RF_APP = RF_APP_AJH; const uint8_t RF_PROTOCOL_VER = RF_PROTOCOL_VER_1; uint8_t RF_UP_CHANNEL = 9; // 上行信道: 498M uint8_t RF_DOWN_CHANNEL = 8; // 下行信道: 499M const uint8_t RF_BROADCAST_PSN[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; const uint8_t RF_EMPTYPSN[6] = {0, 0, 0, 0, 0, 0}; uint8_t RF_GatewayPSN[6] = {0, 0, 0, 0, 0, 0}; #define RF_SelfPSN (dcBuff.configBottle.PSN) uint8_t RF_MAC_FN = 0; uint8_t RF_APP_PN = 0; uint8_t RF_APP_IDX = 0; // 发送、接收、处理帧 rf_frame_t RF_Send_Frame, RF_RecvFrame, RF_ProcFrame; // 发送、上传队列记录 rf_send_queue_t RF_Send_Rec, RF_Send_Rec1; // RF串口接收帧的循环缓冲 #define RF_TASKM_DATA_COUNT 256 loopbuff_t RF_TaskM; uint8_t RF_TaskM_Data[sizeof(rf_frame_t) * (RF_TASKM_DATA_COUNT + 1)] = {0}; // 射频初始化状态 uint8_t RF_initStatus = 0; uint32_t RF_seconds = 0; // RF串口接收的消息通知 SemaphoreHandle_t RF_TaskQ = NULL; // 二值信号量句柄 SemaphoreHandle_t RF_semAck = NULL; // 二值信号量句柄 SemaphoreHandle_t RF_semGateway = NULL; // 二值信号量句柄 SemaphoreHandle_t RF_semResp = NULL; // 二值信号量句柄 // RF串口发送帧的循环缓冲 #define RF_SENDM_DATA_COUNT 512 loopbuff_t RF_SendM; uint8_t RF_SendM_Data[sizeof(rf_send_queue_t) * (RF_SENDM_DATA_COUNT + 1)] = {0}; // RF串口接收的消息通知 SemaphoreHandle_t RF_SendQ = NULL; // 二值信号量句柄 loopbuff_t RF_GatewayBuff; uint8_t RF_GatewayBuff_Data[6 * (4 + 1)] = {0}; loopbuff_t RF_AckBuff; uint8_t RF_AckBuff_Data[sizeof(rf_ack_t) * (2 + 1)] = {0}; loopbuff_t RF_RespBuff; uint8_t RF_RespBuff_Data[sizeof(rf_resp_t) * (2 + 1)] = {0}; #define RF_MOD_MD0_1() LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_5) #define RF_MOD_MD0_0() LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_5) #define RF_MOD_MD1_1() LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_6) #define RF_MOD_MD1_0() LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_6) volatile uint8_t RF_hasPowered = 0; // 多项式为x16+x15+x2+1,LSB顺序 // 同ibutton的crc算法,不同于modbus的crc算法 uint16_t rf_crc_16(uint8_t *message, int16_t len) { #if 0 int16_t i, j; uint16_t crc_reg = 0; uint16_t current; for (i = 0; i < len; i++) { current = message[i]; for (j = 0; j < 8; j++) { if ((crc_reg ^ current) & 0x0001) crc_reg = (crc_reg >> 1) ^ 0xA001; else crc_reg >>= 1; current >>= 1; } } // 交换高低字节顺序 return ((crc_reg & 0xFF) << 8) | ((crc_reg >> 8) & 0xFF); #else return MODBUS_RTU_CRC16(message, len); #endif } // 计算自启动以来经过的秒数 uint32_t rf_get_seconds() { S_RTC_TIME_DATA_T sRTC; RTC_GetDateAndTime(&sRTC); return Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); } // 设置网关 void rf_set_gateway(uint8_t PSN[6]) { memmove(RF_GatewayPSN, PSN, 6); } // 清除网关 void rf_clear_gateway() { memmove(RF_GatewayPSN, RF_EMPTYPSN, 6); } // 计算通信地址,用于定点传输 uint16_t rf_get_addr(uint8_t PSN[6]) { uint16_t addr = rf_crc_16(PSN, 6); if(addr == 0xFFFF) // 不能为广播地址 return 0; return addr; } // 物理层校验 uint8_t rf_phy_valid(rf_frame_t *frame) { if(frame->vendor_id != RF_MARK_LS || frame->app_id != RF_APP || frame->protocol_ver != RF_PROTOCOL_VER) { // 物理层校验失败 return 0; } return 1; } // mac层校验 uint8_t rf_mac_valid(rf_frame_t *frame, uint8_t dir) { if(frame->dir != dir || (memcmp(frame->destPSN, RF_SelfPSN, 6) != 0 && (dir == RF_DIR_DOWN || memcmp(frame->destPSN, RF_BROADCAST_PSN, 6) != 0)) ) { // mac层校验失败 return 0; } return 1; } // 重新寻找SOF void RF_SearchSOF(uint8_t *buf, uint16_t fromPos, uint16_t *len) { uint16_t i; for(i = fromPos; i < *len && buf[i] != RF_FRAME_SOF; i++) { } *len -= i; memmove(buf, buf + i, *len); } // 分析串口数据,组帧 void RF_ParseFrame(uint8_t c) { BaseType_t xHigherPriorityTaskWoken; static uint16_t RdIdx = 0; uint8_t *RF_ModuleData = (uint8_t *) &RF_RecvFrame; uint8_t frameOk, frameErr; if(RdIdx == 0 && c != RF_FRAME_SOF) return; RF_ModuleData[RdIdx++] = c; do { frameErr = (RdIdx >= 2 && (RF_ModuleData[1] < RF_MIN_FRAME_LEN || RF_ModuleData[1] > RF_MAX_FRAME_LEN)); if(frameErr) { // 从1开始寻找SOF RF_SearchSOF(RF_ModuleData, 1, &RdIdx); } frameOk = (RdIdx >= 2 && RF_ModuleData[1] >= RF_MIN_FRAME_LEN && RF_ModuleData[1] <= RF_MAX_FRAME_LEN && RdIdx >= RF_ModuleData[1]); if(frameOk) { if(rf_crc_16(RF_ModuleData, RF_ModuleData[1]) == 0) { if(rf_phy_valid(&RF_RecvFrame) && rf_mac_valid(&RF_RecvFrame, RF_DIR_UP)) { LoopBuff_PutItem(&RF_TaskM, RF_ModuleData); } // 继续寻找下一帧 RdIdx -= RF_ModuleData[1]; memmove(RF_ModuleData, RF_ModuleData + RF_ModuleData[1], RdIdx); // 从0开始寻找SOF RF_SearchSOF(RF_ModuleData, 0, &RdIdx); // 发消息给任务 xSemaphoreGiveFromISR(RF_TaskQ, &xHigherPriorityTaskWoken); } else { // 从1开始寻找SOF RF_SearchSOF(RF_ModuleData, 1, &RdIdx); } } } while(frameOk || frameErr); } void RF_IRQHandler(USART_Handle *huart) { uint8_t c = (uint8_t) huart->Instance->DR; // printf("%02X ", c); // 直接解析帧 RF_ParseFrame(c); } // 初始化 void RF_Uart_Open(u32 baudrate) { LL_USART_InitTypeDef USART_InitStruct = {0}; USART_InitStruct.BaudRate = baudrate; USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B; USART_InitStruct.StopBits = LL_USART_STOPBITS_1; USART_InitStruct.Parity = LL_USART_PARITY_NONE; USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16; LL_USART_Init(UART8, &USART_InitStruct); LL_USART_ConfigAsyncMode(UART8); LL_USART_Enable(UART8); huart8.RxISR = RF_IRQHandler; SET_BIT(UART8->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); LL_USART_Enable(UART8); } void RF_Open() { // dcBuff.configBottle.PSN[0] = 0xFE; // dcBuff.configBottle.PSN[1] = 0xFE; // dcBuff.configBottle.PSN[2] = 0xFE; // dcBuff.configBottle.PSN[3] = 0xFE; // dcBuff.configBottle.PSN[4] = 0xFE; // dcBuff.configBottle.PSN[5] = 0xFE; // 用PSN的CRC校验值作为伪随机数的种子 srand(rf_crc_16(dcBuff.configBottle.PSN, 6)); RF_MAC_FN = rand() % 256; RF_APP_PN = rand() % 256; // 创建消息队列 LoopBuff_Create(&RF_GatewayBuff, 6, 4, 0, (uint32_t) RF_GatewayBuff_Data); LoopBuff_Create(&RF_AckBuff, sizeof(rf_ack_t), 2, 0, (uint32_t) RF_AckBuff_Data); LoopBuff_Create(&RF_RespBuff, sizeof(rf_resp_t), 2, 0, (uint32_t) RF_RespBuff_Data); // 创建消息队列 LoopBuff_Create(&RF_TaskM, sizeof(rf_frame_t), RF_TASKM_DATA_COUNT, 0, (uint32_t) RF_TaskM_Data); LoopBuff_Create(&RF_SendM, sizeof(rf_send_queue_t), RF_SENDM_DATA_COUNT, 0, (uint32_t) RF_SendM_Data); // 创建信号量 RF_TaskQ = xSemaphoreCreateBinary(); RF_SendQ = xSemaphoreCreateBinary(); RF_semAck = xSemaphoreCreateBinary(); RF_semGateway = xSemaphoreCreateBinary(); RF_semResp = xSemaphoreCreateBinary(); // 创建互斥锁 /*---------------------------------------------------------------------------------------------------------*/ /* Init UART */ /*---------------------------------------------------------------------------------------------------------*/ // 模块上电,设置硬件参数 RF_PowerOn(); } // 初始化帧 void rf_initial_frame(rf_frame_t *frame) { memset((uint8_t *) frame, 0, sizeof(rf_frame_t)); frame->len = RF_MIN_FRAME_LEN; } // 追加负载数据 uint8_t rf_append_payload(rf_frame_t *frame, uint8_t payload_len, uint8_t *payload) { if(frame->len < RF_MIN_FRAME_LEN || frame->len + payload_len > RF_MAX_FRAME_LEN) return 0; if(payload_len > 0) memmove(frame->app_payload + (frame->len - RF_MIN_FRAME_LEN), payload, payload_len); frame->len += payload_len; return 1; } // 物理层发送 uint8_t rf_uart_send(rf_frame_t *frame) { uint8_t phy_header[3]; uint16_t crc; uint16_t dst; uint8_t i; // 填写固定字段 frame->sof = RF_FRAME_SOF; frame->vendor_id = RF_MARK_LS; frame->app_id = RF_APP; frame->protocol_ver = RF_PROTOCOL_VER; memmove(frame->srcPSN, RF_SelfPSN, 6); crc = rf_crc_16((uint8_t *) frame, frame->len - 2); ((uint8_t *) frame)[frame->len - 2] = crc >> 8; ((uint8_t *) frame)[frame->len - 1] = crc & 0xFF; // 计算目的地址 if(frame->dir == RF_DIR_UP) dst = rf_get_addr((uint8_t *) RF_BROADCAST_PSN); else dst = rf_get_addr(frame->destPSN); #if 0 // phy_header[0] = dst >> 8; // phy_header[1] = dst & 0xFF; // // 信道 // if(frame->dir == RF_DIR_UP) // phy_header[2] = RF_UP_CHANNEL; // else // phy_header[2] = RF_DOWN_CHANNEL; //// while(!RF_READY()); //// delay_ms((rand() % 10) * (70 + rand() % 20)); // 多个中继器,避免冲突 // delay_ms((rand() % 3) * (10 + rand() % 10)); // 单个中继器,提高效率 // // printf("\nRF send to Module (%02X %02X %02X, %d bytes):\n", // phy_header[0], phy_header[1], phy_header[2], frame->len); // for(i = 0; i < frame->len; i++) // printf(" %02X", ((uint8_t *) frame)[i]); // printf("\n"); // // // 定点发送 // // 因为射频模块接收数据不能中断超过3个字节的时间,故不允许打断。 // __disable_irq(); // UART_Transmit(&huart8, phy_header, 3); // UART_Transmit(&huart8, (uint8_t *) frame, frame->len); // __enable_irq(); #else // 信道 // if(frame->dir == RF_DIR_UP) // { // phy_header[0] = (dcBuff.configBottle.lora_freq%3)*2+7;//RF_UP_CHANNEL; // phy_header[1] = (dcBuff.configBottle.lora_freq%3)*2+6;//RF_DOWN_CHANNEL; // } // else // {} phy_header[0] = (dcBuff.configBottle.lora_freq%3)*2+7;//RF_DOWN_CHANNEL; phy_header[1] = (dcBuff.configBottle.lora_freq%3)*2+6;//RF_UP_CHANNEL; // while(!RF_READY()); // delay_ms((rand() % 10) * (70 + rand() % 20)); // 多个中继器,避免冲突 delay_ms((rand() % 3) * (10 + rand() % 10)); // 单个中继器,提高效率 printf("\nRF send to Module (%02X, %d bytes):\n", phy_header[0], frame->len); for(i = 0; i < frame->len; i++) printf(" %02X", ((uint8_t *) frame)[i]); printf("\n"); // 定点发送 // 因为射频模块接收数据不能中断超过3个字节的时间,故不允许打断。 __disable_irq(); UART_Transmit(&huart8, phy_header, 2); UART_Transmit(&huart8, (uint8_t *) frame, frame->len); __enable_irq(); #endif return 1; } // mac层发送: ACK uint8_t rf_mac_send_ack(uint8_t oriDir, uint8_t oriMac_fn, uint8_t oriPSN[6]) { rf_initial_frame(&RF_Send_Frame); if(oriDir == RF_DIR_UP) RF_Send_Frame.dir = RF_DIR_DOWN; else RF_Send_Frame.dir = RF_DIR_UP; RF_Send_Frame.mac_type = RF_MAC_TYPE_ACK; RF_Send_Frame.mac_ack_req = 0; RF_Send_Frame.mac_fn = oriMac_fn; memmove(RF_Send_Frame.destPSN, oriPSN, 6); // 调用物理层发送 return rf_uart_send(&RF_Send_Frame); } // mac层发送: 数据 uint8_t rf_mac_send_data(rf_frame_t *frame, uint8_t dir, uint8_t fn, uint8_t destPSN[6]) { rf_ack_t ack; uint32_t stop_seconds; uint8_t count; // 清除回应 xSemaphoreTake(RF_semAck, 10); LoopBuff_Clear(&RF_AckBuff); // 数据来自上层 frame->dir = dir; frame->mac_type = RF_MAC_TYPE_DATA; if(frame->dir == RF_DIR_UP && frame->net_type == RF_NET_TYPE_DATA) frame->mac_ack_req = 1; else frame->mac_ack_req = 0; frame->mac_fn = RF_MAC_FN; memmove(frame->destPSN, destPSN, 6); // 调用物理层发送 if(!rf_uart_send(frame)) return 0; // 无须ACK确认 if(!frame->mac_ack_req) { RF_MAC_FN++; return 1; } // 等待ACK确认 stop_seconds = rf_get_seconds() + 3; while(rf_get_seconds() < stop_seconds) { xSemaphoreTake(RF_semAck, 500); count = LoopBuff_GetCount(&RF_AckBuff); while(count--) { memmove(&ack, LoopBuff_GetDataPtr(&RF_AckBuff, RF_AckBuff.info.rdPtr), sizeof(ack)); LoopBuff_RemoveItems(&RF_AckBuff, 1); if(ack.mac_fn == RF_MAC_FN && memcmp(ack.srcPSN, destPSN, 6) == 0) { RF_MAC_FN++; return 1; } } } return 0; } // net层发送:寻找中继器 uint8_t rf_net_send_find_relay() { // 清除回应 xSemaphoreTake(RF_semGateway, 10); LoopBuff_Clear(&RF_GatewayBuff); rf_initial_frame(&RF_Send_Frame); RF_Send_Frame.net_type = RF_NET_TYPE_FIND_RELAY; // 调用mac层发送 return rf_mac_send_data(&RF_Send_Frame, RF_DIR_UP, RF_MAC_TYPE_DATA, (uint8_t *) RF_BROADCAST_PSN); } // net层发送:回应中继器 uint8_t rf_net_send_resp_relay(uint8_t oriPSN[6]) { rf_initial_frame(&RF_Send_Frame); RF_Send_Frame.net_type = RF_NET_TYPE_RESP_RELAY; // 调用mac层发送 return rf_mac_send_data(&RF_Send_Frame, RF_DIR_DOWN, RF_MAC_TYPE_DATA, oriPSN); } // net层发送:数据 uint8_t rf_net_send_data(rf_frame_t *frame, uint8_t dir, uint8_t destPSN[6]) { // 数据来自应用层 frame->net_type = RF_NET_TYPE_DATA; // 调用mac层发送 return rf_mac_send_data(frame, dir, RF_MAC_TYPE_DATA, destPSN); } // 应用层发送:回应 uint8_t rf_app_send_resp(uint8_t oriPSN[6], uint8_t oriApp_pn, uint8_t payload_len, uint8_t *payload) { rf_initial_frame(&RF_Send_Frame); rf_append_payload(&RF_Send_Frame, payload_len, payload); RF_Send_Frame.app_pn = oriApp_pn; RF_Send_Frame.app_idx = 0; // 暂不实现分包组包 RF_Send_Frame.app_tbc = 0; // 调用net层发送 return rf_net_send_data(&RF_Send_Frame, RF_DIR_DOWN, oriPSN); } // 应用层发送:数据 uint8_t rf_app_send_data(uint8_t payload_len, uint8_t *payload) { rf_resp_t resp; uint32_t stop_seconds; uint8_t count; // 清除回应 xSemaphoreTake(RF_semResp, 10); LoopBuff_Clear(&RF_RespBuff); rf_initial_frame(&RF_Send_Frame); rf_append_payload(&RF_Send_Frame, payload_len, payload); RF_Send_Frame.app_pn = RF_APP_PN; RF_Send_Frame.app_idx = 0; // 暂不实现分包组包 RF_Send_Frame.app_tbc = 0; // 调用net层发送 if(rf_net_send_data(&RF_Send_Frame, RF_DIR_UP, RF_GatewayPSN) == 0) return 0; // 等待服务器返回:15秒 stop_seconds = rf_get_seconds() + 15; while(rf_get_seconds() < stop_seconds) { xSemaphoreTake(RF_semResp, 500); count = LoopBuff_GetCount(&RF_RespBuff); while(count--) { memmove(&resp, LoopBuff_GetDataPtr(&RF_RespBuff, RF_RespBuff.info.rdPtr), sizeof(resp)); LoopBuff_RemoveItems(&RF_RespBuff, 1); if(resp.app_pn == RF_APP_PN && memcmp(resp.srcPSN, RF_GatewayPSN, 6) == 0) { // print app_payload RF_APP_PN++; return 1; } } } return 0; } // 终端模块搜寻网关:发送搜寻命令,等待回应。 // 搜寻5次,取回应次数最多的作为通信网关。 // 最多接收10个网关 uint8_t rf_check_gateway() { uint8_t PSN_List[10][6]; // 接收到的网关PSN列表 uint8_t CNT_List[10]; // 接收到网关应答的次数 uint8_t PSN[6]; uint32_t stop_seconds; uint8_t i, j, k; uint8_t count; // 当前存在网关,直接返回 if(memcmp(RF_GatewayPSN, RF_EMPTYPSN, 6) != 0) return 1; // 重新搜索网关 memset(PSN_List, 0, sizeof(PSN_List)); memset(CNT_List, 0, sizeof(CNT_List)); // 搜寻5次 for(i = 0; i < 5; i++) { // 发送搜寻命令 rf_net_send_find_relay(); // 5秒内没有收到网关回应,则停止等待 stop_seconds = rf_get_seconds() + 5; while(rf_get_seconds() <= stop_seconds) { count = LoopBuff_GetCount(&RF_GatewayBuff); while(count--) { memmove(PSN, LoopBuff_GetDataPtr(&RF_GatewayBuff, RF_GatewayBuff.info.rdPtr), 6); LoopBuff_RemoveItems(&RF_GatewayBuff, 1); for(j = 0; j < 10; j++) { // 找到该PSN所在位置,或者第一个空位置 if(memcmp(PSN_List[j], PSN, 6) == 0 || CNT_List[j] == 0) { memmove(PSN_List[j], PSN, 6); CNT_List[j]++; break; } // 没有位置则丢弃 } // 延迟等待3秒 stop_seconds = rf_get_seconds() + 3; } } } // 使用收到次数最多的一个 k = 0; i = CNT_List[0]; for(j = 1; j < 10; j++) { if(CNT_List[j] > i) { k = j; i = CNT_List[j]; } } if(i == 0) return 0; rf_set_gateway(PSN_List[k]); return 1; } // 模块上电,设置硬件参数 void RF_PowerOn() { uint16_t recv_cnt = 0; uint32_t stop_seconds; char last_c = 0, c; uint8_t cfg[6]; uint16_t addr = rf_get_addr((uint8_t *) RF_BROADCAST_PSN); if(RF_hasPowered) return; printf("\nRF power on ...\n"); // 将串口更改为9600bps LL_USART_Disable(huart8.Instance); RF_Uart_Open(9600); NVIC_DisableIRQ(UART8_IRQn); VCC_RF_ON(); delay_ms(500); // while(!RF_READY()); // 进入休眠模式:模式3 RF_MOD_MD1_1(); RF_MOD_MD0_1(); delay_ms(50); cfg[0] = 0xC2; // 设置的参数掉电不保存,每次上电都重新设置 cfg[1] = addr >> 8; cfg[2] = addr & 0xFF; cfg[3] = 6 | (7 << 3) | (0 << 6); // 115200bps cfg[4] = (dcBuff.configBottle.lora_freq%3)*2+6;//RF_UP_CHANNEL; cfg[5] = 1 | (1 << 2) | (9 << 3) | (0 << 7); // freqcast=1, bw=500kHz, unicast=0 printf("\nInitialize RF Module: %02X %02X %02X %02X %02X %02X\n", cfg[0], cfg[1], cfg[2], cfg[3], cfg[4], cfg[5]); UART_Transmit(&huart8, cfg, 6); stop_seconds = rf_get_seconds() + 2; while(rf_get_seconds() < stop_seconds) { if(huart8.Instance->SR & USART_SR_RXNE) { c = huart8.Instance->DR; printf("%c", c); if(c == 'K' && last_c == 'O') { // 设置状态 RF_initStatus = 1; break; } last_c = c; } } // 进入工作模式:模式0 RF_MOD_MD1_0(); RF_MOD_MD0_0(); delay_ms(50); // while(!RF_READY()); // 将串口更改为115200bps LL_USART_Disable(huart8.Instance); RF_Uart_Open(115200ul); NVIC_EnableIRQ(UART8_IRQn); RF_hasPowered = 1; } void RF_PowerOff() { if(!RF_hasPowered) return; RF_hasPowered = 0; printf("\nRF power off ...\n"); VCC_RF_OFF(); delay_ms(200); } // 网关任务主体:处理接收帧(串口成帧在中断里完成) void RF_GatewayTask(void *p_arg) { uint16_t count; uint16_t i; uint32_t seconds; uint8_t oldRequest, incCount, newPSN; int16_t idx; ext_bottle_t bottleRec; while(TRUE) { // 本任务读取处理队列里的帧 // 这条语句用于任务切换(让其它任务有机会得到执行) xSemaphoreTake(RF_TaskQ, 0); count = LoopBuff_GetCount(&RF_TaskM); while(count--) { // 取出帧 RF_ProcFrame = *(rf_frame_t *) LoopBuff_GetDataPtr(&RF_TaskM, RF_TaskM.info.rdPtr); LoopBuff_RemoveItems(&RF_TaskM, 1); printf("\nRF recv from Module (%d bytes):\n", RF_ProcFrame.len); for(i = 0; i < RF_ProcFrame.len; i++) printf(" %02X", ((uint8_t *) &RF_ProcFrame)[i]); printf("\n"); seconds = rf_get_seconds(); RF_seconds = seconds; // 未获取到绝对时间,不能存储和转发,故不能应答 if(RTC_offsetSeconds == 0) { printf("\nRTC_offsetSeconds = 0, ignored ...\n"); //apex continue; } // 处理帧 idx = Ext_Lookup_Bottle_PSN(RF_ProcFrame.srcPSN, bottleCnt.count); if(idx == -1) continue; // 是否需要回应ack if(RF_ProcFrame.mac_ack_req) { // 生成确认帧 RF_Send_Rec.type = 0; memmove(RF_Send_Rec.oriPSN, RF_ProcFrame.srcPSN, 6); RF_Send_Rec.fn_pn = RF_ProcFrame.mac_fn; // 统一加到发送队列 LoopBuff_PutItem(&RF_SendM, (uint8_t *) &RF_Send_Rec); // 发消息给任务 xSemaphoreGive(RF_SendQ); } if(RF_ProcFrame.net_type == RF_NET_TYPE_FIND_RELAY) { // 生成中继应答帧 RF_Send_Rec.type = 1; memmove(RF_Send_Rec.oriPSN, RF_ProcFrame.srcPSN, 6); RF_Send_Rec.fn_pn = RF_ProcFrame.app_pn; // 统一加到发送队列 LoopBuff_PutItem(&RF_SendM, (uint8_t *) &RF_Send_Rec); // 发消息给任务 xSemaphoreGive(RF_SendQ); } else if(RF_ProcFrame.net_type == RF_NET_TYPE_DATA) { printf("\n*** PSN: 20%02d%02d%02d%02d%03d ***, ", RF_ProcFrame.srcPSN[0], RF_ProcFrame.srcPSN[1], RF_ProcFrame.srcPSN[2], RF_ProcFrame.srcPSN[3], (RF_ProcFrame.srcPSN[4] << 8) | RF_ProcFrame.srcPSN[5]); // 查找并维护该节点的状态 oldRequest = 0; incCount = 0; newPSN = 1; // idx = Ext_Lookup_Bottle_PSN(RF_ProcFrame.srcPSN, bottleCnt.count); if(idx >= 0) { newPSN = 0; // 已有PSN FRAM_BufferRead(FRAM_BOTTLE_DATA_BASE + sizeof(ext_bottle_t) * bottlePSN[idx].recNo, (uint8_t *) &bottleRec, sizeof(ext_bottle_t)); oldRequest = (bottleRec.pn == RF_ProcFrame.app_pn && RTC_offsetSeconds + seconds < bottleRec.recvTime + 72 * 3600); } if(idx == -1 && bottleCnt.count < FRAM_BOTTLE_COUNT) { incCount = 1; // 添加一个PSN idx = bottleCnt.count; bottlePSN[idx].recNo = idx; } if(idx == -1) { for(i = 0; i < FRAM_BOTTLE_COUNT; i++) { FRAM_BufferRead(FRAM_BOTTLE_DATA_BASE + sizeof(ext_bottle_t) * bottlePSN[i].recNo, (uint8_t *) &bottleRec, sizeof(ext_bottle_t)); if(bottleRec.lastData == -1) // 取代一个无历史数据的PSN { idx = i; break; } } } if(idx >= 0) { // 修改储罐档案 if(incCount || newPSN) { memset(&bottleRec, 0, sizeof(ext_bottle_t)); bottleRec.lastData = -1; } memmove(bottleRec.PSN, RF_ProcFrame.srcPSN, 6); bottleRec.pn = RF_ProcFrame.app_pn; bottleRec.recvTime = RTC_offsetSeconds + seconds; FRAM_BufferWrite(FRAM_BOTTLE_DATA_BASE + sizeof(ext_bottle_t) * bottlePSN[idx].recNo, (uint8_t *) &bottleRec, sizeof(ext_bottle_t)); // 修改总数 if(incCount) { bottleCnt.count++; FRAM_SaveInfo(FRAM_BOTTLE_INFO_BASE, (uint8_t *) &bottleCnt, sizeof(ext_count_t)); } // 重建索引 if(incCount || newPSN) { memmove(bottlePSN[idx].PSN, bottleRec.PSN, 6); Ext_Sort_Bottle_PSN(bottlePSN, 0, bottleCnt.count - 1); } } if(!oldRequest) // 新节点或新记录,需要转发给服务器 { printf("\nNew request, add to queue\n"); // 生成上传记录,加到上传队列 memmove(Ext_Data_Rec.oriPSN, RF_ProcFrame.srcPSN, 6); Ext_Data_Rec.payload_len = RF_ProcFrame.len - RF_MIN_FRAME_LEN; memmove(Ext_Data_Rec.payload, RF_ProcFrame.app_payload, Ext_Data_Rec.payload_len); Ext_Data_Rec.recvTime = RTC_offsetSeconds + seconds; // 加到上传队列 Data_PutToQueue(&Ext_Data_Rec); } // 直接生成返回数据帧(上传记录存到flash里) RF_Send_Rec.type = 2; memmove(RF_Send_Rec.oriPSN, RF_ProcFrame.srcPSN, 6); RF_Send_Rec.fn_pn = RF_ProcFrame.app_pn; RF_Send_Rec.payload_len = 2; RF_Send_Rec.payload[0] = 0xFF; RF_Send_Rec.payload[1] = 0xFF; // 统一加到发送队列 LoopBuff_PutItem(&RF_SendM, (uint8_t *) &RF_Send_Rec); // 发消息给任务 xSemaphoreGive(RF_SendQ); } } } } // 网关任务主体:处理上传帧 void RF_TranTask(void *p_arg) { uint32_t stop_seconds; uint16_t i; uint32_t checkTick = 30000; static int Ethernet_fail_count = 0; S_RTC_TIME_DATA_T sRTC; while(TRUE) { // 每30秒检查一次网络连接情况 if(IsTickOut(checkTick)) { checkTick = GetDelayTick(30000); Ethernet_connected = IS_VCC_ETHERNET_ON() && Ethernet_IsConnected(); if(IS_VCC_ETHERNET_ON() && !Ethernet_connected) Ethernet_fail_count++; } // 获取锁(4G优先,4G不能发送时才用网口发送) if(xSemaphoreTake(RF_TranLock, 500) != pdTRUE) { VCC_ETHERNET_OFF(); Ethernet_connected = 0; continue; } // // 多次失败,重启网络模块(因网络模块设置了超时重启,故此处不用人工重启) // if(Ethernet_fail_count >= 6) // VCC_ETHERNET_OFF(); if(!IS_VCC_ETHERNET_ON()) { Ethernet_fail_count = 0; Ethernet_Config(); } // 掉电有效,如果未获取到UTC时间,不转发 if(RTC_offsetSeconds > 0 && LoopBuff_GetCount(&RF_TranM) > 0 && Ethernet_connected) { if(!SFlash_LoadInfo(LoopBuff_GetDataPos(&RF_TranM, RF_TranM.info.rdPtr), (uint8_t *) &Ext_Data_Rec1, sizeof(ext_data_t))) { LoopBuff_RemoveItems(&RF_TranM, 1); // 保存到铁电 FRAM_SaveInfo(RF_TranM.info_base, (uint8_t *) &RF_TranM.info, sizeof(RF_TranM.info)); } else { i = pack_gprs_tran_data(&Ext_Data_Rec1, 0); delay_ms(20); // 先清除接收消息和缓冲区 do { LoopBuff_Clear(&Ethernet_Buff); } while(xSemaphoreTake(Ethernet_semQ, 100) == pdTRUE || LoopBuff_GetCount(&Ethernet_Buff) > 0); // TODO: 发送到服务器,并等待返回 printf("\nEthernet send to server\n"); UART_Transmit(&huart3, Task_sendBuff, i); // 先预设发送失败,以防止假连接状态 Ethernet_fail_count++; stop_seconds = rf_get_seconds() + 6; while(rf_get_seconds() < stop_seconds) { // 这条语句用于任务切换(让其它任务有机会得到执行) xSemaphoreTake(Ethernet_semQ, 500); if(LoopBuff_GetCount(&Ethernet_Buff) >= 2) // 服务器有返回 { printf("\nResponse from server:"); while(LoopBuff_GetCount(&Ethernet_Buff) > 0) { printf(" %02X", *LoopBuff_GetDataPtr(&Ethernet_Buff, Ethernet_Buff.info.rdPtr)); LoopBuff_RemoveItems(&Ethernet_Buff, 1); } printf("\n"); // 发送成功,失败次数清零 Ethernet_connected = IS_VCC_ETHERNET_ON(); Ethernet_fail_count = 0; // 删除当前记录 LoopBuff_RemoveItems(&RF_TranM, 1); // 保存到铁电 FRAM_SaveInfo(RF_TranM.info_base, (uint8_t *) &RF_TranM.info, sizeof(RF_TranM.info)); // 记录发送成功的时间 RTC_GetDateAndTime(&sRTC); DTU_succTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); break; } } } } // 释放锁(4G优先,让4G有机会发送) xSemaphoreGive(RF_TranLock); } } // 网关任务主体:处理发送帧 void RF_SendTask(void *p_arg) { uint16_t count; while(TRUE) { // 喂狗 HAL_IWDG_Refresh(&hiwdg); // 本任务读取发送队列的记录 // 这条语句用于任务切换(让其它任务有机会得到执行) xSemaphoreTake(RF_SendQ, 1000); count = LoopBuff_GetCount(&RF_SendM); while(count--) { // 取出记录 RF_Send_Rec1 = *(rf_send_queue_t *) LoopBuff_GetDataPtr(&RF_SendM, RF_SendM.info.rdPtr); LoopBuff_RemoveItems(&RF_SendM, 1); if(RF_Send_Rec1.type == 0) // 发送MAC_ACK rf_mac_send_ack(RF_DIR_UP, RF_Send_Rec1.fn_pn, RF_Send_Rec1.oriPSN); else if(RF_Send_Rec1.type == 1) // 发送RESP_RELAY rf_net_send_resp_relay(RF_Send_Rec1.oriPSN); else if(RF_Send_Rec1.type == 2) // 发送应用层返回数据 rf_app_send_resp(RF_Send_Rec1.oriPSN, RF_Send_Rec1.fn_pn, RF_Send_Rec1.payload_len, RF_Send_Rec1.payload); // 延时,让设备端处理 osDelay(250); } } }