STM32_WGY/User/uart_dtu.c

650 lines
18 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_dtu.c
* Version : V1.00
* Programmer(s) : Qian Xianghong
*********************************************************************************************************
*/
#include "includes.h"
#include "drv_dtu.h"
#include "drv_gps.h"
// 初始唤醒次数(快速发送)
#define INITIAL_TRAN_COUNT 6
// 绝对值
#define abs(x) ((x) < 0 ? -(x) : (x))
// GPS上报数据的时间戳年基数为2010
#define GPS_BASE_YEAR 2010
// Boot-loader地址在线升级以后重启运行
#define LDROM_BASE 0x100000ul // 1M
// GPRS串口接收的循环缓冲
#define DTU_TASKM_DATA_COUNT 200
loopbuff_t DTU_TaskM;
uint8_t DTU_TaskM_Data[sizeof(uint8_t) * (DTU_TASKM_DATA_COUNT + 1)] = {0};
// 维护平台连接计时
volatile uint32_t DTU_ldmsTime = 0;
// 最近一条上传数据的采集时间
volatile uint32_t DTU_dataTime = 0;
// 发送成功时间
volatile uint32_t DTU_succTime = 0;
// 这个缓冲区比较大不放在stack里面
char DTU_gpsData[2][DTU_GPSDATA_SIZE] = {0}; // 扩展内存
char DTU_recvBuff[DTU_RECVBUFF_SIZE] = {0}; // 扩展内存
// 一次请求升级包数据大小
#define UPGRADE_DATA_LEN 1024
// DTU_Task任务和服务器之间的收发缓冲
#define TASK_SENDBUFF_SIZE 400
uint8_t Task_sendBuff[TASK_SENDBUFF_SIZE] = {0}; // 扩展内存
#define TASK_RECVBUFF_SIZE (UPGRADE_DATA_LEN + 32)
uint8_t Task_recvBuff[TASK_RECVBUFF_SIZE] = {0}; // 扩展内存
// 信号量,用于通知执行任务
volatile uint8_t DTU_semGPS = 0;
volatile uint8_t DTU_semGPRS = 0;
volatile uint8_t DTU_semSync = 0;
// 用于发送到服务器的数据结构
// 和蓝牙的相应命令一致
#pragma pack(push, 1)
typedef struct
{
uint16_t mark;
unsigned ver : 7;
unsigned trans : 1;
unsigned reserved: 8;
uint16_t len;
union
{
uint16_t cmd;
struct
{
uint8_t err;
uint8_t cmd_L;
};
};
} bluetooth_recv_t;
typedef bluetooth_recv_t bluetooth_send_t;
typedef struct
{
unsigned staEPress3 : 2;
unsigned staETempr1 : 2;
unsigned staETempr2 : 2;
unsigned staETempr3 : 2;
unsigned staDiff : 2;
unsigned staPress : 2;
unsigned staEPress1 : 2;
unsigned staEPress2 : 2;
} bluetooth_sensor_t;
typedef struct
{
unsigned maskStamp : 1;
unsigned maskEPress1 : 1;
unsigned maskEPress2 : 1;
unsigned maskEPress3 : 1;
unsigned : 1;
unsigned maskLowPower : 1;
unsigned maskAbnormal : 1;
unsigned maskCharging : 1;
unsigned maskRssi : 1;
unsigned maskGPS : 1;
unsigned maskETempr1 : 1;
unsigned maskETempr2 : 1;
unsigned maskETempr3 : 1;
unsigned maskBattery : 1;
unsigned maskFlow : 1;
unsigned maskLeak : 1;
} bluetooth_mask_t;
typedef union
{
struct
{
unsigned sec : 6;
unsigned min : 6;
unsigned hour_L : 4;
unsigned hour_H : 1;
unsigned day : 5;
unsigned mon : 4;
unsigned year : 6;
};
uint32_t tm;
} bluetooth_timestamp_t;
typedef union
{
unsigned long long ll;
struct
{
unsigned long l;
unsigned long h;
};
} longlong_mask_t;
typedef struct
{
union
{
struct
{
unsigned sateCount : 5; // gps可见卫星数量
unsigned posState : 1; // gps定位状态 0-GPS未定位1-GPS已定位
unsigned carState : 1; // 车辆是否启动 0-车辆未启动1-车辆已启动)
unsigned carEvent : 1; // 车辆启动或停止事件0-启动状态未改变1-启动状态已改变)
};
uint8_t state;
};
bluetooth_timestamp_t time; // 时间戳
int32_t latitude;
int32_t longitude;
uint16_t speed;
} gps_data_t;
typedef struct // size = 158
{
uint32_t sample_time; // 采集时间:自启动以来经过的秒数
data_dtu_t dtuData; // size = 36
data_sample_t sampleData; // size = 118
} gprs_data_t;
// 双向通讯的数据结构
typedef struct // size = 120
{
uint16_t serverVer; // 服务器参数版本号
uint8_t type; // 储罐类型
uint32_t diameter; // 内径
uint32_t len; // 圆柱体长度
uint32_t lenExtra; // 直边封头长度
uint32_t reserved_1[3];
uint8_t source; // 液源
uint32_t density; // 各液源的比重kg/m3)
uint16_t fullPct; // 满液位百分比
uint16_t priPct; // 关键液位百分比
uint16_t orderPct; // 订货液位百分比
uint16_t emptyPct; // 空液位百分比
uint32_t planMount; // 每日计划用量
uint32_t predictMount; // 每日预测用量
uint16_t warnVolt; // 电压报警低点: 10mV
uint16_t warnVoltH; // 电压报警高点: 10mV
uint16_t warnPress; // 压力报警低点: KPa
uint16_t warnPressH; // 压力报警高点: KPa
uint32_t intervalTrans; // 数据上报周期
uint32_t intervalSample; // 数据采集周期
uint32_t intervalGPSTrans; // 位置上报周期
uint32_t intervalGPS; // 位置采集周期
union
{
struct
{
char gpsServer[20]; // 远传服务器 (只上传,不修改)
int16_t gpsPort; // 远传端口 (只上传,不修改)
char pwd1[6]; // 储罐参数修改密码
};
struct
{
char gprsServer[26]; // praxair修改数据服务器地址
int16_t gprsPort; // praxair: 修改数据服务器端口
};
};
uint32_t options; // 参数开关
union
{
uint8_t reserved_2[12];
struct
{
uint16_t floorLevel; // praxair: 液量报警下限
uint16_t span; // praxair: 液量变化报警门限
uint16_t spanPeriod; // praxair: 液量变化报警时间
unsigned floorLevelAssigned : 1; // praxair: 参数中floorLevel是否有效
unsigned spanAssigned : 1; // praxair: 参数中span是否有效
unsigned spanPeriodAssigned : 1; // praxair: 参数中spanPeriod是否有效
unsigned intervalTransAssigned : 1; // praxair: 参数中intervalTrans是否有效
unsigned gprsServerAssigned : 1; // praxair: 参数中数据服务器地址是否有效
unsigned gprsPortAssigned : 1; // praxair: 参数中数据服务器端口是否有效
unsigned : 2;
};
};
uint32_t ts; // 参数时间戳
} param_data_t;
// 升级进度信息存放在FRAM中可断点续传
typedef struct
{
uint16_t check; // 标志固定为0x55AA
uint32_t ver; // 固件版本
int32_t fileSize; // 固件总字节数
uint16_t fileCrc; // 固件总的crc
int32_t offset; // 本次固件偏移量
int32_t len; // 本次数据长度
uint16_t crc; // 本记录的crc
} upgrade_info_t;
// 升级包接收记录
typedef struct
{
uint32_t ver; // 固件版本
int32_t fileSize; // 固件总字节数
uint16_t fileCrc; // 固件总的crc
int32_t offset; // 本次固件偏移量
int32_t len; // 本次数据长度
uint8_t data[UPGRADE_DATA_LEN]; // 本次数据
uint16_t crc; // 本次数据的crc
} upgrade_frame_t;
// 升级文件头
typedef struct // size=12
{
unsigned short check; // 数据有效标志, 0x55AA表示有效
unsigned upgrade_request : 1; // 升级请求标志0-无升级1-有升级
unsigned upgrade_result : 3; // 升级失败标志0-成功1-失败,其余保留
unsigned encrypt_flag : 2; // 加密标志, 0-无加密,其余保留
unsigned compress_flag : 2; // 压缩标志, 0-无压缩1-有压缩,其余保留
unsigned rerseved1 : 8; // 保留必须为0xFF
unsigned long upgrade_length; // 升级文件长度
unsigned rerseved2 : 8; // 保留必须为0xFF
unsigned rerseved3 : 8; // 保留必须为0xFF
unsigned short crc; // 对前面内容的crc校验
} TUpgradeHeader;
// 阿里云密钥记录
typedef struct // size=76
{
unsigned short check; // 数据有效标志, 0x55AA表示有效
uint8_t PSN[6]; // 获取密钥所用的PSN如果PSN改变需重新获取
char product[12]; // 产品代码
char device[21]; // 默认为cPSN
char secret[33]; // 设备密钥
unsigned short crc; // 对前面内容的crc校验
} TAliyunSecret;
#define ALIYUN_SECRET_SIZE (66)
#pragma pack(pop)
// 阿里云密钥
TAliyunSecret aliyunSecret = {0};
// 升级包记录
upgrade_info_t upInfo = {0};
// GPS循环缓冲记录
loopbuff_t gpsBuff = {0};
// 存放GPRS记录的循环缓冲
loopbuff_t gprsBuff = {0};
loopbuff_t bd_gprsBuff = {0};
// GPRS记录读写缓冲
gprs_data_t gprsRWBuf;
/**
* @brief ?????,?????????
*/
struct reportInf_t {
uint32_t lastTime; //!< ?????????
uint32_t nextTime; //!< ??????????
uint32_t redoTime; //!< ????????????
uint8_t redoNum; //!< ????????????
uint8_t fiRedo; //!< ????,??????????????,(??)????????
};
/**
* @brief reportInf:????,????????
*/
// 是否GPS定位
volatile uint8_t GPS_Locate = 1;
volatile uint8_t GPS_Located = 0;
volatile uint32_t GPS_waitTick = 0;
volatile uint8_t GPS_Waiting = 0;
// GPS定位超时
const uint8_t DTU_tmrLocate = 90;
// GPS发送数据
volatile uint32_t GPS_tranTick = 0;
// 保存上次数据的时间
bluetooth_timestamp_t GPS_LastTime = {0};
// 是否发送GPRS数据
uint8_t GPRS_Send_Task = 0;
uint32_t GPRS_Send_Time = 0;
// 是否保存GPRS数据
uint8_t GPRS_Save_Task = 0;
uint32_t GPRS_Save_Time = 0;
/////////////////////////////////////////
uint32_t Fre[5] = {498000000, 499000000, 509770000, 868000000, 915000000};
uint8_t RXbuffer[60];
#define TASK_SENDBUFF_SIZE 400
//uint8_t Task_sendBuff[TASK_SENDBUFF_SIZE] = {0}; // 扩展内存
uint8_t TXbuffer[10] = {0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA};
tSX127xError set_lora_freq(int freq)
{
G_LoRaConfig.LoRa_Freq = Fre[freq]; //????470MHz
G_LoRaConfig.BandWidth = BW500KHZ; //BW = 125KHz BW125KHZ
G_LoRaConfig.SpreadingFactor = SF12; //SF = 9
G_LoRaConfig.CodingRate = CR_4_5; //CR = 4/6
G_LoRaConfig.PowerCfig = 15; //19±1dBm
G_LoRaConfig.MaxPowerOn = true; //最大功率开启
G_LoRaConfig.CRCON = true; //CRC校验开启<E5BC80>
G_LoRaConfig.ExplicitHeaderOn = true; //Header开启
G_LoRaConfig.PayloadLength = 42; //数据包长度
return SX127X_Lora_init(G_LoRaConfig.LoRa_Freq);
}
////////////////////////////////////////////////////////////////////////////////////////
//-->add
#define LORA_COMMU_IDLE_STATE 0
#define LORA_COMMU_START_STATE 1
#define LORA_COMMU_SEND_STATE 2
#define LORA_COMMU_REC_STATE 3
#define LORA_COMMU_FAIL_STATE 4
#define LORA_COMMU_SUCC_STATE 5
uint16_t g_lora_commu_state=LORA_COMMU_IDLE_STATE;
////////////////////////////////////
uint8_t pack_lora_send_data(gprs_data_t *pGprs, uint32_t totalSeconds)
{
int i=0;
uint16_t val = 0;
Task_sendBuff[i++]=0x01;
Int2ByteS(Task_sendBuff, i, /*htons*/(dcBuff.sampleData.diff));
i +=2 ;
Int2ByteS(Task_sendBuff, i, /*htons*/(dcBuff.dtuData.batVoltage));
i += 2;
// 版本号
Task_sendBuff[i++] = dcBuff.powerInfo.hardVer.minor;
Task_sendBuff[i++] = dcBuff.powerInfo.softVer.minor;
Int2ByteS(Task_sendBuff, i, /*htons*/(dcBuff.configData.intervalSample));
i += 2;
Int2ByteL(Task_sendBuff, i, /*htonl*/(dcBuff.configData.intervalTrans));
i += 4;
Int2ByteS(Task_sendBuff, i, /*htons*/(dcBuff.configBottle.fullPct)); //、apex需要改为压强
i += 2;
Int2ByteS(Task_sendBuff, i, /*htons*/(dcBuff.configBottle.emptyPct));
i += 2;
// // 压力报警上限
// Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnPressH));
// i += 2;
// // 压力报警下限
// Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnPress));
// i += 2;
// // 温度报警上限
// Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnTemprH));
// i += 2;
// // 温度报警下限
// Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnTempr));
// i += 2;
return i;
}
uint8_t parse_load(uint8_t *buf)
{
#pragma pack(push, 1)
typedef struct
{
uint8_t type;
uint32_t flag;
uint16_t intervalSample; // 数据采集周期
uint32_t intervalTrans; // 数据上报周期
uint16_t fullPct;
uint16_t emptyPct;
// uint16_t warnPressH;
// uint16_t warnPress;
// int16_t warnTemprH;
// int16_t warnTempr;
} parse_data_t;
#pragma pack(pop)
parse_data_t *buf2;
buf2 = (parse_data_t*) buf;
if(buf2->flag == 0) return 0;
dcBuff.configData.intervalSample=buf2->intervalSample;
dcBuff.configData.intervalTrans=buf2->intervalTrans;
dcBuff.configBottle.fullPct=buf2->fullPct;
dcBuff.configBottle.emptyPct=buf2->emptyPct;
//dcBuff.configBottle.warnPressH=buf2->warnPressH;
//dcBuff.configBottle.warnPress=buf2->warnPress;
//dcBuff.configBottle.warnTemprH=buf2->warnTemprH;
//dcBuff.configBottle.warnTempr=buf2->warnTempr;
dcBuff.configBottle.updateFlag = 1; // 参数更新标志
// 保存
Config_SaveConfig();
// uint8_t ret = 0;
// S_RTC_TIME_DATA_T sRTC;
//
// if(strncmp(message, "$GPGGA", 6) == 0 || strncmp(message, "$GNGGA", 6) == 0)
// {
//// printf("\n%s\n", message);
// *bufIdx = 1 - *bufIdx;
// }
// else if(strncmp(message, "$GPRMC", 6) == 0 || strncmp(message, "$GNRMC", 6) == 0)
// {
// printf("\n%s\n", message);
// // 获取当前时间
// RTC_GetDateAndTime(&sRTC);
// // 记录GPS上次数据时间
// DTU_gpsTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
// sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
// parse_gga(DTU_gpsData[1 - *bufIdx], sample);
// ret = parse_rmc(message, sample);
// if(!ret)
// sample->posState = 0;
// }
return 1;
}
static uint8_t first_send=1;
// 任务主体发送运行数据和GPS数据读取网络信号强度等
void DTU_Task(void *p_arg)
{
bluetooth_send_t *pSend = (bluetooth_send_t *) Task_sendBuff;
bluetooth_send_t *pRecv = (bluetooth_send_t *) Task_recvBuff;
uint16_t i, j, k;
uint8_t gpsCount, gpsDone;
uint16_t gpsInterval;
uint32_t totalSeconds;
uint32_t relativeTime;
S_RTC_TIME_DATA_T sRTC;
gprs_data_t *pGprs;
uint8_t try_count;
uint16_t recvLen;
uint8_t upgrade;
uint8_t ackUpgrade;
uint8_t downloadParam;
uint8_t ackParam;
uint8_t downloadConfig;
uint8_t ackConfig;
uint8_t reset = 0;
param_data_t *pParam;
TUpgradeHeader upHeader;
upgrade_frame_t *pFrame;
gps_data_t gps;
uint16_t nextPtr;
uint8_t write_count;
uint8_t rf_fail_count = 0;
uint8_t semSync, semGPRS, semGPS;
uint32_t tick;
// 清除数据
memset(&dcBuff.dtuData, 0, sizeof(dcBuff.dtuData));
// 读取其它板子的配置数据
// 启动定时器
GPS_tranTick = GetDelayTick(dcBuff.configData.intervalGPSTrans * 1000);
// 上电运行一次任务
DTU_semSync = 1;
DTU_semGPRS = 1;
DTU_semGPS = 1;
while(1)
{
// 获取当前时间
RTC_GetDateAndTime(&sRTC);
printf("\n%04d-%02d-%02d %02d:%02d:%02d\n", sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
// 计算自上次gps定位以来的时间
totalSeconds = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
// 刚开始运行的时候,回退到刚启动的时间(忽略系统初始化时间)
if(totalSeconds < 10)
totalSeconds = 0;
// 读取信号量
semSync = DTU_semSync;
DTU_semSync = 0;
semGPRS = DTU_semGPRS;
DTU_semGPRS = 0;
semGPS = DTU_semGPS;
DTU_semGPS = 0;
printf("\n\n\n------semGPRS=%d-------semSync=%d------\n\n\n",semGPRS,semSync);
if(semGPRS || semSync)
{
GPRS_Send_Task = 0;
printf("\n*** dcBuff.sampleData.warnning = %d ***\n", dcBuff.sampleData.warnning);
if(dcBuff.sampleData.warnning||first_send)
{
GPRS_Send_Task = 1;
dcBuff.sampleData.warnning = 0;
first_send=0;
}
// 判断是否发送周期
// 发送间隔最小值
if(totalSeconds + 3 >= GPRS_Send_Time + (dcBuff.configData.intervalTrans > 300 ? 300 : dcBuff.configData.intervalTrans))
{
GPRS_Send_Task = 1;
}
if(((SYS_RSTSTS & 0x13) && !(SYS_RSTSTS & 0x04) && // 上电或手动复位, 非看门狗复位
totalSeconds < INITIAL_TRAN_COUNT * (dcBuff.configData.intervalSample > 300 ? 300 : dcBuff.configData.intervalSample))
|| totalSeconds + 3 >= GPRS_Send_Time + dcBuff.configData.intervalTrans )
{
// 发送间隔最小值
if(totalSeconds + 3 >= GPRS_Send_Time + (dcBuff.configData.intervalTrans > 300 ? 300 : dcBuff.configData.intervalTrans))
GPRS_Send_Task = 1;
}
if(Wakeup_GetWorkMode() == WORK_MODE_NORMAL && GPRS_Send_Task)
{
if(set_lora_freq(0) != NORMAL) //
{
printf("\nlora init err\n");
}
// 先清除信号量
GPRS_semSampled = 0;
// 采集数据
Sample_Notify();
tick = GetDelayTick(3000);
while(!GPRS_semSampled && !IsTickOut(tick))
{
}
i = pack_lora_send_data(pGprs, totalSeconds);
try_count = 3;
while(try_count--)
{
j = rf_app_send_data(i, Task_sendBuff);
osDelay(5000);
if(g_lora_commu_state==LORA_COMMU_SUCC_STATE)
{
// 记录发送成功的时间
RTC_GetDateAndTime(&sRTC);
DTU_succTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
printf("\ncommu success\n");
break;
}
else
{
printf("\ncommu fail\n");
}
}
GPRS_Send_Time = totalSeconds;
osDelay(1000);
}
}
printf("\nlora to SleepMode\n");
SX127X_SleepMode();
// DIO0_DisableInterrupt();
// printf("\nlora spi deinit\n");
Lora_spi_di_deinit();
osDelay(2000);
printf("\nlora to powerdown\n");
Wakeup_Powerdown();
//continue;
}
}