ShipCentralControl/Anjiehui7_DTU/User/uart_RFGateway.c

999 lines
26 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
*********************************************************************************************************
* 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;
const uint8_t RF_UP_CHANNEL = 28; // 上行信道: 498M
const uint8_t RF_DOWN_CHANNEL = 29; // 下行信道: 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+1LSB顺序
// 同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] = RF_UP_CHANNEL;
else
phy_header[0] = 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, %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, 1);
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] = 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;
}
// 处理帧
// 是否需要回应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);
}
}
}