初始版本

This commit is contained in:
2026-04-23 13:56:52 +08:00
parent 6c611f1fa3
commit 23ab9ca0f9
252 changed files with 136838 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
#ifndef __ADS1231__
#define __ADS1231__
#include "bsp.h"
void ADS1231_Open(void);
void ADS1231_SpeedSet(void);
bool ADS1231_Read(uint32_t *r_data, uint8_t channel);
void ADS1231_HighSpeedSet(void);
void ADS1231_LowSpeedSet(void);
#endif
@@ -0,0 +1,107 @@
#ifndef __CAT_ONE_TASK_H
#define __CAT_ONE_TASK_H
#include "main.h"
#include "Public.h"
#define CAT_ONE_REV_TIMEOUT_MAX (10 * 60 * 1000)
#define CAT_ONE_REV_LEN_MAX 512
#define CAT_ONE_POW_ON() CAT1_POW_ON()
#define CAT_ONE_POW_OFF() CAT1_POW_OFF()
#define CAT_ONE_LINKA_GET() CAT1_LINKA_GET()
#define CAT_ONE_LINKB_GET() CAT1_LINKB_GET()
#define CAT_ONE_DELAY_1MS(X)
typedef enum {
CAT_ONE_AT_NULL,
CAT_ONE_AT, //开机检测
CAT_ONE_ATE0, //关回显
CAT_ONE_CPIN, //识卡
CAT_ONE_IMEI,
CAT_ONE_LCCID, //读卡
CAT_ONE_CEREG, //查询注册状态
CAT_ONE_CGPADDR, //查询IP地址
CAT_ONE_CSQ, //查询信号强度
CAT_ONE_LDNSGIP, //域名解析
CAT_ONE_LBS, //获取基站定位信息
CAT_ONE_LIPOPEN, //设置TCP服务器地址和端口
CAT_ONE_LIPSEND, //发送数据
CAT_ONE_LTPCLOSE, //断开连接
CAT_ONE_LBSPARA,
CAT_ONE_CCLK, //获取时间
CAT_ONE_AT_CMD_END,
}CatOneATCMD_m;
typedef enum {
CAT_ONE_IDEL,
CAT_ONE_INIT,
CAT_ONE_TCP_CONN,
CAT_ONE_WAIT_CONN,
CAT_ONE_SEND_DATA,
CAT_ONE_WAIT_SEND,
CAT_ONE_REV_DATA,
CAT_ONE_REG_SVR,
CAT_ONE_WAIT_REV,
CAT_ONE_RESET,
CAT_ONE_OFF,
CAT_ONE_CLOSE_TCP,
}CatOneStatus_m;
typedef enum {
CAT_ONE_RET_NULL,
CAT_ONE_RET_OK,
CAT_ONE_RET_ERR,
CAT_ONE_RET_TIMEOUT,
}CatOneRetStatus_m;
typedef enum {
CAT_ONE_CMD_MODE,
CAT_ONE_PT_MODE,
}CatOneMode_m;
typedef enum {
CAT_ONE_2G,
CAT_ONE_ATE,
}CatOneNetType_m;
typedef struct {
CatOneStatus_m Status;
CatOneStatus_m NextStatus;
CatOneRetStatus_m ATCmdRet;
uint32_t CatOne1mSDelayCnt;
uint32_t ResetDelayCnt;
uint32_t RegisterDelayCnt;
uint8_t AtCmdResendCnt;
uint8_t AtCmdIdx;
CatOneATCMD_m AtCmd;
bool RxFlag;
uint16_t CSQ;
char IMEI[20];
char SIM[32];
CatOneNetType_m NetType;
bool TcpConnFlag;
bool LBSFlag;
int Longitude;
int Latitude;
char CatOneSendBuff[1024];
GateWayPara GateWay;
DataRevCallBack CatOneRevCallBack;
}CatOne_t, *pCatOne_t;
CatOneRetStatus_m CatOneSend(uint8_t *sData, uint16_t sLen);
void CatOneStart(void);
void CatOneStop(void);
void CatOneReset(void);
void Cat1DBGOnOff(bool OnOff);
void CatOneGetLocationInfo(int *Longitude, int *Latitude);
void CatOneGetIMEIAndSIM(char *Imei, char *Sim);
bool CatOneGetStatus(void);
bool CatOneEthSendQueue(uint8_t *sData, uint16_t sLen);
void CatOne_Eth_Thread_Entry(void *parameter);
void EthRxOverhandler(void);
void CatReadImeiOrSim(char *Imei, char *Sim);
#endif
@@ -0,0 +1,7 @@
#ifndef __DEBUG_CMD_H
#define __DEBUG_CMD_H
void Debug_Thread_Entry(void *parameter);
void DebugRxOverhandler(void);
void Debug_Printf(char *format, ...);
#endif
@@ -0,0 +1,7 @@
#ifndef __EPT__
#define __EPT__
void Encrypt_Code(unsigned char *data, unsigned char *EPT_data);
void Decrypt_Code(unsigned char *EPT_data,unsigned char *DPT_data);
#endif
@@ -0,0 +1,11 @@
#ifndef __LORA_TASK_H
#define __LORA_TASK_H
#include "bsp.h"
#include "sx127x.h"
void Lora_Thread_Entry(void *parameter);
int LoraRevCallBack(GateWayPara GateWay, uint8_t *rData, uint16_t rLen);
void LoraInit(void);
#endif
+283
View File
@@ -0,0 +1,283 @@
#ifndef __PUBLIC_H
#define __PUBLIC_H
#include "bsp.h"
#define LORA_LOWPOWER //LORA低功耗设备,采用主动上报方式
#define SENSOR_DATA_LEN_MAX 50
#define SENSOR_NUM_MAX 16
#define COMMUNIT_NUM_MAX 32
#define REGISTER_INTERVAL_MAX (2 * 60)
#define COMMUNIT_READ_SENSOR_INTERVAL_MAX (1 * 60)
#define LORA_ERR_RESET_DLY_MAX (10 * 60) //LORA接收超时复位延时,单位秒
#define CAT1_ERR_RESET_DLY_MAX (60 * 60) //CAT1接收超时复位延时,单位秒
typedef struct GateWay_t GateWayPara_t, *GateWayPara;
typedef void (*SendData)(uint8_t *sData, uint16_t sLen);
typedef int (*DataRevCallBack)(GateWayPara GateWay, uint8_t *rData, uint16_t rLen);
typedef int (*DataRevResCallBack)(GateWayPara GateWay, uint8_t *rData, uint16_t rLen, SendData Response);
typedef int (*SendDataOrg)(uint8_t *sData);
typedef enum {
DEBUG_CH_DBG,
DEBUG_CH_RS485_1,
DEBUG_CH_RS485_2,
}DebugChannel_m;
typedef enum {
DEV_TYPE_BROADCAST,
DEV_TYPE_INC_COMMUNIT = 0x8001,
DEV_TYPE_EXT_COMMUNIT,
DEV_TYPE_ICE_SENSOR,
DEV_TYPE_CRACK_SENSOR,
DEV_TYPE_PRESSURE_SENSOR,
DEV_TYPE_RAIN_SENSOR,
}DevType_m;
typedef enum {
CATONE_COMM,
ETH_COMM,
}CommType_m;
typedef enum {
LORA_COMM,
RS485CH1_COMM,
RS485CH2_COMM
}SensorComm_m;
typedef enum {
COMM_UNIT_CMD_REG,
COMM_UNIT_CMD_CAIL,
COMM_UNIT_CMD_READ,
COMM_UNIT_CMD_SET_SENSOR_COLL_TIME = 5,
COMM_UNIT_CMD_TIME_SYNC,
COMM_UNIT_CMD_CONT_LASER = 8,//激光独有指令
COMM_UNIT_CMD_END,
}CommUnitCmd_m;
typedef enum {
NET_COMM_CMD_REG,
NET_COMM_CMD_CAIL,
NET_COMM_CMD_UPDATE,
NET_COMM_CMD_READ_GW_INFO,
//NET_COMM_CMD_READ_UNIT_INFO,
NET_COMM_CMD_GW_PARA_CONFIG,
NET_COMM_CMD_HIS_DATA,
NET_COMM_CMD_ADD_UNIT,
NET_COMM_CMD_LP_DEV_CONFIG,
NET_COMM_CMD_ALARM,
NET_COMM_CMD_CONT_LASER,//激光独有指令
NET_COMM_CMD_END,
}NetCommCmd_m;
typedef enum {
SENSOR_TYPE_NULL, //0x0000 空设备
FORCE_6D, //0x0001 六维应力
OSMOTIC_PRESSURE, //0x0002 渗透压
ELASTIC_WAVEGUIDE, //0x0003 弹性波导
DIELECTRIC_MASS, //0x0004 介电质普
VIBRATE_SENSOR, //0x0005 微振动传感器
CONT_DEFOR_3D, //0x0006 三维连续变形
COMM_UNIT, //0x0007 通讯单元
FORCE_3D, //0x0008 三维应力
LASER_TRACING, //0x0009 激光示踪
WATER_LEVEL, //0x000A 水位计
_0x000B, //0x000B 保留
_0x000C, //0x000C 保留
MULTI_PARAMETER_FUSION, //0x000D 多参数融合
CRACK_DETECTION, //0x000E 裂缝仪
_0x000F, //0x000F 保留
ATTITUDE_MONITOR, //0x0010 姿态检测
LASER_DISPLACE, //0x0011 激光位移
REBAR_STRESS, //0x0012 钢筋应力
ANCHOR_ROD_STRESS, //0x0013 锚杆轴力
SURFACE_STRESS, //0x0014 表面应力
PRESSURE, //0x0015 压力
MICROWAVE_DISPLACE, //0x0016 微波位移
}SensorType_m;
typedef struct {//主设备固定包头
uint8_t BatLevel; //电池电量
int8_t RSSI; //信号强度
int8_t Nsr; //信噪比
}__attribute__ ((packed))MasterDev_T,*MasterDevDp;
typedef struct {
int16_t AccX;
int16_t AccY;
int16_t AccZ;
int32_t Strain1;
int32_t Strain2;
int32_t Strain3;
int32_t Strain4;
int32_t Strain5;
int32_t Strain6;
}__attribute__((packed))Force6D_T;
typedef struct {
MasterDev_T MasterDev;
int16_t PitchAngle; //俯仰角偏斜 (范围±900)单位0.1°
int16_t RollAngle; //横滚角偏斜 (范围±900)单位0.1°
int16_t YawAngle; //偏航角偏斜 (范围0~3600)单位0.1°
}__attribute__((packed))LaserTracingType_t;
typedef struct {
uint8_t CommDevAddr[6]; //通讯单元地址
uint16_t CollectInterval; //采集时间间隔
uint16_t ReportInterval; //上报时间间隔
uint8_t ERInterval; //紧急上报时间间隔
uint8_t ERTime; //紧急上报时长
}__attribute__((packed))SvrDownLPDevConfigPara_t;
typedef struct {
int Distance;
}__attribute__((packed))LaserDistanceSensorType_t;
typedef struct {
uint8_t AlarmType;
uint8_t AlarmState;
uint8_t AlarmPara;
}__attribute__((packed))GateWayAlarmType_t;
#define LW_DEV_COLLECT_INTERVAL_MAX 300//默认300秒
#define LW_DEV_REPORT_INTERVAL_MAX 20//20分钟
#define LW_DEV_ER_INTERVAL_MAX 2//2分钟
#define LW_DEV_ER_TIME_MAX 20//20分钟
typedef struct {
uint16_t CollectInterval; //采集时间间隔
uint16_t ReportInterval; //上报时间间隔
uint8_t ERInterval; //紧急上报时间间隔
uint8_t ERTime; //紧急上报时长
uint32_t TimeStamp; //时间戳
}__attribute__((packed))LPDevConfigPara_t;
typedef struct {
bool RegFlag;
bool RevNewDataFlag;
bool CommStatus; //通讯状态,1-在线,0-离线
bool CailFlag; //校准标志(低功耗)
bool TimeSyncFlag; //时间同步标志(低功耗)
bool ContLaser; //激光控制标志(低功耗)
bool LaserOnOff; //激光状态(低功耗)
uint32_t CommErrCnt;
uint8_t MasterMac[6];
uint8_t Mac[SENSOR_NUM_MAX][6];//第一位是主设备,后面全是子设备
uint8_t BatLevel;
int8_t RSSI; //信号强度
int8_t Nsr; //信噪比
uint16_t CUType;
uint8_t SensorN;
uint16_t SensorType[SENSOR_NUM_MAX];
//低功耗设备配置信息
bool ConfigFlag; //配置标志,为1表示有新配置,应答低功耗设备时需要附带发送
uint16_t CollectInterval; //采集时间间隔
uint16_t ReportInterval; //上报时间间隔
uint8_t ERInterval; //紧急上报时间间隔
uint8_t ERTime; //紧急上报时长
}CommUnitPara_t, *CommUnitPara;
typedef struct {
uint8_t Data[SENSOR_NUM_MAX][SENSOR_DATA_LEN_MAX];
}CommUnitData_t, *CommUnitData;
typedef struct {
CommUnitPara_t Para;
}CommUnit_t, *CommUnit;
typedef struct {
bool Enable; //串口使能
bool CommUnitEnable; //通讯单元使能,开启(使用内部通讯单元功能,直接和传感器通讯),关闭(直接和RS485类型的通讯单元通讯)
bool QuerySensorFlag; //查询传感器标志
bool UpgradeEnable;//升级功能使能
uint8_t Power;
uint32_t BaudRate;
SendData RS485Send;
CommUnit_t CUData;
}RS485Para_t, *RS485Para;
typedef struct {
uint8_t Header;
uint8_t GWMac[6];
uint8_t DevMac[6];
uint8_t Cmd;
//uint16_t DevType;
uint16_t PayloadLen;
}__attribute__((packed))CommUnitFrameHeader_t, *CommUnitFrameHeader;
typedef struct {
uint8_t Header;
uint8_t GWMac[6];
//uint8_t SvrMac[6];
uint8_t Cmd;
uint8_t BatLevel;
uint32_t Timestamp;
uint8_t PacketNum;
uint8_t PacketIdx;
uint16_t PayloadLen;
}__attribute__((packed))NetCommFrameHeader_t, *NetCommFrameHeader;
typedef struct {
bool OnOff;
SendData LoraSend;
uint8_t ucChannel;
int8_t ucPower;
uint8_t SignalBw;
uint8_t SpreadFactor;
uint8_t ErrorCoding;
uint8_t RegPreamble;
uint32_t FreqCent;
}LoraPara_t, *pLoraPara;
typedef struct {
uint32_t SavFlag; //存储标志
CommType_m Comm; //网关通讯方式
uint8_t GwMac[6]; //网关mac
char SvrAddr[4]; //服务器地址
uint32_t SvrPort; //服务器端口
uint32_t CommUnitReadInterval; //通讯单元读取时间间隔,单位S
CommUnitPara_t CommUnitArray[COMMUNIT_NUM_MAX]; //注册的通讯单元信息
RS485Para_t Rs485Ch1; //RS485通道1配置
RS485Para_t Rs485Ch2; //RS485通道2配置
uint8_t DebugChannel; //调试通道
LoraPara_t Lora; //Lora配置
bool OutageFlag; //断电报警标志
uint16_t crc16;
}__attribute__((packed))GWConfigPara_t, *GWConfigPara;
struct GateWay_t{
bool TimeSyncFlag; //时间同步标志
bool SvrRegFlag; //服务器注册标志
uint8_t SvrMac[6]; //服务器mac
GWConfigPara_t ConfigPara; //配置参数
CommUnitData_t CUDataArray[COMMUNIT_NUM_MAX];
uint8_t Battery; //电池电量
uint16_t UploadInterval; //上传间隔
uint32_t HistoryNum; //历史数据数量
DataRevCallBack SvrRevCallBack; //接收到服务器回调
DataRevResCallBack CommUnitRevCallBack; //通讯单元接收回调
rt_mq_t NetSendData_MQ; //网络发送数据队列,第一个字节用于存储消息长度, 第二字节存储命令字,后为数据
rt_mq_t LoraRev_MQ; //Lora接收消息队列,第一个字节用于存储消息长度,后为数据
rt_mutex_t UartRevMutex;
uint8_t BatteryReadDlyCnt; //读取电压延时,单位秒,防止4G发送拉低电池电压,造成断电误报
};
int Cat1EthRevCallBack(GateWayPara GateWay, uint8_t *rData, uint16_t rLen);
uint16_t CRC_Modbus(uint16_t wBase, __IO uint8_t *para, uint16_t length);
uint8_t AsciiToHex(char *ASCData, uint8_t *HexData, uint8_t sLen);
void HexToAscii(uint8_t *HexData, char *ASCData, uint8_t sLen);
int NetCommOrgData(GateWayPara GateWay, uint8_t *MegData, uint8_t *OutData);
int CommUnitAnalyze(GateWayPara GateWay, uint8_t *rData, uint16_t rLen, SendData Response);
void DebugAnalyze(GateWayPara GateWay, uint8_t *rData, uint16_t rLen);
void CommUnitCmdSend(GateWayPara GateWay, uint8_t *CommUnitMac, CommUnitCmd_m Cmd, uint8_t *Payload, uint16_t PayloadLen, SendData Send);
int CheckCommUnitReg(GateWayPara GateWay, uint8_t *CommUnitMac);
int CommUintOrgData(GateWayPara GateWay, CommUnitPara CUPara, CommUnitData CUData, uint8_t *sData);
void DebugDisplaySensorData(int SensorIdx, uint16_t SensorType, uint8_t *SensorData);
#endif
@@ -0,0 +1,14 @@
#ifndef __PUBLIC_TYPES_H
#define __PUBLIC_TYPES_H
#include <stdint.h>
#include <stdbool.h>
typedef void (*ReadPara)(pSFBTPara rPara);
typedef void (*SavPara)(pSFBTPara wPara);
typedef void (*UartSend)(uint8_t *sData, int sLen);
typedef void (*DataRevCallBack)(uint8_t *rData, uint8_t rLen);
typedef int (*SendDataOrg)(uint8_t *sData);
#endif
@@ -0,0 +1,70 @@
#ifndef __RS485_TASK_H
#define __RS485_TASK_H
#include "bsp.h"
#include "Public.h"
#define RS485_RX_BUFF_LEN_MAX 64
typedef struct {
SensorComm_m Com;
uint16_t SensorType;
}SensorTypes_t;
typedef enum {
RS485_OUT_VOLTAGE_OV,
RS485_OUT_VOLTAGE_5V,
RS485_OUT_VOLTAGE_12V,
}RS485Vol_m;
typedef struct {
uint8_t Header;
uint8_t SlvAddr;
uint8_t Cmd;
//uint16_t DevType;
uint8_t PayloadLen;
}__attribute__((packed))FrameHeader_t, *FrameHeader;
typedef enum {
RS485_SENSOR_CMD_NULL,
RS485_SENSOR_CMD_CAIL,
RS485_SENSOR_CMD_READ,
RS485_SENSOR_CMD_QUERY,
RS485_SENSOR_CMD_SET_ADDR,
RS485_SENSOR_CMD_SET_INV_TIME,
RS485_SENSOR_CMD_TIME_SYNC,
RS485_SENSOR_CMD_END,
}RS485SensorCmd_m;
//´«¸ÐÆ÷Êý¾Ý·¢ËͽṹÌå
typedef struct {
bool SendFlag;
uint8_t SensorCnt;
uint8_t SensorErrCnt[SENSOR_NUM_MAX];
uint8_t ReadSensorCnt;
int32_t ReadSensorInterval;
RS485SensorCmd_m Cmd;
uint8_t SensorAddr;
uint16_t SensorType;
uint8_t CmdParaLen;
uint8_t *CmdPara;
uint8_t RS485RxBuff[RS485_RX_BUFF_LEN_MAX];
uint8_t RS485RxLen;
uint8_t RS485TimeOutCnt;
uint32_t RS485CommUnitReadTimeDelay;
uint8_t SendUnitCommIdx;
rt_sem_t RS485Rev_Sem;
bool InitOverFlag;
CommUnitData_t SensorData;
}SensorCommPara_t, *SensorCommPara;
void RS485CmdSend(GateWayPara GateWay, uint8_t CommUintAddr, SensorCommPara SensorComm);
void RS485Ch1_Thread_Entry(void *parameter);
void RS485Ch2_Thread_Entry(void *parameter);
void RS485RxOverhandler(void);
extern SensorCommPara_t SComm1Para;
extern SensorCommPara_t SComm2Para;
#endif
@@ -0,0 +1,10 @@
#ifndef _APP_COMM_H_
#define _APP_COMM_H_
#include "rtthread.h"
#define BSP_LOG(format,...) do { \
rt_kprintf(format, ##__VA_ARGS__); \
} while (0)
#endif
+414
View File
@@ -0,0 +1,414 @@
#ifndef __BSP_H
#define __BSP_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "hc32_ddl.h"
#include "rtthread.h"
#include "ff.h"
//#define USE_BOOTLOADER
//#define FLASH_SECTOR_SIZE 0x2000ul
//#define FLASH_BASE ((uint32_t)0x00000000)
//#define FLASH_SIZE (64u * FLASH_SECTOR_SIZE)
//#define SRAM_BASE ((uint32_t)0x1FFF8000)
//#define RAM_SIZE 0x2F000ul
//#define BOOT_SIZE (4 * FLASH_SECTOR_SIZE)
//#define APP_ADDRESS (FLASH_BASE + BOOT_SIZE)
//#define BOOT_PARA_ADDRESS (FLASH_SIZE - FLASH_SECTOR_SIZE)
//#define BOOT_PARA_SIZE (FLASH_SECTOR_SIZE)
/* flash rom map 存储分区*/
//boot 16k
#define FLASH_BASE ((uint32_t)0x00000000)
#define FLASH_SECTOR_SIZE 0x2000ul
#define FLASH_BOOT_BASE (FLASH_BASE)
#define FLASH_BOOT_SIZE (4*FLASH_SECTOR_SIZE)
//app
#define FLASH_APP_BASE (FLASH_BOOT_BASE+ FLASH_BOOT_SIZE)
#define FLASH_APP_SIZE (58*FLASH_SECTOR_SIZE)
//boot info
#define FLASH_BINFO_BASE (FLASH_APP_BASE + FLASH_APP_SIZE)
#define FLASH_BINFO_SIZE (1*FLASH_SECTOR_SIZE)
//user config
#define FLASH_CFG_BASE (FLASH_BINFO_BASE + FLASH_BINFO_SIZE)
#define FLASH_CFG_SIZE (1*FLASH_SECTOR_SIZE)
#define FLASH_CFG_MAGIC (0xa5)
#define APP_START_FLAG 0x55AA5A5A
#define APP_UPDATE_FLAG 0xA5A5AA55
#define WATCH_DOG 1
#define DEBUG 1
#define USE_SD_CARD 0
#define RTC_IRQn Int001_IRQn
#define LORA_DIO0_IRQn Int005_IRQn
#define DBGUART_IRQn Int006_IRQn
#define DBGUART_EI_IRQn Int007_IRQn
#define RS485CH1_UART_IRQn Int008_IRQn
#define RS485CH1_UART_EI_IRQn Int009_IRQn
#define RS485CH2_UART_IRQn Int010_IRQn
#define RS485CH2_UART_EI_IRQn Int011_IRQn
#define ETH_OR_CAT1_UART_IRQn Int012_IRQn
#define ETH_OR_CAT1_UART_EI_IRQn Int013_IRQn
#define DBG_RXPIN_IRQn Int002_IRQn
//DEBUG
#define DBG_USART_CH (M4_USART1)
#define DBG_USART_RX_PORT (PortA)
#define DBG_USART_RX_PIN (Pin11)
#define DBG_USART_TX_PORT (PortA)
#define DBG_USART_TX_PIN (Pin12)
#define DBG_USART_RX_FUNC (Func_Usart1_Rx)
#define DBG_USART_TX_FUNC (Func_Usart1_Tx)
#define DBG_USART_RI_NUM (INT_USART1_RI)
#define DBG_USART_EI_NUM (INT_USART1_EI)
#define DBG_USART_TI_NUM (INT_USART1_TI)
#define DBG_USART_TCI_NUM (INT_USART1_TCI)
#define DBG_FCG1_PERIPH (PWC_FCG1_PERIPH_USART1)
//RS485 Ch1
#define RS485_CH1_USART_CH (M4_USART2)
#define RS485_CH1_USART_RX_PORT (PortA)
#define RS485_CH1_USART_RX_PIN (Pin10)
#define RS485_CH1_USART_TX_PORT (PortA)
#define RS485_CH1_USART_TX_PIN (Pin08)
#define RS485_CH1_USART_RX_FUNC (Func_Usart2_Rx)
#define RS485_CH1_USART_TX_FUNC (Func_Usart2_Tx)
#define RS485_CH1_USART_RI_NUM (INT_USART2_RI)
#define RS485_CH1_USART_EI_NUM (INT_USART2_EI)
#define RS485_CH1_USART_TI_NUM (INT_USART2_TI)
#define RS485_CH1_USART_TCI_NUM (INT_USART2_TCI)
#define RS485_CH1_FCG1_PERIPH (PWC_FCG1_PERIPH_USART2)
#define RS485_CH1_CTRL_PORT (PortC)
#define RS485_CH1_CTRL_PIN (Pin07)
#define RS485_CH1_TX() PORT_SetBits(RS485_CH1_CTRL_PORT, RS485_CH1_CTRL_PIN)
#define RS485_CH1_RX() PORT_ResetBits(RS485_CH1_CTRL_PORT, RS485_CH1_CTRL_PIN)
#define RS485_CH1_POW_PORT (PortC)
#define RS485_CH1_POW_PIN (Pin10)
#define RS485_CH1_POW_ON() PORT_SetBits(RS485_CH1_POW_PORT, RS485_CH1_POW_PIN)
#define RS485_CH1_POW_OFF() PORT_ResetBits(RS485_CH1_POW_PORT, RS485_CH1_POW_PIN)
//#define RS485_CH1_VOL_CTRL_PORT (PortA)
//#define RS485_CH1_VOL_CTRL_PIN (Pin15)
//#define RS485_CH1_VOL_5V() PORT_SetBits(RS485_CH1_VOL_CTRL_PORT, RS485_CH1_VOL_CTRL_PIN)
//#define RS485_CH1_VOL_12V() PORT_ResetBits(RS485_CH1_VOL_CTRL_PORT, RS485_CH1_VOL_CTRL_PIN)
//RS485 Ch2
#define RS485_CH2_USART_CH (M4_USART3)
#define RS485_CH2_USART_RX_PORT (PortB)
#define RS485_CH2_USART_RX_PIN (Pin14)
#define RS485_CH2_USART_TX_PORT (PortB)
#define RS485_CH2_USART_TX_PIN (Pin12)
#define RS485_CH2_USART_RX_FUNC (Func_Usart3_Rx)
#define RS485_CH2_USART_TX_FUNC (Func_Usart3_Tx)
#define RS485_CH2_USART_RI_NUM (INT_USART3_RI)
#define RS485_CH2_USART_EI_NUM (INT_USART3_EI)
#define RS485_CH2_USART_TI_NUM (INT_USART3_TI)
#define RS485_CH2_USART_TCI_NUM (INT_USART3_TCI)
#define RS485_CH2_FCG1_PERIPH (PWC_FCG1_PERIPH_USART3)
#define RS485_CH2_CTRL_PORT (PortB)
#define RS485_CH2_CTRL_PIN (Pin13)
#define RS485_CH2_TX() PORT_SetBits(RS485_CH2_CTRL_PORT, RS485_CH2_CTRL_PIN)
#define RS485_CH2_RX() PORT_ResetBits(RS485_CH2_CTRL_PORT, RS485_CH2_CTRL_PIN)
#define RS485_CH2_POW_PORT (PortB)
#define RS485_CH2_POW_PIN (Pin02)
#define RS485_CH2_POW_ON() PORT_SetBits(RS485_CH2_POW_PORT, RS485_CH2_POW_PIN)
#define RS485_CH2_POW_OFF() PORT_ResetBits(RS485_CH2_POW_PORT, RS485_CH2_POW_PIN)
//#define RS485_CH2_VOL_CTRL_PORT (PortB)
//#define RS485_CH2_VOL_CTRL_PIN (Pin10)
//#define RS485_CH2_VOL_5V() PORT_SetBits(RS485_CH2_VOL_CTRL_PORT, RS485_CH2_VOL_CTRL_PIN)
//#define RS485_CH2_VOL_12V() PORT_ResetBits(RS485_CH2_VOL_CTRL_PORT, RS485_CH2_VOL_CTRL_PIN)
//ETH OR CAT1
#define ETH_OR_CAT1_USART_CH (M4_USART4)
#define ETH_OR_CAT1_USART_RX_PORT (PortB)
#define ETH_OR_CAT1_USART_RX_PIN (Pin09)
#define ETH_OR_CAT1_USART_TX_PORT (PortC)
#define ETH_OR_CAT1_USART_TX_PIN (Pin13)
#define ETH_OR_CAT1_USART_RX_FUNC (Func_Usart4_Rx)
#define ETH_OR_CAT1_USART_TX_FUNC (Func_Usart4_Tx)
#define ETH_OR_CAT1_USART_RI_NUM (INT_USART4_RI)
#define ETH_OR_CAT1_USART_EI_NUM (INT_USART4_EI)
#define ETH_OR_CAT1_USART_TI_NUM (INT_USART4_TI)
#define ETH_OR_CAT1_USART_TCI_NUM (INT_USART4_TCI)
#define ETH_OR_CAT1_FCG1_PERIPH (PWC_FCG1_PERIPH_USART4)
#define ETH_OR_CAT1_CTRL_PORT (PortB)
#define ETH_OR_CAT1_CTRL_PIN (Pin08)
#define ETH_ON() PORT_SetBits(ETH_OR_CAT1_CTRL_PORT, ETH_OR_CAT1_CTRL_PIN)
#define CAT1_ON() PORT_ResetBits(ETH_OR_CAT1_CTRL_PORT, ETH_OR_CAT1_CTRL_PIN)
//#define ETH_OR_CAT1_TX_CTRL_PORT (PortH)
//#define ETH_OR_CAT1_TX_CTRL_PIN (Pin02)
//#define ETH_ON() { PORT_SetBits(ETH_OR_CAT1_CTRL_PORT, ETH_OR_CAT1_CTRL_PIN); PORT_SetBits(ETH_OR_CAT1_TX_CTRL_PORT, ETH_OR_CAT1_TX_CTRL_PIN); }
//#define CAT1_ON() { PORT_ResetBits(ETH_OR_CAT1_CTRL_PORT, ETH_OR_CAT1_CTRL_PIN); PORT_ResetBits(ETH_OR_CAT1_TX_CTRL_PORT, ETH_OR_CAT1_TX_CTRL_PIN);}
#define CAT1_PWR_KEY_PORT (PortA)
#define CAT1_PWR_KEY_PIN (Pin03)
#define CAT1_PWR_KEY_CLR() PORT_SetBits(CAT1_PWR_KEY_PORT, CAT1_PWR_KEY_PIN)
#define CAT1_PWR_KEY_SET() PORT_ResetBits(CAT1_PWR_KEY_PORT, CAT1_PWR_KEY_PIN)
#define CAT1_RESET_PORT (PortA)
#define CAT1_RESET_PIN (Pin00)
#define CAT1_RESET_CLR() PORT_SetBits(CAT1_RESET_PORT, CAT1_RESET_PIN)
#define CAT1_RESET_SET() PORT_ResetBits(CAT1_RESET_PORT, CAT1_RESET_PIN)
//#define CAT1_POW_PORT (PortA)
//#define CAT1_POW_PIN (Pin00)
//#define CAT1_POW_ON() PORT_SetBits(CAT1_POW_PORT, CAT1_POW_PIN)
//#define CAT1_POW_OFF() PORT_ResetBits(CAT1_POW_PORT, CAT1_POW_PIN)
#define ETH_RESET_PORT (PortB)
#define ETH_RESET_PIN (Pin05)
#define ETH_RESET_SET() PORT_SetBits(ETH_RESET_PORT, ETH_RESET_PIN)
#define ETH_RESET_CLR() PORT_ResetBits(ETH_RESET_PORT, ETH_RESET_PIN)
#define ETH_DEF_PORT (PortB)
#define ETH_DEF_PIN (Pin07)
#define ETH_DEF_SET() PORT_SetBits(ETH_DEF_PORT, ETH_DEF_PIN)
#define ETH_DEF_CLR() PORT_ResetBits(ETH_DEF_PORT, ETH_DEF_PIN)
#define ETH_LINK_PORT (PortB)
#define ETH_LINK_PIN (Pin06)
#define ETH_LINK_GET() PORT_GetBit(ETH_LINK_PORT, ETH_LINK_PIN)
/* SPI_MOSI Port/Pin definition */
#define SPI_NSS_PORT (PortC)
#define SPI_NSS_PIN (Pin00)
#define SPI_NSS_FUNC (Func_Spi1_Nss0)
#define SPI_NSS_SET() PORT_SetBits(SPI_NSS_PORT, SPI_NSS_PIN)
#define SPI_NSS_CLR() PORT_ResetBits(SPI_NSS_PORT, SPI_NSS_PIN)
/* SPI_SCK Port/Pin definition */
#define SPI_SCK_PORT (PortC)
#define SPI_SCK_PIN (Pin02)
#define SPI_SCK_FUNC (Func_Spi1_Sck)
/* SPI_MOSI Port/Pin definition */
#define SPI_MOSI_PORT (PortC)
#define SPI_MOSI_PIN (Pin03)
#define SPI_MOSI_FUNC (Func_Spi1_Mosi)
/* SPI_MISO Port/Pin definition */
#define SPI_MISO_PORT (PortC)
#define SPI_MISO_PIN (Pin01)
#define SPI_MISO_FUNC (Func_Spi1_Miso)
/* SPI unit and clock definition */
#define SPI_UNIT (M4_SPI1)
#define SPI_UNIT_CLOCK (PWC_FCG1_PERIPH_SPI1)
//LORA IO
/* SPI_SCK Port/Pin definition */
#define SPI2_SCK_PORT (PortC)
#define SPI2_SCK_PIN (Pin04)
#define SPI2_SCK_FUNC (Func_Spi2_Sck)
/* SPI_MOSI Port/Pin definition */
#define SPI2_MOSI_PORT (PortA)
#define SPI2_MOSI_PIN (Pin07)
#define SPI2_MOSI_FUNC (Func_Spi2_Mosi)
/* SPI_MISO Port/Pin definition */
#define SPI2_MISO_PORT (PortA)
#define SPI2_MISO_PIN (Pin06)
#define SPI2_MISO_FUNC (Func_Spi2_Miso)
/* SPI_MOSI Port/Pin definition */
#define SPI2_NSS_PORT (PortC)
#define SPI2_NSS_PIN (Pin05)
#define SPI2_NSS_FUNC (Func_Spi2_Nss0)
#define SPI2_NSS_SET() PORT_SetBits(SPI2_NSS_PORT, SPI2_NSS_PIN)
#define SPI2_NSS_CLR() PORT_ResetBits(SPI2_NSS_PORT, SPI2_NSS_PIN)
/* SPI unit and clock definition */
#define SPI2_UNIT (M4_SPI2)
#define SPI2_UNIT_CLOCK (PWC_FCG1_PERIPH_SPI2)
#define LORA_DIO_PORT (PortA)
#define LORA_DIO_PIN (Pin04)
#define LORA_DIO_GET() PORT_GetBit(LORA_DIO_PORT, LORA_DIO_PIN)
#define LORA_DIO_EXIT_CH (ExtiCh04)
#define LORA_DIO_EXIT_SRC (INT_PORT_EIRQ4)
#define LORA_RESET_PORT (PortA)
#define LORA_RESET_PIN (Pin05)
#define LORA_RESET_SET() PORT_SetBits(LORA_RESET_PORT, LORA_RESET_PIN)
#define LORA_RESET_CLR() PORT_ResetBits(LORA_RESET_PORT, LORA_RESET_PIN)
#define LORA_RXEN_PORT (PortB)
#define LORA_RXEN_PIN (Pin00)
#define LORA_RXEN_SET() PORT_SetBits(LORA_RXEN_PORT, LORA_RXEN_PIN)
#define LORA_RXEN_CLR() PORT_ResetBits(LORA_RXEN_PORT, LORA_RXEN_PIN)
#define LORA_TXEN_PORT (PortB)
#define LORA_TXEN_PIN (Pin01)
#define LORA_TXEN_SET() PORT_SetBits(LORA_TXEN_PORT, LORA_TXEN_PIN)
#define LORA_TXEN_CLR() PORT_ResetBits(LORA_TXEN_PORT, LORA_TXEN_PIN)
#define LORA_RX_LED_PORT (PortB)
#define LORA_RX_LED_PIN (Pin03)
#define LORA_RX_LED_SET() PORT_SetBits(LORA_RX_LED_PORT, LORA_RX_LED_PIN)
#define LORA_RX_LED_CLR() PORT_ResetBits(LORA_RX_LED_PORT, LORA_RX_LED_PIN)
#define LORA_RX_TOGGLE() PORT_Toggle(LORA_RX_LED_PORT, LORA_RX_LED_PIN)
#define LORA_POW_PORT (PortC)
#define LORA_POW_PIN (Pin06)
#define LORA_POW_ON() PORT_SetBits(LORA_POW_PORT, LORA_POW_PIN)
#define LORA_POW_OFF() PORT_ResetBits(LORA_POW_PORT, LORA_POW_PIN)
#define POWER_LED_PORT (PortB)
#define POWER_LED_PIN (Pin04)
#define POWER_LED_ON() PORT_SetBits(POWER_LED_PORT, POWER_LED_PIN)
#define POWER_LED_OFF() PORT_ResetBits(POWER_LED_PORT, POWER_LED_PIN)
#define POWER_TOGGLE() PORT_Toggle(POWER_LED_PORT, POWER_LED_PIN)
#if USE_SD_CARD
#include "sd_card.h"
/* SDIOC Port/Pin definition */
#define SDIOC_CD_PORT (PortA)
#define SDIOC_CD_PIN (Pin10)
#define SDIOC_CK_PORT (PortC)
#define SDIOC_CK_PIN (Pin12)
#define SDIOC_CMD_PORT (PortD)
#define SDIOC_CMD_PIN (Pin02)
#define SDIOC_D0_PORT (PortC)
#define SDIOC_D0_PIN (Pin08)
#define SDIOC_D1_PORT (PortC)
#define SDIOC_D1_PIN (Pin09)
#define SDIOC_D2_PORT (PortA)
#define SDIOC_D2_PIN (Pin09)
#define SDIOC_D3_PORT (PortC)
#define SDIOC_D3_PIN (Pin11)
/* SD sector && count */
#define SD_SECTOR_START (0u)
#define SD_SECTOR_COUNT (4u)
/* SDIOC unit */
#define SDIOC_UNIT (M4_SDIOC1)
en_result_t SdioInit(void);
bool SDCardErase(uint32_t u32BlkStartAddr, uint32_t u32BlkEndAddr);
bool SDCardReadBlocks(uint32_t u32BlkStartAddr, uint32_t u32BlkEndAddr, uint8_t *ReadBuff);
bool SDCardWriteBlocks(uint32_t u32BlkStartAddr, uint32_t u32BlkEndAddr, uint8_t *WriteBuff);
#endif
#define BAT_COLL_ADC_CH (ADC1_CH1)
//帧头结构体
typedef struct {
uint8_t Header;
uint8_t SlvAddr;
uint8_t Cmd;
uint8_t PayloadLen;
}update_protocol_hd_t;
//主机下发升级请求载荷结构体
typedef struct {
uint16_t PackageNum;
uint32_t AppSize;
uint32_t AppCrc32;
}__attribute__ ((packed))update_protocol_req_t;
//从机请求下发结构体
typedef struct {
uint16_t PackageIndex;
uint32_t PackageNum;
}__attribute__ ((packed))update_protocol_get_t;
//主机应答下发数据结构体
typedef struct {
uint16_t PackageIndex;
uint16_t PackageNum;
uint8_t DataLen;
}__attribute__ ((packed))update_protocol_rsp_t;
typedef struct {
uint32_t AppFlag;
uint32_t DevType;
uint32_t DevAddr;
uint32_t UpdateFlag;
uint32_t PackageNum;
uint32_t AppSize;
uint32_t Crc32Check;
}boot_para_t;
void BSP_Init(void);
void DbgUart_Config(uint32_t BaudRate);
void DebugUartSend(uint8_t *sData, uint16_t sLen);
void DbgRxIrqCallback(uint8_t rData);
void RS485Ch1_Config(uint32_t BaudRate);
void RS485Ch1UartSend(uint8_t *sData, uint16_t sLen);
void RS485Ch1RxIrqCallback(uint8_t rData);
void RS485Ch2_Config(uint32_t BaudRate);
void RS485Ch2UartSend(uint8_t *sData, uint16_t sLen);
void RS485Ch2RxIrqCallback(uint8_t rData);
void EthOrCat1UartSend(uint8_t *sData, uint16_t sLen);
void EthOrCat1RxIrqCallback(uint8_t rData);
void LoraTxRxIrqCallback(void);
uint16_t Spi1SendReceive(uint16_t sData);
uint16_t Spi2SendReceive(uint16_t sData);
//void ReadAdcValue(uint16_t *ADValue);
uint16_t GetADCBuffPoint(void);
void ADC_Start(void) ;
void FeedDog(void);
void Error_Handler(void);
int TimeTs(void);
void TimeShow(uint32_t dwStamp);
void TimeSync(time_t ts) ;
void TimeGet(struct tm *cTime);
void TimeSync2(uint8_t Year, uint8_t Month, uint8_t Day, uint8_t Hour, uint8_t Min, uint8_t Sec);
void FlashWrite(uint32_t Addr, uint32_t *wData, uint8_t wLen);
void FlashRead(uint32_t Addr,uint32_t *rData, uint8_t rLen);
void dev_boot_read_param(boot_para_t *pParam);
int dev_boot_write_param(boot_para_t Param);
//extern stc_sd_handle_t stcSdhandle;
#endif
@@ -0,0 +1,164 @@
/*******************************************************************************
* Copyright (C) 2020, Huada Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by HDSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*/
/******************************************************************************/
/** \file ddl_config.h
**
** A detailed description is available at
** @link DdlConfigGroup Ddl Config description @endlink
**
** - 2021-04-16 CDT First version for Device Driver Library config.
**
******************************************************************************/
#ifndef __DDL_CONFIG_H__
#define __DDL_CONFIG_H__
/*******************************************************************************
* Include files
******************************************************************************/
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/**
*******************************************************************************
** \defgroup DdlConfigGroup Device Driver Library config(DDLCONFIG)
**
******************************************************************************/
//@{
/*******************************************************************************
* Global type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
/*! Chip module on-off define */
#define DDL_ON (1u)
#define DDL_OFF (0u)
/**
*******************************************************************************
** \brief This is the list of modules to be used in the device driver library
** Select the modules you need to use to DDL_ON.
**
** \note DDL_ICG_ENABLE must be turned on(DDL_ON) to ensure that the chip works
** properly.
**
** \note DDL_UTILITY_ENABLE must be turned on(DDL_ON) if using Device Driver
** Library.
**
** \note DDL_PRINT_ENABLE must be turned on(DDL_ON) if using printf function.
******************************************************************************/
#ifndef BOOT_ENABLE
#define DDL_ICG_ENABLE (DDL_ON)
#endif
//#define DDL_ICG_ENABLE (DDL_ON)
#define DDL_UTILITY_ENABLE (DDL_ON)
#define DDL_PRINT_ENABLE (DDL_OFF)
#define DDL_ADC_ENABLE (DDL_ON)
#define DDL_AES_ENABLE (DDL_OFF)
#define DDL_CAN_ENABLE (DDL_OFF)
#define DDL_CLK_ENABLE (DDL_ON)
#define DDL_CMP_ENABLE (DDL_OFF)
#define DDL_CRC_ENABLE (DDL_OFF)
#define DDL_DCU_ENABLE (DDL_OFF)
#define DDL_DMAC_ENABLE (DDL_ON)
#define DDL_EFM_ENABLE (DDL_ON)
#define DDL_EMB_ENABLE (DDL_OFF)
#define DDL_EVENT_PORT_ENABLE (DDL_OFF)
#define DDL_EXINT_NMI_SWI_ENABLE (DDL_ON)
#define DDL_GPIO_ENABLE (DDL_ON)
#define DDL_HASH_ENABLE (DDL_OFF)
#define DDL_I2C_ENABLE (DDL_OFF)
#define DDL_I2S_ENABLE (DDL_OFF)
#define DDL_INTERRUPTS_ENABLE (DDL_ON)
#define DDL_INTERRUPTS_SHARE_ENABLE (DDL_OFF)
#define DDL_KEYSCAN_ENABLE (DDL_OFF)
#define DDL_MPU_ENABLE (DDL_OFF)
#define DDL_OTS_ENABLE (DDL_OFF)
#define DDL_PWC_ENABLE (DDL_ON)
#define DDL_QSPI_ENABLE (DDL_OFF)
#define DDL_RMU_ENABLE (DDL_OFF)
#define DDL_RTC_ENABLE (DDL_ON)
#define DDL_SDIOC_ENABLE (DDL_ON)
#define DDL_SPI_ENABLE (DDL_ON)
#define DDL_SRAM_ENABLE (DDL_ON)
#define DDL_SWDT_ENABLE (DDL_ON)
#define DDL_TIMER0_ENABLE (DDL_OFF)
#define DDL_TIMER4_CNT_ENABLE (DDL_OFF)
#define DDL_TIMER4_EMB_ENABLE (DDL_OFF)
#define DDL_TIMER4_OCO_ENABLE (DDL_OFF)
#define DDL_TIMER4_PWM_ENABLE (DDL_OFF)
#define DDL_TIMER4_SEVT_ENABLE (DDL_OFF)
#define DDL_TIMER6_ENABLE (DDL_OFF)
#define DDL_TIMERA_ENABLE (DDL_OFF)
#define DDL_TRNG_ENABLE (DDL_OFF)
#define DDL_USART_ENABLE (DDL_ON)
#define DDL_USBFS_ENABLE (DDL_OFF)
#define DDL_WDT_ENABLE (DDL_OFF)
/*! Midware module on-off define */
#define MW_ON (1u)
#define MW_OFF (0u)
/**
*******************************************************************************
** \brief This is the list of Midware modules to use
** Select the modules you need to use to MW_ON.
******************************************************************************/
#define MW_FS_ENABLE (MW_OFF)
#define MW_SD_CARD_ENABLE (MW_OFF)
#define MW_W25QXX_ENABLE (MW_OFF)
#define MW_WM8731_ENABLE (MW_OFF)
/* BSP on-off define */
#define BSP_ON (1u)
#define BSP_OFF (0u)
/**
* @brief The following is a list of currently supported BSP boards.
*/
#define BSP_EV_HC32F460_LQFP100_V1 (1u)
#define BSP_EV_HC32F460_LQFP100_V2 (2u)
/**
* @brief The macro BSP_EV_HC32F460 is used to specify the BSP board currently
* in use.
* The value should be set to one of the list of currently supported BSP boards.
* @note If there is no supported BSP board or the BSP function is not used,
* the value needs to be set to BSP_EV_HC32F460.
*/
#define BSP_EV_HC32F460 (BSP_EV_HC32F460_LQFP100_V2)
/*******************************************************************************
* Global variable definitions ('extern')
******************************************************************************/
/*******************************************************************************
* Global function prototypes (definition in C source)
******************************************************************************/
//@} // DdlConfigGroup
#ifdef __cplusplus
}
#endif
#endif /* __DDL_CONFIG_H__ */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/
+16
View File
@@ -0,0 +1,16 @@
#ifndef __MAIN__H
#define __MAIN__H
#include "bsp.h"
#include "Public.h"
#include "DebugCmd.h"
#define SOFTWARE_VERSION 12
#define HARDWARE_VERSION 12
#define MAC_ADDR_TYPE 1//0为测试服务器
extern bool MainDispEn;
#define MAIN_DBG_LOG(...) { if(MainDispEn) Debug_Printf(__VA_ARGS__);}
void MainDBGOnOff(bool OnOff);
#endif
@@ -0,0 +1,96 @@
#ifndef _PROTOCOL_H_
#define _PROTOCOL_H_
#include "stdint.h"
#define PROTOCOL_BUF_MAX (512)
#define PROTOCOL_HEAD (0x527A)
#define PROTOCOL_FRAME_HEAD_SIZE (7) // 最小帧长:头(2) + 地址(2) + 命令(1) + 长度(2) + CRC(2)
#define PROTOCOL_FRAME_MIN_SIZE (9) // 最小帧长:头(2) + 地址(2) + 命令(1) + 长度(2) + CRC(2)
// 错误码定义
typedef enum {
PROTOCOL_SUCCESS = 0,
PROTOCOL_ERR_INVALID_PARAM,
PROTOCOL_ERR_BUFFER_OVERFLOW,
PROTOCOL_ERR_CRC
}protocol_err_t;
typedef enum
{
PROTOCOL_CMD_GET_AD =0x81,
PROTOCOL_CMD_GET_TP =0x82,
PROTOCOL_CMD_SET_ID =0x83,
PROTOCOL_CMD_GET_ID =0x84,
PROTOCOL_CMD_SET_TP_OFFSET =0x8A,
PROTOCOL_CMD_GET_TP_OFFSET =0x8B,
PROTOCOL_CMD_RESET_CHANNEL =0x8F,
}protocol_cmd_t;
typedef struct __attribute__((packed)) {
uint8_t status;
float value;
} ch_data_t;
typedef struct __attribute__((packed)) {
uint8_t dev_status;
ch_data_t channels[8];
uint8_t reserved[7];
} ad_datas_t;
typedef struct __attribute__((packed)) {
uint8_t dev_status;
ch_data_t channels[8];
uint8_t reserved[7];
} tp_datas_t;
typedef struct __attribute__((packed)) {
uint8_t id;
uint8_t reserved[3];
} id_data_t;
typedef struct __attribute__((packed)) {
uint8_t id;
union{
uint8_t bytes[4];
float value;
}prams;
} offset_set_data_t,offset_get_data_t;
typedef struct __attribute__((packed)) {
uint8_t id;
}offset_get_param_t;
extern int protocol_pack_frame(
uint16_t slave_addr,
uint8_t command,const
uint8_t *payload,
uint16_t payload_len,
uint8_t *buffer,uint16_t buffer_size,
uint16_t *packed_len
);
extern int protocol_unpack_frame(
const uint8_t *frame,
uint16_t frame_len,
uint16_t *slave_addr,
uint8_t *command,
uint8_t *payload,
uint16_t *payload_len);
#endif
@@ -0,0 +1,45 @@
/******************************************************************************
* @brief 环形缓冲区管理(参考linux/kfifo)
*
* Copyright (c) 2016~2020, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2016-05-30 Morro 初版完成
******************************************************************************/
#ifndef _RING_BUF_H_
#define _RING_BUF_H_
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*环形缓冲区管理器*/
typedef struct {
unsigned char *buf; /*环形缓冲区 */
unsigned int size; /*环形缓冲区 */
unsigned int front; /*头指针 */
unsigned int rear; /*尾指针 */
}ring_buf_t;
bool ring_buf_init(ring_buf_t *r,unsigned char *buf,unsigned int size);
void ring_buf_clr(ring_buf_t *r);
int ring_buf_len(ring_buf_t *r);
int ring_buf_put(ring_buf_t *r,unsigned char *buf,unsigned int len);
int ring_buf_get(ring_buf_t *r,unsigned char *buf,unsigned int len);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,76 @@
#ifndef __SPI_FLASH_H
#define __SPI_FLASH_H
#include "bsp.h"
#define LOG_SAV_FLAG (0xAA5555AA)
#define LOG_INFO_SAV_FLAG (0xA55A)
#define SpiFlashClrNss() SPI_NSS_CLR()
#define SpiFlashSetNss() SPI_NSS_SET()
#define SPIFLASH_CMD_WRITE 0x02 /* Write to Memory instruction */
#define SPIFLASH_CMD_WRSR 0x01 /* Write Status Register instruction */
#define SPIFLASH_CMD_WREN 0x06 /* Write enable instruction */
#define SPIFLASH_CMD_READ 0x03 /* Read from Memory instruction */
#define SPIFLASH_CMD_RDSR 0x05 /* Read Status Register instruction */
#define SPIFLASH_CMD_RDID 0x9F /* Read identification */
#define SPIFLASH_CMD_SE 0x20 /* 4KSector Erase instruction */
#define SPIFLASH_CMD_BE 0xC7 /* Bulk Erase instruction */
#define SPIFLASH_WIP_FLAG 0x01 /* Write In Progress (WIP) flag */
#define SPIFLASH_DUMMY_BYTE 0xA5
#define SPIFLASH_PAGESIZE 0x100
#define SPIFLASH_SECTORSIZE 4096
#define SPIFLASH_M25P128_ID 0x202018
#define SPIFLASH_M25P64_ID 0x202017
void SpiFlashEraseChip(void);
void SpiFlashEraseSector(uint32_t SectorAddr);
void SpiFlashWriteAnyLengthData(uint8_t* wData, uint32_t wAddr, uint16_t wLen);
void SpiFlashReadAnyLengthData(uint8_t* rData, uint32_t rAddr, uint16_t rLen);
uint32_t SpiFlashReadId(void);
/* USER CODE BEGIN */
#define SPIFLASH_SIZE 16777216
#define SPIFLASH_SECTOR_NUM 4096
#define GATEWEY_PARA_SAV_ADDR 0x00
#define GATEWEY_PARA_SAV_SECTOR 0x00
#define LOG_INFO_START_SECTOR 0x01
#define LOG_SAV_START_SECTOR 0x02
//#if (LORA_MODULE == WH_LR36_L)
//#define LOG_SAV_SIZE 78
//#define LOG_SAV_NUM_SECTOR 52 //每扇区存储数量
//#else
//#define LOG_SAV_SIZE 78 //150
//#define LOG_SAV_NUM_SECTOR 52 //27 //每扇区存储数量
//#endif
#define LOG_SAV_SIZE_MAX 256
#define LOG_SAV_NUM_MAX ((SPIFLASH_SECTOR_NUM - LOG_SAV_START_SECTOR) * LOG_SAV_NUM_SECTOR)
typedef struct {
uint32_t LogSavFlag; //日志存储标志
uint32_t LogIdx; //日志序号
uint32_t LogEndAddr; //日志结束地址
uint32_t TimeStamp; //存储时间
}LogHeader_t, *LogHeader;
void SavMMC5983Calib(uint8_t *wData, uint32_t wLen);
void ReadMMC5983Calib(uint8_t *rData, uint32_t rLen);
void LogInit(void);
uint32_t ReadLogNum(void);
uint32_t ReadLastLogEndAddr(void);
uint32_t ReadFirstLogStartAddr(void);
void SavLogNum(uint32_t LogNum);
void AddLog(uint8_t *wData, uint32_t wLen);
int ReadLog(LogHeader Header, uint8_t **wData, uint32_t LogIdx);
int ReadPara(uint8_t *Para, uint32_t ParaLen);
int WritePara(uint8_t *Para, uint32_t ParaLen);
/* USER CODE END */
#endif
@@ -0,0 +1,20 @@
#ifndef _UPDATE_PROTOCOL_H_
#define _UPDATE_PROTOCOL_H_
#include "stdint.h"
#define CRC16_BASE 0xA001
typedef void (*update_send_t)(uint8_t *pBuf,uint16_t len);
void update_init(update_send_t pCbs);
int update_unpack(uint8_t* rxData, int rLen,uint8_t *cmd, uint8_t* dev_addr, void *pUser, int *pLen);
void update_send_cmd(uint8_t Cmd, uint16_t Indx, int PageNum);
#endif
+8
View File
@@ -0,0 +1,8 @@
#ifndef _UTILS_H_
#define _UTILS_H_
#include "stdint.h"
extern uint16_t modbus_crc16(uint8_t *buf, int len);
#endif
+126
View File
@@ -0,0 +1,126 @@
#include "ADS1231.h"
extern float Temperature;
void ADS1231_Open(void)
{
PDWN1_SET();
PDWN2_SET();
PDWN3_SET();
PDWN4_SET();
}
void ADS1231_HighSpeedSet(void)
{
SPEED1_SET();
SPEED2_SET();
SPEED3_SET();
SPEED4_SET();
}
void ADS1231_LowSpeedSet(void)
{
SPEED1_RESET();
SPEED2_RESET();
SPEED3_RESET();
SPEED4_RESET();
}
uint32_t GpioAGetDout(en_pin_t enPin)
{
return *(uint32_t *)((uint32_t)(&M4_PORT->PIDRA)) & (enPin);
}
uint32_t GpioBGetDout(en_pin_t enPin)
{
return *(uint32_t *)((uint32_t)(&M4_PORT->PIDRB)) & (enPin);
}
bool ADS1231_Read(uint32_t *r_data, uint8_t channel) {
uint8_t i;
uint32_t data = 0;
switch(channel) {
case 0:
if(GpioAGetDout(DRDY_DOUT1_PIN) != 0)
return false;
for(i = 0; i < 24; i++) {
SCLK1_SET();
data <<= 0x01;
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
SCLK1_RESET();
if(GpioAGetDout(DRDY_DOUT1_PIN) != 0)
data |= 0x01;
}
SCLK1_SET();
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
SCLK1_RESET();
break;
case 1:
if(GpioAGetDout(DRDY_DOUT2_PIN) != 0)
return false;
for(i = 0; i < 24; i++) {
SCLK2_SET();
data <<= 0x01;
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
SCLK2_RESET();
__NOP(); __NOP();
if(GpioAGetDout(DRDY_DOUT2_PIN) != 0)
data |= 0x01;
}
SCLK2_SET();
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
SCLK2_RESET();
break;
case 2:
if(GpioBGetDout(DRDY_DOUT3_PIN) != 0)
return false;
for(i = 0; i < 24; i++) {
SCLK3_SET();
data <<= 0x01;
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
SCLK3_RESET();
if(GpioBGetDout(DRDY_DOUT3_PIN) != 0 )
data |= 0x01;
}
SCLK3_SET();
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
SCLK3_RESET();
break;
case 3:
if(GpioBGetDout(DRDY_DOUT4_PIN) != 0 )
return false;
for(i = 0; i < 24; i++) {
SCLK4_SET();
data <<= 0x01;
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
SCLK4_RESET();
if(GpioBGetDout(DRDY_DOUT4_PIN) != 0 )
data |= 0x01;
}
SCLK4_SET();
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
SCLK4_RESET();
break;
default:
return false;
}
if(data <= 0x00ffffff) {
if(data > 0x007fffff)
*r_data = data|0xff000000;
else
*r_data = data;
}
else
return false;
return true;
}
@@ -0,0 +1,730 @@
#include "CatOneTask.h"
#include "Public.h"
#include "DebugCmd.h"
static rt_sem_t CatOneRev_Sem = RT_NULL;
static rt_sem_t CatOneIRQ_Sem = RT_NULL;
static rt_sem_t EthIRQ_Sem = RT_NULL;
static rt_thread_t Cat1Rev_Thread = RT_NULL;
static uint8_t CAT1DispEn = false;
static CatOne_t CatOne;
static char CatOneEthRxBuff[CAT_ONE_REV_LEN_MAX];
static uint16_t CatOneEthRxLen;
static uint8_t CatOneEthTxBuff[CAT_ONE_REV_LEN_MAX];
static uint16_t CatOneEthTxLen;
static uint8_t Payload[CAT_ONE_REV_LEN_MAX];
static char CommUnitSendASCII[CAT_ONE_REV_LEN_MAX * 2];
static uint8_t EthRevTimeOutCnt;
static uint16_t CatSendErrCnt = 0;
#define CAT1_DBG_LOG(...) { if(CAT1DispEn) Debug_Printf(__VA_ARGS__);}
//#define CAT1_DBG_ARRAY(ARRAY, SIZE) { if(CAT1DispEn) {DBG_ARRAY(ARRAY,SIZE)}}
#define CATONE_RESET_DELAY_TIME_MAX (5 * 60 * 1000)
const char *CatOneATCmdStr[16] = {
"NULL",
"AT\r\n", //开机检测
"ATE0\r\n", //关回显
"AT+CPIN?\r\n", //识卡
// "AT+CIMI\r\n", //IMEI
"AT+CGSN=1\r\n",
"AT+LCCID\r\n", //读卡号
"AT+CEREG?\r\n", //查询注册状态
"AT+CGPADDR=1\r\n", //查询IP地址
"AT+CSQ\r\n", //查询信号强度
"AT+LDNSGIP=gxjt.cui635.cn\r\n",
"AT+LBS=0\r\n", //获取基站定位信息
"AT+LIPOPEN=", //设置TCP服务器地址和端口,AT+LIPOPEN="TCP","114.55.52.96",6803
"AT+LIPSEND=", //发送数据, AT+LIPSEND=0,1,20,"31313131313131323232323232"
"AT+LIPCLOSE=0\r\n",//断开连接
"AT+LBSPARA=http://locator-aep.xiot.senthink.com:80/locator/v0.1/locate,B84E427D95B1DF4A3F49B18DDF714C72\r\n",
"AT+CCLK?\r\n", //获取时间
};
void Cat1DBGOnOff(bool OnOff)
{
CAT1DispEn = OnOff;
if(OnOff)
Debug_Printf("\r\nCat1 Display Enable!\r\n\r\n");
else
Debug_Printf("\r\nCat1 Display Disable!\r\n\r\n");
}
const CatOneATCMD_m CatOneModeSetCmdArray[] = {
CAT_ONE_AT_NULL,
CAT_ONE_AT,
CAT_ONE_ATE0,
//CAT_ONE_LBSPARA,
CAT_ONE_LCCID,
CAT_ONE_IMEI,
CAT_ONE_CPIN,
CAT_ONE_CEREG,
CAT_ONE_CSQ,
//CAT_ONE_LDNSGIP,
//CAT_ONE_LBS,
CAT_ONE_CCLK,
CAT_ONE_AT_CMD_END
};
//CatOneRetStatus_m CatOneSend(uint8_t *sData, uint16_t sLen)
//{
// rt_err_t result;
//
// if(CatOne.Status != CAT_ONE_IDEL && CatOne.Status != CAT_ONE_WAIT_SEND)
// return CAT_ONE_RET_ERR;
//
// //CatOne.Status = CAT_ONE_RESET;
// result = rt_mq_send(CatOneRev_MQ, sData, sLen);
// if(result != RT_EOK) {
// CAT1_DBG_LOG("CatOne MQ Send ERR...\r\n");
// return CAT_ONE_RET_ERR;
// }
// CAT1_DBG_LOG("CatOne Send Message: \r\n", sData);
// return CAT_ONE_RET_OK;
//}
void CatOneStop(void)
{
CatOne.Status = CAT_ONE_OFF;
}
void CatOneGetLocationInfo(int *Longitude, int *Latitude)
{
if(CatOne.LBSFlag) {
*Longitude = CatOne.Longitude;
*Latitude = CatOne.Latitude;
}
else {
*Longitude = 0;
*Latitude = 0;
}
}
void CatOneGetIMEIAndSIM(char *Imei, char *Sim)
{
memcpy(Imei, CatOne.IMEI, 15);
memcpy(Sim, CatOne.SIM, 20);
}
//返回true-busy, false-Idle
bool CatOneGetStatus(void)
{
if(CatOne.Status == CAT_ONE_IDEL)
return false;
return true;
}
void CatOneReset(void)
{
CatOne.Status = CAT_ONE_RESET;
}
void CatTimeSync(char *Data)
{
struct tm sTimet;
time_t sTime;
char *p;
p = strchr(Data, '\"');
if(p == NULL)
return;
int ret = sscanf(p, "\"%d/%d/%d,%d:%d:%d+",
&sTimet.tm_year, &sTimet.tm_mon, &sTimet.tm_mday,
&sTimet.tm_hour, &sTimet.tm_min, & sTimet.tm_sec);
if(ret != 6) {
int ret = sscanf(p, "\"%d/%d/%d,%d:%d:%d-",
&sTimet.tm_year, &sTimet.tm_mon, &sTimet.tm_mday,
&sTimet.tm_hour, &sTimet.tm_min, & sTimet.tm_sec);
if(ret != 6)
return;
}
sTimet.tm_isdst = 0;
if(sTimet.tm_year < 24 || sTimet.tm_year > 50)
return;
sTimet.tm_year += 100;
if(sTimet.tm_mon > 12 || sTimet.tm_mon == 0)
return;
sTimet.tm_mon--;
sTime = mktime(&sTimet);
TimeSync(sTime);
CAT1_DBG_LOG("Set Time:");
TimeShow(TimeTs());
}
void CatOneAtCmdAnalyze(char *RxBuff)
{
char *p;
int ret;
CatOne.ATCmdRet = CAT_ONE_RET_OK;
CAT1_DBG_LOG(RxBuff);
switch(CatOne.AtCmd) {
case CAT_ONE_AT:
case CAT_ONE_ATE0:
case CAT_ONE_LIPSEND:
case CAT_ONE_LDNSGIP:
case CAT_ONE_LBSPARA:
if(strstr(RxBuff, "OK") == NULL) {
CatOne.ATCmdRet = CAT_ONE_RET_ERR;
}
break;
case CAT_ONE_IMEI:
if(strstr(RxBuff, "OK") == NULL) {
CatOne.ATCmdRet = CAT_ONE_RET_ERR;
}
p = strstr(RxBuff, "+CGSN");
if(p == NULL) {
CatOne.ATCmdRet = CAT_ONE_RET_ERR;
}
p = strchr(p, '"');
if(p != NULL) {
memcpy(CatOne.IMEI, p+1, 15);
}
else {
memset(CatOne.IMEI, 0, 15);
}
// ret = sscanf(p, "+CGSN: \"%s\"\r\n", CatOne.IMEI);
// if(ret != 1) {
// memset(CatOne.IMEI, 0, 15);
// }
CatOne.IMEI[15] = 0;
break;
case CAT_ONE_CCLK:
if(strstr(RxBuff, "+CCLK") != NULL) {
CatTimeSync(RxBuff);
}
break;
case CAT_ONE_LCCID:
if(strstr(RxBuff, "OK") == NULL) {
CatOne.ATCmdRet = CAT_ONE_RET_ERR;
}
p = strstr(RxBuff, "+LCCID");
if(p == NULL) {
CatOne.ATCmdRet = CAT_ONE_RET_ERR;
}
memset(CatOne.SIM, 0, 32);
ret = sscanf(p, "+LCCID: %s\r\n", CatOne.SIM);
if(ret != 1) {
memset(CatOne.SIM, 0, 32);
}
break;
case CAT_ONE_LBS:
p = strstr(RxBuff, "+LBS");
if(p != NULL) {
double Longitude, Latitude;
int ret = sscanf(p, "+LBS: %lf,%lf\r\n", &Longitude, &Latitude);
if(ret == 2) {
CatOne.LBSFlag = true;
CatOne.Longitude = Longitude * 100000;
CatOne.Latitude = Latitude * 100000;
}
}
break;
case CAT_ONE_LIPOPEN:
if(strstr(RxBuff, "OK") != NULL) {
CatOne.Status = CatOne.NextStatus;
CatOne.CatOne1mSDelayCnt = 10 * 1000;
return;
}
else {
if(strstr(RxBuff, "LIPOPEN: 0,1") != NULL) {
CAT1_DBG_LOG("Cat1 successfully to connect to the server.\r\n\r\n");
CatOne.TcpConnFlag = true;
CatOne.Status = CatOne.NextStatus;
rt_sem_release(CatOneRev_Sem);
}
else if(strstr(RxBuff, "LIPOPEN: 0,0") != NULL) {
CAT1_DBG_LOG("Cat1 failed to connect to the server.\r\n\r\n");
CatOne.TcpConnFlag = false;
CatOne.Status = CAT_ONE_OFF;
}
return;
}
case CAT_ONE_CPIN:
if(strstr(RxBuff, "READY") == NULL) {
CatOne.ATCmdRet = CAT_ONE_RET_ERR;
}
break;
case CAT_ONE_CEREG:
if(strstr(RxBuff, "CEREG: 0,1") == NULL) {
CatOne.CatOne1mSDelayCnt = 3000;
CatOne.ATCmdRet = CAT_ONE_RET_ERR;
}
break;
case CAT_ONE_CGPADDR:
if(strstr(RxBuff, "+CGPADDR") == NULL) {
CatOne.ATCmdRet = CAT_ONE_RET_ERR;
}
break;
case CAT_ONE_CSQ:
if(strstr(RxBuff, "+CSQ") == NULL) {
CatOne.ATCmdRet = CAT_ONE_RET_ERR;
}
break;
case CAT_ONE_LTPCLOSE:
if(strstr(RxBuff, "CLOSE OK") != NULL) {
break;
}
else if(strstr(RxBuff, "ERROR") != NULL) {
break;
}
else if(strstr(RxBuff, "OK") != NULL){
break;
}
CatOne.ATCmdRet = CAT_ONE_RET_ERR;
break;
case CAT_ONE_AT_NULL:
p = strstr(RxBuff, "+LIPURC");
if(p != NULL) {
char rData[120];
uint8_t hData[60];
int rLen, hLen, ret;
if(strstr(p, "+LIPURC: 0,0") != NULL) {
CAT1_DBG_LOG("TCP connection disconnected.\r\n\r\n");
CatOne.TcpConnFlag = false;
CatOne.Status = CAT_ONE_OFF;
return;
}
ret = sscanf(p, "+LIPURC: 0,1,%d,%s\r\n", &rLen, rData);
if(ret == 2) {
if(rLen < 24)
return;
memset(hData, 0x00, 60);
hLen = AsciiToHex(rData, hData, rLen);
CatSendErrCnt = 0;
CatOne.GateWay->SvrRevCallBack(CatOne.GateWay, hData, hLen);
}
else {
return;
}
//CatOne.Status = CAT_ONE_CLOSE_TCP;
rt_sem_release(CatOneRev_Sem);//接收任务
return;
}
default:
CatOne.ATCmdRet = CAT_ONE_RET_ERR;
}
if(CatOne.ATCmdRet == CAT_ONE_RET_OK) {
CatOne.Status = CatOne.NextStatus;
if(CatOne.AtCmd == CAT_ONE_LIPSEND)
CatOne.CatOne1mSDelayCnt = 5 * 1000;
else
CatOne.CatOne1mSDelayCnt = 10;
CatOne.AtCmd = CAT_ONE_AT_NULL;
rt_sem_release(CatOneRev_Sem);
}
}
void CatOneAtCmdSend(CatOneATCMD_m Cmd, uint32_t Dly, CatOneStatus_m NextStatus)
{
CatOne.AtCmd = Cmd;
if(CatOne.AtCmd == CAT_ONE_LIPSEND) {
HexToAscii(CatOneEthTxBuff, CommUnitSendASCII, CatOneEthTxLen);
sprintf(CatOne.CatOneSendBuff,"AT+LIPSEND=0,1,%d,\"%s\"\r\n",CatOneEthTxLen * 2, CommUnitSendASCII);
CatOne.GateWay->BatteryReadDlyCnt = 30;
}
else if(CatOne.AtCmd == CAT_ONE_LIPOPEN) {
sprintf(CatOne.CatOneSendBuff,"AT+LIPOPEN=\"TCP\",\"%d.%d.%d.%d\",%d\r\n",
CatOne.GateWay->ConfigPara.SvrAddr[0],
CatOne.GateWay->ConfigPara.SvrAddr[1],
CatOne.GateWay->ConfigPara.SvrAddr[2],
CatOne.GateWay->ConfigPara.SvrAddr[3],
CatOne.GateWay->ConfigPara.SvrPort);
}
else {
strcpy(CatOne.CatOneSendBuff, CatOneATCmdStr[CatOne.AtCmd]);
}
CAT1_DBG_LOG(CatOne.CatOneSendBuff);
EthRevTimeOutCnt = 0;
EthOrCat1UartSend((uint8_t *)CatOne.CatOneSendBuff, strlen(CatOne.CatOneSendBuff));
CatOne.CatOne1mSDelayCnt = Dly;
CatOne.Status = CAT_ONE_WAIT_REV;
CatOne.NextStatus = NextStatus;
}
int GateWayRegister(uint8_t *TxBuff)
{
uint16_t UnitCommCnt = 0;
uint8_t *p = &TxBuff[0];
uint16_t len = 5;
if(CatOne.GateWay->ConfigPara.Rs485Ch1.CommUnitEnable == true && CatOne.GateWay->ConfigPara.Rs485Ch1.Enable == true) {
UnitCommCnt++;
memcpy(&p[len], CatOne.GateWay->ConfigPara.Rs485Ch1.CUData.Para.Mac[0], 6);
len += 6;
}
if(CatOne.GateWay->ConfigPara.Rs485Ch2.CommUnitEnable == true && CatOne.GateWay->ConfigPara.Rs485Ch2.Enable == true) {
UnitCommCnt++;
memcpy(&p[len], CatOne.GateWay->ConfigPara.Rs485Ch2.CUData.Para.Mac[0], 6);
len += 6;
}
for(int i = 0; i < COMMUNIT_NUM_MAX; i++) {
if(CatOne.GateWay->ConfigPara.CommUnitArray[i].RegFlag == true) {
for(int j = 0; j < CatOne.GateWay->ConfigPara.CommUnitArray[i].SensorN; j++)
{
memcpy(&p[len], CatOne.GateWay->ConfigPara.CommUnitArray[i].Mac[j], 6);
len += 6;
UnitCommCnt++;
}
}
}
TxBuff[0] = (len - 3) & 0x00ff;
TxBuff[1] = ((len - 3) >> 8) & 0x00ff;
TxBuff[2] = NET_COMM_CMD_REG;
TxBuff[3] = UnitCommCnt & 0x00ff;
TxBuff[4] = (UnitCommCnt >> 8) & 0x00ff;
return len;
}
void CatOneLoopHandler(void)
{
static rt_err_t result;
uint16_t ret;
static uint8_t Cat1RevErrCnt = 0;
switch(CatOne.Status){
case CAT_ONE_IDEL:
rt_thread_delay(1);
if(CatOne.ResetDelayCnt > 0) {
CatOne.ResetDelayCnt--;
}
else {
CatOne.Status = CAT_ONE_RESET;
}
break;
case CAT_ONE_WAIT_REV:
result = rt_sem_take(CatOneRev_Sem, CatOne.CatOne1mSDelayCnt);
if(result != RT_EOK) {
if(CatOne.AtCmdResendCnt > 0) {
CatOne.AtCmdResendCnt--;
CatOneAtCmdSend(CatOne.AtCmd, 2000, CatOne.NextStatus);
CAT1_DBG_LOG("Cat1 Ret TimeOut, ReSend(%d)...\r\n", CatOne.AtCmdResendCnt);
}
else { //3次错误,关机
CAT1_DBG_LOG("Cat1 error, Close!\r\n");
if(CatOne.AtCmd == CAT_ONE_LIPSEND)
CatOne.Status = CAT_ONE_CLOSE_TCP;
else
CatOne.Status = CAT_ONE_OFF;
}
}
break;
case CAT_ONE_INIT:
CatOne.AtCmdIdx++;
if(CatOneModeSetCmdArray[CatOne.AtCmdIdx] != CAT_ONE_AT_CMD_END) {
if(CatOneModeSetCmdArray[CatOne.AtCmdIdx] == CAT_ONE_CEREG)
CatOne.AtCmdResendCnt = 30;
else
CatOne.AtCmdResendCnt = 3;
CatOneAtCmdSend(CatOneModeSetCmdArray[CatOne.AtCmdIdx], 1000, CAT_ONE_INIT);
}
else {
CatOne.Status = CAT_ONE_TCP_CONN;
CatOne.CatOne1mSDelayCnt = 0;
CatOne.AtCmdIdx = 0;
CatOne.AtCmd = CAT_ONE_AT_NULL;
}
break;
case CAT_ONE_TCP_CONN:
CatOneAtCmdSend(CAT_ONE_LIPOPEN, 2000, CAT_ONE_WAIT_CONN);
break;
case CAT_ONE_WAIT_CONN:
if(CatOne.TcpConnFlag) {
if(CatOne.GateWay->SvrRegFlag == false)
CatOne.Status = CAT_ONE_REG_SVR;
else
CatOne.Status = CAT_ONE_WAIT_SEND;
}
break;
case CAT_ONE_REG_SVR: //注册服务器
ret = GateWayRegister(CatOneEthTxBuff);
rt_mq_send(CatOne.GateWay->NetSendData_MQ, CatOneEthTxBuff, ret);
CatOne.Status = CAT_ONE_WAIT_SEND;
break;
case CAT_ONE_WAIT_SEND:
result = rt_mq_recv(CatOne.GateWay->NetSendData_MQ, Payload, CAT_ONE_REV_LEN_MAX, 1000);
if(result == RT_EOK) {
CatOneEthTxLen = NetCommOrgData(CatOne.GateWay, Payload, CatOneEthTxBuff);
CatOne.Status = CAT_ONE_SEND_DATA;
}
else {
if(CatOne.Status == CAT_ONE_RESET || CatOne.Status == CAT_ONE_OFF) //外部命令执行,状态改变
return;
if(!CatOne.TcpConnFlag) {
CatOne.Status = CAT_ONE_OFF;
}
else {
CatSendErrCnt++;
if(CatSendErrCnt > CAT1_ERR_RESET_DLY_MAX) {
CatOne.Status = CAT_ONE_RESET;
CAT1_DBG_LOG("Cat1 has no data for a long time, Reset!\r\n");
CatSendErrCnt = 0;
break;
}
CatOne.Status = CAT_ONE_WAIT_SEND;
}
}
break;
case CAT_ONE_SEND_DATA:
CatOne.AtCmdResendCnt = 3;
Cat1RevErrCnt++;
if(Cat1RevErrCnt > 10) {
CatOne.Status = CAT_ONE_RESET;
CAT1_DBG_LOG("Cat1 has no receive data for a long time, Reset!\r\n");
Cat1RevErrCnt = 0;
break;
}
CatOneAtCmdSend(CAT_ONE_LIPSEND, 5000, CAT_ONE_REV_DATA);
break;
case CAT_ONE_REV_DATA:
result = rt_sem_take(CatOneRev_Sem, CatOne.CatOne1mSDelayCnt);
if(result != RT_EOK) {
if(CatOne.TcpConnFlag == false) {
CAT1_DBG_LOG("Cat1 Rec Server Data Timeout!\r\n");
break;
}
}
else {
Cat1RevErrCnt = 0;
}
if(CatOne.GateWay->SvrRegFlag == false) //设备没注册,关闭4G,等待下一次重新注册
CatOne.Status = CAT_ONE_OFF;
else
CatOne.Status = CAT_ONE_WAIT_SEND;
break;
case CAT_ONE_CLOSE_TCP:
CatOne.AtCmdResendCnt = 3;
CatOneAtCmdSend(CAT_ONE_LTPCLOSE, 1000, CAT_ONE_OFF);
break;
case CAT_ONE_OFF:
//CAT1_POW_OFF();
CAT1_RESET_SET();
CAT1_PWR_KEY_CLR();
rt_thread_delay(3000);
CAT1_PWR_KEY_SET();
CatSendErrCnt = 0;
CAT1_DBG_LOG("Cat1 Power Off!\r\n");
CatOne.Status = CAT_ONE_IDEL;
CatOne.ResetDelayCnt = CATONE_RESET_DELAY_TIME_MAX;
break;
case CAT_ONE_RESET:
CatSendErrCnt = 0;
CAT1_DBG_LOG("Cat1 Reset!\r\n");
CAT1_RESET_CLR();
CAT1_PWR_KEY_SET();
//CAT1_POW_ON();
rt_thread_delay(50);
CAT1_RESET_SET();
CAT1_PWR_KEY_CLR();
rt_thread_delay(1000);
CAT1_PWR_KEY_SET();
CatOne.Status = CAT_ONE_INIT;
CatOne.AtCmdIdx = 0;
rt_thread_delay(1000);
CatOne.GateWay->BatteryReadDlyCnt = 60;
break;
}
}
void EthLoopHandler(void)
{
rt_err_t result;
if(CatOne.GateWay->SvrRegFlag == false) {
if(CatOne.RegisterDelayCnt == 0) {
if(ETH_LINK_GET() == Reset) {
CatOne.RegisterDelayCnt = REGISTER_INTERVAL_MAX * 10;
uint8_t ret = GateWayRegister(CatOneEthTxBuff);
rt_mq_send(CatOne.GateWay->NetSendData_MQ, CatOneEthTxBuff, ret);
}
}
else {
CatOne.RegisterDelayCnt--;
}
}
result = rt_mq_recv(CatOne.GateWay->NetSendData_MQ, Payload, CAT_ONE_REV_LEN_MAX, 100);
if(result == RT_EOK) {
CatOneEthTxLen = NetCommOrgData(CatOne.GateWay, Payload, CatOneEthTxBuff);
HexToAscii(CatOneEthTxBuff, CommUnitSendASCII, CatOneEthTxLen);
EthRevTimeOutCnt = 0;
EthOrCat1UartSend((uint8_t *)CommUnitSendASCII, CatOneEthTxLen * 2);
CommUnitSendASCII[CatOneEthTxLen * 2] = 0;
CAT1_DBG_LOG("Eth Send: %s\r\n",CommUnitSendASCII);
}
}
bool CatOneEthSendQueue(uint8_t *sData, uint16_t sLen)
{
if(CatOne.GateWay->SvrRegFlag == false)
return false;
rt_mq_send(CatOne.GateWay->NetSendData_MQ, sData, sLen);
return true;
}
static void CatOneInit(GateWayPara GateWay)
{
memset(&CatOne, 0x00, sizeof(CatOne_t));
CatOne.Status = CAT_ONE_RESET;
CatOne.GateWay = GateWay;
CatOne.CatOneRevCallBack = GateWay->SvrRevCallBack;
}
void CatOneEthRev_Thread_Entry(void *parameter)
{
rt_err_t result;
char RxBuffTemp[CAT_ONE_REV_LEN_MAX];
uint8_t HexData[CAT_ONE_REV_LEN_MAX / 2];
GateWayPara GateWay = (GateWayPara)parameter;
rt_kprintf("CatOneTthRev Thread is running!\r\n");
while(1) {
if(GateWay->ConfigPara.Comm == CATONE_COMM) {
result = rt_sem_take(CatOneIRQ_Sem, 500);
if(result == RT_EOK) {
memcpy(RxBuffTemp, CatOneEthRxBuff, CatOneEthRxLen);
RxBuffTemp[CatOneEthRxLen] = 0;
CatOneAtCmdAnalyze(RxBuffTemp);
memset(CatOneEthRxBuff, 0x00, CAT_ONE_REV_LEN_MAX);
CatOneEthRxLen = 0;
}
//CatOneEthRxLen = 0;
}
else if(GateWay->ConfigPara.Comm == ETH_COMM) {
result = rt_sem_take(EthIRQ_Sem, 500);
if(result == RT_EOK) {
memcpy(RxBuffTemp, CatOneEthRxBuff, CatOneEthRxLen);
RxBuffTemp[CatOneEthRxLen] = 0;
CAT1_DBG_LOG("Eth Rev: %s\r\n",RxBuffTemp);
memset(HexData, 0x00, CatOneEthRxLen / 2);
uint8_t ret = AsciiToHex(RxBuffTemp, HexData, CatOneEthRxLen);
if(ret > 0)
GateWay->SvrRevCallBack(GateWay, HexData, ret);
memset(CatOneEthRxBuff, 0x00, CAT_ONE_REV_LEN_MAX);
CatOneEthRxLen = 0;
}
//CatOneEthRxLen = 0;
}
}
}
void CatOne_Eth_Thread_Entry(void *parameter)
{
GateWayPara GateWay = (GateWayPara)parameter;
CatOneRev_Sem = rt_sem_create("cat1r_sem", 0, RT_IPC_FLAG_FIFO);
if(CatOneRev_Sem == RT_NULL) {
rt_kprintf("CatOne Sem Create Failed!\r\n");
}
EthIRQ_Sem = rt_sem_create("eth_sem", 0, RT_IPC_FLAG_FIFO);
if(EthIRQ_Sem == RT_NULL) {
rt_kprintf("Eth Sem Create Failed!\r\n");
}
CatOneIRQ_Sem = rt_sem_create("cat1_sem", 0, RT_IPC_FLAG_FIFO);
if(CatOneIRQ_Sem == RT_NULL) {
rt_kprintf("CatOneIRQ Sem Create Failed!\r\n");
}
CatOneInit(GateWay);
ETH_RESET_CLR();
rt_thread_delay(10);
ETH_RESET_SET();
Cat1Rev_Thread = rt_thread_create("Cat1Rev", CatOneEthRev_Thread_Entry, parameter, 3000, 3, 20);
if (Cat1Rev_Thread != RT_NULL) {
rt_thread_startup(Cat1Rev_Thread);
}
else {
rt_kprintf("CatOneRev Thread Create Failed! Exit...\r\n");
return;
}
rt_kprintf("CatOne Thread is running\r\n");
while(1) {
//rt_mutex_take(GateWay->UartRevMutex, RT_WAITING_FOREVER);
if(GateWay->ConfigPara.Comm == CATONE_COMM)
CatOneLoopHandler();
else if(GateWay->ConfigPara.Comm == ETH_COMM)
EthLoopHandler();
else
rt_thread_delay(1);
//rt_mutex_release(GateWay->UartRevMutex);
}
}
void EthOrCat1RxIrqCallback(uint8_t rData)
{
if(EthRevTimeOutCnt == 0)
CatOneEthRxLen = 0;
if(CatOneEthRxLen < CAT_ONE_REV_LEN_MAX) {
CatOneEthRxBuff[CatOneEthRxLen++] = rData;
}
EthRevTimeOutCnt = 3;
}
void EthRxOverhandler(void)
{
if(EthRevTimeOutCnt > 0)
EthRevTimeOutCnt--;
if(CatOneEthRxLen > 5 && EthRevTimeOutCnt == 0) {
EthRevTimeOutCnt = 20;
if(CatOne.GateWay->ConfigPara.Comm == CATONE_COMM)
rt_sem_release(CatOneIRQ_Sem);
else
rt_sem_release(EthIRQ_Sem);
}
}
void CatReadImeiOrSim(char *Imei, char *Sim)
{
if(Imei != NULL) {
memcpy(Imei, CatOne.IMEI, 15);
Imei[15] = 0x00;
}
if(Sim != NULL) {
memcpy(Sim, CatOne.SIM, 20);
Sim[20] = 0x00;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,87 @@
#include "encryption.h"
//从机加密表
const unsigned char EPT_Table[32][6] = {
{1, 6, 4, 2, 3, 5}, {2, 4, 6, 3, 5, 1}, {3, 5, 6, 2, 1, 4}, {5, 3, 2, 1, 4, 6},
{4, 2, 3, 1, 5, 6}, {6, 3, 5, 1, 4, 2}, {3, 5, 2, 6, 4, 1}, {2, 5, 4, 3, 1, 6},
{2, 4, 1, 5, 3, 6}, {4, 6, 1, 3, 2, 5}, {4, 2, 1, 5, 6, 3}, {3, 2, 6, 5, 1, 4},
{2, 6, 5, 1, 4, 3}, {6, 4, 3, 1, 2, 5}, {1, 6, 3, 2, 4, 5}, {5, 3, 4, 6, 2, 1},
{5, 3, 1, 2, 6, 4}, {1, 4, 2, 6, 5, 3}, {3, 5, 2, 1, 4, 6}, {6, 1, 4, 2, 3, 5},
{4, 1, 2, 5, 3, 6}, {4, 2, 6, 3, 5, 1}, {2, 6, 1, 4, 3, 5}, {4, 3, 1, 5, 6, 2},
{5, 1, 2, 4, 6, 3}, {6, 5, 1, 3, 4, 2}, {2, 1, 6, 3, 5, 4}, {1, 5, 6, 3, 4, 2},
{3, 6, 5, 4, 2, 1}, {1, 2, 6, 3, 5, 4}, {4, 6, 5, 3, 2, 1}, {5, 3, 4, 2, 6, 1}
};
//从机解密表:
const unsigned char DPT_Table[32][5] ={
{1, 4, 2, 3, 5}, {2, 4, 3, 5, 1}, {3, 5, 2, 1, 4}, {5, 3, 2, 1, 4},
{4, 2, 3, 1, 5}, {3, 5, 1, 4, 2}, {3, 5, 2, 4, 1}, {2, 5, 4, 3, 1},
{2, 4, 1, 5, 3}, {4, 1, 3, 2, 5}, {4, 2, 1, 5, 3}, {3, 2, 5, 1, 4},
{2, 5, 1, 4, 3}, {4, 3, 1, 2, 5}, {1, 3, 2, 4, 5}, {5, 3, 4, 2, 1},
{5, 3, 1, 2, 4}, {1, 4, 2, 5, 3}, {3, 2, 1, 4, 5}, {1, 4, 5, 2, 3},
{4, 1, 2, 5, 3}, {4, 2, 3, 5, 1}, {2, 1, 4, 3, 5}, {4, 3, 1, 5, 2},
{5, 1, 2, 4, 3}, {5, 1, 3, 4, 2}, {2, 1, 3, 5, 4}, {1, 5, 3, 4, 2},
{3, 5, 4, 2, 1}, {1, 2, 3, 5, 4}, {4, 5, 3, 2, 1}, {5, 3, 4, 2, 1}
};
//数据位加密表:
const unsigned char EPT_D[32] = {
0x23, 0x4c, 0x92, 0x38, 0x52, 0xa4, 0x9a, 0x61,
0x86, 0xc8, 0x70, 0x16, 0x32, 0x58, 0x62, 0x83,
0xa5, 0x16, 0x1c, 0x49, 0x48, 0xc1, 0x8c, 0x91,
0xd0, 0x2c, 0x49, 0x42, 0xc1, 0x8c, 0x98, 0xd0
};
/****************************************************************/
/* 加密函数 */
/* */
/*函数入口: *data,未加密的普通协议数据 */
/* */
/*函数出口: *EPT_data,生成的加密协议 */
/****************************************************************/
void Encrypt_Code(unsigned char *data, unsigned char *EPT_data) {
unsigned char Edata[6];
unsigned char i = 0;
unsigned char check;
unsigned char ept_byte;
check = (data[0]+data[1]+data[2]+data[3]+data[4]+data[5]) % 0xff;
ept_byte = check % 32;
for (i = 0; i < 6; i++) {
Edata[i] = ((~(data[i] & EPT_D[ept_byte])) & EPT_D[ept_byte]) | (data[i] & (~EPT_D[ept_byte]));
}
for (i = 0; i < 6; i++) {
EPT_data[i] = Edata[EPT_Table[ept_byte][i]-1];
}
EPT_data[6] = ((~(check & 0xaa)) & 0xaa) | (check & 0x55);
}
/****************************************************************/
/* 解密函数 */
/* */
/*函数入口: *EPT_data,需要解密的加密协议 */
/* */
/*函数出口: *DPT_data,生成的普通协议 */
/****************************************************************/
void Decrypt_Code(unsigned char *EPT_data,unsigned char *DPT_data) {
unsigned char data[5];
unsigned char i = 0;
unsigned char check;
unsigned char ept_byte;
check = ((~(EPT_data[5]&0xaa))&0xaa)|(EPT_data[5]&0x55);
ept_byte = check % 32;
for(i=0;i<5;i++) {
data[i] = ((~(EPT_data[i]&EPT_D[ept_byte]))&EPT_D[ept_byte])|(EPT_data[i]&(~EPT_D[ept_byte]));
}
for(i=0;i<5;i++) {
DPT_data[DPT_Table[ept_byte][i]-1] = data[i];
}
DPT_data[5] = check;
}
+212
View File
@@ -0,0 +1,212 @@
#include "LoraTask.h"
#include "main.h"
#include "CatOneTask.h"
#include "DebugCmd.h"
#define UC_OFFLINE_TIME_INTERVAL_MAX (2 * 60 * 60)//离线判断最大时间间隔,单位秒
static rt_sem_t LoraDioIRQ_Sem = RT_NULL;
static rt_thread_t LoraIRQ_Thread = RT_NULL;
static GateWayPara GateWay;
void LoraSend(uint8_t* pucBuff, uint8_t ucLen)
{
Sx1276LoRaSendBuffer(pucBuff, ucLen);
}
//Lora接收消息统一放到消息队列,由接收任务处理
int LoraRevCallBack(GateWayPara GateWay, uint8_t *rData, uint16_t rLen)
{
uint8_t *sData;
if(rLen > 255)
return -1;
sData = rt_malloc(rLen + 5);
sData[0] = rLen;
// Debug_Printf("Lora Rev: ");
// for(int i = 0; i < rLen; i++) {
// Debug_Printf("%02x ", rData[i]);
// }
// Debug_Printf("\r\n");
memcpy(&sData[1], rData, rLen);
rt_mq_send(GateWay->LoraRev_MQ, sData, rLen + 1);
rt_free(sData);
return 0;
}
void LoraIRQ_Thread_Entry(void *parameter)
{
rt_err_t result;
static uint16_t LoraErrCnt = 0;
Debug_Printf("LoraRev Thread is running\r\n");
while(1) {
if(GateWay->ConfigPara.Lora.OnOff == false) {
rt_thread_delay(100);
continue;
}
result = rt_sem_take(LoraDioIRQ_Sem, 1000);
if(result == RT_EOK) {
IsrSx1276LoRaTxRx(GateWay);
LoraErrCnt = 0;
}
else {
LoraErrCnt++;
if(LoraErrCnt > LORA_ERR_RESET_DLY_MAX) { //15分钟内没有收到lora数据重启lora模块
LoraErrCnt = 0;
Debug_Printf("Lora Reset\r\n");
Sx1276LoRaInit(LoraRevCallBack);
}
}
}
}
static void LoRaSendBuffer(uint8_t* pucBuff, uint16_t ucLen)
{
if(GateWay->ConfigPara.Lora.OnOff)
Sx1276LoRaSendBuffer(pucBuff, ucLen);
}
void Lora_Thread_Entry(void *parameter)
{
rt_err_t result;
#ifndef LORA_LOWPOWER
bool UnitCommSendFlag = false;
uint8_t SendUnitCommIdx = 0;
uint16_t UnitCommReadDelayCnt = 0;
#endif
uint8_t Payload[256];
uint8_t MegData[9];
GateWay = (GateWayPara)parameter;
while(GateWay->ConfigPara.Lora.OnOff == false) {
rt_thread_delay(100);
}
LoraDioIRQ_Sem = rt_sem_create("loradioirq_sem", 0, RT_IPC_FLAG_FIFO);
if(LoraDioIRQ_Sem == RT_NULL) {
Debug_Printf("CatOneIRQ Sem Create Failed!\r\n");
}
LoraIRQ_Thread = rt_thread_create("LoraIRQ", LoraIRQ_Thread_Entry, NULL, 512, 3, 20);
if (LoraIRQ_Thread != RT_NULL)
rt_thread_startup(LoraIRQ_Thread);
Sx1276LoRaInit(LoraRevCallBack);
Debug_Printf("Lora Thread is running\r\n");
#ifdef LORA_LOWPOWER
while(1) {
if(GateWay->ConfigPara.Lora.OnOff == false) {
rt_thread_delay(100);
continue;
}
result = rt_mq_recv(GateWay->LoraRev_MQ, Payload, 256, 1000);
if(result == RT_EOK) {
int ret = GateWay->CommUnitRevCallBack(GateWay, &Payload[1], Payload[0], LoRaSendBuffer);
if(ret == 0xff) //注册信息
continue;
}
else { //离线判断
for(int i = 0; i < COMMUNIT_NUM_MAX; i++) {
if(GateWay->ConfigPara.CommUnitArray[i].RegFlag == true) {
if(GateWay->ConfigPara.CommUnitArray[i].CommErrCnt < UC_OFFLINE_TIME_INTERVAL_MAX) {
GateWay->ConfigPara.CommUnitArray[i].CommErrCnt++;
}
else if(GateWay->ConfigPara.CommUnitArray[i].CommStatus) {
GateWay->ConfigPara.CommUnitArray[i].CommStatus = 0;
MegData[0] = 7;
MegData[1] = 0;
MegData[2] = COMM_UNIT_CMD_READ;
memcpy(&MegData[3], GateWay->ConfigPara.CommUnitArray[i].Mac[0], 6);
MegData[9] = GateWay->ConfigPara.CommUnitArray[i].CommStatus;
Debug_Printf("The CommUnit is offline.Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
GateWay->ConfigPara.CommUnitArray[i].Mac[0][0],
GateWay->ConfigPara.CommUnitArray[i].Mac[0][1],
GateWay->ConfigPara.CommUnitArray[i].Mac[0][2],
GateWay->ConfigPara.CommUnitArray[i].Mac[0][3],
GateWay->ConfigPara.CommUnitArray[i].Mac[0][4],
GateWay->ConfigPara.CommUnitArray[i].Mac[0][5]);
CatOneEthSendQueue(MegData, 10); //发送离线消息
}
}
}
}
}
#else
while(1) {
if(UnitCommSendFlag == false && UnitCommReadDelayCnt >= GateWay->ConfigPara.CommUnitReadInterval) {
if(SendUnitCommIdx < COMMUNIT_NUM_MAX) {
if(GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].RegFlag &&
GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].Mac[2] == 0x01) {
GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].RevNewDataFlag = false;
Debug_Printf("Lora Read CommUnit: %02X:%02X:%02X:%02X:%02X:%02X\r\n",
GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].Mac[0],
GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].Mac[1],
GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].Mac[2],
GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].Mac[3],
GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].Mac[4],
GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].Mac[5]);
CommUnitCmdSend(GateWay, GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].Mac[0], COMM_UNIT_CMD_READ, NULL, 0, Sx1276LoRaSendBuffer);
UnitCommSendFlag = true;
}
else {
SendUnitCommIdx++;
continue;
}
}
else {
SendUnitCommIdx = 0;
UnitCommReadDelayCnt = 0;
}
}
if(UnitCommReadDelayCnt < GateWay->ConfigPara.CommUnitReadInterval)
UnitCommReadDelayCnt++;
result = rt_mq_recv(GateWay->LoraRev_MQ, Payload, 256, 1000);
if(result == RT_EOK) {
int ret = GateWay->CommUnitRevCallBack(GateWay, &Payload[1], Payload[0], Sx1276LoRaSendBuffer);
if(ret == 0xff) //注册信息
continue;
if(UnitCommSendFlag && GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].RevNewDataFlag) {
UnitCommSendFlag = false;
SendUnitCommIdx++;
}
}
else if(UnitCommSendFlag) { //离线判断
GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].CommErrCnt++;
if(GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].CommErrCnt == 10) {
GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].CommErrCnt = 0;
if(GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].CommStatus) {
GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].CommStatus = 0;
MegData[0] = 7;
MegData[1] = 0;
MegData[2] = COMM_UNIT_CMD_READ;
memcpy(&MegData[3], GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].Mac[0], 6);
MegData[9] = GateWay->ConfigPara.CommUnitArray[SendUnitCommIdx].CommStatus;
CatOneEthSendQueue(MegData, 10); //发送离线消息
}
}
UnitCommSendFlag = false;
SendUnitCommIdx++;
}
}
#endif
}
void LoraTxRxIrqCallback(void)
{
rt_sem_release(LoraDioIRQ_Sem);
}
void LoraInit(void)
{
Sx1276LoRaInit(LoraRevCallBack);
}
File diff suppressed because it is too large Load Diff
+623
View File
@@ -0,0 +1,623 @@
#include "main.h"
#include "RS485Task.h"
#include "Public.h"
#include "spiflash.h"
#include "CatOneTask.h"
#include "DebugCmd.h"
#include "update_protocol.h"
#include "bsp.h"
//#define RS485_DBG_LOG(...) { if(RS485DispEn) Debug_Printf(__VA_ARGS__);}
//static uint8_t RS485DispEn = false;
SensorCommPara_t SComm1Para;
SensorCommPara_t SComm2Para;
const uint8_t RS485SensorCmdPayLoadLen[RS485_SENSOR_CMD_END] = {0, 0, 0, 1, 0};
/*****************************************************************************************
* 函数名称: SavSensorData
* 功能描述: 记录传感器数据
* 参 数: SensorIdx, 传感器序号
Para,传感器结构指针
Data, 传感器数据
Len, 传感器数据长度
* 返 回 值: 无
*****************************************************************************************/
static void SavSensorData(uint8_t SensorIdx, CommUnitData CUData, uint8_t *Data, uint8_t Len)
{
if(Data == NULL) {
memset(CUData->Data[SensorIdx], 0x00, SENSOR_DATA_LEN_MAX);
}
else {
memcpy(CUData->Data[SensorIdx], Data, Len);
}
}
/*****************************************************************************************
* 函数名称: RS485Analyze
* 功能描述: 485数据解析
* 参 数: SCPara, 传感器发送参数
Para, 传感器结构指针
rData, 传感器数据入口
rLen, 传感器数据长度
* 返 回 值: 无
*****************************************************************************************/
void RS485Analyze(GateWayPara GateWay, SensorCommPara SCPara, CommUnit Para, uint8_t *rData, uint8_t rLen)
{
uint16_t crc16;
uint8_t *Payload;
crc16 = (rData[rLen - 1] << 8)|rData[rLen - 2];
uint16_t Check = CRC_Modbus(0xA001, rData, rLen - 2);
if(crc16 != Check)
return;
FrameHeader Header = (FrameHeader)rData;
if(Header->Cmd != RS485_SENSOR_CMD_QUERY) {
if(Header->SlvAddr != SCPara->SensorAddr)
return;
}
Payload = &rData[sizeof(FrameHeader)];
if(Header->PayloadLen == 0)
return;
if(Header->SlvAddr == 0 || Header->SlvAddr > SENSOR_NUM_MAX)
return;
SCPara->SensorErrCnt[Header->SlvAddr - 1] = 0;
switch(Header->Cmd) {
case RS485_SENSOR_CMD_SET_ADDR:
if(*Payload == 1) {
MAIN_DBG_LOG("Sensor%d Addr Set succeed!\r\n", Header->SlvAddr);
}
else {
MAIN_DBG_LOG("Sensor%d Addr Set failed!\r\n", Header->SlvAddr);
}
break;
case RS485_SENSOR_CMD_CAIL:
if(*Payload == 1) {
MAIN_DBG_LOG("Sensor%d calibration succeeded!\r\n", Header->SlvAddr);
}
else {
MAIN_DBG_LOG("Sensor%d calibration succeeded!\r\n", Header->SlvAddr);
}
break;
case RS485_SENSOR_CMD_QUERY:
if(Para->Para.SensorN < 16) {
Para->Para.SensorN++;
Para->Para.SensorType[SCPara->SensorAddr - 1] = rData[6] | (rData[7] << 8);
MAIN_DBG_LOG("Found Sensor%d, Type: %d!\r\n", Header->SlvAddr, Para->Para.SensorType[SCPara->SensorAddr - 1]);
}
break;
case RS485_SENSOR_CMD_READ: {
memcpy(SCPara->SensorData.Data[SCPara->SensorAddr - 1], &rData[sizeof(FrameHeader_t)], Header->PayloadLen);
if(SCPara->SendFlag)
SCPara->ReadSensorCnt++;
DebugDisplaySensorData(Header->SlvAddr, 0, &rData[sizeof(FrameHeader_t)]);
}
default:
break;
}
}
static void update_on_start(uint8_t* frame, int len, uint8_t* pload, int size)
{
update_protocol_req_t* pReq = (void*)&frame[sizeof(update_protocol_hd_t)];
//TODO:
boot_para_t cfg = {0};
cfg.AppFlag = 0;
cfg.UpdateFlag = APP_UPDATE_FLAG;
cfg.Crc32Check = pReq->AppCrc32;
cfg.PackageNum = pReq->PackageNum;
cfg.AppSize = pReq->AppSize;
/**
操作FALSH ,写升级参数
**/
dev_boot_write_param(cfg);
update_send_cmd(0x01, 1, pReq->PackageNum);
//重启进入BOOT
NVIC_SystemReset();
}
static int update_cmd_process(uint8_t cmd, void* frame, int len, void* pload, int size)
{
int res = -1;
switch (cmd) {
case 0x81: {
update_on_start(frame, len, pload, size);
res = 0;
}
break;
default:
break;
}
return res;
}
static int update_process(void* frame, int len)
{
uint8_t cmd = 0;
uint8_t slave_addr = 0;
uint8_t user_data[256] = {0};
int user_data_len = 0;
int res = update_unpack(frame, len, &cmd, &slave_addr, user_data, &user_data_len);
if (res != 0)
return -1;
if (slave_addr != 0x01)
return -2;
res = update_cmd_process(cmd, frame, len, user_data, user_data_len);
if (res != 0)
return -3;
return 0;
}
/*****************************************************************************************
* 函数名称: RS485SensorCmdSend
* 功能描述: 下发传感器指令函数
* 参 数: Para,通讯参数入口
* 返 回 值: 无
*****************************************************************************************/
static void RS485SensorCmdSend(GateWayPara GateWay, SensorCommPara SensorComm)
{
uint8_t sData[50];
uint8_t sLen;
if(SensorComm->Cmd >= RS485_SENSOR_CMD_END)
return;
FrameHeader Header = (FrameHeader)sData;
Header->Header = 0x7C;
Header->SlvAddr = SensorComm->SensorAddr;
Header->Cmd = SensorComm->Cmd;
//Header->DevType = SensorComm->SensorType;
Header->PayloadLen = SensorComm->CmdParaLen;
sLen = sizeof(FrameHeader_t);
if(SensorComm->CmdParaLen > 0) {
memcpy(&sData[sLen], SensorComm->CmdPara, SensorComm->CmdParaLen);
sLen += SensorComm->CmdParaLen;
}
uint16_t Check = CRC_Modbus(0xA001, sData, sLen);
sData[sLen++] = Check & 0xff;
sData[sLen++] = (Check >> 0x08) & 0x00ff;
if(SensorComm == &SComm1Para)
GateWay->ConfigPara.Rs485Ch1.RS485Send(sData, sLen);
else
GateWay->ConfigPara.Rs485Ch2.RS485Send(sData, sLen);
}
/*****************************************************************************************
* 函数名称: RS485SensorCmdSend
* 功能描述: 下发传感器指令函数
* 参 数: CommUintAddr 通讯单元地址
Para,通讯参数入口
* 返 回 值: 无
*****************************************************************************************/
void RS485CmdSend(GateWayPara GateWay, uint8_t CommUintAddr, SensorCommPara SensorComm)
{
SensorCommPara SC;
if(CommUintAddr)
SC = &SComm1Para;
else
SC = &SComm2Para;
SC->Cmd = SensorComm->Cmd;
SC->CmdPara = SensorComm->CmdPara;
SC->CmdParaLen = SensorComm->CmdParaLen;
SC->SensorAddr = SensorComm->SensorAddr;
//SC->SensorType = SensorComm->SensorType;
RS485SensorCmdSend(GateWay, SC);
}
/*****************************************************************************************
* 函数名称: RS485LoopHandler
* 功能描述: RS485循环处理函数
* 参 数: GateWay, 网关参数句柄
RS485Ch, RS485通道句柄
SCPara RS485通讯句柄
* 返 回 值: 无
*****************************************************************************************/
static uint8_t CommUintData[512];
int test = 0;
void RS485LoopHandler(GateWayPara GateWay, RS485Para RS485Ch, SensorCommPara SCPara)
{
uint8_t RxBuffTemp[RS485_RX_BUFF_LEN_MAX];
uint8_t RxLenTemp;
uint16_t CommUintLen;
rt_err_t result;
uint8_t MegData[9];
int ret;
if(RS485Ch->Enable == false) {
rt_thread_delay(10);
return;
}
if(RS485Ch->CommUnitEnable == true) { //使用内置通讯单元
if(RS485Ch->QuerySensorFlag == true) { //开机查找传感器
if(SCPara->SensorCnt < SENSOR_NUM_MAX) {
rt_thread_delay(50);
SCPara->Cmd = RS485_SENSOR_CMD_QUERY;
SCPara->SensorAddr = SCPara->SensorCnt + 1;
SCPara->SensorType = 0;
SCPara->CmdParaLen = RS485SensorCmdPayLoadLen[RS485_SENSOR_CMD_QUERY];
SCPara->CmdPara = NULL;
//rt_mutex_take(GateWay->UartRevMutex, RT_WAITING_FOREVER);
SCPara->RS485TimeOutCnt = 0;
SCPara->RS485RxLen = 0;
RS485SensorCmdSend(GateWay, SCPara);
SCPara->SendFlag = true;
SCPara->SensorCnt++;
if(SCPara->SensorCnt >= SENSOR_NUM_MAX) {
SCPara->ReadSensorInterval = 2;
SCPara->SensorCnt = 0;
SCPara->ReadSensorCnt = 0;
RS485Ch->QuerySensorFlag = false;
}
}
}
else if(RS485Ch->CUData.Para.SensorN > 0){
SCPara->SendFlag = false;
if(SCPara->ReadSensorInterval > 0) {
SCPara->ReadSensorInterval--;
}
else {
if(SCPara->ReadSensorCnt >= RS485Ch->CUData.Para.SensorN || SCPara->SensorCnt >= SENSOR_NUM_MAX) {
SCPara->SensorCnt = 0;
SCPara->ReadSensorCnt = 0;
SCPara->ReadSensorInterval = GateWay->ConfigPara.CommUnitReadInterval * 5;
RS485Ch->CUData.Para.BatLevel = GateWay->Battery;
CommUintLen = CommUintOrgData(GateWay, &RS485Ch->CUData.Para, &SCPara->SensorData, CommUintData);
//AddLog(&CommUintData[2], CommUintLen - 2);
CatOneEthSendQueue(CommUintData, CommUintLen);
if(RS485Ch == &GateWay->ConfigPara.Rs485Ch1) {
MAIN_DBG_LOG("InCommUint1 Send Meg...\r\n");
}
else {
MAIN_DBG_LOG("InCommUint2 Send Meg...\r\n");
}
SCPara->SensorCnt = 0;
}
else {
if(RS485Ch->CUData.Para.SensorType[SCPara->SensorCnt] != 0) {
rt_thread_delay(50);
SCPara->Cmd = RS485_SENSOR_CMD_READ;
SCPara->SensorAddr = SCPara->SensorCnt + 1;
SCPara->SensorType = RS485Ch->CUData.Para.SensorType[SCPara->SensorCnt];
SCPara->CmdParaLen = RS485SensorCmdPayLoadLen[RS485_SENSOR_CMD_READ];
SCPara->CmdPara = NULL;
//rt_mutex_take(GateWay->UartRevMutex, RT_WAITING_FOREVER);
RS485SensorCmdSend(GateWay, SCPara);
SCPara->SendFlag = true;
}
SCPara->SensorCnt++;
}
}
}
}
else { //读取外置通讯单元
if(SCPara->RS485CommUnitReadTimeDelay >= (GateWay->ConfigPara.CommUnitReadInterval * 5) && SCPara->SendFlag == false) {
if(SCPara->SendUnitCommIdx < COMMUNIT_NUM_MAX) {
if(GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].RegFlag &&
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][2] == 0x02) {
Debug_Printf("RS485Ch%d Read CommUnit: %02X:%02X:%02X:%02X:%02X:%02X\r\n",
((SCPara == &SComm1Para) ? 1 : 2),
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][0],
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][1],
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][2],
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][3],
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][4],
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][5]);
CommUnitCmdSend(GateWay, GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0], COMM_UNIT_CMD_READ, NULL, 0, RS485Ch->RS485Send);
SCPara->SendFlag = true;
}
else {
SCPara->SendUnitCommIdx++;
return;
}
}
else {
SCPara->SendUnitCommIdx = 0;
SCPara->RS485CommUnitReadTimeDelay = 0;
}
}
}
if(SCPara->RS485CommUnitReadTimeDelay < (GateWay->ConfigPara.CommUnitReadInterval * 5))
SCPara->RS485CommUnitReadTimeDelay++;
result = rt_sem_take(SCPara->RS485Rev_Sem, 200);
if(result == RT_EOK) {
memcpy(RxBuffTemp, SCPara->RS485RxBuff, SCPara->RS485RxLen);
RxLenTemp = SCPara->RS485RxLen;
// memset(SCPara->RS485RxBuff, 0x00, RS485_RX_BUFF_LEN_MAX);
SCPara->RS485RxLen = 0;
if(RxBuffTemp[0] == 0x7A && RS485Ch->UpgradeEnable == true) { //升级
update_process(RxBuffTemp,RxLenTemp);
}
else if(RxBuffTemp[0] == 0x7A && RS485Ch->CommUnitEnable == true) { //内置通讯单元数据解析
if(SCPara->SendFlag == false) {
SCPara->RS485RxLen = 0;
return;
}
RS485Analyze(GateWay, SCPara, &RS485Ch->CUData, RxBuffTemp, RxLenTemp);
//rt_mutex_release(GateWay->UartRevMutex);
}
else if(RxBuffTemp[0] == 0x7B && RS485Ch->CommUnitEnable == false){ //读取外部通讯单元数据解析
if(SCPara == &SComm1Para)
ret = GateWay->CommUnitRevCallBack(GateWay, RxBuffTemp, RxLenTemp, GateWay->ConfigPara.Rs485Ch1.RS485Send);
else
ret = GateWay->CommUnitRevCallBack(GateWay, RxBuffTemp, RxLenTemp, GateWay->ConfigPara.Rs485Ch2.RS485Send);
if(ret == 0xff) { //注册信息
SCPara->RS485RxLen = 0;
return;
}
if(SCPara->SendFlag && GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].RevNewDataFlag) {
SCPara->SendUnitCommIdx++;
}
else {
SCPara->RS485RxLen = 0;
return;
}
}
else { //调试命令解析
DebugAnalyze(GateWay, RxBuffTemp, RxLenTemp);
}
SCPara->RS485RxLen = 0;
SCPara->SendFlag = false;
}
else {
if(RS485Ch->CommUnitEnable == true) {
//rt_mutex_release(GateWay->UartRevMutex);
if(SCPara->SendFlag == true) { //&& RS485Ch->CUData.Para.SensorN > 0 && RS485Ch->QuerySensorFlag == false){
if(RS485Ch == &GateWay->ConfigPara.Rs485Ch1) {
test++;
MAIN_DBG_LOG("InCommUint1, Sensor %d Comm Error, Cmd %d...\r\n", SCPara->SensorAddr, SCPara->Cmd);
}
else {
MAIN_DBG_LOG("InCommUint2, Sensor %d Comm Error, Cmd %d...\r\n", SCPara->SensorAddr, SCPara->Cmd);
}
SCPara->SensorErrCnt[SCPara->SensorAddr - 1]++;
if(SCPara->SensorErrCnt[SCPara->SensorAddr - 1] >= 5)
SavSensorData(SCPara->SensorAddr - 1, &SCPara->SensorData, NULL, 0);
}
}
else if(SCPara->SendFlag){
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommErrCnt++;
if(GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommErrCnt == 10) {
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommErrCnt = 0;
if(GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommStatus) {
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommStatus = 0;
MegData[0] = 7;
MegData[1] = COMM_UNIT_CMD_READ;
memcpy(&MegData[2], GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0], 6);
MegData[8] = GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommStatus;
CatOneEthSendQueue(MegData, 9); //发送离线消息
}
}
SCPara->SendUnitCommIdx++;
}
SCPara->SendFlag = false;
}
}
/*****************************************************************************************
* 函数名称: RS485Ch1_Thread_Entry
* 功能描述: RS485通道1任务函数
* 参 数: 任务参数入口
* 返 回 值: 无
*****************************************************************************************/
void RS485Ch1_Thread_Entry(void *parameter)
{
uint8_t InCommUnitMac[6] = {0x01, 0x80, 0x02, 0x00, 0x00, 0x01};
GateWayPara GateWay;
SensorCommPara SCPara;
RS485Para RS485Ch;
SCPara = &SComm1Para;
SCPara->SensorCnt = 0;
SCPara->InitOverFlag = false;
SCPara->ReadSensorInterval = 300;
GateWay = (GateWayPara)parameter;
InCommUnitMac[3] = GateWay->ConfigPara.GwMac[4];
InCommUnitMac[4] = GateWay->ConfigPara.GwMac[5];
RS485Ch = &GateWay->ConfigPara.Rs485Ch1;
memcpy(RS485Ch->CUData.Para.Mac, InCommUnitMac, 6);
if(RS485Ch->CommUnitEnable == true) {
RS485_CH1_POW_ON();
RS485Ch->CUData.Para.SensorN = 0;
memset(RS485Ch->CUData.Para.SensorType, 0x00, sizeof(SENSOR_NUM_MAX * 2));
RS485Ch->QuerySensorFlag = true;
RS485Ch->CUData.Para.CommStatus = true;
}
SCPara->RS485CommUnitReadTimeDelay = 100;
SCPara->RS485Rev_Sem = rt_sem_create("rsch1sem", 0, RT_IPC_FLAG_FIFO);
if(SCPara->RS485Rev_Sem == RT_NULL) {
Debug_Printf("RS485Ch1Rev Sem Create Failed!\r\n");
}
Debug_Printf("RS485Ch1Rev Thread is running\r\n");
rt_thread_delay(3000);
SCPara->InitOverFlag = true;
update_init(RS485Ch1UartSend);
while(1) {
RS485LoopHandler(GateWay, RS485Ch, SCPara);
//rt_thread_delay(10);
}
}
/*****************************************************************************************
* 函数名称: RS485Ch1RxIrqCallback
* 功能描述: RS485通道1中断处理回调函数
* 参 数: rData 接收到的数据
* 返 回 值: 无
*****************************************************************************************/
void RS485Ch1RxIrqCallback(uint8_t rData)
{
if(SComm1Para.RS485TimeOutCnt == 0) {
SComm1Para.RS485RxLen = 0;
}
if(SComm1Para.RS485RxLen < RS485_RX_BUFF_LEN_MAX)
SComm1Para.RS485RxBuff[SComm1Para.RS485RxLen++] = rData;
SComm1Para.RS485TimeOutCnt = 3;
}
/*****************************************************************************************
* 函数名称: RS485Ch2_Thread_Entry
* 功能描述: RS485通道1任务函数
* 参 数: 任务参数入口
* 返 回 值: 无
*****************************************************************************************/
void RS485Ch2_Thread_Entry(void *parameter)
{
uint8_t InCommUnitMac[6] = {0x01, 0x80, 0x02, 0x00, 0x00, 0x02};
GateWayPara GateWay;
SensorCommPara SCPara;
RS485Para RS485Ch;
SCPara = &SComm2Para;
SCPara->SensorCnt = 0;
SCPara->InitOverFlag = false;
SCPara->ReadSensorInterval = 0;
GateWay = (GateWayPara)parameter;
InCommUnitMac[3] = GateWay->ConfigPara.GwMac[4];
InCommUnitMac[4] = GateWay->ConfigPara.GwMac[5];
RS485Ch = &GateWay->ConfigPara.Rs485Ch2;
memcpy(RS485Ch->CUData.Para.Mac, InCommUnitMac, 6);
if(RS485Ch->CommUnitEnable == true) {
RS485_CH2_POW_ON();
RS485Ch->CUData.Para.SensorN = 0;
memset(RS485Ch->CUData.Para.SensorType, 0x00, sizeof(SENSOR_NUM_MAX * 2));
RS485Ch->QuerySensorFlag = true;
RS485Ch->CUData.Para.CommStatus = 1;
}
SCPara->RS485CommUnitReadTimeDelay = 100;
SCPara->RS485Rev_Sem = rt_sem_create("rsch2sem", 0, RT_IPC_FLAG_FIFO);
if(SCPara->RS485Rev_Sem == RT_NULL) {
Debug_Printf("RS485Ch2Rev Sem Create Failed!\r\n");
}
Debug_Printf("RS485Ch2Rev Thread is running\r\n");
rt_thread_delay(3000);
SCPara->InitOverFlag = true;
while(1) {
RS485LoopHandler(GateWay, RS485Ch, SCPara);
//rt_thread_delay(10);
}
}
/*****************************************************************************************
* 函数名称: RS485Ch2RxIrqCallback
* 功能描述: RS485通道1中断处理回调函数
* 参 数: rData 接收到的数据
* 返 回 值: 无
*****************************************************************************************/
void RS485Ch2RxIrqCallback(uint8_t rData)
{
if(SComm2Para.RS485TimeOutCnt == 0) {
SComm2Para.RS485RxLen = 0;
}
if(SComm2Para.RS485RxLen < RS485_RX_BUFF_LEN_MAX)
SComm2Para.RS485RxBuff[SComm2Para.RS485RxLen++] = rData;
SComm2Para.RS485TimeOutCnt = 3;
}
void RS485RxOverhandler(void)
{
if(SComm1Para.RS485TimeOutCnt > 0)
SComm1Para.RS485TimeOutCnt--;
if(SComm1Para.RS485RxLen > 5 && SComm1Para.RS485TimeOutCnt == 0) {
if(SComm1Para.InitOverFlag == true) {
rt_sem_release(SComm1Para.RS485Rev_Sem);
SComm1Para.RS485TimeOutCnt = 20;
}
else {
SComm1Para.RS485RxLen = 0;
SComm1Para.RS485TimeOutCnt = 0;
}
}
if(SComm2Para.RS485TimeOutCnt > 0)
SComm2Para.RS485TimeOutCnt--;
if(SComm2Para.RS485RxLen > 5 && SComm2Para.RS485TimeOutCnt == 0) {
if(SComm2Para.InitOverFlag == true) {
SComm2Para.RS485TimeOutCnt = 20;
rt_sem_release(SComm2Para.RS485Rev_Sem);
}
else {
SComm2Para.RS485RxLen = 0;
SComm2Para.RS485TimeOutCnt = 0;
}
}
}
#if 0
void RS485Ch2RxIrqCallback(uint8_t rData)
{
static bool FrameHeader = false;
static uint8_t rLen = 0;
if(FrameHeader == false) {
if(rData == 0x7a || rData == 0x7b) {
FrameHeader = true;
RS485Chr2RxLen = 0;
}
}
if(RS485Chr2RxLen < RS485_RX_BUFF_LEN_MAX) {
RS485Chr2RxBuff[RS485Chr2RxLen++] = rData;
}
else {
FrameHeader = false;
RS485Chr2RxLen = 0;
}
if(RS485Chr2RxLen == 6) {
rLen = rData + 8;
}
else if(RS485Chr2RxLen > 6) {
if(RS485Chr2RxLen >= rLen) {
rt_sem_release(RS485Ch2Rev_Sem);
FrameHeader = false;
}
}
}
#endif
+420
View File
@@ -0,0 +1,420 @@
/*
数据通信任务
*/
#include "bsp.h"
#include "ringbuffer.h"
#include "protocol.h"
#include "update_protocol.h"
#include "app_comm.h"
#include "app_tp_collect.h"
#include "app_ad_collect.h"
#define USING_SIMULATOR ( 0 )
#define COMM_RECV_OUTTIME (20)
static struct {
ring_buf_t rb;
uint8_t rb_pool[128];
} g_comm;
static struct {
uint8_t rxbuf[256];
int rxbytes;
} g_frame;
static void rs485_rx_cb(uint8_t data)
{
ring_buf_put(&g_comm.rb, &data, 1);
}
/**
返回值:成功:len,失败: 0
***/
static int recive_frame(void)
{
uint8_t data = 0;
int len = ring_buf_len(&g_comm.rb);
if (len == 0)
return 0;
for (int i = 0; i < len; i++) {
if (g_frame.rxbytes < sizeof(g_frame.rxbuf)) {
int byte = ring_buf_get(&g_comm.rb, &data, 1);
if (byte > 0) {
g_frame.rxbuf[ g_frame.rxbytes] = data;
g_frame.rxbytes++;
}
}
}
return len;
}
static void update_on_start(uint8_t* frame, int len, uint8_t* pload, int size)
{
update_protocol_req_t* pReq = (void*)&frame[sizeof(update_protocol_hd_t)];
boot_para_t cfg = {0};
cfg.AppFlag = 0;
cfg.UpdateFlag = APP_UPDATE_FLAG;
cfg.Crc32Check = pReq->AppCrc32;
cfg.PackageNum = pReq->PackageNum;
cfg.AppSize = pReq->AppSize;
dev_boot_write_param(cfg);
update_send_cmd(0x01, 1, pReq->PackageNum);
//重启进入BOOT
NVIC_SystemReset();
}
static int update_cmd_process(uint8_t cmd, void* frame, int len, void* pload, int size)
{
int res = -1;
switch (cmd) {
case 0x81: {
update_on_start(frame, len, pload, size);
res = 0;
}
break;
default:
break;
}
return res;
}
static int update_process(void* frame, int len)
{
uint8_t cmd = 0;
uint8_t slave_addr = 0;
uint8_t user_data[256] = {0};
int user_data_len = 0;
int res = update_unpack(frame, len, &cmd, &slave_addr, user_data, &user_data_len);
if (res != 0)
return -1;
if (slave_addr != 0x01)
return -2;
res = update_cmd_process(cmd, frame, len, user_data, user_data_len);
if (res != 0)
return -3;
return 0;
}
static void comm_rsp(uint8_t slave_addr,uint8_t frame_cmd,void *pay, int len)
{
uint8_t frame_ack[128] = {0};
uint16_t frame_ack_len = 0;
protocol_pack_frame(slave_addr, frame_cmd - 0x80, pay, len, frame_ack, sizeof(frame_ack), &frame_ack_len);
dev_rs485_send(frame_ack, frame_ack_len);
}
static void comm_process(uint8_t* frame, int len)
{
uint16_t slave_addr = 0;
uint8_t frame_cmd = 0;
uint8_t frame_data[64] = {0};
uint16_t frame_data_len = 0;
/***数据解码***/
int err = -1;
err= protocol_unpack_frame(frame, len, &slave_addr, &frame_cmd, frame_data, &frame_data_len);
if (err != PROTOCOL_SUCCESS)
return ;
//TODO:获取本机地址
uint8_t local_addr = 0;
dev_cfg_get_devid(&local_addr);
uint8_t rsp_data[64] = {0};
void* payload = rsp_data;
uint16_t payload_len = 0;
uint8_t is_match =1;
switch (frame_cmd) {
case PROTOCOL_CMD_SET_ID: {
//
if (slave_addr != local_addr)
return ;
id_data_t data = {0};
memcpy(&data, &frame_data, sizeof(data));
dev_cfg_set_devid(data.id);
BSP_LOG("set: device id =[%d] =[0x%x] \n", data.id,data.id);
}
break;
case PROTOCOL_CMD_GET_ID:{
id_data_t id_data = {0};
id_data.id = local_addr;
payload_len = sizeof(id_data);
memcpy(payload ,&id_data,payload_len);
BSP_LOG("get: device id =[%d] =[0x%x] \n", id_data.id,id_data.id);
}break;
case PROTOCOL_CMD_GET_TP: {
//TODO: get tp datas
if (slave_addr != local_addr)
return ;
tp_datas_t tp_data = {0};
collect_tp_info_t tp_info={0};
app_collect_tp_get(&tp_info);
memcpy( &tp_data,&tp_info.tp_datas,sizeof(tp_data));
//兼容旧协议,没有用到的通道,填充无效数据
for(int i=0; i <8-TP_SENSOR_NUM; i++){
tp_data.channels[i+TP_SENSOR_NUM].status =1;
tp_data.channels[i+TP_SENSOR_NUM].value =0;
}
for (int i = 0; i < TP_SENSOR_NUM ; i++) {
char strbuf[128]={0};
snprintf(strbuf,sizeof(strbuf)," comm ad ch[%d] %08.4f \r\n", i, tp_data.channels[i].value);
BSP_LOG("%s",strbuf);
}
BSP_LOG("\r\n");
payload_len = sizeof(tp_data);
memcpy(payload, &tp_data, payload_len);
}break;
case PROTOCOL_CMD_GET_AD: {
//
if (slave_addr != local_addr)
return ;
//TODO: get ad datas
ad_datas_t ad_data = {0};
app_collect_ad_get(&ad_data);
//兼容旧协议,没有用到的通道,填充无效数据
for(int i=0; i <8-YB_SENSOR_NUM; i++){
ad_data.channels[i+5].status =1;
}
BSP_LOG("\r\n");
for (int i = 0; i < YB_SENSOR_NUM ; i++) {
char strbuf[128] = {0};
snprintf(strbuf, sizeof(strbuf), " comm ad ch[%d] %08.4f \r\n", i, ad_data.channels[i].value);
BSP_LOG("%s", strbuf);
}
BSP_LOG("\r\n");
payload_len = sizeof(ad_data);
memcpy(payload, &ad_data, payload_len);
}
break;
case PROTOCOL_CMD_SET_TP_OFFSET:{
if (slave_addr != local_addr)
return ;
offset_set_data_t offset_data={0};
memcpy( &offset_data,frame_data,sizeof(offset_data));
dev_cfg_set_temp_offset(offset_data.id, offset_data.prams.value);
char strbuf[128]={0};
snprintf(strbuf,sizeof(strbuf)," set[%d] offset %.2f \r\n", offset_data.id , offset_data.prams.value);
BSP_LOG("%s",strbuf);
}break;
case PROTOCOL_CMD_GET_TP_OFFSET:{
//
if (slave_addr != local_addr)
return ;
offset_get_param_t *param = (void *)frame_data;
offset_get_data_t offset_data={0};
float val = 200;
dev_cfg_get_temp_offset( param->id,&val);
offset_data.id = param->id;
offset_data.prams.value = val;
payload_len = sizeof(offset_data);
memcpy(payload,&offset_data,payload_len);
char strbuf[128]={0};
snprintf(strbuf,sizeof(strbuf)," get[%d] offset %.2f \r\n", offset_data.id , offset_data.prams.value);
BSP_LOG("%s",strbuf);
}break;
case PROTOCOL_CMD_RESET_CHANNEL: {
//
if (slave_addr != local_addr)
return ;
app_collect_ad_reset_offset();
BSP_LOG("reset offset start");
}
break;
default:
is_match =0;
break;
}
if(is_match ==0)
return;
comm_rsp(slave_addr,frame_cmd, payload, payload_len);
}
void app_comm_entry(void *param)
{
int len = 0;
dev_rs485_init();
dev_rs485_rx_register(rs485_rx_cb);
ring_buf_init(&g_comm.rb, g_comm.rb_pool, sizeof(g_comm.rb_pool));
/***/
update_init(dev_rs485_send);
while (1) {
rt_thread_mdelay(1);
len = recive_frame();
if (len == 0) {
rt_thread_mdelay(5);
len = recive_frame();
if (len == 0) {
if (g_frame.rxbytes > 0) {
update_process(g_frame.rxbuf, g_frame.rxbytes);
comm_process(g_frame.rxbuf, g_frame.rxbytes);
g_frame.rxbytes = 0;
}
}
}
}
}
ALIGN(RT_ALIGN_SIZE)
static uint8_t comm_thd_stack[4096];
static struct rt_thread comm_thd;
int app_comm_init(void)
{
#if USING_SIMULATOR
BSP_LOG("comm data using simulator \n");
#endif
int ret = rt_thread_init(&comm_thd,
"app_comm",
app_comm_entry,
RT_NULL,
comm_thd_stack,
sizeof(comm_thd_stack),
10,
20
);
if(ret == RT_EOK){
rt_thread_startup(&comm_thd);
}
return 0;
}
INIT_APP_EXPORT(app_comm_init);
File diff suppressed because it is too large Load Diff
+645
View File
@@ -0,0 +1,645 @@
#include <stdlib.h>
#include <math.h>
#include "main.h"
#include "CatOneTask.h"
#include "LoraTask.h"
#include "CatOneTask.h"
#include "RS485Task.h"
#include "DebugCmd.h"
#include "spiflash.h"
//雅下: 81-00-00-06-00-01
// 81-00-00-06-00-02
// 81-00-00-06-00-03
// 81-00-00-06-00-04
// 81-00-00-06-00-05
// 81-00-00-06-00-06
// 81-00-00-06-00-07
// 81-00-00-06-00-08
// 81-00-00-06-00-09
// 81-00-00-06-00-0A
static const uint8_t GateWayMac_Test[6] = {0x81, 0x00, 0x00, 0x06, 0x00, 0x00};
static const uint8_t GateWayMac_BL1[6] = {0x81, 0x00, 0x00, 0x06, 0x00, 0x01};
static const uint8_t GateWayMac_BL2[6] = {0x81, 0x00, 0x00, 0x06, 0x00, 0x02};
static const uint8_t GateWayMac_BL3[6] = {0x81, 0x00, 0x00, 0x06, 0x00, 0x03};
static const uint8_t GateWayMac_BL4[6] = {0x81, 0x00, 0x00, 0x06, 0x00, 0x04};
static const uint8_t GateWayMac_BL5[6] = {0x81, 0x00, 0x00, 0x06, 0x00, 0x05};
static const uint8_t GateWayMac_BL6[6] = {0x81, 0x00, 0x00, 0x06, 0x00, 0x06};
static const uint8_t GateWayMac_BL7[6] = {0x81, 0x00, 0x00, 0x06, 0x00, 0x07};
static const uint8_t GateWayMac_BL8[6] = {0x81, 0x00, 0x00, 0x06, 0x00, 0x08};
static const uint8_t GateWayMac_BL9[6] = {0x81, 0x00, 0x00, 0x06, 0x00, 0x09};
static const uint8_t GateWayMac_BL10[6] = {0x81, 0x00, 0x00, 0x06, 0x00, 0x0A};
bool MainDispEn = true;
static rt_thread_t Lora_Thread = RT_NULL;
static rt_thread_t Cat1Eth_Thread = RT_NULL;
static rt_thread_t RS485Ch1_Thread = RT_NULL;
static rt_thread_t RS485Ch2_Thread = RT_NULL;
static rt_thread_t Debug_Thread = RT_NULL;
GateWayPara_t GateWay;
#define ARRAY_DIM(a) (sizeof(a) / sizeof((a)[0]))
//static int Battery_Level_Percent_Table[11] = {3000, 3650, 3700, 3740, 3760, 3795, 3840, 3910, 3980, 4070, 4150};
static int Battery_Level_Percent_Table[11] = {6000, 7300, 7400, 7480, 7520, 7590, 7680, 7820, 7960, 8140, 8300};
int toPercentage(int voltage)
{
int i;
if(voltage < Battery_Level_Percent_Table[0])
return 0;
for(i = 0; i<ARRAY_DIM(Battery_Level_Percent_Table); i++){
if(voltage < Battery_Level_Percent_Table[i])
return i*10 - (10UL * (int)(Battery_Level_Percent_Table[i] - voltage)) /
(int)(Battery_Level_Percent_Table[i] - Battery_Level_Percent_Table[i-1]);;
}
return 100;
}
/*****************************************************************************************
* 函数名称: MainDBGOnOff
* 功能描述: 主调试信息开关函数
* 参 数: OnOff,开关
* 返 回 值: 无
*****************************************************************************************/
void MainDBGOnOff(bool OnOff)
{
MainDispEn = OnOff;
if(OnOff)
Debug_Printf("\r\nMain Display Enable!\r\n\r\n");
else
Debug_Printf("\r\nMain Display Disable!\r\n\r\n");
}
#if 0
uint32_t SDStartBlock;
uint8_t TestData[10 * 512];
uint8_t ADBuff[10 * 512];
void SDCardTest(void)
{
SDStartBlock = 0;
SDCardReadBlocks(SDStartBlock, 10, TestData);
if(TestData[0] != 0xAA) {
SDCardErase(SDStartBlock, 10);
memset(ADBuff, 0xAA, 10 * 512);
SDCardWriteBlocks(SDStartBlock, 10, (uint8_t *)&ADBuff);
}
SDCardReadBlocks(SDStartBlock, 10, TestData);
}
#endif
void InfTest(void)
{
uint8_t sData[10] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A};
RS485_CH1_RX();
RS485_CH1_POW_ON();
rt_thread_delay(100);
RS485_CH1_POW_OFF();
RS485_CH2_POW_ON();
rt_thread_delay(100);
RS485_CH2_POW_OFF();
POWER_LED_OFF();
POWER_LED_ON();
LORA_RX_LED_SET();
LORA_RX_LED_CLR();
RS485_CH1_TX();
RS485_CH2_RX();
RS485Ch1_Config(500000);
RS485Ch2_Config(500000);
RS485Ch1UartSend(sData, 10);
rt_thread_delay(100);
RS485_CH2_TX();
RS485_CH1_RX();
RS485Ch2UartSend(sData, 10);
rt_thread_delay(100);
// SDCardTest();
}
void GateWayInit(void)
{
LogHeader_t Header;
uint32_t FlashID = SpiFlashReadId();
Debug_Printf("FlashID: %08x\r\n", FlashID);
memset((uint8_t *)&GateWay.ConfigPara, 0x00, sizeof(GWConfigPara_t));
int ret = ReadPara((uint8_t *)&GateWay.ConfigPara, sizeof(GWConfigPara_t));
if(GateWay.ConfigPara.SavFlag != LOG_SAV_FLAG) {
memset((uint8_t *)&GateWay.ConfigPara, 0x00, sizeof(GWConfigPara_t));
GateWay.ConfigPara.SavFlag = LOG_SAV_FLAG;
GateWay.ConfigPara.Comm = CATONE_COMM;
// memcpy(GateWay.ConfigPara.GwMac, GateWayMac, 6);
GateWay.ConfigPara.SvrAddr[0] = 8;
GateWay.ConfigPara.SvrAddr[1] = 137;
GateWay.ConfigPara.SvrAddr[2] = 104;
GateWay.ConfigPara.SvrAddr[3] = 4;
GateWay.ConfigPara.SvrPort = 8007;
GateWay.ConfigPara.CommUnitReadInterval = COMMUNIT_READ_SENSOR_INTERVAL_MAX;
memset(GateWay.ConfigPara.CommUnitArray, 0x00, sizeof(CommUnitData_t) * COMMUNIT_NUM_MAX);
GateWay.ConfigPara.Rs485Ch1.Enable = true;
GateWay.ConfigPara.Rs485Ch1.CommUnitEnable = false;
GateWay.ConfigPara.Rs485Ch1.BaudRate = 500000;
GateWay.ConfigPara.Rs485Ch1.UpgradeEnable = true;
GateWay.ConfigPara.Rs485Ch1.Power = false;
GateWay.ConfigPara.Rs485Ch2.Enable = true;
GateWay.ConfigPara.Rs485Ch2.BaudRate = 500000;
GateWay.ConfigPara.Rs485Ch2.UpgradeEnable = false;
GateWay.ConfigPara.Rs485Ch2.CommUnitEnable = false;
GateWay.ConfigPara.Rs485Ch2.Power = true;
GateWay.ConfigPara.Lora.OnOff = true;
GateWay.ConfigPara.Lora.ucChannel = 8;
GateWay.ConfigPara.Lora.ucPower = 20;
GateWay.ConfigPara.Lora.SignalBw = 8;
GateWay.ConfigPara.Lora.SpreadFactor = 9;
GateWay.ConfigPara.Lora.ErrorCoding = 2;
GateWay.ConfigPara.Lora.RegPreamble = 10;
GateWay.ConfigPara.Lora.FreqCent = FREQ_CENT;
GateWay.ConfigPara.OutageFlag = false;
GateWay.ConfigPara.DebugChannel = DEBUG_CH_RS485_1;
}
if(GateWay.ConfigPara.OutageFlag != true && GateWay.ConfigPara.OutageFlag != false)
GateWay.ConfigPara.OutageFlag = false;
GateWay.SvrRegFlag = false;
memset(GateWay.SvrMac, 0x00, 6);
GateWay.ConfigPara.Rs485Ch1.RS485Send = RS485Ch1UartSend;
GateWay.ConfigPara.Rs485Ch2.RS485Send = RS485Ch2UartSend;
GateWay.ConfigPara.Rs485Ch1.Enable = true;
GateWay.ConfigPara.Rs485Ch1.CommUnitEnable = false;
GateWay.ConfigPara.Rs485Ch1.UpgradeEnable = true;
GateWay.ConfigPara.Rs485Ch1.BaudRate = 500000;
GateWay.ConfigPara.Rs485Ch1.Power = false;
GateWay.ConfigPara.Rs485Ch2.Enable = true;
GateWay.ConfigPara.Rs485Ch2.BaudRate = 500000;
GateWay.ConfigPara.Rs485Ch2.CommUnitEnable = false;
GateWay.ConfigPara.Rs485Ch2.UpgradeEnable = false;
GateWay.ConfigPara.Rs485Ch2.Power = false;
GateWay.ConfigPara.Lora.OnOff = true;
GateWay.ConfigPara.Lora.ucChannel = 8;
GateWay.ConfigPara.Lora.ucPower = 20;
GateWay.ConfigPara.Lora.SignalBw = 8;
GateWay.ConfigPara.Lora.SpreadFactor = 9;
GateWay.ConfigPara.Lora.ErrorCoding = 2;
GateWay.ConfigPara.Lora.RegPreamble = 10;
GateWay.ConfigPara.Lora.FreqCent = FREQ_CENT;
#if MAC_ADDR_TYPE == 0
memcpy(GateWay.ConfigPara.GwMac, GateWayMac_Test, 6);
GateWay.ConfigPara.DebugChannel = DEBUG_CH_DBG;
#elif MAC_ADDR_TYPE == 1
memcpy(GateWay.ConfigPara.GwMac, GateWayMac_BL1, 6);
//GateWay.ConfigPara.DebugChannel = DEBUG_CH_RS485_1;
GateWay.ConfigPara.DebugChannel = DEBUG_CH_DBG;
#elif MAC_ADDR_TYPE == 2
memcpy(GateWay.ConfigPara.GwMac, GateWayMac_BL2, 6);
GateWay.ConfigPara.DebugChannel = DEBUG_CH_RS485_1;
//GateWay.ConfigPara.DebugChannel = DEBUG_CH_DBG;
#elif MAC_ADDR_TYPE == 3
memcpy(GateWay.ConfigPara.GwMac, GateWayMac_BL3, 6);
GateWay.ConfigPara.DebugChannel = DEBUG_CH_RS485_1;
#elif MAC_ADDR_TYPE == 4
memcpy(GateWay.ConfigPara.GwMac, GateWayMac_BL4, 6);
GateWay.ConfigPara.DebugChannel = DEBUG_CH_RS485_1;
#elif MAC_ADDR_TYPE == 5
memcpy(GateWay.ConfigPara.GwMac, GateWayMac_BL5, 6);
GateWay.ConfigPara.DebugChannel = DEBUG_CH_RS485_1;
#elif MAC_ADDR_TYPE == 6
memcpy(GateWay.ConfigPara.GwMac, GateWayMac_BL6, 6);
GateWay.ConfigPara.DebugChannel = DEBUG_CH_RS485_1;
#elif MAC_ADDR_TYPE == 7
memcpy(GateWay.ConfigPara.GwMac, GateWayMac_BL7, 6);
GateWay.ConfigPara.DebugChannel = DEBUG_CH_RS485_1;
#elif MAC_ADDR_TYPE == 8
memcpy(GateWay.ConfigPara.GwMac, GateWayMac_BL8, 6);
GateWay.ConfigPara.DebugChannel = DEBUG_CH_RS485_1;
#elif MAC_ADDR_TYPE == 9
memcpy(GateWay.ConfigPara.GwMac, GateWayMac_BL9, 6);
GateWay.ConfigPara.DebugChannel = DEBUG_CH_RS485_1;
#elif MAC_ADDR_TYPE == 10
memcpy(GateWay.ConfigPara.GwMac, GateWayMac_BL10, 6);
GateWay.ConfigPara.DebugChannel = DEBUG_CH_RS485_1;
#endif
#if MAC_ADDR_TYPE == 0//测试服务器
GateWay.ConfigPara.SvrAddr[0] = 39;
GateWay.ConfigPara.SvrAddr[1] = 106;
GateWay.ConfigPara.SvrAddr[2] = 103;
GateWay.ConfigPara.SvrAddr[3] = 147;
GateWay.ConfigPara.SvrPort = 8080;
#elif MAC_ADDR_TYPE > 0
// GateWay.ConfigPara.SvrAddr[0] = 39;
// GateWay.ConfigPara.SvrAddr[1] = 106;
// GateWay.ConfigPara.SvrAddr[2] = 103;
// GateWay.ConfigPara.SvrAddr[3] = 147;
// GateWay.ConfigPara.SvrPort = 8080;
GateWay.ConfigPara.SvrAddr[0] = 103;
GateWay.ConfigPara.SvrAddr[1] = 217;
GateWay.ConfigPara.SvrAddr[2] = 192;
GateWay.ConfigPara.SvrAddr[3] = 248;
GateWay.ConfigPara.SvrPort = 12111;
#endif
if(GateWay.ConfigPara.DebugChannel == DEBUG_CH_RS485_1) {
GateWay.ConfigPara.Rs485Ch1.Enable = true;
GateWay.ConfigPara.Rs485Ch1.BaudRate = 500000;
}
if(GateWay.ConfigPara.Rs485Ch1.BaudRate < 2400 || GateWay.ConfigPara.Rs485Ch1.BaudRate > 921600)
GateWay.ConfigPara.Rs485Ch1.BaudRate = 500000;
RS485Ch1_Config(GateWay.ConfigPara.Rs485Ch1.BaudRate);
if(GateWay.ConfigPara.DebugChannel == DEBUG_CH_RS485_2) {
GateWay.ConfigPara.Rs485Ch2.Enable = true;
GateWay.ConfigPara.Rs485Ch2.BaudRate = 500000;
}
if(GateWay.ConfigPara.Rs485Ch2.BaudRate < 2400 || GateWay.ConfigPara.Rs485Ch2.BaudRate > 921600)
GateWay.ConfigPara.Rs485Ch2.BaudRate = 500000;
RS485Ch2_Config(GateWay.ConfigPara.Rs485Ch2.BaudRate);
if(GateWay.ConfigPara.Rs485Ch1.Power)
RS485_CH1_POW_ON();
else
RS485_CH1_POW_OFF();
if(GateWay.ConfigPara.Rs485Ch2.Power) {
RS485_CH2_POW_OFF();
rt_thread_delay(1000);
RS485_CH2_POW_ON();
}
else
RS485_CH2_POW_OFF();
if(GateWay.ConfigPara.Lora.OnOff == true) {
LORA_POW_ON();
}
else {
LORA_POW_OFF();
}
if(LoraSetChannel(GateWay.ConfigPara.Lora.ucChannel) == false) {
GateWay.ConfigPara.Lora.ucChannel = 8;
LoraSetChannel(GateWay.ConfigPara.Lora.ucChannel);
//WritePara((uint8_t *)&GateWay.ConfigPara, sizeof(GWConfigPara_t));
}
if(LoraSetPower(GateWay.ConfigPara.Lora.ucPower) == false) {
GateWay.ConfigPara.Lora.ucPower = 20;
LoraSetPower(GateWay.ConfigPara.Lora.ucPower);
//WritePara((uint8_t *)&GateWay.ConfigPara, sizeof(GWConfigPara_t));
}
if(LoraSetSignalBw(GateWay.ConfigPara.Lora.SignalBw) == false) {
GateWay.ConfigPara.Lora.SignalBw = 8;
LoraSetSignalBw(GateWay.ConfigPara.Lora.SignalBw);
//WritePara((uint8_t *)&GateWay.ConfigPara, sizeof(GWConfigPara_t));
}
if(LoraSetSpreadFactor(GateWay.ConfigPara.Lora.SpreadFactor) == false) {
GateWay.ConfigPara.Lora.SpreadFactor = 9;
LoraSetSpreadFactor(GateWay.ConfigPara.Lora.SpreadFactor);
//WritePara((uint8_t *)&GateWay.ConfigPara, sizeof(GWConfigPara_t));
}
if(LoraSetErrorCoding(GateWay.ConfigPara.Lora.ErrorCoding) == false) {
GateWay.ConfigPara.Lora.ErrorCoding = 2;
LoraSetErrorCoding(GateWay.ConfigPara.Lora.ErrorCoding);
//WritePara((uint8_t *)&GateWay.ConfigPara, sizeof(GWConfigPara_t));
}
if(GateWay.ConfigPara.Lora.RegPreamble > 0xFE) {
GateWay.ConfigPara.Lora.RegPreamble = 10;
//WritePara((uint8_t *)&GateWay.ConfigPara, sizeof(GWConfigPara_t));
}
LoraSetRegPreamble(GateWay.ConfigPara.Lora.RegPreamble);
WritePara((uint8_t *)&GateWay.ConfigPara, sizeof(GWConfigPara_t));
LogInit();
Header.LogEndAddr = 0;
if(ReadLogNum() > 0) {
int ret = ReadLog(&Header, NULL, 0);
if(ret > 0) {
GateWay.HistoryNum = ReadLogNum() - Header.LogIdx + 1;
rt_kprintf("History Num: %d\r\n", GateWay.HistoryNum);
}
else {
rt_kprintf("History Num: 0\r\n");
}
}
else
rt_kprintf("History Num: 0\r\n");
if(GateWay.ConfigPara.Comm == CATONE_COMM) {
CAT1_ON();
}
else {
ETH_ON();
}
}
void OutageUpdate(uint8_t AlarmType, bool AlarmState, uint8_t Batt)
{
GateWayAlarmType_t *Alarm;
uint8_t MegData[6],len;
len = sizeof(GateWayAlarmType_t);
MegData[0] = len & 0x00ff;;
MegData[1] = (len >> 8) & 0x00ff;
MegData[2] = NET_COMM_CMD_ALARM;
Alarm = (GateWayAlarmType_t *)&MegData[3];
Alarm->AlarmType = AlarmType;
Alarm->AlarmState = AlarmState;
Alarm->AlarmPara = Batt;
CatOneEthSendQueue(MegData, 6); //发送报警信息
}
/*****************************************************************************************
* 函数名称: main
* 功能描述: 主函数
* 参 数: 无
* 返 回 值: 运行错误返回-1
*****************************************************************************************/
static uint8_t LastBattery = 0xff; //上一次电池电压
int main(void)
{
uint16_t OneSecondDlyCnt = 0;
// struct tm cTime;
uint16_t PowerONLedDly = 2000;
uint32_t SystemRseetDlyCnt = 0;
uint32_t BatteryUpdateDlyCnt = 0;
uint8_t AlarmType = 0;
GateWayInit();
rt_kprintf("\r\n\r\n");
rt_kprintf("****************************************************\r\n");
rt_kprintf("** **\r\n");
rt_kprintf("** GateWay **\r\n");
rt_kprintf("** SoftWare V%d.%d **\r\n", SOFTWARE_VERSION / 10, SOFTWARE_VERSION % 10);
rt_kprintf("** HardWare V%d.%d **\r\n", HARDWARE_VERSION / 10, HARDWARE_VERSION % 10);
rt_kprintf("** Compile: %s %s **\r\n", __DATE__, __TIME__);
rt_kprintf("** **\r\n");
rt_kprintf("****************************************************\r\n\r\n");
// TimeGet(&cTime);
// TimeShow(TimeTs());
FeedDog();
//rt_thread_delay(500);
//InfTest();
//FeedDog();
//Cat1DBGOnOff(true);
GateWay.CommUnitRevCallBack = CommUnitAnalyze;
GateWay.SvrRevCallBack = Cat1EthRevCallBack;
GateWay.NetSendData_MQ = rt_mq_create("NetSendMQ", 512, 10, RT_IPC_FLAG_FIFO);
if(GateWay.NetSendData_MQ == RT_NULL) {
rt_kprintf("CatOne MQ Create Failed!\r\n");
}
GateWay.LoraRev_MQ = rt_mq_create("LoraRevMQ", 256, 10, RT_IPC_FLAG_FIFO);
if(GateWay.LoraRev_MQ == RT_NULL) {
rt_kprintf("LoraRev MQ Create Failed!\r\n");
}
GateWay.UartRevMutex = rt_mutex_create("urmutex", RT_IPC_FLAG_FIFO);
if(GateWay.UartRevMutex == RT_NULL) {
rt_kprintf("UR Mutex Create Failed!\r\n");
}
GateWay.SvrRevCallBack = Cat1EthRevCallBack;
RS485Ch1_Thread = rt_thread_create("RS485Ch1", RS485Ch1_Thread_Entry, &GateWay, 2048, 3, 20);
if (RS485Ch1_Thread != RT_NULL)
rt_thread_startup(RS485Ch1_Thread);
else
return -1;
RS485Ch2_Thread = rt_thread_create("RS485Ch2", RS485Ch2_Thread_Entry, &GateWay, 2048, 3, 20);
if (RS485Ch2_Thread != RT_NULL)
rt_thread_startup(RS485Ch2_Thread);
else
return -1;
Debug_Thread = rt_thread_create("DebugUart", Debug_Thread_Entry, &GateWay, 2048, 3, 20);
if (RS485Ch2_Thread != RT_NULL)
rt_thread_startup(Debug_Thread);
else
return -1;
Cat1Eth_Thread = rt_thread_create("Cat1Eth", CatOne_Eth_Thread_Entry, &GateWay, 4096, 3, 20);
if (Cat1Eth_Thread != RT_NULL)
rt_thread_startup(Cat1Eth_Thread);
else
return -1;
Lora_Thread = rt_thread_create("Lora", Lora_Thread_Entry, &GateWay, 1024, 3, 20);
if (Lora_Thread != RT_NULL)
rt_thread_startup(Lora_Thread);
else
return -1;
while(1) {
if(PowerONLedDly > 0) {
PowerONLedDly--;
if(PowerONLedDly == 1) {
POWER_LED_OFF();
}
}
EthRxOverhandler();
RS485RxOverhandler();
DebugRxOverhandler();
if(OneSecondDlyCnt % 200 == 0) {
FeedDog();
LORA_RX_TOGGLE();
POWER_TOGGLE();
}
OneSecondDlyCnt++;
if(OneSecondDlyCnt == 1000) {
OneSecondDlyCnt = 0;
if(GateWay.BatteryReadDlyCnt > 0) {
GateWay.BatteryReadDlyCnt--;
continue;
}
uint16_t ADValue = GetADCBuffPoint();
//V = (AD * 3.3 / 4096) * (R1+R2) / R1; R1 = 200, R2 = 120
//计算出常数为0.0021484375,扩大1000倍
float Voltage = ADValue * 2.1484375;
GateWay.Battery = toPercentage(Voltage);
//上电判断电量
if(LastBattery == 0xff) {
LastBattery = GateWay.Battery;
if(GateWay.ConfigPara.OutageFlag == true) { //有报警
AlarmType = 1;
}
else {
AlarmType = 0;
}
//BatteryUpdateDlyCnt = 2 * 60;
BatteryUpdateDlyCnt = 10;
}
else {
if(GateWay.ConfigPara.OutageFlag == false) { //没有告警,判断电池电压是否降低
if(GateWay.Battery <= LastBattery) {
if(LastBattery <= 5) {
GateWay.ConfigPara.OutageFlag = true;
WritePara((uint8_t *)&GateWay.ConfigPara, sizeof(GWConfigPara_t));
Debug_Printf("The power is cutted.(1) Bat = %d, LBat = %d\r\n", GateWay.Battery, LastBattery);
LastBattery = GateWay.Battery;
AlarmType = 1;
OutageUpdate(AlarmType, GateWay.ConfigPara.OutageFlag, LastBattery);
BatteryUpdateDlyCnt = 20 * 60;
}
else if((LastBattery - GateWay.Battery) > 2) {
GateWay.ConfigPara.OutageFlag = true;
WritePara((uint8_t *)&GateWay.ConfigPara, sizeof(GWConfigPara_t));
LastBattery = GateWay.Battery;
AlarmType = 1;
Debug_Printf("The power is cutted.(2) Bat = %d, LBat = %d\r\n", GateWay.Battery, LastBattery);
OutageUpdate(AlarmType, GateWay.ConfigPara.OutageFlag, LastBattery);
BatteryUpdateDlyCnt = 20 * 60;
}
}
else { //充电,更新上一次电池电压
LastBattery = GateWay.Battery;
}
}
else {
if(GateWay.Battery >= LastBattery) {
if(LastBattery > 95) {
GateWay.ConfigPara.OutageFlag = false;
WritePara((uint8_t *)&GateWay.ConfigPara, sizeof(GWConfigPara_t));
Debug_Printf("The power is restored.(1) Bat = %d, LBat = %d\r\n", GateWay.Battery, LastBattery);
LastBattery = GateWay.Battery;
AlarmType = 1;
OutageUpdate(AlarmType, GateWay.ConfigPara.OutageFlag, LastBattery);
BatteryUpdateDlyCnt = 90 * 60;
AlarmType = 0;
}
else if(GateWay.Battery - LastBattery > 5) {
GateWay.ConfigPara.OutageFlag = false;
WritePara((uint8_t *)&GateWay.ConfigPara, sizeof(GWConfigPara_t));
Debug_Printf("The power is restored.(2) Bat = %d, LBat = %d\r\n", GateWay.Battery, LastBattery);
LastBattery = GateWay.Battery;
AlarmType = 1;
OutageUpdate(AlarmType, GateWay.ConfigPara.OutageFlag, LastBattery);
BatteryUpdateDlyCnt = 90 * 60;
AlarmType = 0;
}
}
else { //电池继续放电,更新上一次电池电压
LastBattery = GateWay.Battery;
}
}
}
BatteryUpdateDlyCnt--;
if(BatteryUpdateDlyCnt == 0) {
if(GateWay.ConfigPara.OutageFlag) { //有报警
BatteryUpdateDlyCnt = 20 * 60;
}
else {
BatteryUpdateDlyCnt = 90 * 60;
}
OutageUpdate(AlarmType, GateWay.ConfigPara.OutageFlag, LastBattery);
}
//ADC_Start();
}
SystemRseetDlyCnt++;
if(SystemRseetDlyCnt > (24 * 60 * 60 * 1000)) {
SystemRseetDlyCnt = 0;
Debug_Printf("The system resets periodically.\r\n");
rt_thread_delay(10);
NVIC_SystemReset();
}
rt_thread_delay(1);
}
}
#if 0
static FATFS SDFatFs;
static FIL TestFile;
static uint8_t u8WorkBuffer[FF_MAX_SS];
void FSInit(void)
{
FRESULT fRet;
uint32_t u32WBNbr, u32RBNbr;
char SDPath[] = "1:";
MKFS_PARM opt;
uint8_t u8ReadText[100];
en_result_t enTestRet = Error;
uint8_t u8WriteText[] = "This is a string used to test the FatFs";
if (FR_OK != f_mount(&SDFatFs, (TCHAR const*)SDPath, 0U)) {
rt_kprintf("FatFs Initialization Error!\r\n");
}
else {
memset(&opt, 0, sizeof(MKFS_PARM));
opt.fmt = (BYTE)FM_FAT32;
/* Create a FAT file system (format) on the logical drive */
if (FR_OK != f_mkfs((TCHAR const*)SDPath, &opt, u8WorkBuffer, sizeof(u8WorkBuffer))) {
rt_kprintf("FatFs Format Error!\r\n");
}
else {
/* Create and Open a new text file object with write access */
if (FR_OK != f_open(&TestFile, "1:Test.txt", ((BYTE)FA_CREATE_ALWAYS | (BYTE)FA_WRITE))) {
rt_kprintf("\"Test.txt\" file Open for write Error!\r\n");
}
else {
/* Write data to the text file */
fRet = f_write(&TestFile, u8WriteText, sizeof(u8WriteText), (void *)&u32WBNbr);
if ((0UL == u32WBNbr) || (FR_OK != fRet)) {
rt_kprintf("\"Test.txt\" file Write or EOF Error!\r\n");
else {
/* Close the open text file */
f_close(&TestFile);
/* Open the text file object with read access */
if (FR_OK != f_open(&TestFile, "1:Test.txt", (BYTE)FA_READ)) {
rt_kprintf("\"Test.txt\" file Open for read Error!\r\n");
}
else {
memset(u8ReadText, 0, sizeof(u8ReadText));
/* Read data from the text file */
fRet = f_read(&TestFile, u8ReadText, sizeof(u8ReadText), (UINT*)(uint32_t)&u32RBNbr);
if ((0UL == u32RBNbr) || (FR_OK != fRet)) {
rt_kprintf("\"Test.txt\" file Read or EOF Error!\r\n");
}
else {
/* Close the open text file */
f_close(&TestFile);
/* Compare read data with the expected data */
if (u32RBNbr == u32WBNbr) {
/* Check data value */
if (0 == memcmp(u8WriteText, u8ReadText, u32RBNbr)) {
enTestRet = Ok;
}
}
}
}
}
}
}
}
/* Unlink the micro SD disk I/O driver */
f_mount(NULL, (TCHAR const*)SDPath, 0U);
if(enTestRet != Ok) {
rt_kprintf("Error!\r\n");
}
else {
rt_kprintf("Ok!\r\n");
}
}
#endif
+120
View File
@@ -0,0 +1,120 @@
#include "protocol.h"
#include "string.h"
#include "utils.h"
int protocol_pack_frame(
uint16_t slave_addr,
uint8_t command,const
uint8_t *payload,
uint16_t payload_len,
uint8_t *buffer,uint16_t buffer_size,
uint16_t *packed_len)
{
// 构建基础帧头
buffer[0] = PROTOCOL_HEAD & 0xFF;
buffer[1] = (PROTOCOL_HEAD >> 8) & 0xFF;
buffer[2] = slave_addr & 0xFF;
buffer[3] = (slave_addr >> 8) & 0xFF;
buffer[4] = command;
buffer[5] = payload_len & 0xFF;
buffer[6] = (payload_len >> 8) & 0xFF;
// 复制有效载荷(保持小端格式)
if (payload_len > 0 && payload != NULL) {
memcpy(buffer + PROTOCOL_FRAME_HEAD_SIZE , payload, payload_len);
}
// 设置实际长度
int fram_len = PROTOCOL_FRAME_MIN_SIZE + payload_len;
// 计算CRC(覆盖地址、命令、长度和有效载荷)
uint16_t crc = 0xFFFF;
crc = modbus_crc16(buffer,fram_len -2);
// 写入CRC(保持小端格式)
buffer[fram_len-2] = (uint8_t)(crc & 0xFF);
buffer[fram_len-1] = (uint8_t)(crc >> 8);
*packed_len =fram_len;
return PROTOCOL_SUCCESS;
}
int protocol_unpack_frame(
const uint8_t *frame,
uint16_t frame_len,
uint16_t *slave_addr,
uint8_t *command,
uint8_t *payload,
uint16_t *payload_len
) {
// 参数校验
if (frame == NULL || slave_addr == NULL || command == NULL || payload_len == NULL) {
return PROTOCOL_ERR_INVALID_PARAM;
}
if (frame_len < PROTOCOL_FRAME_MIN_SIZE) {
return PROTOCOL_ERR_INVALID_PARAM;
}
// 帧头校验
uint16_t header = (frame[0] | frame[1] <<8);
if (header != PROTOCOL_HEAD) {
return PROTOCOL_ERR_INVALID_PARAM;
}
// 基础字段解析
*slave_addr = (frame[2] | frame[3] << 8);
*command = frame[4];
*payload_len = (frame[5] | frame[6] << 8);
// 数据完整性校验
if (*payload_len > (frame_len - PROTOCOL_FRAME_MIN_SIZE)) {
return PROTOCOL_ERR_BUFFER_OVERFLOW;
}
int frame_size = *payload_len + 9;
uint16_t calc_crc =0xffff;
calc_crc = modbus_crc16((uint8_t *)frame, frame_size -2 );
// 校验CRC(保持小端格式)
union{
uint16_t value;
struct{
uint8_t crcl;
uint8_t crch;
}bytes;
}crc_data;
crc_data.bytes.crcl =(frame[frame_size - 2] ) ;
crc_data.bytes.crch =(frame[frame_size - 1] ) ;
if (calc_crc != crc_data.value) {
return PROTOCOL_ERR_CRC;
}
// 复制有效载荷(保持小端格式)
if (*payload_len > 0 && payload != NULL) {
memcpy(payload, frame + PROTOCOL_FRAME_HEAD_SIZE, *payload_len);
}
return PROTOCOL_SUCCESS;
}
@@ -0,0 +1,89 @@
/******************************************************************************
* @brief 环形缓冲区管理(参考linux/kfifo)
*
* Copyright (c) 2016~2020, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2016-05-30 Morro 初版完成
******************************************************************************/
#include "ringbuffer.h"
#include <string.h>
#include <stddef.h>
#define min(a,b) ( (a) < (b) )? (a):(b)
/*
*@brief 构造一个空环形缓冲区
*@param[in] r - 环形缓冲区管理器
*@param[in] buf - 数据缓冲区
*@param[in] len - buf长度(必须是2的N次幂)
*@retval bool
*/
bool ring_buf_init(ring_buf_t *r,unsigned char *buf, unsigned int len)
{
r->buf = buf;
r->size = len;
r->front = r->rear = 0;
return (buf != NULL) && ((len & len -1) == 0);
}
/*
*@brief 清空环形缓冲区
*@param[in] r - 待清空的环形缓冲区
*@retval none
*/
void ring_buf_clr(ring_buf_t *r)
{
r->front = r->rear = 0;
}
/*
*@brief 获取环形缓冲区数据长度
*@retval 环形缓冲区中有效字节数
*/
int ring_buf_len(ring_buf_t *r)
{
return r->rear - r->front;
}
/*
*@brief 将指定长度的数据放到环形缓冲区中
*@param[in] buf - 数据缓冲区
* len - 缓冲区长度
*@retval 实际放到中的数据
*/
int ring_buf_put(ring_buf_t *r,unsigned char *buf,unsigned int len)
{
unsigned int i;
unsigned int left;
left = r->size + r->front - r->rear;
len = min(len , left);
i = min(len, r->size - (r->rear & r->size - 1));
memcpy(r->buf + (r->rear & r->size - 1), buf, i);
memcpy(r->buf, buf + i, len - i);
r->rear += len;
return len;
}
/*
*@brief 从环形缓冲区中读取指定长度的数据
*@param[in] len - 读取长度
*@param[out] buf - 输出数据缓冲区
*@retval 实际读取长度
*/
int ring_buf_get(ring_buf_t *r,unsigned char *buf,unsigned int len)
{
unsigned int i;
unsigned int left;
left = r->rear - r->front;
len = min(len , left);
i = min(len, r->size - (r->front & r->size - 1));
memcpy(buf, r->buf + (r->front & r->size - 1), i);
memcpy(buf + i, r->buf, len - i);
r->front += len;
return len;
}
+497
View File
@@ -0,0 +1,497 @@
#include "spiflash.h"
#include "rtthread.h"
#include "DebugCmd.h"
#include "Public.h"
//#define FLASH_TEST
#ifdef FLASH_TEST
uint8_t flashtestbuff[SPIFLASH_SIZE];
#endif
static uint8_t SpiFlashReadByte(void)
{
return Spi1SendReceive(0);
}
static void SpiFlashSendByte(uint8_t sData)
{
Spi1SendReceive(sData);
}
static void SpiFlashWriteEnable(void)
{
SpiFlashClrNss();
SpiFlashSendByte(SPIFLASH_CMD_WREN);
SpiFlashSetNss();
}
static void SpiFlashWaitForWriteEnd(void)
{
uint8_t flashstatus = 0;
SpiFlashClrNss();
SpiFlashSendByte(SPIFLASH_CMD_RDSR);
do{
flashstatus = SpiFlashReadByte();
}
while ((flashstatus & SPIFLASH_WIP_FLAG) == SPIFLASH_WIP_FLAG);
SpiFlashSetNss();
}
//扇区擦除
void SpiFlashEraseSector(uint32_t SectorAddr)
{
#ifdef FLASH_TEST
memset(&flashtestbuff[SectorAddr], 0xff, 4096);
#else
SpiFlashWriteEnable();
SpiFlashWaitForWriteEnd();
SpiFlashClrNss();
SpiFlashSendByte(SPIFLASH_CMD_SE);
SpiFlashSendByte((SectorAddr >> 16) & 0x00FF);
SpiFlashSendByte((SectorAddr >> 8) & 0x00FF);
SpiFlashSendByte(SectorAddr & 0x00FF);
SpiFlashSetNss();
SpiFlashWaitForWriteEnd();
#endif
}
//整片擦除
void SpiFlashEraseChip(void)
{
SpiFlashWriteEnable();
SpiFlashClrNss();
SpiFlashSendByte(SPIFLASH_CMD_BE);
SpiFlashSetNss();
SpiFlashWaitForWriteEnd();
}
//写数据
void SpiFlashWriteData(uint8_t* wData, uint32_t wAddr, uint16_t wLen)
{
#ifdef FLASH_TEST
memcpy(&flashtestbuff[wAddr], wData, wLen);
#else
SpiFlashWriteEnable();
SpiFlashClrNss();
SpiFlashSendByte(SPIFLASH_CMD_WRITE);
SpiFlashSendByte((wAddr >> 16) & 0x00FF);
SpiFlashSendByte((wAddr >> 8) & 0x00FF);
SpiFlashSendByte(wAddr & 0x00FF);
for(int i = 0; i < wLen; i++) {
SpiFlashSendByte(wData[i]);
}
SpiFlashSetNss();
SpiFlashWaitForWriteEnd();
#endif
}
void SpiFlashWriteAnyLengthData(uint8_t* wData, uint32_t wAddr, uint16_t wLen)
{
uint16_t PageCnt; //需要写入页数
uint16_t FirstPageWriteSize; //在起始地址不为页起始地址的情况下,先写入当前页剩余空间
uint16_t LastPageWriteSize; //最后一页写入长度
uint32_t AddrOffset = 0;
uint32_t WriteAddr;
LogHeader LogH;
WriteAddr = wAddr;
//写入的长度超出最大空间,从起始开始写起
if((WriteAddr + wLen) > SPIFLASH_SIZE) {
LogH = (LogHeader)wData;
WriteAddr = LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE;
LogH->LogEndAddr = WriteAddr + wLen;
}
uint16_t FirstPageRemainSpace = SPIFLASH_PAGESIZE - (WriteAddr % SPIFLASH_PAGESIZE);
// //判断是否跨扇区,跨扇区需要先擦除下一扇区
// CheckDelSecter(wAddr, wLen);
if(wLen < FirstPageRemainSpace) {
FirstPageWriteSize = wLen; //计算首页写入长度
PageCnt = 0;
LastPageWriteSize = 0;
}
else {
// FirstPageWriteSize = FirstPageRemainSpace % SPIFLASH_PAGESIZE;
// PageCnt = (wLen - (FirstPageWriteSize % SPIFLASH_PAGESIZE)) / SPIFLASH_PAGESIZE; //计算需要写入多少整页
// LastPageWriteSize = (wLen - (FirstPageWriteSize % SPIFLASH_PAGESIZE)) % SPIFLASH_PAGESIZE; //计算剩余需要写入的长度
FirstPageWriteSize = FirstPageRemainSpace;
PageCnt = (wLen - FirstPageWriteSize) / SPIFLASH_PAGESIZE; //计算需要写入多少整页
LastPageWriteSize = (wLen - FirstPageWriteSize) % SPIFLASH_PAGESIZE; //计算剩余需要写入的长度
}
if(FirstPageWriteSize > 0) {
SpiFlashWriteData(&wData[AddrOffset], WriteAddr, FirstPageWriteSize);
AddrOffset += FirstPageWriteSize;
WriteAddr += FirstPageWriteSize;
}
for(int i = 0; i < PageCnt; i++) {
SpiFlashWriteData(&wData[AddrOffset], WriteAddr, SPIFLASH_PAGESIZE);
AddrOffset += SPIFLASH_PAGESIZE;
WriteAddr += SPIFLASH_PAGESIZE;
}
if(LastPageWriteSize > 0) {
SpiFlashWriteData(&wData[AddrOffset], WriteAddr, LastPageWriteSize);
}
}
void SpiFlashReadAnyLengthData(uint8_t* rData, uint32_t rAddr, uint16_t rLen)
{
#ifdef FLASH_TEST
memcpy(rData, &flashtestbuff[rAddr], rLen);
#else
SpiFlashClrNss();
SpiFlashSendByte(SPIFLASH_CMD_READ);
SpiFlashSendByte((rAddr >> 16) & 0x00FF);
SpiFlashSendByte((rAddr >> 8) & 0x00FF);
SpiFlashSendByte(rAddr & 0x00FF);
for(int i = 0; i < rLen; i++) {
rData[i] = SpiFlashReadByte();
}
SpiFlashSetNss();
#endif
}
uint32_t SpiFlashReadId(void)
{
uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
SpiFlashClrNss();
SpiFlashSendByte(0x9F);
Temp0 = SpiFlashReadByte();
Temp1 = SpiFlashReadByte();
Temp2 = SpiFlashReadByte();
SpiFlashSetNss();
Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
return Temp;
}
typedef struct {
uint16_t Flag;
uint16_t LoopSavFlag; //循环存储标志
uint32_t LogCnt; //日志最大数量
uint32_t FirstLogStartAddr; //第一个数据的起始地址
uint32_t LastLogEndAddr; //最后一个数据的结束地址
}LogNumSav_t;
static LogNumSav_t LogNumArray[256];
static __IO uint32_t gLogCnt = 0;
static __IO uint32_t FirstLogStartAddr = 0; //第一个日志起始地址
static __IO uint32_t LastLogEndAddr = 0; //最后一个日志结束地址
static __IO uint16_t LoopSavFlag = 0; //循环存储标志
static uint16_t LogNumIdx;
uint16_t ReadLoopSavFlag(void)
{
return LoopSavFlag;
}
void SetLoopSavFlag(uint16_t LoopFlag)
{
LoopSavFlag = LoopFlag;
}
uint32_t ReadLogNum(void)
{
return gLogCnt;
}
void SetLogNum(uint32_t LogCnt)
{
gLogCnt = LogCnt;
}
uint32_t ReadFirstLogStartAddr(void)
{
return FirstLogStartAddr;
}
void SetFirstLogStartAddr(uint32_t FLStartAddr)
{
FirstLogStartAddr = FLStartAddr;
}
uint32_t ReadLastLogEndAddr(void)
{
return LastLogEndAddr;
}
void SetLastLogEndAddr(uint32_t LLEndAddr)
{
LastLogEndAddr = LLEndAddr;
}
void LogInit(void)
{
LogNumIdx = 0xffff;
SpiFlashReadId();
SpiFlashReadAnyLengthData((uint8_t *)&LogNumArray, LOG_INFO_START_SECTOR * SPIFLASH_SECTORSIZE, sizeof(LogNumArray));
for(int i = 0; i < 256; i++) {
if(LogNumArray[i].Flag != LOG_INFO_SAV_FLAG) {
LogNumIdx = i;
break;
}
}
if(LogNumIdx == 0xffff) { //256条记录满,读最后一条记录
LogNumIdx = 0;
SetLogNum(LogNumArray[255].LogCnt);
SetLoopSavFlag(LogNumArray[255].LoopSavFlag);
SetFirstLogStartAddr(LogNumArray[255].FirstLogStartAddr);
SetLastLogEndAddr(LogNumArray[255].LastLogEndAddr);
return;
}
if(LogNumIdx == 0) { //没有记录
LogNumIdx = 0;
SetLogNum(0);
SetLoopSavFlag(0);
SetFirstLogStartAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
SetLastLogEndAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
return;
}
SetLogNum(LogNumArray[LogNumIdx-1].LogCnt);
SetLoopSavFlag(LogNumArray[LogNumIdx-1].LoopSavFlag);
SetFirstLogStartAddr(LogNumArray[LogNumIdx-1].FirstLogStartAddr);
SetLastLogEndAddr(LogNumArray[LogNumIdx-1].LastLogEndAddr);
}
void SavLogNum(uint32_t LogNum)
{
LogNumSav_t CLogSav;
if(LogNum == 0) {
LogNumIdx = 0;
SetLogNum(0);
SetLoopSavFlag(0);
SetFirstLogStartAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
SetLastLogEndAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
SpiFlashEraseSector(LOG_INFO_START_SECTOR * SPIFLASH_SECTORSIZE);
return;
}
SetLogNum(LogNum);
CLogSav.Flag = LOG_INFO_SAV_FLAG;
CLogSav.LogCnt = LogNum;
CLogSav.FirstLogStartAddr = ReadFirstLogStartAddr();
CLogSav.LastLogEndAddr = ReadLastLogEndAddr();
if(LogNumIdx == 256) {
SpiFlashEraseSector(LOG_INFO_START_SECTOR * SPIFLASH_SECTORSIZE);
LogNumIdx = 0;
}
SpiFlashWriteData((uint8_t *)&CLogSav, LogNumIdx * sizeof(LogNumSav_t) + LOG_INFO_START_SECTOR * SPIFLASH_SECTORSIZE, sizeof(LogNumSav_t));
LogNumIdx++;
}
/*****************************************************************************************
* 函数名称: CheckDelSecter
* 功能描述: 检查需要删除的扇区,跨扇区删除下一扇区,如果到了删除最后一个扇区,循环到起始扇区
* 参 数: wAddr, 写入地址
wLen, 写入长度
* 返 回 值: 返回写入起始地址
*****************************************************************************************/
uint8_t LogBuff[LOG_SAV_SIZE_MAX];
const uint8_t SavFlag[4] ={0xAA, 0x55, 0x55, 0xAA};
void CheckDelSecter(uint32_t wAddr, uint16_t wLen)
{
uint32_t DelOffsetAddr, FindFirstLogAddr; //存储起始地址
uint32_t DelSectorNum = 0;
uint32_t SurplusSpace = SPIFLASH_SECTORSIZE - (wAddr % SPIFLASH_SECTORSIZE);
if((wAddr + wLen) > SPIFLASH_SIZE) {
DelOffsetAddr = LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE;
SetLastLogEndAddr(DelOffsetAddr + wLen);
SetLoopSavFlag(1);
SpiFlashEraseSector(DelOffsetAddr);
FindFirstLogAddr = DelOffsetAddr + SPIFLASH_SECTORSIZE;
}
else {
if(wLen < SurplusSpace) { //长度没有超过扇区剩余容量
SetLastLogEndAddr(wAddr + wLen);
return;
}
DelOffsetAddr = (wAddr / SPIFLASH_SECTORSIZE + 1) * SPIFLASH_SECTORSIZE;
DelSectorNum = (wLen - SurplusSpace) / SPIFLASH_SECTORSIZE + 1;
SetLastLogEndAddr(wAddr + wLen);
for(int i = 0; i < DelSectorNum; i++) {
SpiFlashEraseSector(DelOffsetAddr);
DelOffsetAddr += SPIFLASH_SECTORSIZE;
}
if(DelOffsetAddr == SPIFLASH_SIZE) {
DelOffsetAddr = LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE;
}
FindFirstLogAddr = DelOffsetAddr;
}
if(!ReadLoopSavFlag())
return;
uint32_t ReadAddr = FindFirstLogAddr;
while(1) {
SpiFlashReadAnyLengthData(LogBuff, ReadAddr, LOG_SAV_SIZE_MAX);
int i;
for(i = 0; i < LOG_SAV_SIZE_MAX; i++) {
if(memcmp(&LogBuff[i], SavFlag, 4) == 0) {
SetFirstLogStartAddr(ReadAddr + i);
return;;
}
}
if(i == LOG_SAV_SIZE_MAX) {
ReadAddr += LOG_SAV_SIZE_MAX;
if(ReadAddr >= SPIFLASH_SIZE) { //找不到下一条数据,重置flash
Debug_Printf("Add LOG Error, Next Data No Find!\r\n");
SetLogNum(0);
SetLoopSavFlag(0);
SetFirstLogStartAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
SetLastLogEndAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
return;
}
}
}
}
uint8_t LogBuffTemp[LOG_SAV_SIZE_MAX];
void AddLog(uint8_t *wData, uint32_t wLen)
{
//const uint8_t SavFlag[4] ={0xAA, 0x55, 0x55, 0xAA};
uint32_t LogNum;
uint32_t LogSize;
//uint32_t FLStartAddr;
uint32_t LLEndAddr;
// uint32_t SectorN;
LogHeader LogH;
LogH = (LogHeader)LogBuffTemp;
LogNum = ReadLogNum();
if(LogNum == 0) {
SetFirstLogStartAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
SetLastLogEndAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
SpiFlashEraseSector(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
}
//FLStartAddr = ReadFirstLogStartAddr();
LLEndAddr = ReadLastLogEndAddr();
LogNum++;
LogH->LogSavFlag = LOG_SAV_FLAG;
LogH->LogIdx = LogNum;
LogSize = wLen + sizeof(LogHeader_t);
LogH->LogEndAddr = LLEndAddr + LogSize;
LogH->TimeStamp = TimeTs();
memcpy(&LogBuffTemp[sizeof(LogHeader_t)], wData, wLen);
//判断是否跨扇区,跨扇区需要先擦除下一扇区
CheckDelSecter(LLEndAddr, LogSize);
if(LogH->LogEndAddr > SPIFLASH_SIZE) {
LLEndAddr = LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE;
LogH->LogEndAddr = ReadLastLogEndAddr();
}
SpiFlashWriteAnyLengthData(LogBuffTemp, LLEndAddr, LogSize);
SavLogNum(LogNum);
//Debug_Printf("Add LOG: %d,endaddr = %d\r\n", LogNum, ReadLastLogEndAddr());
}
/*****************************************************************************************
* 函数名称: ReadLog
* 功能描述: 读取日志
* 参 数: Header, 上一包日志头信息,连续读取时传入上一包数据信息,缩短日志遍历时间,
Header->LogEndAddr为0读取第一包数据,LogIdx数据无效
rData, 日志出口,需要释放
LogIdx, 读取的日志的序号,为0读取Header->LogEndAddr对应日志
* 返 回 值: 返回数据长度
*****************************************************************************************/
int ReadLog(LogHeader Header, uint8_t **rData, uint32_t LogIdx)
{
uint32_t FSAddr;
int LogLen = 0;
//bool FirstIdx = false;
if(Header == NULL)
return 0;
if(Header->LogEndAddr == 0) {
Header->LogEndAddr = ReadFirstLogStartAddr();
LogIdx = 0;
}
if(LogIdx == 1) {
FSAddr = ReadFirstLogStartAddr();
}
else
FSAddr = Header->LogEndAddr;
while(1) {
SpiFlashReadAnyLengthData((uint8_t *)Header, FSAddr, sizeof(LogHeader_t));
if(Header->LogSavFlag != LOG_SAV_FLAG) {
if((SPIFLASH_SIZE - FSAddr) < LOG_SAV_SIZE_MAX) { //判断是否到片尾
FSAddr = LOG_SAV_START_SECTOR * SPIFLASH_SECTOR_NUM;
continue;
}
else
return 0;
}
if(LogIdx == 0) {
LogIdx = Header->LogIdx;
}
else if(Header->LogIdx != LogIdx) {
FSAddr = Header->LogEndAddr;
continue;
}
if(Header->LogIdx == LogIdx) {
if(*rData == NULL)
return sizeof(LogHeader_t);
SpiFlashReadAnyLengthData(LogBuffTemp, FSAddr, Header->LogEndAddr - FSAddr);
LogLen = Header->LogEndAddr - FSAddr - sizeof(LogHeader_t);
void *pTemp = rt_malloc(LogLen);
if(pTemp == NULL)
return 0;
*rData =pTemp;
memcpy(*rData, &LogBuffTemp[sizeof(LogHeader_t)], LogLen);
break;
}
}
return LogLen;
}
/*****************************************************************************************
* 函数名称: ReadPara
* 功能描述: 读取参数
* 参 数: Para, 网关参数
ParaLen, 参数长度
* 返 回 值: 无
*****************************************************************************************/
int ReadPara(uint8_t *Para, uint32_t ParaLen)
{
SpiFlashReadAnyLengthData(Para, GATEWEY_PARA_SAV_ADDR, ParaLen); //读取片尾数据
uint16_t Check = CRC_Modbus(0xA001, Para, ParaLen - 2);
GWConfigPara CfgPara = (GWConfigPara)Para;
if(CfgPara->crc16 != Check)
return -1;
return 0;
}
/*****************************************************************************************
* 函数名称: WritePara
* 功能描述: 写入参数
* 参 数: Para, 网关参数
ParaLen, 参数长度
* 返 回 值: 无
*****************************************************************************************/
int WritePara(uint8_t *Para, uint32_t ParaLen)
{
SpiFlashEraseSector(GATEWEY_PARA_SAV_ADDR);
uint16_t Check = CRC_Modbus(0xA001, Para, ParaLen - 2);
GWConfigPara CfgPara = (GWConfigPara)Para;
CfgPara->crc16 = Check;
SpiFlashWriteAnyLengthData(Para, GATEWEY_PARA_SAV_ADDR, ParaLen); //读取片尾数据
return 0;
}
/* USER CODE END */
@@ -0,0 +1,95 @@
#include "update_protocol.h"
#include "string.h"
#include "public.h"
static struct
{
update_send_t pfnSend;
}g_update_protoc;
void update_send_cmd(uint8_t Cmd, uint16_t Indx, int PageNum)
{
uint8_t sData[24]={0};
uint8_t sLen =0;
uint16_t crc16;
update_protocol_hd_t *Frame = (update_protocol_hd_t*)sData;
Frame->Header = 0x7a;
Frame->SlvAddr = 0x01;
Frame->Cmd = Cmd;
if (Cmd == 0x01)
{
Frame->PayloadLen = 1;
sData[sizeof(update_protocol_hd_t)] = Indx;
}
else if (Cmd == 0x02)
{
Frame->PayloadLen = 4;
update_protocol_get_t *GDData = (update_protocol_get_t*)&sData[sizeof(update_protocol_hd_t)];
GDData->PackageIndex = Indx;
GDData->PackageNum = PageNum;
}
sLen = sizeof(update_protocol_hd_t) + Frame->PayloadLen;
crc16 = CRC_Modbus(CRC16_BASE, sData, sLen);
sData[sLen++] = crc16;
sData[sLen++] = (crc16 >> 8) & 0x00ff;
g_update_protoc.pfnSend(sData, sLen);
}
void update_init(update_send_t pCbs)
{
g_update_protoc.pfnSend =pCbs;
}
int update_unpack(uint8_t* rxData, int rLen,uint8_t *cmd, uint8_t* dev_addr, void *pload, int *pLen){
uint16_t crc16;
uint16_t check;
check = CRC_Modbus(CRC16_BASE, rxData, rLen - 2);
crc16 = (rxData[rLen - 1] << 8) | rxData[rLen - 2];
if (check != crc16 || rxData[0] !=0x7a || pload ==0)
{
return -1;
}
update_protocol_hd_t *Frame = (update_protocol_hd_t*)rxData;
*dev_addr = Frame->SlvAddr;
*cmd = Frame->Cmd;
if (Frame->Cmd == 0x81){
//update_protocol_req_t *UpData = (update_protocol_req_t*)&rxData[sizeof(update_protocol_hd_t)];
pload = 0;
*pLen = 0;
}else if (Frame->Cmd == 0x82){
update_protocol_rsp_t *DownData = (update_protocol_rsp_t *)&rxData[sizeof(update_protocol_hd_t)];
memcpy(pload , &rxData[sizeof(update_protocol_hd_t) + sizeof(update_protocol_rsp_t)],DownData->DataLen);
*pLen = DownData->DataLen;
}else{
return -2;
}
return 0;
}
+43
View File
@@ -0,0 +1,43 @@
#include "utils.h"
/*
生成多项式 (x^16 + x^15 + x^2 + 1
*/
uint16_t modbus_crc16(uint8_t* data, int length)
{
uint16_t crc = 0xFFFF; // 初始值FFFF
uint16_t polynomial = 0x8005; // 多项式8005
for (int i = 0; i < length; i++) {
// 输入反转(REFIN):对每个字节进行位反转
uint8_t byte = data[i];
uint8_t reversed_byte = 0;
for (int j = 0; j < 8; j++) {
reversed_byte = (reversed_byte << 1) | (byte & 0x01);
byte >>= 1;
}
crc ^= (reversed_byte << 8); // 与高字节异或
for (int j = 0; j < 8; j++) {
if (crc & 0x8000) { // 检查最高位
crc = (crc << 1) ^ polynomial;
} else {
crc <<= 1;
}
}
}
// 输出反转(REFOUT):对16位CRC结果进行位反转
uint16_t reversed_crc = 0;
for (int i = 0; i < 16; i++) {
reversed_crc = (reversed_crc << 1) | (crc & 0x0001);
crc >>= 1;
}
// 结果异或值(XOROUT)0000(实际不变)
return reversed_crc ^ 0x0000;
}