ZNY_Pakistan/Anjiehui7_ZNY/User/uart_RFModule.c

1251 lines
32 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_RFModule.h
* Version : V1.00
* Programmer(s) : Qian Xianghong
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#include "includes.h"
const uint8_t RF_APP = RF_APP_AJH;
const uint8_t RF_PROTOCOL_VER = RF_PROTOCOL_VER_1;
const uint8_t RF_LNG_LORA_CHANNEL = 1; // 通信信道: 471M
const uint8_t RF_UP_CHANNEL = 28; // 上行信道: 438M
const uint8_t RF_DOWN_CHANNEL = 29; // 下行信道: 439M
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};
const uint8_t RF_LNG_LORA_EMPTYPSN[13] = {0, 0, 0, 0, 0, 0, 0, 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_lng_lora_t RF_LNG_LORA_Send_Frame, RF_LNG_LORA_Recv_Frame;
// LNG-LORA发送状态
volatile uint8_t RF_LNG_LORA_State = 0; // 0-不发送1-随机延时15秒内应答一次2-每隔5秒发送一次
// RF串口接收的消息通知
volatile uint8_t RF_semAck = 0;
volatile uint8_t RF_semGateway = 0;
volatile uint8_t RF_semResp = 0;
volatile uint8_t RF_semMatch = 0;
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};
loopbuff_t RF_MatchBuff;
uint8_t RF_MatchBuff_Data[sizeof(rf_charge_match_t) * (2 + 1)] = {0};
#define RF_MOD_MD0_1() LL_GPIO_SetOutputPin(GPIOD, LL_GPIO_PIN_13)
#define RF_MOD_MD0_0() LL_GPIO_ResetOutputPin(GPIOD, LL_GPIO_PIN_13)
#define RF_MOD_MD1_1() LL_GPIO_SetOutputPin(GPIOD, LL_GPIO_PIN_12)
#define RF_MOD_MD1_0() LL_GPIO_ResetOutputPin(GPIOD, LL_GPIO_PIN_12)
#define RF_READY() (1)
// 射频初始化状态
uint8_t RF_initStatus = 0;
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;
}
// 初始化帧
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(dcBuff.configDisplay.op_BOX_VER) // 泽耀
//// {
//// if(frame->dir == RF_DIR_UP)
//// dst = rf_get_addr((uint8_t *) RF_BROADCAST_PSN);
//// else
//// dst = rf_get_addr(frame->destPSN);
//// 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;
//// }
//// else // LORA
{
// 信道
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));
//// if(dcBuff.configDisplay.op_BOX_VER) // 泽耀
//// {
//// printf("\nRF send to Gateway (%02X %02X %02X, %d bytes):\n",
//// phy_header[0], phy_header[1], phy_header[2], frame->len);
//// }
//// else // LORA
{
printf("\nRF send to Gateway (%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();
//// if(dcBuff.configDisplay.op_BOX_VER) // 泽耀
//// UART_Transmit(&huart3, phy_header, 3);
//// else // LORA
UART_Transmit(&huart3, phy_header, 1);
UART_Transmit(&huart3, (uint8_t *) frame, frame->len);
__enable_irq();
return 1;
}
// 物理层发送
uint8_t rf_uart_send_lng_lora(rf_lng_lora_t *frame)
{
uint16_t crc;
uint8_t i;
// 填写固定字段
memmove(frame->frame_header, "TANK", 4);
crc = rf_crc_16((uint8_t *) frame, sizeof(rf_lng_lora_t) - 2);
((uint8_t *) frame)[sizeof(rf_lng_lora_t) - 2] = crc >> 8;
((uint8_t *) frame)[sizeof(rf_lng_lora_t) - 1] = crc & 0xFF;
// while(!RF_READY());
// 随机延时0.8~1s
delay_ms(800 + (rand() % 11) * (10 + rand() % 11));
printf("\nRF send to Gateway:\n");
for(i = 0; i < sizeof(rf_lng_lora_t); i++)
printf(" %02X", ((uint8_t *) frame)[i]);
printf("\n");
// 因为射频模块接收数据不能中断超过3个字节的时间故不允许打断。
__disable_irq();
UART_Transmit(&huart3, (uint8_t *) frame, sizeof(rf_lng_lora_t));
__enable_irq();
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])
{
uint32_t tick;
rf_ack_t ack;
uint32_t stop_seconds;
uint8_t count;
// 清除回应
RF_semAck = 0;
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)
{
tick = GetDelayTick(500);
while(!IsTickOut(tick))
{
if(RF_semAck)
break;
}
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()
{
// 清除回应
RF_semGateway = 0;
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_charge_match(uint8_t charging)
{
rf_charge_match_t *pMatch = (rf_charge_match_t *) RF_Send_Frame.app_payload;
// 清除回应
RF_semMatch = 0;
LoopBuff_Clear(&RF_MatchBuff);
rf_initial_frame(&RF_Send_Frame);
RF_Send_Frame.net_type = RF_NET_TYPE_CHARGE_MATCH;
pMatch->posState = dcBuff.dtuData.posState;
pMatch->longitude = dcBuff.dtuData.longitude;
pMatch->latitude = dcBuff.dtuData.latitude;
pMatch->source = dcBuff.configBottle.source;
pMatch->charging = charging;
rf_append_payload(&RF_Send_Frame, sizeof(rf_charge_match_t), (uint8_t *) pMatch);
// 调用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_charge_match(uint8_t oriPSN[6], uint8_t charging)
{
rf_charge_match_t *pMatch = (rf_charge_match_t *) RF_Send_Frame.app_payload;
rf_initial_frame(&RF_Send_Frame);
RF_Send_Frame.net_type = RF_NET_TYPE_CHARGE_MATCH;
pMatch->posState = dcBuff.dtuData.posState;
pMatch->longitude = dcBuff.dtuData.longitude;
pMatch->latitude = dcBuff.dtuData.latitude;
pMatch->source = dcBuff.configBottle.source;
pMatch->charging = charging;
rf_append_payload(&RF_Send_Frame, sizeof(rf_charge_match_t), (uint8_t *) pMatch);
// 调用mac层发送
return rf_mac_send_data(&RF_Send_Frame, RF_DIR_DOWN, RF_MAC_TYPE_DATA, oriPSN);
}
// net层发送回应遥控命令
uint8_t rf_net_send_resp_remote_ctrl(uint8_t oriPSN[6], uint8_t func)
{
rf_initial_frame(&RF_Send_Frame);
RF_Send_Frame.net_type = RF_NET_TYPE_REMOTE_CTRL;
rf_append_payload(&RF_Send_Frame, 1, &func);
// 调用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)
{
uint32_t tick;
rf_resp_t resp;
uint32_t stop_seconds;
uint8_t count;
S_RTC_TIME_DATA_T sRTC;
// 清除回应
RF_semResp = 0;
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)
{
tick = GetDelayTick(500);
while(!IsTickOut(tick))
{
if(RF_semResp)
break;
}
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++;
// 记录发送成功的时间
RTC_GetDateAndTime(&sRTC);
DTU_succTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
return 1;
}
}
}
return 0;
}
// 检查当前是否已经设置了网关
uint8_t rf_has_gateway()
{
return (memcmp(RF_GatewayPSN, RF_EMPTYPSN, 6) != 0);
}
// 终端模块搜寻网关:发送搜寻命令,等待回应。
// 搜寻5次取回应次数最多的作为通信网关。
// 最多接收10个网关
uint8_t rf_check_gateway()
{
uint32_t tick;
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;
uint8_t done = 0;
// 重新搜索网关
memset(PSN_List, 0, sizeof(PSN_List));
memset(CNT_List, 0, sizeof(CNT_List));
// 搜寻3次如果和原来的中继相同则只搜寻1次
for(i = 0; i < 3 && !done; i++)
{
// 发送搜寻命令
rf_net_send_find_relay();
// 4秒内没有收到网关回应则停止等待
stop_seconds = rf_get_seconds() + 4;
while(rf_get_seconds() <= stop_seconds)
{
tick = GetDelayTick(500);
while(!IsTickOut(tick))
{
if(RF_semGateway)
break;
}
count = LoopBuff_GetCount(&RF_GatewayBuff);
while(count--)
{
memmove(PSN, LoopBuff_GetDataPtr(&RF_GatewayBuff, RF_GatewayBuff.info.rdPtr), 6);
LoopBuff_RemoveItems(&RF_GatewayBuff, 1);
// 如果和原来的中继相同则只搜寻1次
if(memcmp(RF_GatewayPSN, PSN, 6) == 0)
done = 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)
{
rf_clear_gateway();
return 0;
}
rf_set_gateway(PSN_List[k]);
printf("RF_GatewayPSN: 20%02d%02d%02d%02d%03d\n", RF_GatewayPSN[0], RF_GatewayPSN[1],
RF_GatewayPSN[2], RF_GatewayPSN[3], (RF_GatewayPSN[4] << 8) | RF_GatewayPSN[5]);
return 1;
}
// 判断储罐和槽车是否匹配
uint32_t rf_is_charge_match(rf_charge_match_t *pMatch)
{
// 判断介质
if(pMatch->source != dcBuff.configBottle.source)
return 0;
// 判断槽车处于静止状态
if(dcBuff.configDisplay.op_SEND_GPS_DATA && Motion_Status && dcBuff.dtuData.posState && dcBuff.dtuData.speed >= 5)
return 0;
// 无法判断距离
if(pMatch->posState == 0 || dcBuff.dtuData.posState == 0)
return 1;
// 判断储罐和槽车之间的距离
if(GetDistance(pMatch->latitude, pMatch->longitude, dcBuff.dtuData.latitude, dcBuff.dtuData.longitude) > 500)
return 0;
return 1;
}
// 判断槽车是否离开原地
uint32_t rf_is_truck_leave()
{
// 无法判断距离
if(Pump_Stop_posState == 0 || dcBuff.dtuData.posState == 0)
return 0;
// 判断槽车处于运动状态
if(!Motion_Status || dcBuff.dtuData.speed < 5)
return 0;
// 判断槽车离原点之间的距离
if(GetDistance(Pump_Stop_Latitude, Pump_Stop_Longitude, dcBuff.dtuData.latitude, dcBuff.dtuData.longitude) < 2000)
return 0;
return 1;
}
// 储罐发送充装匹配命令,并等待应答
uint8_t rf_charge_match(uint8_t charging)
{
uint32_t tick;
uint32_t stop_tick;
rf_charge_match_t match;
uint8_t count;
uint8_t try_count = 2;
// 发送2次
while(try_count--)
{
// 发送匹配命令
rf_net_send_charge_match(charging);
// 等待3秒内的有效应答
stop_tick = GetDelayTick(3000);
while(!IsTickOut(stop_tick))
{
tick = GetDelayTick(500);
while(!IsTickOut(tick))
{
if(RF_semMatch)
break;
}
count = LoopBuff_GetCount(&RF_MatchBuff);
while(count--)
{
memmove(&match, LoopBuff_GetDataPtr(&RF_MatchBuff, RF_MatchBuff.info.rdPtr), sizeof(match));
LoopBuff_RemoveItems(&RF_MatchBuff, 1);
// 判断匹配是否合法
if(rf_is_charge_match(&match) && match.charging == charging)
return 1;
}
}
}
return 0;
}
// 重新寻找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);
}
// 重新寻找HEADER
void RF_SearchHeader(uint8_t *buf, uint16_t fromPos, uint16_t *len)
{
uint16_t i;
for(i = fromPos; i < *len && buf[i] != 'L'; i++)
{
}
*len -= i;
memmove(buf, buf + i, *len);
}
// 模块任务主体:处理射频接收数据
void RF_ParseFrame(uint8_t c)
{
static uint16_t RdIdx = 0;
static uint32_t outTick = 0;
uint8_t *RF_ModuleData = (uint8_t *) &RF_RecvFrame;
rf_ack_t ack;
rf_resp_t resp;
rf_charge_match_t match;
uint16_t i;
uint8_t frameOk, frameErr;
if(IsTickOut(outTick))
RdIdx = 0;
outTick = GetDelayTick(50);
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_DOWN))
{
// 收到一帧
printf("\nRF recv from Gateway (%d bytes):\n", RF_ModuleData[1]);
for(i = 0; i < RF_ModuleData[1]; i++)
printf(" %02X", RF_ModuleData[i]);
printf("\n");
// 判断帧类型
if(RF_RecvFrame.mac_type == RF_MAC_TYPE_ACK)
{
// Ack确认帧
memmove(ack.srcPSN, RF_RecvFrame.srcPSN, 6);
ack.mac_fn = RF_RecvFrame.mac_fn;
LoopBuff_PutItem(&RF_AckBuff, (uint8_t *) &ack);
// 发消息给任务
RF_semAck = 1;
}
else if(RF_RecvFrame.net_type == RF_NET_TYPE_RESP_RELAY)
{
// 中继应答帧
LoopBuff_PutItem(&RF_GatewayBuff, RF_RecvFrame.srcPSN);
// 发消息给任务
RF_semGateway = 1;
}
else if(RF_RecvFrame.net_type == RF_NET_TYPE_DATA)
{
// 服务器应答帧
memmove(resp.srcPSN, RF_RecvFrame.srcPSN, 6);
resp.app_pn = RF_RecvFrame.app_pn;
resp.payload_len = RF_RecvFrame.len - RF_MIN_FRAME_LEN;
memmove(resp.payload, RF_RecvFrame.app_payload, resp.payload_len);
LoopBuff_PutItem(&RF_RespBuff, (uint8_t *) &resp);
// 发消息给任务
RF_semResp = 1;
}
else if(RF_RecvFrame.net_type == RF_NET_TYPE_CHARGE_MATCH)
{
if(!dcBuff.configDisplay.op_SEND_GPS_DATA)
{
// 储罐收到来自槽车的匹配帧
memmove(&match, RF_RecvFrame.app_payload, sizeof(match));
LoopBuff_PutItem(&RF_MatchBuff, (uint8_t *) &match);
// 发消息给任务
RF_semMatch = 1;
}
}
}
else if(dcBuff.configDisplay.op_SEND_GPS_DATA
&& rf_phy_valid(&RF_RecvFrame) && rf_mac_valid(&RF_RecvFrame, RF_DIR_UP))
{
// 收到一帧
printf("\nRF recv from remote (%d bytes):\n", RF_ModuleData[1]);
for(i = 0; i < RF_ModuleData[1]; i++)
printf(" %02X", RF_ModuleData[i]);
printf("\n");
// 判断帧类型
if(RF_RecvFrame.net_type == RF_NET_TYPE_CHARGE_MATCH)
{
// 槽车收到来自储罐的匹配帧
// 判断是否匹配,如匹配则应答
memmove(&match, RF_RecvFrame.app_payload, sizeof(match));
if(rf_is_charge_match(&match))
{
if(!match.charging)
{
// 记录关泵的时间和GPS地址
Pump_Stop_Time = rf_get_seconds();
Pump_Stop_posState = dcBuff.dtuData.posState;
Pump_Stop_Longitude = dcBuff.dtuData.longitude;
Pump_Stop_Latitude = dcBuff.dtuData.latitude;
// 断开充液泵
KZ_PUMP_OFF();
}
rf_net_send_resp_charge_match(RF_RecvFrame.srcPSN, match.charging);
}
}
else if(RF_RecvFrame.net_type == RF_NET_TYPE_REMOTE_CTRL)
{
// 槽车收到遥控器命令
if(RF_RecvFrame.app_payload[0] == 3) // 配对
{
if(MeterInSamplePage()) // 标定页面:允许遥控配对
rf_net_send_resp_remote_ctrl(RF_RecvFrame.srcPSN, 3);
}
else if(RF_RecvFrame.app_payload[0] == 1 || RF_RecvFrame.app_payload[0] == 2) // 遥控泵
{
if(memcmp(RF_RecvFrame.destPSN, dcBuff.configBottle.PSN, 6) == 0)
{
if(RF_RecvFrame.app_payload[0] == 1) // 开泵
{
KZ_VALUE_ENABLE();
rf_net_send_resp_remote_ctrl(RF_RecvFrame.srcPSN, 1);
}
else // 关泵
{
KZ_VALUE_DISABLE();
rf_net_send_resp_remote_ctrl(RF_RecvFrame.srcPSN, 2);
}
}
}
}
}
// 继续寻找下一帧
RdIdx -= RF_ModuleData[1];
memmove(RF_ModuleData, RF_ModuleData + RF_ModuleData[1], RdIdx);
// 从0开始寻找SOF
RF_SearchSOF(RF_ModuleData, 0, &RdIdx);
}
else
{
// 从1开始寻找SOF
RF_SearchSOF(RF_ModuleData, 1, &RdIdx);
}
}
} while(frameOk || frameErr);
}
// 模块任务主体:处理射频接收数据
void RF_ParseLNGLora(uint8_t c)
{
static uint16_t RdIdx = 0;
static uint32_t outTick = 0;
uint8_t *RF_ModuleData = (uint8_t *) &RF_LNG_LORA_Recv_Frame;
uint16_t i;
uint8_t frameOk, frameErr;
char psn[14];
if(IsTickOut(outTick))
RdIdx = 0;
outTick = GetDelayTick(50);
if(RdIdx == 0 && c != 'L')
return;
RF_ModuleData[RdIdx++] = c;
do
{
frameErr = ((RdIdx >= 2 && RF_ModuleData[1] != 'N')
|| (RdIdx >= 3 && RF_ModuleData[2] != 'G')
|| (RdIdx >= 4 && RF_ModuleData[3] != 'C'));
if(frameErr)
{
// 从1开始寻找SOF
RF_SearchHeader(RF_ModuleData, 1, &RdIdx);
}
frameOk = (RdIdx >= sizeof(rf_lng_lora_t) && memcmp(RF_ModuleData, "LNGC", 4) == 0);
if(frameOk)
{
if(rf_crc_16(RF_ModuleData, sizeof(rf_lng_lora_t)) == 0)
{
// 收到一帧
printf("\nRF recv from Gateway (%d bytes):\n", sizeof(rf_lng_lora_t));
for(i = 0; i < sizeof(rf_lng_lora_t); i++)
printf(" %02X", RF_ModuleData[i]);
printf("\n");
sprintf(psn, "20%02d%02d%02d%02d%03d",
dcBuff.configBottle.PSN[0], dcBuff.configBottle.PSN[1], dcBuff.configBottle.PSN[2],
dcBuff.configBottle.PSN[3], (dcBuff.configBottle.PSN[4] << 8) | dcBuff.configBottle.PSN[5]);
if(memcmp(RF_LNG_LORA_Recv_Frame.tank_psn, RF_LNG_LORA_EMPTYPSN, 13) == 0)
{
if(RF_LNG_LORA_State == 0)
RF_LNG_LORA_State = 1;
}
else if(memcmp(RF_LNG_LORA_Recv_Frame.tank_psn, psn, 13) == 0)
{
if(RF_LNG_LORA_Recv_Frame.send_mod == 0)
RF_LNG_LORA_State = 0;
else
RF_LNG_LORA_State = 2;
}
// 继续寻找下一帧
RdIdx -= sizeof(rf_lng_lora_t);
memmove(RF_ModuleData, RF_ModuleData + sizeof(rf_lng_lora_t), RdIdx);
// 从0开始寻找SOF
RF_SearchHeader(RF_ModuleData, 0, &RdIdx);
}
else
{
// 从1开始寻找SOF
RF_SearchHeader(RF_ModuleData, 1, &RdIdx);
}
}
} while(frameOk || frameErr);
}
void RF_IRQHandler(USART_Handle *huart)
{
uint8_t c = (uint8_t) huart->Instance->RDR;
// printf("%02X ", c);
// 直接解析帧
if(dcBuff.configDisplay.op_LNG_LORA)
RF_ParseLNGLora(c);
else
RF_ParseFrame(c);
}
void RF_Uart_Open(u32 baudrate)
{
LL_USART_InitTypeDef USART_InitStruct = {0};
huart3.RxISR = RF_IRQHandler;
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3);
/* USART3 interrupt Init */
NVIC_SetPriority(USART3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
NVIC_EnableIRQ(USART3_IRQn);
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(USART3, &USART_InitStruct);
LL_USART_ConfigAsyncMode(USART3);
SET_BIT(USART3->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);
LL_USART_Enable(USART3);
}
// 模块上电,设置硬件参数
void RF_PowerOn()
{
uint32_t stop_seconds;
char last_c = 0, c;
uint8_t cfg[6];
static uint8_t first = 1;
uint16_t addr = rf_get_addr(RF_SelfPSN);
// 槽车版本,类似中继器的角色
if(dcBuff.configDisplay.op_SEND_GPS_DATA)
addr = rf_get_addr((uint8_t *) RF_BROADCAST_PSN);
if(RF_hasPowered)
return;
printf("\nRF power on ...\n");
VCC_RF_ON();
delay_ms(500);
// 将串口更改为9600bps
LL_USART_Disable(huart3.Instance);
RF_Uart_Open(9600);
NVIC_DisableIRQ(USART3_IRQn);
// 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;
if(dcBuff.configDisplay.op_LNG_LORA)
cfg[3] = 2 | (7 << 3) | (3 << 6); // sf=8, 115200bps, cr=4/8
//// else if(dcBuff.configDisplay.op_BOX_VER)
//// cfg[3] = 0x3C; // 泽耀模块:【00 111 100】: UART 8N1, 115200bps, 空中速率9.6k
else
cfg[3] = 6 | (7 << 3) | (0 << 6); // sf=12, 115200bps, cr=4/5
cfg[4] = RF_DOWN_CHANNEL;
// LNG-LORA版本
if(dcBuff.configDisplay.op_LNG_LORA)
cfg[4] = RF_LNG_LORA_CHANNEL;
// 槽车版本,类似中继器的角色
else if(dcBuff.configDisplay.op_SEND_GPS_DATA)
cfg[4] = RF_UP_CHANNEL;
if(dcBuff.configDisplay.op_LNG_LORA)
cfg[5] = 1 | (0 << 2) | (9 << 3) | (0 << 7); // freqcast=0, bw=500kHz, unicast=0
//// else if(dcBuff.configDisplay.op_BOX_VER)
//// cfg[5] = 0xC0; // 泽耀模块:【1 1 000 0 00】定点-ON推挽输出唤醒FEC-OFF20dbm100mW
else
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(&huart3, cfg, 6);
stop_seconds = rf_get_seconds() + 2;
while(rf_get_seconds() < stop_seconds)
{
if(huart3.Instance->ISR & USART_ISR_RXNE)
{
c = huart3.Instance->RDR;
printf("%c", c);
if(last_c == 'O' && c == 'K')
{
// 设置状态:以第一次检测的结果为准
if(first)
RF_initStatus = 1;
break;
}
last_c = c;
}
}
first = 0;
// 进入工作模式模式0
RF_MOD_MD1_0();
RF_MOD_MD0_0();
delay_ms(50);
// while(!RF_READY());
// 将串口更改为115200bps
LL_USART_Disable(huart3.Instance);
RF_Uart_Open(115200ul);
NVIC_EnableIRQ(USART3_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_Init()
{
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
// RF MD0, MD1
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Pin = LL_GPIO_PIN_12|LL_GPIO_PIN_13;
LL_GPIO_Init(GPIOD, &GPIO_InitStruct);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
/**USART3 GPIO Configuration
PD8 ------> USART3_TX
PD9 ------> USART3_RX
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_8|LL_GPIO_PIN_9;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
LL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
void RF_UnInit()
{
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
// 反初始化串口
LL_USART_DeInit(USART3);
// 恢复引脚
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
GPIO_InitStruct.Pin = LL_GPIO_PIN_8|LL_GPIO_PIN_9|LL_GPIO_PIN_12|LL_GPIO_PIN_13;
LL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
void RF_Open()
{
// 用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_MatchBuff, sizeof(rf_charge_match_t), 2, 0, (uint32_t) RF_MatchBuff_Data);
RF_Uart_Open(9600);
}
void rf_pack_lng_lora_data()
{
memset(&RF_LNG_LORA_Send_Frame, 0, sizeof(RF_LNG_LORA_Send_Frame));
// psn
sprintf(RF_LNG_LORA_Send_Frame.tank_psn, "20%02d%02d%02d%02d%03d",
dcBuff.configBottle.PSN[0], dcBuff.configBottle.PSN[1], dcBuff.configBottle.PSN[2],
dcBuff.configBottle.PSN[3], (dcBuff.configBottle.PSN[4] << 8) | dcBuff.configBottle.PSN[5]);
// send_mod
RF_LNG_LORA_Send_Frame.send_mod = (RF_LNG_LORA_State == 2 ? 0x5A : 0);
// status
if(dcBuff.sampleData.staDPress.notConnect)
RF_LNG_LORA_Send_Frame.level_conn = 1;
if(dcBuff.sampleData.staExtTempr[0].notConnect)
RF_LNG_LORA_Send_Frame.tempr_conn = 1;
if(dcBuff.sampleData.staPress.notConnect)
RF_LNG_LORA_Send_Frame.press_conn = 1;
if(dcBuff.sampleData.vacuum[0].staVacuum == VACUUM_STATUS_COMM_FAULT)
RF_LNG_LORA_Send_Frame.vacuu_conn = 1;
if(dcBuff.sampleData.staDPress.underFlow || dcBuff.sampleData.staDPress.overFlow)
RF_LNG_LORA_Send_Frame.level_fault = 1;
if(dcBuff.sampleData.staExtTempr[0].underFlow || dcBuff.sampleData.staExtTempr[0].overFlow)
RF_LNG_LORA_Send_Frame.tempr_fault = 1;
if(dcBuff.sampleData.staPress.underFlow || dcBuff.sampleData.staPress.overFlow)
RF_LNG_LORA_Send_Frame.press_fault = 1;
if(dcBuff.sampleData.vacuum[0].staVacuum != VACUUM_STATUS_COMM_FAULT && (dcBuff.sampleData.vacuum[0].vacuum <= 0.00999999 || dcBuff.sampleData.vacuum[0].vacuum > 99.99999999))
RF_LNG_LORA_Send_Frame.vacuu_fault = 1;
// liquid_level、volume、volumePct
if(RF_LNG_LORA_Send_Frame.level_conn || RF_LNG_LORA_Send_Frame.level_fault)
{
RF_LNG_LORA_Send_Frame.liquid_level = 0;
RF_LNG_LORA_Send_Frame.volume = 0;
RF_LNG_LORA_Send_Frame.volumePct = 0;
}
else
{
RF_LNG_LORA_Send_Frame.liquid_level = KPa2mmH2O(dcBuff.sampleData.diff);
RF_LNG_LORA_Send_Frame.volume = dcBuff.sampleData.volume;
RF_LNG_LORA_Send_Frame.volumePct = dcBuff.sampleData.volumePct;
}
// temperature
if(RF_LNG_LORA_Send_Frame.tempr_conn || RF_LNG_LORA_Send_Frame.tempr_fault)
RF_LNG_LORA_Send_Frame.temp = 0;
else
RF_LNG_LORA_Send_Frame.temp = dcBuff.sampleData.extTempr[0];
// press
if(RF_LNG_LORA_Send_Frame.press_conn || RF_LNG_LORA_Send_Frame.press_fault)
RF_LNG_LORA_Send_Frame.pressure = 0;
else
RF_LNG_LORA_Send_Frame.pressure = dcBuff.sampleData.pressure * 0.001;
// vacuum
if(RF_LNG_LORA_Send_Frame.vacuu_conn || RF_LNG_LORA_Send_Frame.vacuu_fault)
RF_LNG_LORA_Send_Frame.vacuum = 0;
else
RF_LNG_LORA_Send_Frame.vacuum = dcBuff.sampleData.vacuum[0].vacuum;
}
void LNG_LORA_Task(void *p_arg)
{
uint32_t seconds = 0;
uint32_t sendSeconds = 0;
uint8_t last_state = 0;
uint32_t resetSeconds = rf_get_seconds() + 300;
while(1)
{
osDelay(500);
// 获取当前时间
seconds = rf_get_seconds();
if(RF_LNG_LORA_State == 1)
{
// 只应答一次
RF_LNG_LORA_State = 0;
// 随机延时14秒以内升级发送的时候还要随机延时0.8~1s总共在15秒以内
osDelay((rand() % 29) * (250 + rand() % 251));
rf_pack_lng_lora_data();
rf_uart_send_lng_lora(&RF_LNG_LORA_Send_Frame);
}
else if(RF_LNG_LORA_State == 2)
{
if(RF_LNG_LORA_State != last_state)
sendSeconds = seconds;
if(seconds >= sendSeconds)
{
// 下次发送的时间
sendSeconds = seconds + 5;
rf_pack_lng_lora_data();
rf_uart_send_lng_lora(&RF_LNG_LORA_Send_Frame);
}
}
else // 如果LORA处于不发送状态且持续5分钟则重启LORA模块
{
if(RF_LNG_LORA_State != last_state)
resetSeconds = seconds + 300;
if(seconds >= resetSeconds)
{
// 下次重启的时间
resetSeconds = seconds + 300;
RF_PowerOff();
RF_PowerOn();
}
}
last_state = RF_LNG_LORA_State;
}
}