Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 93e00b8b0a | |||
| 706eb1247e | |||
| c417d124a0 | |||
| f239690002 |
+24
-7
@@ -103,7 +103,7 @@
|
||||
<bEvRecOn>1</bEvRecOn>
|
||||
<bSchkAxf>0</bSchkAxf>
|
||||
<bTchkAxf>0</bTchkAxf>
|
||||
<nTsel>12</nTsel>
|
||||
<nTsel>6</nTsel>
|
||||
<sDll></sDll>
|
||||
<sDllPa></sDllPa>
|
||||
<sDlgDll></sDlgDll>
|
||||
@@ -114,7 +114,7 @@
|
||||
<tDlgDll></tDlgDll>
|
||||
<tDlgPa></tDlgPa>
|
||||
<tIfile></tIfile>
|
||||
<pMon>BIN\CMSIS_AGDI.dll</pMon>
|
||||
<pMon>Segger\JL2CM3.dll</pMon>
|
||||
</DebugOpt>
|
||||
<TargetDriverDllRegistry>
|
||||
<SetRegEntry>
|
||||
@@ -135,7 +135,7 @@
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>JL2CM3</Key>
|
||||
<Name>-U4294967295 -O78 -S1 -ZTIFSpeedSel10000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(0BC11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8027 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0FlashHC32L17X_128K.FLM -FS00 -FL020000 -FP0($$Device:HC32L170JATA$Flash\FlashHC32L17X_128K.FLM)</Name>
|
||||
<Name>-U12345678 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(0BC11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8027 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0FlashHC32L17X_128K.FLM -FS00 -FL020000 -FP0($$Device:HC32L170JATA$Flash\FlashHC32L17X_128K.FLM)</Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
@@ -411,7 +411,7 @@
|
||||
<bEvRecOn>1</bEvRecOn>
|
||||
<bSchkAxf>0</bSchkAxf>
|
||||
<bTchkAxf>0</bTchkAxf>
|
||||
<nTsel>12</nTsel>
|
||||
<nTsel>6</nTsel>
|
||||
<sDll></sDll>
|
||||
<sDllPa></sDllPa>
|
||||
<sDlgDll></sDlgDll>
|
||||
@@ -422,7 +422,7 @@
|
||||
<tDlgDll></tDlgDll>
|
||||
<tDlgPa></tDlgPa>
|
||||
<tIfile></tIfile>
|
||||
<pMon>BIN\CMSIS_AGDI.dll</pMon>
|
||||
<pMon>Segger\JL2CM3.dll</pMon>
|
||||
</DebugOpt>
|
||||
<TargetDriverDllRegistry>
|
||||
<SetRegEntry>
|
||||
@@ -443,7 +443,7 @@
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>JL2CM3</Key>
|
||||
<Name>-U4294967295 -O78 -S1 -ZTIFSpeedSel10000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(0BC11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8027 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0FlashHC32L17X_128K.FLM -FS00 -FL020000 -FP0($$Device:HC32L170JATA$Flash\FlashHC32L17X_128K.FLM)</Name>
|
||||
<Name>-U12345678 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(0BC11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8027 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0FlashHC32L17X_128K.FLM -FS00 -FL020000 -FP0($$Device:HC32L170JATA$Flash\FlashHC32L17X_128K.FLM)</Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
@@ -461,7 +461,24 @@
|
||||
<Name></Name>
|
||||
</SetRegEntry>
|
||||
</TargetDriverDllRegistry>
|
||||
<Breakpoint/>
|
||||
<Breakpoint>
|
||||
<Bp>
|
||||
<Number>0</Number>
|
||||
<Type>0</Type>
|
||||
<LineNumber>255</LineNumber>
|
||||
<EnabledFlag>1</EnabledFlag>
|
||||
<Address>0</Address>
|
||||
<ByteObject>0</ByteObject>
|
||||
<HtxType>0</HtxType>
|
||||
<ManyObjects>0</ManyObjects>
|
||||
<SizeOfObject>0</SizeOfObject>
|
||||
<BreakByAccess>0</BreakByAccess>
|
||||
<BreakIfRCount>0</BreakIfRCount>
|
||||
<Filename>..\source\inc\bsp.h</Filename>
|
||||
<ExecCommand></ExecCommand>
|
||||
<Expression></Expression>
|
||||
</Bp>
|
||||
</Breakpoint>
|
||||
<WatchWindow1>
|
||||
<Ww>
|
||||
<count>0</count>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "sx127x.h"
|
||||
#include "sx127x.h"
|
||||
#include "ddl.h"
|
||||
#include "UartDebug.h"
|
||||
|
||||
@@ -622,7 +622,7 @@ void Sx1276RxRetValue(void)
|
||||
|
||||
bool LoraSetChannel(uint8_t Channel)
|
||||
{
|
||||
if(Channel > 16)
|
||||
if(Channel > 45)
|
||||
return false;
|
||||
LoRaPara.ucChannel = Channel;
|
||||
return true;
|
||||
@@ -667,7 +667,7 @@ bool LoraSetRegPreamble(uint8_t RegPreamble)
|
||||
}
|
||||
bool LoraSetFreqCent(uint32_t FreqCent)
|
||||
{
|
||||
if(FreqCent < 410000000 || FreqCent > 525000000)
|
||||
if(FreqCent < 470100000ul || FreqCent > 492600000ul)
|
||||
return false;
|
||||
LoRaPara.dwFreqHz = FreqCent;
|
||||
return true;
|
||||
|
||||
+118
-13
@@ -756,19 +756,54 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
/*
|
||||
中心频率配置:433100000ul + 200000*N
|
||||
中心频率配置:470100000ul ~ 492600000ul,步进500000
|
||||
*/
|
||||
#define CH0 (433100000ul + 0) //测试频率
|
||||
#define CH1 (433100000ul + 200000)
|
||||
#define CH2 (433100000ul + 400000)
|
||||
#define CH3 (433100000ul + 600000)
|
||||
#define CH4 (433100000ul + 800000)
|
||||
#define CH5 (433100000ul + 1000000)
|
||||
#define CH6 (433100000ul + 1200000)
|
||||
#define CH7 (433100000ul + 1400000)
|
||||
#define CH8 (433100000ul + 1600000)
|
||||
#define CH9 (433100000ul + 1800000)
|
||||
#define CH10 (433100000ul + 2000000)
|
||||
#define CH0 (470100000ul) //出厂默认频率
|
||||
#define CH1 (470600000ul)
|
||||
#define CH2 (471100000ul)
|
||||
#define CH3 (471600000ul)
|
||||
#define CH4 (472100000ul)
|
||||
#define CH5 (472600000ul)
|
||||
#define CH6 (473100000ul)
|
||||
#define CH7 (473600000ul)
|
||||
#define CH8 (474100000ul)
|
||||
#define CH9 (474600000ul)
|
||||
#define CH10 (475100000ul)
|
||||
#define CH11 (475600000ul)
|
||||
#define CH12 (476100000ul)
|
||||
#define CH13 (476600000ul)
|
||||
#define CH14 (477100000ul)
|
||||
#define CH15 (477600000ul)
|
||||
#define CH16 (478100000ul)
|
||||
#define CH17 (478600000ul)
|
||||
#define CH18 (479100000ul)
|
||||
#define CH19 (479600000ul)
|
||||
#define CH20 (480100000ul)
|
||||
#define CH21 (480600000ul)
|
||||
#define CH22 (481100000ul)
|
||||
#define CH23 (481600000ul)
|
||||
#define CH24 (482100000ul)
|
||||
#define CH25 (482600000ul)
|
||||
#define CH26 (483100000ul)
|
||||
#define CH27 (483600000ul)
|
||||
#define CH28 (484100000ul)
|
||||
#define CH29 (484600000ul)
|
||||
#define CH30 (485100000ul)
|
||||
#define CH31 (485600000ul)
|
||||
#define CH32 (486100000ul)
|
||||
#define CH33 (486600000ul)
|
||||
#define CH34 (487100000ul)
|
||||
#define CH35 (487600000ul)
|
||||
#define CH36 (488100000ul)
|
||||
#define CH37 (488600000ul)
|
||||
#define CH38 (489100000ul)
|
||||
#define CH39 (489600000ul)
|
||||
#define CH40 (490100000ul)
|
||||
#define CH41 (490600000ul)
|
||||
#define CH42 (491100000ul)
|
||||
#define CH43 (491600000ul)
|
||||
#define CH44 (492100000ul)
|
||||
#define CH45 (492600000ul)
|
||||
|
||||
#if (USE_LORA_CH == 0)
|
||||
#define FREQ_CENT CH0
|
||||
@@ -792,10 +827,80 @@ typedef struct {
|
||||
#define FREQ_CENT CH9
|
||||
#elif (USE_LORA_CH == 10)
|
||||
#define FREQ_CENT CH10
|
||||
#elif (USE_LORA_CH == 11)
|
||||
#define FREQ_CENT CH11
|
||||
#elif (USE_LORA_CH == 12)
|
||||
#define FREQ_CENT CH12
|
||||
#elif (USE_LORA_CH == 13)
|
||||
#define FREQ_CENT CH13
|
||||
#elif (USE_LORA_CH == 14)
|
||||
#define FREQ_CENT CH14
|
||||
#elif (USE_LORA_CH == 15)
|
||||
#define FREQ_CENT CH15
|
||||
#elif (USE_LORA_CH == 16)
|
||||
#define FREQ_CENT CH16
|
||||
#elif (USE_LORA_CH == 17)
|
||||
#define FREQ_CENT CH17
|
||||
#elif (USE_LORA_CH == 18)
|
||||
#define FREQ_CENT CH18
|
||||
#elif (USE_LORA_CH == 19)
|
||||
#define FREQ_CENT CH19
|
||||
#elif (USE_LORA_CH == 20)
|
||||
#define FREQ_CENT CH20
|
||||
#elif (USE_LORA_CH == 21)
|
||||
#define FREQ_CENT CH21
|
||||
#elif (USE_LORA_CH == 22)
|
||||
#define FREQ_CENT CH22
|
||||
#elif (USE_LORA_CH == 23)
|
||||
#define FREQ_CENT CH23
|
||||
#elif (USE_LORA_CH == 24)
|
||||
#define FREQ_CENT CH24
|
||||
#elif (USE_LORA_CH == 25)
|
||||
#define FREQ_CENT CH25
|
||||
#elif (USE_LORA_CH == 26)
|
||||
#define FREQ_CENT CH26
|
||||
#elif (USE_LORA_CH == 27)
|
||||
#define FREQ_CENT CH27
|
||||
#elif (USE_LORA_CH == 28)
|
||||
#define FREQ_CENT CH28
|
||||
#elif (USE_LORA_CH == 29)
|
||||
#define FREQ_CENT CH29
|
||||
#elif (USE_LORA_CH == 30)
|
||||
#define FREQ_CENT CH30
|
||||
#elif (USE_LORA_CH == 31)
|
||||
#define FREQ_CENT CH31
|
||||
#elif (USE_LORA_CH == 32)
|
||||
#define FREQ_CENT CH32
|
||||
#elif (USE_LORA_CH == 33)
|
||||
#define FREQ_CENT CH33
|
||||
#elif (USE_LORA_CH == 34)
|
||||
#define FREQ_CENT CH34
|
||||
#elif (USE_LORA_CH == 35)
|
||||
#define FREQ_CENT CH35
|
||||
#elif (USE_LORA_CH == 36)
|
||||
#define FREQ_CENT CH36
|
||||
#elif (USE_LORA_CH == 37)
|
||||
#define FREQ_CENT CH37
|
||||
#elif (USE_LORA_CH == 38)
|
||||
#define FREQ_CENT CH38
|
||||
#elif (USE_LORA_CH == 39)
|
||||
#define FREQ_CENT CH39
|
||||
#elif (USE_LORA_CH == 40)
|
||||
#define FREQ_CENT CH40
|
||||
#elif (USE_LORA_CH == 41)
|
||||
#define FREQ_CENT CH41
|
||||
#elif (USE_LORA_CH == 42)
|
||||
#define FREQ_CENT CH42
|
||||
#elif (USE_LORA_CH == 43)
|
||||
#define FREQ_CENT CH43
|
||||
#elif (USE_LORA_CH == 44)
|
||||
#define FREQ_CENT CH44
|
||||
#elif (USE_LORA_CH == 45)
|
||||
#define FREQ_CENT CH45
|
||||
#endif
|
||||
|
||||
#if !defined FREQ_CENT
|
||||
#define FREQ_CENT (433100000ul + 0)//200000
|
||||
#define FREQ_CENT (470100000ul)//500000
|
||||
#endif
|
||||
#if !defined FREQ_DEV
|
||||
#define FREQ_DEV 1000000ul
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
|
||||
#if (USE_DEBUG != 0)
|
||||
#define DEBUG_CMD_CNT 17
|
||||
#define DEBUG_CMD_CNT 18
|
||||
const DBGFunType DebugFun[DEBUG_CMD_CNT];
|
||||
|
||||
volatile DebugChannel_e gDebugChannel = DBG_CH_RS485_1;//上电默认调试口
|
||||
@@ -214,6 +214,10 @@ static void DebugCmdGetPara(int argc, char *argv[])
|
||||
DBG_LOG("Lora: ch %d, rp %d, fc %d\r\n", App.Para.Lora.ucChannel, App.Para.Lora.RegPreamble, App.Para.Lora.FreqCent);
|
||||
DBG_LOG("LpCfg: CI:%dsec, RI:%dmin, EI:%dmin, ET:%dmin\r\n",
|
||||
App.Para.Layout.CollectTime*30, App.Para.Layout.ReportInterval/2, App.Para.Layout.ERInterval/2, App.Para.Layout.ERTime/2);
|
||||
DBG_LOG("FpoCfg: Start:%02d:00, Dur:%dh, End:%02d:00, %s\r\n",
|
||||
App.Para.Layout.FPOTimeStart, App.Para.Layout.FPOTime,
|
||||
(App.Para.Layout.FPOTimeStart + App.Para.Layout.FPOTime) % 24,
|
||||
(IsFullPowerTime() == true) ? "FullPower" : "LowPower");
|
||||
DBG_LOG("Laser: %s, AutoOff: %dmin\r\n",
|
||||
(SGCP.LaserOnOff == true) ? "ON" : "OFF", SGCP.LaserTimerMinutes);
|
||||
struct tm *stime;
|
||||
@@ -558,7 +562,7 @@ static void DebugLoraConfig(int argc, char *argv[])
|
||||
if(strcmp(argv[1], "?") == 0) {
|
||||
DBG_LOG("Debug Cmd: lora arg1 arg2\r\n");
|
||||
DBG_LOG(" brief --> Configure Lora parameters.\r\n");
|
||||
DBG_LOG(" arg1 --> ch: Channel--para=(0~16)\r\n");
|
||||
DBG_LOG(" arg1 --> ch: Channel--para=(0~45)\r\n");
|
||||
DBG_LOG(" pw: Power--para=(0~20)\r\n");
|
||||
DBG_LOG(" bw: SignalBw--para=(0~9)\r\n");
|
||||
DBG_LOG(" sf: SpreadFactor--para=(6~12)\r\n");
|
||||
@@ -739,6 +743,58 @@ static void DebugCmdLPConfig(int argc, char *argv[])
|
||||
DBG_LOG("The low-power device is configured.\r\n");
|
||||
}
|
||||
/*****************************************************************************************
|
||||
* 函数名称: DebugCmdFPOConfig
|
||||
* 功能描述: 全功率运行时间段配置
|
||||
* 参 数: argc, 输入参数数量
|
||||
argv, 输入参数
|
||||
* 返 回 值: 无
|
||||
*****************************************************************************************/
|
||||
static void DebugCmdFPOConfig(int argc, char *argv[])
|
||||
{
|
||||
DBG_LOG("\r\n");
|
||||
if(argc < 2)
|
||||
return;
|
||||
|
||||
if(strcmp(argv[1], "?") == 0) {
|
||||
DBG_LOG("Debug Cmd: fpocfg arg1 arg2\r\n");
|
||||
DBG_LOG(" brief --> Configure full-power work period.\r\n");
|
||||
DBG_LOG(" arg1 --> Full-power work start hour. (0~23 hour)\r\n");
|
||||
DBG_LOG(" arg2 --> Full-power work duration. (0~24 hour, 0=off)\r\n\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(argc < 3)
|
||||
return;
|
||||
|
||||
uint8_t FPOTimeStart = (uint8_t)atoi(argv[1]);
|
||||
uint8_t FPOTime = (uint8_t)atoi(argv[2]);
|
||||
if(FPOTimeStart > 23) {
|
||||
DBG_LOG("FPOTimeStart Para Error! (0~23)\r\n");
|
||||
return;
|
||||
}
|
||||
if(FPOTime > 24) {
|
||||
DBG_LOG("FPOTime Para Error! (0~24)\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
App.Para.Layout.FPOTimeStart = FPOTimeStart;
|
||||
App.Para.Layout.FPOTime = FPOTime;
|
||||
SAVE_APP_PARA((uint32_t *)&App.Para);
|
||||
DBG_LOG("The full-power work period is configured. Start:%02d:00, Dur:%dh, End:%02d:00\r\n",
|
||||
App.Para.Layout.FPOTimeStart, App.Para.Layout.FPOTime,
|
||||
(App.Para.Layout.FPOTimeStart + App.Para.Layout.FPOTime) % 24);
|
||||
|
||||
if(SGCP.LoginOk)
|
||||
{
|
||||
ToGWSetFPORes();
|
||||
DBG_LOG("FPO config update sent to gateway.\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG_LOG("Gateway not logged in, skip sending FPO config update.\r\n");
|
||||
}
|
||||
}
|
||||
/*****************************************************************************************
|
||||
* 函数名称: DebugLaserConfig
|
||||
* 功能描述: 激光控制
|
||||
* 参 数: argc, 输入参数数量
|
||||
@@ -1062,6 +1118,16 @@ void DebugCmdHelp(int argc, char *argv[])
|
||||
}
|
||||
DebugCmdLPConfig(argc1, argv1);
|
||||
|
||||
memset(Data, 0x00, 10);
|
||||
len = strlen("fpocfg ?\0");
|
||||
memcpy(Data, "fpocfg ?\0", len);
|
||||
token = strtok(Data, " "); // 假设分隔符是空格
|
||||
for(argc1 = 0; (token != NULL && argc1 < 10); argc1++) {
|
||||
argv1[argc1] = token;
|
||||
token = strtok(NULL, " ");
|
||||
}
|
||||
DebugCmdFPOConfig(argc1, argv1);
|
||||
|
||||
memset(Data, 0x00, 10);
|
||||
len = strlen("laser ?\0");
|
||||
memcpy(Data, "laser ?\0", len);
|
||||
@@ -1134,6 +1200,7 @@ const DBGFunType DebugFun[DEBUG_CMD_CNT] = {
|
||||
"rs485", DebugCmdRS485Ctrl,
|
||||
"lora", DebugLoraConfig,
|
||||
"lpcfg", DebugCmdLPConfig,
|
||||
"fpocfg", DebugCmdFPOConfig,
|
||||
"laser", DebugLaserConfig,
|
||||
"res", DebugCmdRestoreFactory,
|
||||
"dch", DebugCmdChannel,
|
||||
|
||||
+107
-127
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "lsm6dsl_app.h"
|
||||
#include "lsm6dsl_reg.h"
|
||||
@@ -13,31 +13,24 @@
|
||||
dev_ctx_t dev_ctx;
|
||||
static bool InitFlag;
|
||||
|
||||
#define ACC_CVTTIME (20 * 1000)
|
||||
#define ACC_COLL_CNT_MAX 6
|
||||
#define ACC_FIFO_WATERMASK (ACC_COLL_CNT_MAX * 6) //采集一秒数据
|
||||
#define TX_BUF_DIM 1000
|
||||
#define ACC_COLL_CNT_MAX 4 //每组平均样本数,输出速率=ODR/4=13Hz
|
||||
#define ACC_FIFO_WATERMASK (ACC_COLL_CNT_MAX * 6) //FIFO水印:4组 × (3陀螺+3加速度)=24
|
||||
#define BOOT_TIME 15 //ms
|
||||
|
||||
typedef enum {
|
||||
Acc_Idle,
|
||||
Acc_Start,
|
||||
Acc_Get_Data,
|
||||
Acc_Wait_GetData,
|
||||
Acc_Go_Bypass,
|
||||
Acc_Get_Data, //连续采集运行中
|
||||
}AccStatusType_m;
|
||||
|
||||
static AccStatusType_m acc_status;
|
||||
static uint32_t acc_cvttime;
|
||||
static bool Lsm6dslWaterMarkFullIntFlag;
|
||||
static bool Lsm6dslWakeupIntFlag;
|
||||
static uint16_t Lsm6dslIntWatchdog; //无数据看门狗计数(1ms)
|
||||
static bool Lsm6dslRecoverReq; //自恢复请求(1ms置位,主循环执行)
|
||||
|
||||
static int16_t data_raw_acceleration[3];
|
||||
static int16_t data_raw_angular_rate[3];
|
||||
static int16_t data_raw_temperature;
|
||||
static float acceleration_mg[3][ACC_COLL_CNT_MAX];
|
||||
static float angular_rate_mdps[3][ACC_COLL_CNT_MAX];
|
||||
static float temperature_degC;
|
||||
static uint8_t whoamI, rst;
|
||||
|
||||
|
||||
@@ -60,6 +53,57 @@ static void platform_read(uint8_t reg, uint8_t *bufp, uint32_t len)
|
||||
I2C_MasterReadData(M0P_I2C0, Selve_Add, reg, bufp, len);
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
* 函数名称: Lsm6dsl_Config
|
||||
* 功能描述: LSM6DSL寄存器配置,配置完成后开启连续采集(常开,不进入低功耗)
|
||||
* 参 数: 无
|
||||
* 返 回 值: 无
|
||||
*****************************************************************************************/
|
||||
static void Lsm6dsl_Config(void)
|
||||
{
|
||||
/* Restore default configuration */
|
||||
lsm6dsl_reset_set(&dev_ctx, PROPERTY_ENABLE);
|
||||
|
||||
do {
|
||||
lsm6dsl_reset_get(&dev_ctx, &rst);
|
||||
} while (rst);
|
||||
|
||||
/* 高性能模式(传感器常开,噪声最低) */
|
||||
lsm6dsl_xl_power_mode_set(&dev_ctx, LSM6DSL_XL_HIGH_PERFORMANCE);
|
||||
lsm6dsl_gy_power_mode_set(&dev_ctx, LSM6DSL_GY_HIGH_PERFORMANCE);
|
||||
/* Enable Block Data Update */
|
||||
lsm6dsl_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
|
||||
/* Set full scale */
|
||||
lsm6dsl_xl_full_scale_set(&dev_ctx, LSM6DSL_2g);
|
||||
lsm6dsl_gy_full_scale_set(&dev_ctx, LSM6DSL_500dps);
|
||||
/* Configure filtering chain(No aux interface) */
|
||||
/* Accelerometer - analog filter */
|
||||
lsm6dsl_xl_filter_analog_set(&dev_ctx, LSM6DSL_XL_ANA_BW_400Hz);
|
||||
/* Accelerometer - LPF1 + LPF2 path */
|
||||
lsm6dsl_xl_lp2_bandwidth_set(&dev_ctx, LSM6DSL_XL_LOW_NOISE_LP_ODR_DIV_9);
|
||||
/* Gyroscope - filtering chain */
|
||||
lsm6dsl_gy_band_pass_set(&dev_ctx, LSM6DSL_HP_260mHz_LP1_STRONG);
|
||||
|
||||
/* FIFO:连续流模式,存满水印触发中断但不停采 */
|
||||
lsm6dsl_fifo_xl_batch_set(&dev_ctx, LSM6DSL_FIFO_XL_NO_DEC); //fifo加速度写入频率设置
|
||||
lsm6dsl_fifo_gy_batch_set(&dev_ctx, LSM6DSL_FIFO_GY_NO_DEC); //fifo陀螺仪写入频率设置
|
||||
lsm6dsl_fifo_data_rate_set(&dev_ctx, LSM6DSL_FIFO_52Hz); //FIFO ODR选择,与传感器ODR一致
|
||||
lsm6dsl_fifo_watermark_set(&dev_ctx, ACC_FIFO_WATERMASK); //FIFO水印电平设置,4组数据
|
||||
lsm6dsl_fifo_stop_on_wtm_set(&dev_ctx, 0); //存满水印后继续采集,不停
|
||||
lsm6dsl_block_data_update_set(&dev_ctx, 1); //fifo模式ctrl3_c bdu必须为1
|
||||
lsm6dsl_auto_increment_set(&dev_ctx, 1); //fifo模式ctrl3_c if_inc必须为1
|
||||
|
||||
/* 中断1:FIFO水印阈值中断 */
|
||||
lsm6dsl_int1_route_t int1val ={0, 0, 0};
|
||||
int1val.int1_fth = 1; //FIFO存储达到水印深度时触发
|
||||
lsm6dsl_pin_int1_route_set(&dev_ctx, int1val);
|
||||
|
||||
/* 最后开启ODR和FIFO连续模式,保证先配置后采样 */
|
||||
lsm6dsl_fifo_mode_set(&dev_ctx, LSM6DSL_STREAM_MODE);
|
||||
lsm6dsl_xl_data_rate_set(&dev_ctx, LSM6DSL_XL_ODR_52Hz);
|
||||
lsm6dsl_gy_data_rate_set(&dev_ctx, LSM6DSL_GY_ODR_52Hz);
|
||||
}
|
||||
|
||||
static void Lsm6dsl_Init(void)
|
||||
{
|
||||
/* Initialize mems driver interface */
|
||||
@@ -80,63 +124,7 @@ static void Lsm6dsl_Init(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore default configuration */
|
||||
lsm6dsl_reset_set(&dev_ctx, PROPERTY_ENABLE);
|
||||
|
||||
do {
|
||||
lsm6dsl_reset_get(&dev_ctx, &rst);
|
||||
} while (rst);
|
||||
|
||||
lsm6dsl_xl_power_mode_set(&dev_ctx, LSM6DSL_XL_NORMAL);
|
||||
/* Enable Block Data Update */
|
||||
lsm6dsl_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
|
||||
/* Set Output Data Rate */
|
||||
lsm6dsl_xl_data_rate_set(&dev_ctx, LSM6DSL_XL_ODR_12Hz5);
|
||||
lsm6dsl_gy_data_rate_set(&dev_ctx, LSM6DSL_GY_ODR_12Hz5);
|
||||
//lsm6dsl_gy_data_rate_set(&left_dev_ctx, LSM6DSL_GY_ODR_OFF); //关闭地磁
|
||||
/* Set full scale */
|
||||
lsm6dsl_xl_full_scale_set(&dev_ctx, LSM6DSL_2g);
|
||||
lsm6dsl_gy_full_scale_set(&dev_ctx, LSM6DSL_2000dps);
|
||||
/* Configure filtering chain(No aux interface) */
|
||||
/* Accelerometer - analog filter */
|
||||
lsm6dsl_xl_filter_analog_set(&dev_ctx, LSM6DSL_XL_ANA_BW_400Hz);
|
||||
/* Accelerometer - LPF1 path ( LPF2 not used )*/
|
||||
/*lsm6dsl_xl_lp1_bandwidth_set(&left_dev_ctx, LSM6DSL_XL_LP1_ODR_DIV_4);*/
|
||||
/* Accelerometer - LPF1 + LPF2 path */
|
||||
lsm6dsl_xl_lp2_bandwidth_set(&dev_ctx, LSM6DSL_XL_LOW_NOISE_LP_ODR_DIV_9);
|
||||
/* Accelerometer - High Pass / Slope path */
|
||||
/*lsm6dsl_xl_reference_mode_set(&left_dev_ctx, PROPERTY_DISABLE);*/
|
||||
/*lsm6dsl_xl_hp_bandwidth_set(&left_dev_ctx, LSM6DSL_XL_HP_ODR_DIV_100);*/
|
||||
/* Gyroscope - filtering chain */
|
||||
lsm6dsl_gy_band_pass_set(&dev_ctx, LSM6DSL_HP_260mHz_LP1_STRONG);
|
||||
|
||||
//fifo模式设置
|
||||
lsm6dsl_fifo_xl_batch_set(&dev_ctx, LSM6DSL_FIFO_XL_NO_DEC);//fifo加速度写入频率设置
|
||||
lsm6dsl_fifo_gy_batch_set(&dev_ctx, LSM6DSL_FIFO_GY_NO_DEC);//fifo陀螺仪写入频率设置
|
||||
lsm6dsl_fifo_data_rate_set(&dev_ctx, LSM6DSL_FIFO_12Hz5);//FIFO ODR选择
|
||||
|
||||
//中断1设置,watermark full中断
|
||||
lsm6dsl_int1_route_t int1val ={0, 0, 0};
|
||||
int1val.int1_full_flag = 1; //开阀值中断,fifo存储到缓存深度时触发
|
||||
lsm6dsl_pin_int1_route_set(&dev_ctx, int1val);
|
||||
lsm6dsl_fifo_watermark_set(&dev_ctx, ACC_FIFO_WATERMASK);//FIFO水印电平设置,阈值设置,缓存深度
|
||||
lsm6dsl_fifo_stop_on_wtm_set(&dev_ctx, 1);//fifo缓存深度存满时,不再存储
|
||||
//lsm6dsl_fifo_xl_gy_8bit_format_set(&left_dev_ctx, 1);//在FIFO中为XL和陀螺启用MSByte记忆,缓存宽度
|
||||
lsm6dsl_block_data_update_set(&dev_ctx, 1); //fifo模式ctrl3_c bdu必须为1,直到读取MSB和LSB后才更新输出寄存器
|
||||
lsm6dsl_auto_increment_set(&dev_ctx, 1); //fifo模式ctrl3_c if_inc必须为1,通过串行接口(I2C或SPI)进行多字节访问时自动增加寄存器地址。
|
||||
lsm6dsl_ctrl3_c_t ctrl3_c;
|
||||
platform_read(LSM6DSL_CTRL3_C, (uint8_t *)&ctrl3_c, 1);
|
||||
//lsm6dsl_fifo_mode_set(&dev_ctx, LSM6DSL_FIFO_MODE);
|
||||
|
||||
//中断2设置,唤醒中断
|
||||
// uint8_t temp = 0x90; //唤醒中断
|
||||
// platform_write(LSM6DSL_TAP_CFG, &temp, 1);
|
||||
// temp = 0;
|
||||
// platform_write(LSM6DSL_WAKE_UP_DUR, &temp, 1);
|
||||
// lsm6dsl_wkup_threshold_set(&left_dev_ctx, 0x20);
|
||||
// lsm6dsl_int2_route_t int2val ={0, 0, 0};
|
||||
// int2val.int2_wu = 1;
|
||||
// lsm6dsl_pin_int2_route_set(&left_dev_ctx, int2val);
|
||||
Lsm6dsl_Config();
|
||||
|
||||
if(InitFlag == false){
|
||||
DBG_LOG("LSM6DS INIT OK...\r\n");
|
||||
@@ -148,36 +136,37 @@ extern void Lsm6dDataProcessCallBack(float *Acc, float *Gy);
|
||||
static void Acc_IntHandler(void)
|
||||
{
|
||||
uint16_t DiffFifo;
|
||||
uint16_t Sets;
|
||||
uint8_t Cnt;
|
||||
uint8_t Slot;
|
||||
uint16_t i;
|
||||
AccGyData_t AccGy;
|
||||
AccData_t Acc;
|
||||
float VectorG;
|
||||
float AverageAcc[XYZ], AverageGy[XYZ];
|
||||
|
||||
lsm6dsl_fifo_data_level_get(&dev_ctx, &DiffFifo);
|
||||
if(DiffFifo == 0) {
|
||||
if(DiffFifo < ACC_FIFO_WATERMASK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(DiffFifo > ACC_FIFO_WATERMASK)
|
||||
DiffFifo = ACC_FIFO_WATERMASK;
|
||||
for(int i = 0; i < DiffFifo / 6; i++) {
|
||||
Sets = DiffFifo / 6;
|
||||
for(i = 0; i < Sets; i++) {
|
||||
lsm6dsl_fifo_raw_data_get(&dev_ctx, (uint8_t *)&AccGy, sizeof(AccGy));
|
||||
angular_rate_mdps[X][i] = lsm6dsl_from_fs2000dps_to_mdps(AccGy.GyX);
|
||||
angular_rate_mdps[Y][i] = lsm6dsl_from_fs2000dps_to_mdps(AccGy.GyY);
|
||||
angular_rate_mdps[Z][i] = lsm6dsl_from_fs2000dps_to_mdps(AccGy.GyZ);
|
||||
acceleration_mg[X][i] = lsm6dsl_from_fs2g_to_mg(AccGy.AccX);
|
||||
acceleration_mg[Y][i] = lsm6dsl_from_fs2g_to_mg(AccGy.AccY);
|
||||
acceleration_mg[Z][i] = lsm6dsl_from_fs2g_to_mg(AccGy.AccZ);
|
||||
Slot = i % ACC_COLL_CNT_MAX; //环形缓存,始终保留最新ACC_COLL_CNT_MAX组
|
||||
angular_rate_mdps[X][Slot] = lsm6dsl_from_fs500dps_to_mdps(AccGy.GyX);
|
||||
angular_rate_mdps[Y][Slot] = lsm6dsl_from_fs500dps_to_mdps(AccGy.GyY);
|
||||
angular_rate_mdps[Z][Slot] = lsm6dsl_from_fs500dps_to_mdps(AccGy.GyZ);
|
||||
acceleration_mg[X][Slot] = lsm6dsl_from_fs2g_to_mg(AccGy.AccX);
|
||||
acceleration_mg[Y][Slot] = lsm6dsl_from_fs2g_to_mg(AccGy.AccY);
|
||||
acceleration_mg[Z][Slot] = lsm6dsl_from_fs2g_to_mg(AccGy.AccZ);
|
||||
}
|
||||
AverageGy[X] = IntFilter_Float(angular_rate_mdps[0], DiffFifo / 6, 2);
|
||||
AverageGy[Y] = IntFilter_Float(angular_rate_mdps[1], DiffFifo / 6, 2);
|
||||
AverageGy[Z] = IntFilter_Float(angular_rate_mdps[2], DiffFifo / 6, 2);
|
||||
AverageAcc[X] = IntFilter_Float(acceleration_mg[0], DiffFifo / 6, 2);
|
||||
AverageAcc[Y] = IntFilter_Float(acceleration_mg[1], DiffFifo / 6, 2);
|
||||
AverageAcc[Z] = IntFilter_Float(acceleration_mg[2], DiffFifo / 6, 2);
|
||||
Cnt = (Sets >= ACC_COLL_CNT_MAX) ? ACC_COLL_CNT_MAX : (uint8_t)Sets;
|
||||
AverageGy[X] = IntFilter_Float(angular_rate_mdps[0], Cnt, 0);
|
||||
AverageGy[Y] = IntFilter_Float(angular_rate_mdps[1], Cnt, 0);
|
||||
AverageGy[Z] = IntFilter_Float(angular_rate_mdps[2], Cnt, 0);
|
||||
AverageAcc[X] = IntFilter_Float(acceleration_mg[0], Cnt, 0);
|
||||
AverageAcc[Y] = IntFilter_Float(acceleration_mg[1], Cnt, 0);
|
||||
AverageAcc[Z] = IntFilter_Float(acceleration_mg[2], Cnt, 0);
|
||||
Lsm6dDataProcessCallBack(AverageAcc, AverageGy);
|
||||
|
||||
acc_status = Acc_Go_Bypass;
|
||||
}
|
||||
|
||||
static void ReadWakeUpIntStatus(void)
|
||||
@@ -192,43 +181,19 @@ static void ReadWakeUpIntStatus(void)
|
||||
void Lsm6dslLoopHandler(void)
|
||||
{
|
||||
ReadWakeUpIntStatus();
|
||||
switch(acc_status)
|
||||
{
|
||||
case Acc_Idle:
|
||||
break;
|
||||
|
||||
case Acc_Start:
|
||||
if(acc_cvttime > 0)
|
||||
break;
|
||||
lsm6dsl_fifo_mode_set(&dev_ctx, LSM6DSL_FIFO_MODE);
|
||||
acc_status = Acc_Get_Data;
|
||||
acc_cvttime = ACC_CVTTIME;
|
||||
break;
|
||||
|
||||
case Acc_Get_Data:
|
||||
acc_cvttime = 1000;
|
||||
acc_status = Acc_Wait_GetData;
|
||||
break;
|
||||
|
||||
case Acc_Wait_GetData:
|
||||
if(acc_cvttime <= 0){
|
||||
acc_status = Acc_Go_Bypass;
|
||||
if(acc_status != Acc_Get_Data) {
|
||||
return;
|
||||
}
|
||||
else if(Lsm6dslWaterMarkFullIntFlag) {
|
||||
if(Lsm6dslRecoverReq) {
|
||||
Lsm6dslRecoverReq = false;
|
||||
Lsm6dsl_Config(); //1秒无水印中断,重新配置FIFO/ODR自恢复
|
||||
Lsm6dslIntWatchdog = 0;
|
||||
return;
|
||||
}
|
||||
if(Lsm6dslWaterMarkFullIntFlag) {
|
||||
Lsm6dslWaterMarkFullIntFlag = false;
|
||||
uint8_t wtm_flag;
|
||||
lsm6dsl_fifo_wtm_flag_get(&dev_ctx, &wtm_flag);
|
||||
Lsm6dslIntWatchdog = 0;
|
||||
Acc_IntHandler();
|
||||
acc_status = Acc_Go_Bypass;
|
||||
}
|
||||
break;
|
||||
|
||||
case Acc_Go_Bypass:
|
||||
lsm6dsl_fifo_mode_set(&dev_ctx, LSM6DSL_BYPASS_MODE);
|
||||
Lsm6dsStop();
|
||||
acc_status = Acc_Idle;
|
||||
acc_cvttime = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,6 +201,17 @@ void Lsm6dsl1mSRoutine(void)
|
||||
{
|
||||
if(acc_cvttime > 0)
|
||||
acc_cvttime--;
|
||||
if(acc_status == Acc_Get_Data) {
|
||||
if(Lsm6dslIntWatchdog < 2000)
|
||||
Lsm6dslIntWatchdog++;
|
||||
if(Lsm6dslIntWatchdog >= 1000) { //连续1秒无FIFO水印中断
|
||||
Lsm6dslIntWatchdog = 0;
|
||||
Lsm6dslRecoverReq = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Lsm6dslIntWatchdog = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Lsm6dslInit(void)
|
||||
@@ -245,15 +221,19 @@ void Lsm6dslInit(void)
|
||||
|
||||
void Lsm6dsStart(void)
|
||||
{
|
||||
Lsm6dsl_Init();
|
||||
acc_status = Acc_Start;
|
||||
if(acc_status == Acc_Get_Data) {
|
||||
return; //已在连续采集,不重复配置
|
||||
}
|
||||
Lsm6dsl_Init(); //配置寄存器并开启连续采集
|
||||
acc_status = Acc_Get_Data;
|
||||
}
|
||||
|
||||
void Lsm6dsStop(void)
|
||||
{
|
||||
lsm6dsl_fifo_mode_set(&dev_ctx, LSM6DSL_BYPASS_MODE);
|
||||
lsm6dsl_fifo_data_rate_set(&dev_ctx, LSM6DSL_FIFO_DISABLE);
|
||||
lsm6dsl_xl_data_rate_set(&dev_ctx, LSM6DSL_XL_ODR_OFF);
|
||||
lsm6dsl_gy_data_rate_set(&dev_ctx, LSM6DSL_GY_ODR_OFF);
|
||||
lsm6dsl_fifo_data_rate_set(&dev_ctx, LSM6DSL_FIFO_DISABLE);
|
||||
acc_status = Acc_Idle;
|
||||
}
|
||||
|
||||
|
||||
+89
-100
@@ -1,14 +1,21 @@
|
||||
#include "main.h"
|
||||
#include "main.h"
|
||||
#include "mmc5983.h"
|
||||
#include "UartDebug.h"
|
||||
#include "i2c.h"
|
||||
#include "Algorithm.h"
|
||||
|
||||
static int32_t max_in[XYZ];
|
||||
static int32_t min_in[XYZ];
|
||||
#define MAG_AVG_CNT 2 //每2个样本平均输出1次,输出速率=20Hz/2=10Hz
|
||||
#define MAG_POLL_MS 20 //测量完成标志轮询周期,与20Hz测量周期一致
|
||||
#define MAG_POLL_FAIL_MAX 5 //连续5次(100ms)轮询无数据则重写配置自恢复
|
||||
|
||||
static bool InitFlag;
|
||||
static bool MMC5983IntFlag;
|
||||
static MMC5983Var_t MMC5983Var;
|
||||
static int32_t mag_array[XYZ][MAG_AVG_CNT];
|
||||
static uint8_t magcnt;
|
||||
static uint8_t PollFailCnt;
|
||||
|
||||
extern void MmcDataProcessCallBack(float *Mag);
|
||||
|
||||
/*****************************************************************************************
|
||||
* 函数名称: MMC5983_Write_Reg
|
||||
@@ -50,19 +57,24 @@ static bool MMC5983_Read_Buffer(uint8_t reg, void *buffer, uint8_t len)
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
* 函数名称: MMC5983StartCov
|
||||
* 功能描述: MMC5983开启连续转换
|
||||
* 函数名称: MMC5983StartContinuous
|
||||
* 功能描述: MMC5983开启20Hz连续转换(常开,不进入低功耗)
|
||||
* 参 数: 无
|
||||
* 返 回 值: 无
|
||||
*****************************************************************************************/
|
||||
static void MMC5983StartCov(void)
|
||||
static void MMC5983StartContinuous(void)
|
||||
{
|
||||
MMC5983RegCtrl0 Ctrl0Reg;
|
||||
MMC5983RegCtrl2 Ctrl2Reg; //开启/关闭连续转换
|
||||
Ctrl0Reg.Byte = 0x00;
|
||||
Ctrl0Reg.Bit.Auto_SR_en = 1; //自动SET/RESET,消除温漂零场漂移
|
||||
Ctrl0Reg.Bit.NT_meas_done_en = 1; //测量完成中断使能(Stop会清CTRL0,启动时必须重写)
|
||||
MMC5983_Write_Reg(MMC5983_CTRL_0, Ctrl0Reg.Byte);
|
||||
Ctrl2Reg.Byte = 0x00;
|
||||
Ctrl2Reg.Bit.Cm_freq = 0x04;
|
||||
Ctrl2Reg.Bit.Cm_freq = 0x03; //011=20Hz连续测量
|
||||
Ctrl2Reg.Bit.Cmm_en = 1; //连续设1,单次设0
|
||||
Ctrl2Reg.Bit.Prd_set = 3;
|
||||
Ctrl2Reg.Bit.En_prd_set = 1; //连续设1,单次设0
|
||||
Ctrl2Reg.Bit.Prd_set = 3; //每100次测量自动SET一次,消除温漂
|
||||
Ctrl2Reg.Bit.En_prd_set = 1;
|
||||
MMC5983_Write_Reg(MMC5983_CTRL_2, Ctrl2Reg.Byte);
|
||||
}
|
||||
|
||||
@@ -81,7 +93,7 @@ static void MMC5983_Init(void)
|
||||
MMC5983Var.MMC5983Delay1mSCnt = 100;
|
||||
while(id != 0x30){
|
||||
if(MMC5983Var.MMC5983Delay1mSCnt <= 0) {
|
||||
DBG_LOG("LEFT MMC5983 INIT Err...\r\n");
|
||||
DBG_LOG("MMC5983 INIT Err...\r\n");
|
||||
InitFlag = false;
|
||||
return;
|
||||
}
|
||||
@@ -93,12 +105,8 @@ static void MMC5983_Init(void)
|
||||
MMC5983_Write_Reg(MMC5983_CTRL_1, Ctrl1Reg.Byte);
|
||||
MMC5983Delay(15);
|
||||
|
||||
MMC5983RegCtrl2 Ctrl2Reg; //开启/关闭连续转换
|
||||
MMC5983RegCtrl2 Ctrl2Reg; //连续模式在StartContinuous中开启
|
||||
Ctrl2Reg.Byte = 0x00;
|
||||
Ctrl2Reg.Bit.Cm_freq = 0x04;
|
||||
Ctrl2Reg.Bit.Cmm_en = 0; //连续设1,单次设0
|
||||
Ctrl2Reg.Bit.Prd_set = 3;
|
||||
Ctrl2Reg.Bit.En_prd_set = 0; //连续设1,单次设0
|
||||
MMC5983_Write_Reg(MMC5983_CTRL_2, Ctrl2Reg.Byte);
|
||||
|
||||
MMC5983RegCtrl3 Ctrl3Reg;
|
||||
@@ -109,9 +117,8 @@ static void MMC5983_Init(void)
|
||||
|
||||
MMC5983RegCtrl0 Ctrl0Reg;
|
||||
Ctrl0Reg.Byte = 0x00;
|
||||
Ctrl0Reg.Bit.TM_M = 1;
|
||||
Ctrl0Reg.Bit.Auto_SR_en = 1;
|
||||
Ctrl0Reg.Bit.NT_meas_done_en = 1;
|
||||
Ctrl0Reg.Bit.Auto_SR_en = 1; //自动SET/RESET,消除温漂零场漂移
|
||||
Ctrl0Reg.Bit.NT_meas_done_en = 1; //测量完成中断使能
|
||||
MMC5983_Write_Reg(MMC5983_CTRL_0, Ctrl0Reg.Byte);
|
||||
|
||||
if(InitFlag == false){
|
||||
@@ -122,7 +129,7 @@ static void MMC5983_Init(void)
|
||||
|
||||
/*****************************************************************************************
|
||||
* 函数名称: MMC5983_Read
|
||||
* 功能描述: MMC5983读取原始数据
|
||||
* 功能描述: MMC5983读取原始数据(18bit)
|
||||
* 参 数: MagAdcX X轴数据
|
||||
MagAdcY Y轴数据
|
||||
MagAdcZ Z轴数据
|
||||
@@ -164,100 +171,89 @@ void MMC5983_Get_Mag(float *mag)
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
* 函数名称: MMC5983LoopHandler
|
||||
* 功能描述: MMC5983循环处理函数
|
||||
* 函数名称: MMC5983MeasDoneProcess
|
||||
* 功能描述: 单次测量完成处理:读取样本、清除中断锁存,凑够MAG_AVG_CNT个样本后平均输出
|
||||
* 参 数: 无
|
||||
* 返 回 值: 无
|
||||
*****************************************************************************************/
|
||||
static void MMC5983MeasDoneProcess(void)
|
||||
{
|
||||
MMC5983Var.MMC5983Delay1mSCnt = MAG_POLL_MS;
|
||||
if(MMC5983_Read(&mag_array[X][magcnt], &mag_array[Y][magcnt], &mag_array[Z][magcnt])){
|
||||
magcnt++;
|
||||
}
|
||||
MMC5983_Write_Reg(MMC5983_STATUS, 0x01); //写1清Meas_M_Done,释放INT锁存,下次测量产生新上升沿
|
||||
if(magcnt >= MAG_AVG_CNT){
|
||||
MMC5983Var.Mag_Original[X] = AverageFilter_32t(mag_array[X], magcnt);
|
||||
MMC5983Var.Mag_Original[Y] = AverageFilter_32t(mag_array[Y], magcnt);
|
||||
MMC5983Var.Mag_Original[Z] = AverageFilter_32t(mag_array[Z], magcnt);
|
||||
magcnt = 0;
|
||||
MMC5983_Get_Mag(MMC5983Var.Mag);
|
||||
MmcDataProcessCallBack(MMC5983Var.Mag);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
* 函数名称: MMC5983LoopHandler
|
||||
* 功能描述: MMC5983循环处理函数,20Hz连续采样,2样本平均后10Hz输出
|
||||
* 参 数: 无
|
||||
* 返 回 值: 无
|
||||
*****************************************************************************************/
|
||||
extern void MmcDataProcessCallBack(float *Mag);
|
||||
|
||||
void MMC5983LoopHandler(void)
|
||||
{
|
||||
static int32_t mag_array[XYZ][10];
|
||||
static uint8_t magcnt;
|
||||
static uint8_t TimeOutMagcnt;
|
||||
|
||||
switch(MMC5983Var.Status) {
|
||||
case MMC5983_STATUS_IDLE:{
|
||||
break;}
|
||||
|
||||
case MMC5983_STATUS_START:{
|
||||
for(int i = 0; i < 10; i++) {
|
||||
mag_array[X][i] = 0;
|
||||
mag_array[Y][i] = 0;
|
||||
mag_array[Z][i] = 0;
|
||||
if(!InitFlag){
|
||||
MMC5983_Init();
|
||||
if(!InitFlag){
|
||||
MMC5983Var.Status = MMC5983_STATUS_IDLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
magcnt = 0;
|
||||
TimeOutMagcnt = 0;
|
||||
memset(&MMC5983Var, NULL, sizeof(MMC5983Var));
|
||||
MMC5983Var.Status = MMC5983_STATUS_DELAY;
|
||||
break;}
|
||||
|
||||
case MMC5983_STATUS_DELAY:{
|
||||
MMC5983StartRead();
|
||||
MMC5983Var.MMC5983Delay1mSCnt = 50;
|
||||
MMC5983Var.Status = MMC5983_STATUS_WAIT_DELAY;
|
||||
break;}
|
||||
|
||||
case MMC5983_STATUS_WAIT_DELAY:{
|
||||
if(MMC5983Var.MMC5983Delay1mSCnt <= 0){
|
||||
MMC5983Var.Status = MMC5983_STATUS_READ;
|
||||
}
|
||||
break;}
|
||||
|
||||
case MMC5983_STATUS_READ:{
|
||||
MMC5983Var.MMC5983Delay1mSCnt = 50;
|
||||
PollFailCnt = 0;
|
||||
MMC5983StartContinuous(); //开启20Hz连续测量
|
||||
MMC5983Var.MMC5983Delay1mSCnt = MAG_POLL_MS;
|
||||
MMC5983Var.Status = MMC5983_STATUS_WAIT_READ;
|
||||
break;}
|
||||
|
||||
case MMC5983_STATUS_WAIT_READ:{
|
||||
if(MMC5983Var.MMC5983Delay1mSCnt <= 0){
|
||||
MMC5983Var.Status = MMC5983_STATUS_DELAY;
|
||||
TimeOutMagcnt++;
|
||||
}
|
||||
if(MMC5983IntFlag == true){
|
||||
MMC5983IntFlag = false;
|
||||
MMC5983_Read(&mag_array[X][magcnt], &mag_array[Y][magcnt], &mag_array[Z][magcnt]);
|
||||
magcnt++;
|
||||
MMC5983Var.Status = MMC5983_STATUS_DELAY;
|
||||
PollFailCnt = 0;
|
||||
MMC5983MeasDoneProcess(); //INT触发,立即读数
|
||||
}
|
||||
if(TimeOutMagcnt >= 10){
|
||||
TimeOutMagcnt = 0;
|
||||
if(magcnt > 0){
|
||||
MMC5983Var.Mag_Original[X] = AverageFilter_32t(mag_array[X], magcnt);
|
||||
MMC5983Var.Mag_Original[Y] = AverageFilter_32t(mag_array[Y], magcnt);
|
||||
MMC5983Var.Mag_Original[Z] = AverageFilter_32t(mag_array[Z], magcnt);
|
||||
magcnt = 0;
|
||||
MMC5983_Get_Mag(MMC5983Var.Mag);
|
||||
MmcDataProcessCallBack(MMC5983Var.Mag);
|
||||
MMC5983Var.Status = MMC5983_STATUS_STOP;
|
||||
else if(MMC5983Var.MMC5983Delay1mSCnt <= 0){
|
||||
uint8_t StatusReg;
|
||||
MMC5983Var.MMC5983Delay1mSCnt = MAG_POLL_MS; //20ms轮询一次测量完成标志
|
||||
StatusReg = MMC5983_Read_Reg(MMC5983_STATUS);
|
||||
if((StatusReg & 0x01) != 0){ //Meas_M_Done=1,测量完成
|
||||
PollFailCnt = 0;
|
||||
MMC5983MeasDoneProcess();
|
||||
}
|
||||
else{
|
||||
MMC5983Var.Status = MMC5983_STATUS_STOP;
|
||||
// DBG_LOG("LEFT MMC5983 TimeOut...\r\n");
|
||||
PollFailCnt++;
|
||||
if(PollFailCnt >= MAG_POLL_FAIL_MAX){
|
||||
PollFailCnt = 0;
|
||||
MMC5983StartContinuous(); //连续无数据,重写配置自恢复
|
||||
}
|
||||
}
|
||||
if(magcnt >= 10){
|
||||
MMC5983Var.Mag_Original[X] = AverageFilter_32t(mag_array[X], magcnt);
|
||||
MMC5983Var.Mag_Original[Y] = AverageFilter_32t(mag_array[Y], magcnt);
|
||||
MMC5983Var.Mag_Original[Z] = AverageFilter_32t(mag_array[Z], magcnt);
|
||||
magcnt = 0;
|
||||
MMC5983_Get_Mag(MMC5983Var.Mag);
|
||||
MmcDataProcessCallBack(MMC5983Var.Mag);
|
||||
MMC5983Var.Status = MMC5983_STATUS_STOP;
|
||||
}
|
||||
break;}
|
||||
|
||||
case MMC5983_STATUS_STOP:{
|
||||
MMC5983Stop();
|
||||
MMC5983Var.Status = MMC5983_STATUS_IDLE;
|
||||
//MMC5983Var.Status = MMC5983_STATUS_START;//持续工作
|
||||
break;}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
* 函数名称: LeftMMC59831mSRoutine
|
||||
* 函数名称: MMC59831mSRoutine
|
||||
* 功能描述: MMC59831ms时基循环处理函数
|
||||
* 参 数: 无
|
||||
* 返 回 值: 无
|
||||
@@ -269,7 +265,7 @@ void MMC59831mSRoutine(void)
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
* 函数名称: LeftMMC5983Init
|
||||
* 函数名称: MMC5983Init
|
||||
* 功能描述: MMC5983初始化
|
||||
* 参 数: 无
|
||||
* 返 回 值: 无
|
||||
@@ -285,53 +281,47 @@ void MMC5983Init(void)
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
* 函数名称: LeftMMC5983Start
|
||||
* 功能描述: MMC5983启动
|
||||
* 函数名称: MMC5983Start
|
||||
* 功能描述: MMC5983启动(幂等,已运行则直接返回)
|
||||
* 参 数: 无
|
||||
* 返 回 值: 无
|
||||
*****************************************************************************************/
|
||||
void MMC5983Start(void)
|
||||
{
|
||||
if(MMC5983Var.Status == MMC5983_STATUS_WAIT_READ){
|
||||
return; //已在连续采样,不重复配置
|
||||
}
|
||||
if(!InitFlag){
|
||||
MMC5983_Init();
|
||||
if(!InitFlag){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MMC5983Var.Status = MMC5983_STATUS_START;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
* 函数名称: LeftMMC5983StartRead
|
||||
* 功能描述: MMC5983启动读取
|
||||
* 参 数: 无
|
||||
* 返 回 值: 无
|
||||
*****************************************************************************************/
|
||||
void MMC5983StartRead(void)
|
||||
{
|
||||
MMC5983_Init();//读取时重新初始化
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
* 函数名称: MMC5983Stop
|
||||
* 功能描述: MMC5983停止
|
||||
* 功能描述: MMC5983停止(关闭连续转换)
|
||||
* 参 数: 无
|
||||
* 返 回 值: 无
|
||||
*****************************************************************************************/
|
||||
void MMC5983Stop(void)
|
||||
{
|
||||
MMC5983RegCtrl2 Ctrl2Reg;
|
||||
Ctrl2Reg.Byte = 0x00;
|
||||
MMC5983_Write_Reg(MMC5983_CTRL_2, Ctrl2Reg.Byte); //Cmm_en=0,关闭连续转换
|
||||
|
||||
MMC5983RegCtrl0 Ctrl0Reg;
|
||||
Ctrl0Reg.Byte = 0x00;
|
||||
MMC5983_Write_Reg(MMC5983_CTRL_0, Ctrl0Reg.Byte);
|
||||
|
||||
MMC5983RegStatus StatusReg;
|
||||
StatusReg.Byte = MMC5983_Read_Reg(MMC5983_STATUS);
|
||||
if(StatusReg.Bit.Meas_M_Done == 1){
|
||||
MMC5983_Write_Reg(MMC5983_STATUS, StatusReg.Byte);
|
||||
}
|
||||
MMC5983Var.Status = MMC5983_STATUS_IDLE;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
* 函数名称: LeftMMC5983IntCallBack
|
||||
* 函数名称: MMC5983IntCallBack
|
||||
* 功能描述: MMC5983中断回调
|
||||
* 参 数: 无
|
||||
* 返 回 值: 无
|
||||
@@ -340,4 +330,3 @@ void MMC5983IntCallBack(void)
|
||||
{
|
||||
MMC5983IntFlag = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -103,9 +103,6 @@ typedef union {
|
||||
typedef enum{
|
||||
MMC5983_STATUS_IDLE,
|
||||
MMC5983_STATUS_START,
|
||||
MMC5983_STATUS_DELAY,
|
||||
MMC5983_STATUS_WAIT_DELAY,
|
||||
MMC5983_STATUS_READ,
|
||||
MMC5983_STATUS_WAIT_READ,
|
||||
MMC5983_STATUS_STOP,
|
||||
}MMC5983Status_m;
|
||||
@@ -129,7 +126,6 @@ void MMC5983Calib(void);
|
||||
void MMC5983GetADValue(int32_t *Mag);
|
||||
void MMC5983_Get_Mag(float *mag);
|
||||
MMC5983Status_m GetMMC5983Status(void);
|
||||
void MMC5983StartRead(void);
|
||||
bool GetMMC5983CalibStatus(void);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
# LaserTracing 项目架构与工作流程分析
|
||||
|
||||
## 1. 项目概述
|
||||
|
||||
LaserTracing(激光示踪)是基于华大 HC32L170(ARM Cortex-M0+)超低功耗 MCU 的嵌入式传感器项目。设备通过 LoRa(SX1276)无线通信接入网关,采集三维姿态角(俯仰/横滚/偏航)并定时上报,同时支持激光控制、低功耗休眠、FPO 全功率时间段等特性。
|
||||
|
||||
### 1.1 硬件组成
|
||||
|
||||
| 模块 | 型号/接口 | 用途 |
|
||||
|------|-----------|------|
|
||||
| MCU | HC32L170 | 主控,Cortex-M0+ |
|
||||
| LoRa | SX1276 (SPI0) | 与网关无线通信 |
|
||||
| 加速度计 | LSM6DSL (I2C0) | 采集加速度/陀螺仪 |
|
||||
| 地磁 | MMC5983 (I2C0) | 采集磁场 |
|
||||
| 激光 | LASER1~3 (GPIO) | 激光开关控制 |
|
||||
| ADC | ADC (EXCH4) | 电池电压采样 |
|
||||
| 调试口 | UART/RS485 | 调试命令交互 |
|
||||
|
||||
### 1.2 软件版本
|
||||
|
||||
- 软件版本: `SOFTWARE_VERSION = 13`
|
||||
- 硬件版本: `HARDWARE_VERSION = 11`
|
||||
|
||||
## 2. 目录结构
|
||||
|
||||
```
|
||||
LaserTracing/
|
||||
├── MDK/ # Keil 工程文件 (uvprojx/uvoptx/RTE)
|
||||
├── Module/ # 功能模块
|
||||
│ ├── Imu/ # IMU 姿态解算上层
|
||||
│ ├── LORA/ # SX1276 LoRa 驱动 (sx127x.c/h)
|
||||
│ ├── LaserTracing_Debug/ # 调试命令模块 (UartDebug.c/h)
|
||||
│ ├── MahonyAHRS/ # 姿态解算算法库
|
||||
│ ├── lsm6dsl/ # LSM6DSL 驱动 (含寄存器层)
|
||||
│ └── mmc5983/ # MMC5983 驱动
|
||||
├── driver/ # HC32L170 官方外设驱动库 (inc/src)
|
||||
├── mcu/ # 芯片支持包 (启动文件、FlashLoader)
|
||||
├── source/
|
||||
│ ├── inc/ # 项目头文件
|
||||
│ │ ├── main.h # 应用结构体/状态机/全局声明
|
||||
│ │ ├── bsp.h # 板级定义/参数结构/外设宏
|
||||
│ │ ├── SGCP.h # 通信协议定义
|
||||
│ │ ├── Algorithm.h # 算法接口
|
||||
│ │ ├── Update.h # 升级接口
|
||||
│ │ └── UartDebug.h # 调试接口
|
||||
│ └── src/
|
||||
│ ├── main.c # 主流程/状态机/数据采集
|
||||
│ ├── bsp.c # 板级初始化/中断处理/外设封装
|
||||
│ ├── SGCP.c # 通信协议栈 (网关交互)
|
||||
│ ├── Algorithm.c # 工具函数/辅助算法
|
||||
│ └── Update.c # 固件升级逻辑
|
||||
└── docs/ # 本文档
|
||||
```
|
||||
|
||||
## 3. 核心架构分层
|
||||
|
||||
### 3.1 分层结构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 应用层 (main.c) │
|
||||
│ - AppInit/主循环/状态机/数据采集与处理 │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ 协议层 (SGCP.c) │
|
||||
│ - 注册/上报/配置/激光/信号 帧处理与状态机 │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ 模块层 (Module/) │
|
||||
│ - LoRa/IMU/AHRS/传感器/调试 各功能模块 │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ 驱动层 (driver/ + bsp.c) │
|
||||
│ - HC32L170 外设驱动 + 板级封装 │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.2 关键全局对象
|
||||
|
||||
- `App` (`AppDetect_t`):应用状态、传感器数据、姿态结果、配置参数、各类标志与计数器。
|
||||
- `SGCP` (`SGCP_t`):通信协议状态、网关/设备 MAC、接收缓冲区、指令状态机标志。
|
||||
- `LocalMAC` / `GatewayMAC`:本机 6 字节 MAC 与网关 MAC。
|
||||
- `LocalDataPack`:本机待上报的打包数据。
|
||||
|
||||
## 4. 工作流程分析
|
||||
|
||||
### 4.1 系统启动流程 (main)
|
||||
|
||||
```
|
||||
main()
|
||||
├─ BspInit() # 时钟、GPIO、外设、中断初始化
|
||||
├─ delay_ms(3000) # 上电等待
|
||||
├─ AppInit() # 读参数、校验恢复默认、初始化 RTC/LPTimer/LoRa/传感器
|
||||
├─ 打印版本信息
|
||||
└─ while(1) 主循环
|
||||
├─ ADCLoopHandler() # 电池电压采样
|
||||
├─ FeedDogHandler() # 看门狗喂狗
|
||||
├─ DebugLoopHandler() # 调试命令处理
|
||||
├─ Lsm6dslLoopHandler() # 加速度数据处理
|
||||
├─ MMC5983LoopHandler() # 地磁数据处理
|
||||
├─ ReadDataLoopHandler() # 数据采集状态机
|
||||
├─ GwRevLoopHandler() # 网关收发状态机
|
||||
├─ InRevLoopHandler() # 内部指令处理
|
||||
└─ AppLoopHandler() # 应用状态机
|
||||
```
|
||||
|
||||
### 4.2 时基中断与回调
|
||||
|
||||
| 中断 | 功能 |
|
||||
|------|------|
|
||||
| SysTick_CallBack (1ms) | 调用各 1mSRoutine 递减计数器 |
|
||||
| RtcIRQHander (30s) | 系统定时重启、定时采集触发、周期上报、紧急上报 |
|
||||
| LPTimer0IRQHander | 注册/上传重试定时器 |
|
||||
| PortB_IRQHandler | LoRa DIO0(发送完成/接收完成) |
|
||||
| PortC_IRQHandler | 加速度 INT1 / 地磁 INT 回调 |
|
||||
|
||||
### 4.3 应用状态机 (AppLoopHandler / APP_STATUS_*)
|
||||
|
||||
```
|
||||
APP_STATUS_SLEEP → APP_STATUS_ON → APP_STATUS_ACTION
|
||||
│
|
||||
┌─────────────────────────────────┼───────────────────────────────┐
|
||||
▼ ▼ ▼
|
||||
APP_STATUS_WAIT_LOGIN (数据采集) APP_STATUS_WAIT_UPLOAD
|
||||
│ 注册成功 │ 采集完成(UpdateOk) │ 上传完成/超时
|
||||
└───────▶ APP_STATUS_ACTION └───────▶ 触发上传 └──────▶ ACTION
|
||||
```
|
||||
|
||||
关键转移条件(`AppLoopHandler` 中按优先级判断):
|
||||
1. `InStatus != IDLE` → 等待内部指令完成
|
||||
2. `LoginOk == false && LoginFlag == true && GWStatus == IDLE` → 发起注册
|
||||
3. `TimingAcquisition == true && RDStatus == IDLE` → 启动传感器采集
|
||||
4. `LoginOk == true && UploadFlag == true && GWStatus == IDLE && UpdateOk == true` → 上传数据
|
||||
5. `LaserOnOff == true && LaserTimerCount == 0` → 激光状态处理
|
||||
6. 全部空闲且 `IsFullPowerTime() == false` → 进入休眠 (`APP_STATUS_OFF`)
|
||||
|
||||
### 4.4 数据采集状态机 (ReadDataLoopHandler / READDATA_STATUS_*)
|
||||
|
||||
```
|
||||
READDATA_STATUS_IDLE
|
||||
└─(TimingAcquisition=true)─▶ READDATA_STATUS_UPDAING
|
||||
(启动 LSM6DSL + MMC5983,置 ReadData1mSDelayCnt=2000)
|
||||
└─▶ READDATA_STATUS_WAIT_UPDAING
|
||||
(等待中断回调置 MagRead_EndFlag / AccRead_EndFlag 或 2s 超时)
|
||||
└─▶ READDATA_STATUS_DATA_HANDLE
|
||||
(IMU_Update 解算 → 存 ConvertedData → 拷入 LocalDataPack)
|
||||
└─▶ READDATA_STATUS_IDLE (置 UpdateOk=true)
|
||||
```
|
||||
|
||||
若任一传感器超时(未收到中断),`UpdateOk` 保持 false,本周期数据不用于上报。
|
||||
|
||||
### 4.5 注册与数据上报时序
|
||||
|
||||
1. 上电后 `LPTimer0_ON(50)`(5s)后 `LoginFlag=true`。
|
||||
2. `APP_STATUS_ACTION` 检测到注册条件 → `GW_STATUS_LOGIN` → `ToGWDevLogin()` 发送注册帧(Cmd=0x00)。
|
||||
3. 网关回应注册 → `GWRevHandler` 置 `LoginOk`、保存 `GatewayMAC` → `GW_STATUS_WAIT_LOGIN` 置 `LoginMess`、`TimingAcquisition=true`。
|
||||
4. `APP_STATUS_WAIT_LOGIN` 置 `UploadFlag=true` 并触发采集。
|
||||
5. 采集完成 `UpdateOk=true` → `APP_STATUS_ACTION` 置 `GW_STATUS_UPLOAD_SENSOR` → `ToGWReadDataRes()` 发送数据帧(Cmd=0x02)。
|
||||
6. `GW_STATUS_WAIT_UPLOAD` 等网关回应(2s 超时)。收到回应 `UploadOk=true` → 上报成功;超时则 `UploadMess=true`,由 `APP_STATUS_WAIT_UPLOAD` 计数重试,3 次失败后重新注册。
|
||||
|
||||
### 4.6 协议帧格式 (SGCP)
|
||||
|
||||
网关↔设备固定帧(16 字节头):
|
||||
|
||||
```
|
||||
| Header(1) | GWAddr(6) | MDAddr(6) | Cmd(1) | PayloadLen(2) | Payload(N) | CRC16(2) |
|
||||
```
|
||||
|
||||
命令字(网关→设备):
|
||||
|
||||
| Cmd | 含义 |
|
||||
|-----|------|
|
||||
| 0x00 | 设备注册 (GWTOMD_CMD_LOGIN) |
|
||||
| 0x01 | 校准 (GWTOMD_CMD_CALI) |
|
||||
| 0x02 | 读取/上传数据 (GWTOMD_CMD_READ_UPLOAD_SENSOR) |
|
||||
| 0x05 | 设置采集时间间隔 (GWTOMD_CMD_SET_COL_TIME) |
|
||||
| 0x06 | 时间同步 (GWTOMD_CMD_SYNC_TIME) |
|
||||
| 0x08 | 打开/关闭激光 (GWTOMD_CMD_SET_LASER) |
|
||||
| 0x09 | 信号质量查询 (GWTOMD_CMD_SIGNAL) |
|
||||
| 0x0A | 设置全功率运行时间段 (GWTOMD_CMD_SET_FPO) |
|
||||
|
||||
`LayoutPara_t` 参数(网关下发,10 字节 + 时间戳):CollectTime / ReportInterval / ERInterval / ERTime / FPOTimeStart / FPOTime / TimeStamp。
|
||||
|
||||
### 4.7 网关状态机 (GwRevLoopHandler / GW_STATUS_*)
|
||||
|
||||
```
|
||||
GW_STATUS_IDLE
|
||||
├─▶ LOGIN → WAIT_LOGIN → IDLE # 注册流程
|
||||
├─▶ CALI → 校准回应 # 校准
|
||||
├─▶ SET_COL_TIME → 采集间隔回应
|
||||
├─▶ SET_FPO → 全功率时间段回应 (0x0A)
|
||||
├─▶ SYNC_TIME → 时间同步
|
||||
├─▶ UPLOAD_SENSOR → WAIT_UPLOAD # 上报流程
|
||||
├─▶ LASER_STARES → 激光状态回应
|
||||
└─▶ SIGNAL → WAIT_SIGNAL → 信号质量
|
||||
```
|
||||
|
||||
### 4.8 低功耗与休眠
|
||||
|
||||
- 空闲时判断:`RDStatus==IDLE && GWStatus==IDLE && InStatus==IDLE && !TimingAcquisition && 各延时==0 && !LaserOnOff && !AttTestMode && !IsFullPowerTime()` → `APP_STATUS_OFF` → 关闭 LED → `APP_STATUS_SLEEP`。
|
||||
- `APP_STATUS_SLEEP` 中调用 `EnterDeepSleep()` 深睡眠,`WakeUpInit()` 唤醒后回 `APP_STATUS_ON`。
|
||||
- **FPO 全功率时间段**:由 `IsFullPowerTime()` 判断当前本地小时是否落在 `[FPOTimeStart, FPOTimeStart+FPOTime)` 区间内(支持跨天、0 时长表示关闭),在 FPO 时段内不进入休眠。FPOTime 默认 0,`TimeGet` 从 RTC 读取当前小时(本地时间)。
|
||||
|
||||
### 4.9 激光控制
|
||||
|
||||
- 网关下发 0x08 指令置 `SGCP.LaserOnOff`,`LaserTimerMinutes`(默认 **1 分钟**)决定自动关闭时长。
|
||||
- `GW_STATUS_LASER_STARES` 中执行 `LASER1_ON/OFF()` 并回应网关。
|
||||
- RTC 30s 中断中 `LaserTimerCount--`,归零后再次进入 `GW_STATUS_LASER_STARES` 执行关闭。
|
||||
|
||||
## 5. 通信模式配置
|
||||
|
||||
| 宏 | 值 | 说明 |
|
||||
|----|----|------|
|
||||
| `WORK_MODE` | 1 | 0=查询模式,1=上报模式(低功耗) |
|
||||
| `SGCP_SELECT` | 1 | 0=主+子多设备,1=单主设备(当前),2=单子设备 |
|
||||
| `USE_VBAT_AD` | 1 | 电池电压采样开关 |
|
||||
| `USE_WDT` | 1 | 看门狗开关 |
|
||||
| `USE_DEBUG` | 1 | 调试命令开关 |
|
||||
| `USE_BOOTLOADER` | 0 | BootLoader 升级开关 |
|
||||
|
||||
## 6. LoRa 信道配置
|
||||
|
||||
中心频率范围 **470100000 ~ 492600000 Hz**,步进 **500000 Hz**,共 **46 个信道**(CH0~CH45):
|
||||
|
||||
- CH0 = 470100000,CH1 = 470600000,...,CH45 = 492600000。
|
||||
- 默认 `FREQ_CENT = CH0`;信道切换上限 `LoraSetChannel` 允许 0~45。
|
||||
- 频率范围校验(`LoraSetFreqCent` / AppInit):470100000 ~ 492600000,覆盖全部信道。
|
||||
- 可通过调试命令 `lora ch <0~45>` 配置信道。
|
||||
|
||||
## 7. 调试命令 (UartDebug)
|
||||
|
||||
| 命令 | 说明 |
|
||||
|------|------|
|
||||
| `reg` | 手动触发注册 |
|
||||
| `para` | 打印当前配置参数(含 FPO、激光状态) |
|
||||
| `lpcfg CI RI EI ET` | 配置低功耗采集/上报参数 |
|
||||
| `fpocfg Start Dur` | 配置全功率运行时间段(配置后自动向网关发送 0x0A 通知) |
|
||||
| `lora ch/pw/bw/sf/ec/rp/fc/o` | 配置 LoRa 参数 |
|
||||
| `laser` | 激光控制与定时配置 |
|
||||
| `rs485` / `dch` | RS485 通道控制 / 调试通道切换 |
|
||||
| `res` | 恢复出厂设置 |
|
||||
| `dbg` | 调试开关控制 |
|
||||
|
||||
## 8. 关键文件与职责对照
|
||||
|
||||
| 文件 | 主要职责 |
|
||||
|------|----------|
|
||||
| `source/src/main.c` | 主流程、应用状态机、数据采集状态机、FPO 判断、中断回调 |
|
||||
| `source/src/SGCP.c` | 协议栈:帧组包/解析、网关状态机、注册/上报/配置/激光/信号处理 |
|
||||
| `source/src/bsp.c` | 板级初始化、外设封装、中断处理、RTC/TimeGet/低功耗 |
|
||||
| `source/inc/SGCP.h` | 协议常量、帧结构、命令字、状态机、设备数据定义 |
|
||||
| `source/inc/bsp.h` | 板级宏、参数结构(LayoutPara_t 等)、外设引脚定义 |
|
||||
| `source/inc/main.h` | 应用结构体、状态机枚举、宏定义 |
|
||||
| `Module/LORA/sx127x.c` | LoRa 收发、信道/频率/功率配置 |
|
||||
| `Module/LaserTracing_Debug/UartDebug.c` | 调试命令解析执行 |
|
||||
| `Module/lsm6dsl` / `mmc5983` | 传感器驱动与数据回调 |
|
||||
| `Module/MahonyAHRS` / `Imu` | 姿态解算 |
|
||||
|
||||
## 9. 典型问题排查路径
|
||||
|
||||
- **注册失败/超时**:查 `GW_STATUS_WAIT_LOGIN` 超时日志、网关 MAC 是否保存、LoRa 接收是否正常。
|
||||
- **上传超时**:查 `GW_STATUS_WAIT_UPLOAD` 日志、`LocalDataPack` 是否全 0(`is_all_byte` 检查)、`UpdateOk` 是否被置位、传感器采集是否超时。
|
||||
- **无法休眠**:查 `IsFullPowerTime()` 时段判断、`InStatus/GWStatus/RDStatus` 是否处于非 IDLE、各类延时计数是否清零。
|
||||
- **LoRa 通信异常**:核对信道频率范围(470.1~492.6MHz)与网关是否一致、`FREQ_CENT`/`FreqCent` 配置、天线开关状态。
|
||||
+107
-73
@@ -66,11 +66,11 @@
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief I2C设置波特率配置寄存器
|
||||
** \brief I2C设置波特率配置寄存器
|
||||
**
|
||||
** \param [in] u8Tm 波特率配置值
|
||||
** \param [in] u8Tm 波特率配置值
|
||||
**
|
||||
** \retval enRet 成功或失败
|
||||
** \retval enRet 成功或失败
|
||||
**
|
||||
******************************************************************************/
|
||||
en_result_t I2C_SetBaud(M0P_I2C_TypeDef* I2Cx, uint8_t u8Tm)
|
||||
@@ -84,11 +84,11 @@
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief I2C功能设置相关函数
|
||||
** \brief I2C功能设置相关函数
|
||||
**
|
||||
** \param [in] enFunc功能参数
|
||||
** \param [in] enFunc功能参数
|
||||
**
|
||||
** \retval enRet 成功或失败
|
||||
** \retval enRet 成功或失败
|
||||
**
|
||||
******************************************************************************/
|
||||
en_result_t I2C_SetFunc(M0P_I2C_TypeDef* I2Cx, en_i2c_func_t enFunc)
|
||||
@@ -102,11 +102,11 @@ en_result_t I2C_SetFunc(M0P_I2C_TypeDef* I2Cx, en_i2c_func_t enFunc)
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief I2C功能清除相关函数
|
||||
** \brief I2C功能清除相关函数
|
||||
**
|
||||
** \param [in] enFunc功能参数
|
||||
** \param [in] enFunc功能参数
|
||||
**
|
||||
** \retval enRet 成功或失败
|
||||
** \retval enRet 成功或失败
|
||||
**
|
||||
******************************************************************************/
|
||||
en_result_t I2C_ClearFunc(M0P_I2C_TypeDef* I2Cx, en_i2c_func_t enFunc)
|
||||
@@ -120,11 +120,11 @@ en_result_t I2C_SetFunc(M0P_I2C_TypeDef* I2Cx, en_i2c_func_t enFunc)
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief I2C获取中断标记函数
|
||||
** \brief I2C获取中断标记函数
|
||||
**
|
||||
** \param 无
|
||||
** \param 无
|
||||
**
|
||||
** \retval bIrq中断标记
|
||||
** \retval bIrq中断标记
|
||||
**
|
||||
******************************************************************************/
|
||||
boolean_t I2C_GetIrq(M0P_I2C_TypeDef* I2Cx)
|
||||
@@ -140,11 +140,11 @@ boolean_t I2C_GetIrq(M0P_I2C_TypeDef* I2Cx)
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief I2C清除中断标记函数
|
||||
** \brief I2C清除中断标记函数
|
||||
**
|
||||
** \param 无
|
||||
** \param 无
|
||||
**
|
||||
** \retval bIrq中断标记
|
||||
** \retval bIrq中断标记
|
||||
**
|
||||
******************************************************************************/
|
||||
en_result_t I2C_ClearIrq(M0P_I2C_TypeDef* I2Cx)
|
||||
@@ -158,11 +158,11 @@ en_result_t I2C_ClearIrq(M0P_I2C_TypeDef* I2Cx)
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief I2C获取相关状态
|
||||
** \brief I2C获取相关状态
|
||||
**
|
||||
** \param 无
|
||||
** \param 无
|
||||
**
|
||||
** \retval I2C状态
|
||||
** \retval I2C状态
|
||||
**
|
||||
******************************************************************************/
|
||||
uint8_t I2C_GetState(M0P_I2C_TypeDef* I2Cx)
|
||||
@@ -176,11 +176,11 @@ uint8_t I2C_GetState(M0P_I2C_TypeDef* I2Cx)
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief 字节数据写函数
|
||||
** \brief 字节数据写函数
|
||||
**
|
||||
** \param u8Data写数据
|
||||
** \param u8Data写数据
|
||||
**
|
||||
** \retval 写数据是否成功
|
||||
** \retval 写数据是否成功
|
||||
**
|
||||
******************************************************************************/
|
||||
en_result_t I2C_WriteByte(M0P_I2C_TypeDef* I2Cx, uint8_t u8Data)
|
||||
@@ -194,11 +194,11 @@ en_result_t I2C_WriteByte(M0P_I2C_TypeDef* I2Cx, uint8_t u8Data)
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief 字节数据读函数
|
||||
** \brief 字节数据读函数
|
||||
**
|
||||
** \param 无
|
||||
** \param 无
|
||||
**
|
||||
** \retval 读取数据
|
||||
** \retval 读取数据
|
||||
**
|
||||
******************************************************************************/
|
||||
uint8_t I2C_ReadByte(M0P_I2C_TypeDef* I2Cx)
|
||||
@@ -212,11 +212,11 @@ uint8_t I2C_ReadByte(M0P_I2C_TypeDef* I2Cx)
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief I2C模块初始化
|
||||
** \brief I2C模块初始化
|
||||
**
|
||||
** \param pstcI2CCfg初始化配置结构体
|
||||
** \param pstcI2CCfg初始化配置结构体
|
||||
**
|
||||
** \retval 初始化是否成功
|
||||
** \retval 初始化是否成功
|
||||
**
|
||||
******************************************************************************/
|
||||
en_result_t I2C_Init(M0P_I2C_TypeDef* I2Cx, stc_i2c_cfg_t *pstcI2CCfg)
|
||||
@@ -265,71 +265,89 @@ en_result_t I2C_Init(M0P_I2C_TypeDef* I2Cx, stc_i2c_cfg_t *pstcI2CCfg)
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief I2C模块接收指定长度函数
|
||||
** \brief I2C模块接收指定长度函数
|
||||
**
|
||||
** \param u8SlaveAddr从机设备地址,u8Addr从机内存地址,pu8Data读数据存放缓存,u32Len读数据长度
|
||||
** \param u8SlaveAddr从机设备地址,u8Addr从机内存地址,pu8Data读数据存放缓存,u32Len读数据长度
|
||||
**
|
||||
** \retval 读数据是否成功
|
||||
** \retval 读数据是否成功
|
||||
**
|
||||
******************************************************************************/
|
||||
#define I2C_WAIT_TIMEOUT 20000u ///< 单步等待超时计数,防止总线卡死导致系统死循环
|
||||
#define I2C_READ_PASS_MAX 200u ///< 读传输状态机最大循环次数(48字节FIFO读约需120次)
|
||||
#define I2C_WRITE_PASS_MAX 64u ///< 写传输状态机最大循环次数
|
||||
|
||||
boolean_t I2C_MasterReadData(M0P_I2C_TypeDef* I2CX,uint8_t u8SlaveAddr,uint8_t u8Addr,uint8_t *pu8Data,uint32_t u32Len)
|
||||
{
|
||||
boolean_t enRet = FALSE;
|
||||
uint8_t u8i=0,u8State;
|
||||
uint32_t u32Wait = 0;
|
||||
uint16_t u16Pass = 0;
|
||||
|
||||
I2C_SetFunc(I2CX,I2cStart_En);//开始
|
||||
I2C_SetFunc(I2CX,I2cStart_En);//开始
|
||||
|
||||
while(1)
|
||||
{
|
||||
while(0 == I2C_GetIrq(I2CX))//获取中断标记函数
|
||||
{;}
|
||||
u8State = I2C_GetState(I2CX);//获取i2c相关状态
|
||||
while(0 == I2C_GetIrq(I2CX))//获取中断标记函数
|
||||
{
|
||||
if(++u32Wait >= I2C_WAIT_TIMEOUT) ///< 等待超时,总线异常
|
||||
{
|
||||
I2C_SetFunc(I2CX,I2cStop_En); ///< 尝试发送停止条件释放总线
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
u32Wait = 0;
|
||||
if(++u16Pass >= I2C_READ_PASS_MAX) ///< 状态机重试超限(持续NACK等),放弃本次传输
|
||||
{
|
||||
I2C_SetFunc(I2CX,I2cStop_En);
|
||||
return FALSE;
|
||||
}
|
||||
u8State = I2C_GetState(I2CX);//获取i2c相关状态
|
||||
switch(u8State)
|
||||
{
|
||||
case 0x08: ///< 主设备向总线已发出了一个起始条件
|
||||
case 0x08: ///< 主设备向总线已发出了一个起始条件
|
||||
I2C_ClearFunc(I2CX,I2cStart_En);
|
||||
I2C_WriteByte(I2CX,(u8SlaveAddr << 1));
|
||||
break;
|
||||
case 0x18: ///< 主设备向总线已发出了一个从设备地址(写方向)并且接收到从设备的应答
|
||||
I2C_WriteByte(I2CX,u8Addr); ///< 发送从机内存地址
|
||||
case 0x18: ///< 主设备向总线已发出了一个从设备地址(写方向)并且接收到从设备的应答
|
||||
I2C_WriteByte(I2CX,u8Addr); ///< 发送从机内存地址
|
||||
break;
|
||||
case 0x28: ///< 已发送数据,接收到ACK, 此处是已发送从机内存地址u8Addr并接收到ACK
|
||||
I2C_SetFunc(I2CX,I2cStart_En); ///< 发送重复起始条件
|
||||
case 0x28: ///< 已发送数据,接收到ACK, 此处是已发送从机内存地址u8Addr并接收到ACK
|
||||
I2C_SetFunc(I2CX,I2cStart_En); ///< 发送重复起始条件
|
||||
break;
|
||||
case 0x10: ///< 主设备向总线已发出了一个重复的起始条件
|
||||
case 0x10: ///< 主设备向总线已发出了一个重复的起始条件
|
||||
I2C_ClearFunc(I2CX,I2cStart_En);
|
||||
I2C_WriteByte(I2CX,(u8SlaveAddr << 1) | 0x01);///< 发送SLA+R,开始从从机读取数据
|
||||
I2C_WriteByte(I2CX,(u8SlaveAddr << 1) | 0x01);///< 发送SLA+R,开始从从机读取数据
|
||||
break;
|
||||
case 0x40: ///< 已发送SLA+R,并接收到ACK
|
||||
case 0x40: ///< 已发送SLA+R,并接收到ACK
|
||||
if(u32Len>1)
|
||||
{
|
||||
I2C_SetFunc(I2CX,I2cAck_En); ///< 使能主机应答功能
|
||||
I2C_SetFunc(I2CX,I2cAck_En); ///< 使能主机应答功能
|
||||
}
|
||||
break;
|
||||
case 0x50: ///< 已接收数据字节,并已返回ACK信号
|
||||
case 0x50: ///< 已接收数据字节,并已返回ACK信号
|
||||
pu8Data[u8i++] = I2C_ReadByte(I2CX);
|
||||
if(u8i==u32Len-1)
|
||||
{
|
||||
I2C_ClearFunc(I2CX,I2cAck_En); ///< 已接收到倒数第二个字节,关闭ACK应答功能
|
||||
I2C_ClearFunc(I2CX,I2cAck_En); ///< 已接收到倒数第二个字节,关闭ACK应答功能
|
||||
}
|
||||
break;
|
||||
case 0x58: ///< 已接收到最后一个数据,NACK已返回
|
||||
case 0x58: ///< 已接收到最后一个数据,NACK已返回
|
||||
pu8Data[u8i++] = I2C_ReadByte(I2CX);
|
||||
I2C_SetFunc(I2CX,I2cStop_En); ///< 发送停止条件
|
||||
I2C_SetFunc(I2CX,I2cStop_En); ///< 发送停止条件
|
||||
break;
|
||||
case 0x38: ///< 在发送地址或数据时,仲裁丢失
|
||||
I2C_SetFunc(I2CX,I2cStart_En); ///< 当总线空闲时发起起始条件
|
||||
case 0x38: ///< 在发送地址或数据时,仲裁丢失
|
||||
I2C_SetFunc(I2CX,I2cStart_En); ///< 当总线空闲时发起起始条件
|
||||
break;
|
||||
case 0x48: ///< 发送SLA+R后,收到一个NACK
|
||||
I2C_SetFunc(I2CX,I2cStop_En); ///< 发送停止条件
|
||||
I2C_SetFunc(I2CX,I2cStart_En); ///< 发送起始条件
|
||||
case 0x48: ///< 发送SLA+R后,收到一个NACK
|
||||
I2C_SetFunc(I2CX,I2cStop_En); ///< 发送停止条件
|
||||
I2C_SetFunc(I2CX,I2cStart_En); ///< 发送起始条件
|
||||
break;
|
||||
default:
|
||||
I2C_SetFunc(I2CX,I2cStart_En); ///< 其他错误状态,重新发送起始条件
|
||||
I2C_SetFunc(I2CX,I2cStart_En); ///< 其他错误状态,重新发送起始条件
|
||||
break;
|
||||
}
|
||||
I2C_ClearIrq(I2CX); ///< 清除中断状态标志位
|
||||
if(u8i==u32Len) ///< 数据全部读取完成,跳出while循环
|
||||
I2C_ClearIrq(I2CX); ///< 清除中断状态标志位
|
||||
if(u8i==u32Len) ///< 数据全部读取完成,跳出while循环
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -339,60 +357,76 @@ en_result_t I2C_Init(M0P_I2C_TypeDef* I2Cx, stc_i2c_cfg_t *pstcI2CCfg)
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief I2C模块主机发送指定长度函数
|
||||
** \brief I2C模块主机发送指定长度函数
|
||||
**
|
||||
** \param u8SlaveAddr从机设备地址,u8Addr从机内存地址,pu8Data写数据,u32Len写数据长度
|
||||
** \param u8SlaveAddr从机设备地址,u8Addr从机内存地址,pu8Data写数据,u32Len写数据长度
|
||||
**
|
||||
** \retval 写数据是否成功
|
||||
** \retval 写数据是否成功
|
||||
**
|
||||
******************************************************************************/
|
||||
boolean_t I2C_MasterWriteData(M0P_I2C_TypeDef* I2CX,uint8_t u8SlaveAddr,uint8_t u8Addr,uint8_t *pu8Data,uint32_t u32Len)
|
||||
{
|
||||
boolean_t enRet = FALSE;
|
||||
uint8_t u8i=0,u8State, u8Flag=FALSE;
|
||||
uint32_t u32Wait = 0;
|
||||
uint16_t u16Pass = 0;
|
||||
I2C_SetFunc(I2CX,I2cStart_En);
|
||||
while(1)
|
||||
{
|
||||
while(0 == I2C_GetIrq(I2CX))
|
||||
{;}
|
||||
{
|
||||
if(++u32Wait >= I2C_WAIT_TIMEOUT) ///< 等待超时,总线异常
|
||||
{
|
||||
I2C_SetFunc(I2CX,I2cStop_En); ///< 尝试发送停止条件释放总线
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
u32Wait = 0;
|
||||
if(++u16Pass >= I2C_WRITE_PASS_MAX) ///< 状态机重试超限(持续NACK等),放弃本次传输
|
||||
{
|
||||
I2C_SetFunc(I2CX,I2cStop_En);
|
||||
return FALSE;
|
||||
}
|
||||
u8State = I2C_GetState(I2CX);
|
||||
switch(u8State)
|
||||
{
|
||||
case 0x08: ///< 已发送起始条件
|
||||
case 0x08: ///< 已发送起始条件
|
||||
I2C_ClearFunc(I2CX,I2cStart_En);
|
||||
I2C_WriteByte(I2CX,(u8SlaveAddr << 1)); ///< 从设备地址发送
|
||||
I2C_WriteByte(I2CX,(u8SlaveAddr << 1)); ///< 从设备地址发送
|
||||
break;
|
||||
case 0x18: ///< 已发送SLA+W,并接收到ACK
|
||||
I2C_WriteByte(I2CX,u8Addr); ///< 从设备内存地址发送
|
||||
case 0x18: ///< 已发送SLA+W,并接收到ACK
|
||||
I2C_WriteByte(I2CX,u8Addr); ///< 从设备内存地址发送
|
||||
break;
|
||||
case 0x28: ///< 上一次发送数据后接收到ACK
|
||||
case 0x28: ///< 上一次发送数据后接收到ACK
|
||||
if (u8i < u32Len)
|
||||
{
|
||||
I2C_WriteByte(I2CX,pu8Data[u8i++]); ///< 继续发送数据
|
||||
I2C_WriteByte(I2CX,pu8Data[u8i++]); ///< 继续发送数据
|
||||
}else
|
||||
{
|
||||
I2C_SetFunc(I2CX,I2cStop_En); ///< 出停止条件
|
||||
I2C_SetFunc(I2CX,I2cStop_En); ///< 出停止条件
|
||||
u8Flag = TRUE;
|
||||
enRet = TRUE; ///< 全部数据发送完成
|
||||
}
|
||||
break;
|
||||
case 0x38: ///< 上一次在SLA+读或写时丢失仲裁
|
||||
I2C_SetFunc(I2CX,I2cStart_En); ///< 当I2C总线空闲时发送起始条件
|
||||
case 0x38: ///< 上一次在SLA+读或写时丢失仲裁
|
||||
I2C_SetFunc(I2CX,I2cStart_En); ///< 当I2C总线空闲时发送起始条件
|
||||
break;
|
||||
case 0x30: ///< 已发送I2Cx_DATA中的数据,收到NACK,将传输一个STOP条件
|
||||
I2C_SetFunc(I2CX,I2cStop_En); ///< 发送停止条件
|
||||
case 0x30: ///< 已发送I2Cx_DATA中的数据,收到NACK,将传输一个STOP条件
|
||||
I2C_SetFunc(I2CX,I2cStop_En); ///< 发送停止条件
|
||||
u8Flag = TRUE;
|
||||
enRet = FALSE; ///< 从机NACK,本次传输失败
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
I2C_ClearIrq(I2CX); ///< 清除中断状态标志位
|
||||
I2C_ClearIrq(I2CX); ///< 清除中断状态标志位
|
||||
|
||||
if(u8Flag == TRUE) ///< 数据发送完成
|
||||
if(u8Flag == TRUE) ///< 数据发送完成
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
enRet = TRUE;
|
||||
return enRet;
|
||||
}
|
||||
//@} // I2cGroup
|
||||
|
||||
@@ -98,6 +98,7 @@ typedef enum {
|
||||
GW_STATUS_CALI,
|
||||
GW_STATUS_READ_SENSOR,
|
||||
GW_STATUS_SET_COL_TIME,
|
||||
GW_STATUS_SET_FPO,//设置全功率运行时间段
|
||||
GW_STATUS_SYNC_TIME,
|
||||
GW_STATUS_UPLOAD_SENSOR,//主动上报模式时会使用该状态
|
||||
GW_STATUS_WAIT_UPLOAD,//主动上报模式时会使用该状态
|
||||
@@ -125,6 +126,7 @@ typedef enum {
|
||||
GWTOMD_CMD_LOGIN = 0x00, //0x00,设备注册
|
||||
GWTOMD_CMD_CALI = 0x01, //0x01, 校准指令
|
||||
GWTOMD_CMD_READ_UPLOAD_SENSOR = 0x02, //0x02,读取数据指令or上传数据指令
|
||||
GWTOMD_CMD_SET_FPO = 0x0A, //0x0A, 设置全功率运行时间段(低功耗设备)
|
||||
GWTOMD_CMD_SET_COL_TIME = 0x05, //0x05,设置采集时间间隔
|
||||
GWTOMD_CMD_SYNC_TIME = 0x06, //0x06,时间同步
|
||||
GWTOMD_CMD_SET_LASER = 0x08,//打开or关闭激光
|
||||
@@ -281,6 +283,7 @@ typedef struct {
|
||||
extern SGCP_t SGCP;
|
||||
|
||||
void SGCP1mSRoutine(void);
|
||||
void ToGWSetFPORes(void);
|
||||
|
||||
void GwRevLoopHandler(void);
|
||||
void MasRevLoopHandler(void);
|
||||
|
||||
+4
-1
@@ -1,4 +1,4 @@
|
||||
#ifndef _BSP_H
|
||||
#ifndef _BSP_H
|
||||
#define _BSP_H
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -225,6 +225,8 @@ typedef struct {
|
||||
uint16_t ReportInterval; //上报时间间隔,设置范围,30*N秒,10<=N<=1440(默认1200秒,N=40)
|
||||
uint8_t ERInterval; //紧急上报时间间隔,设置范围,30*N秒,2<=N<=10(默认120秒,N=4)
|
||||
uint8_t ERTime; //紧急上报时长,设置范围,30*N秒,20<=N<=240(默认1200秒,N=40)
|
||||
uint8_t FPOTimeStart; //每天全功率工作时间起始点时间,设置范围0~23小时整点时间(默认0点整)
|
||||
uint8_t FPOTime; //每天全功率工作时间时长,设置范围0~24小时(默认0小时)
|
||||
uint32_t TimeStamp; //网关返回RTC时间戳
|
||||
}__attribute__((packed))LayoutPara_t,*LayoutPara;//上位机下发的配置参数
|
||||
|
||||
@@ -279,6 +281,7 @@ uint32_t GetSysTick(void);
|
||||
void delay_ms(uint32_t ms);
|
||||
void Delay(uint32_t time);
|
||||
void RTCInit(uint8_t sec);
|
||||
void TimeGet(struct tm *cTime);
|
||||
void LPTimer0_ON(uint16_t _100ms);
|
||||
void LPTimer0_OFF(void);
|
||||
void WakeUpInit(void);
|
||||
|
||||
+2
-1
@@ -5,7 +5,7 @@
|
||||
#include "Update.h"
|
||||
#include "Imu.h"
|
||||
|
||||
#define SOFTWARE_VERSION 12 //软件版本
|
||||
#define SOFTWARE_VERSION 13 //软件版本
|
||||
#define HARDWARE_VERSION 11 //硬件版本
|
||||
|
||||
#define MAIN_DBG_LOG(...) { if(MainDispEn) DBG_LOG(__VA_ARGS__);}
|
||||
@@ -107,6 +107,7 @@ extern AppDetect_t App;
|
||||
|
||||
void MainDBGOnOff(bool OnOff);
|
||||
void DataDBGOnOff(bool OnOff);
|
||||
bool IsFullPowerTime(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -652,6 +652,46 @@ SGCP.GWRS485Rx.sCmdMDToGW = (GWTOMD_CMD_M)GFHeader->Cmd;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief 网关设置全功率运行时间段指令回应
|
||||
**
|
||||
** \param 无(回显已配置的 FPOTimeStart 与 FPOTime,与接收格式一致)
|
||||
**
|
||||
** \retval 无
|
||||
******************************************************************************/
|
||||
void ToGWSetFPORes(void)
|
||||
{
|
||||
uint8_t Pack[256];
|
||||
uint16_t Crc16;
|
||||
uint8_t Len;
|
||||
|
||||
GatewayFrameHeader GFHeader = (GatewayFrameHeader)Pack;
|
||||
|
||||
GFHeader->Header = 0x7B;
|
||||
memcpy(&GFHeader->GWAddr[0], &GatewayMAC[0], sizeof(GFHeader->GWAddr));
|
||||
memcpy(&GFHeader->MDAddr[0], &LocalMAC[0], sizeof(GFHeader->MDAddr));
|
||||
GFHeader->Cmd = GWTOMD_CMD_SET_FPO;
|
||||
GFHeader->PayloadLen = 2;
|
||||
|
||||
Len = sizeof(GatewayFrameHeader_t);
|
||||
|
||||
Pack[Len++] = App.Para.Layout.FPOTimeStart;
|
||||
Pack[Len++] = App.Para.Layout.FPOTime;
|
||||
|
||||
Crc16 = CRC_Modbus(CRC16_BASE, Pack, Len);
|
||||
Pack[Len++] = Crc16 & 0x00ff;
|
||||
Pack[Len++] = (Crc16 >> 8) & 0x00ff;
|
||||
|
||||
SGCP.GWRS485Rx.sCmdMDToGW = (GWTOMD_CMD_M)GFHeader->Cmd;
|
||||
#if(SGCP_SELECT == 1 || SGCP_SELECT == 2)
|
||||
Sx1276LoRaSendBuffer(Pack, Len);
|
||||
#endif
|
||||
#if(SGCP_SELECT == 3)
|
||||
LPUart0SendArray(Pack, Len);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief 网关时间同步指令回应
|
||||
@@ -1007,6 +1047,46 @@ static void GWRevHandler(void)
|
||||
}
|
||||
break;}
|
||||
|
||||
case GWTOMD_CMD_SET_FPO:{
|
||||
if(SGCP.LoginOk == true)
|
||||
{
|
||||
uint8_t Start = PayLoad[0];
|
||||
uint8_t Duration = PayLoad[1];
|
||||
if(Start > 23)
|
||||
{
|
||||
DBG_LOG("FPOTimeStart Err\r\n");
|
||||
if(SGCP.GWStatus == GW_STATUS_WAIT_UPLOAD)
|
||||
{
|
||||
SGCP.UploadOk = true;
|
||||
SGCP.NextGWStatus = GW_STATUS_IDLE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(Duration > 24)
|
||||
{
|
||||
DBG_LOG("FPOTime Err\r\n");
|
||||
if(SGCP.GWStatus == GW_STATUS_WAIT_UPLOAD)
|
||||
{
|
||||
SGCP.UploadOk = true;
|
||||
SGCP.NextGWStatus = GW_STATUS_IDLE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(SGCP.GWStatus == GW_STATUS_WAIT_UPLOAD)
|
||||
{
|
||||
SGCP.UploadOk = true;
|
||||
SGCP.NextGWStatus = GW_STATUS_SET_FPO;
|
||||
}
|
||||
else
|
||||
{
|
||||
SGCP.GWStatus = GW_STATUS_SET_FPO;
|
||||
}
|
||||
App.Para.Layout.FPOTimeStart = Start;
|
||||
App.Para.Layout.FPOTime = Duration;
|
||||
SAVE_APP_PARA((uint32_t *)&App.Para);
|
||||
}
|
||||
break;}
|
||||
|
||||
case GWTOMD_CMD_SET_COL_TIME:{
|
||||
if(SGCP.LoginOk == true)
|
||||
{
|
||||
@@ -1471,6 +1551,25 @@ void GwRevLoopHandler(void)
|
||||
SGCP.GW1mSDelayCnt = 5000;
|
||||
break;}
|
||||
|
||||
case GW_STATUS_SET_FPO:{
|
||||
PrintfMess();
|
||||
if(SGCP.BroadCmd == true)
|
||||
{
|
||||
SGCP.BroadCmd = false;
|
||||
DBG_LOG("Broad FPO Set as %02d:00 ~ %02d:00\r\n", App.Para.Layout.FPOTimeStart,
|
||||
(App.Para.Layout.FPOTimeStart + App.Para.Layout.FPOTime) % 24);
|
||||
}
|
||||
else
|
||||
{
|
||||
ToGWSetFPORes();
|
||||
DBG_LOG("Alone FPO Set as %02d:00 ~ %02d:00\r\n", App.Para.Layout.FPOTimeStart,
|
||||
(App.Para.Layout.FPOTimeStart + App.Para.Layout.FPOTime) % 24);
|
||||
}
|
||||
SGCP.GWStatus = GW_STATUS_WAIT_SUBIDLE;
|
||||
SGCP.NextSubStatus = SUB_STATUS_BROADCAST_SET_COLTIME;
|
||||
SGCP.GW1mSDelayCnt = 5000;
|
||||
break;}
|
||||
|
||||
case GW_STATUS_SYNC_TIME:{
|
||||
PrintfMess();
|
||||
if(SGCP.BroadCmd == true)
|
||||
@@ -1795,6 +1894,24 @@ void GwRevLoopHandler(void)
|
||||
SGCP.GWStatus = GW_STATUS_IDLE;
|
||||
break;}
|
||||
|
||||
case GW_STATUS_SET_FPO:{
|
||||
PrintfMess();
|
||||
if(SGCP.BroadCmd == true)
|
||||
{
|
||||
SGCP.BroadCmd = false;
|
||||
DBG_LOG("Broad FPO Set as %02d:00 ~ %02d:00\r\n", App.Para.Layout.FPOTimeStart,
|
||||
(App.Para.Layout.FPOTimeStart + App.Para.Layout.FPOTime) % 24);
|
||||
}
|
||||
else
|
||||
{
|
||||
ToGWSetFPORes();
|
||||
DBG_LOG("Alone FPO Set as %02d:00 ~ %02d:00\r\n", App.Para.Layout.FPOTimeStart,
|
||||
(App.Para.Layout.FPOTimeStart + App.Para.Layout.FPOTime) % 24);
|
||||
}
|
||||
/*GWRevHandler函数中已经缓存了接收到的全功率运行时间段*/
|
||||
SGCP.GWStatus = GW_STATUS_IDLE;
|
||||
break;}
|
||||
|
||||
case GW_STATUS_SYNC_TIME:{
|
||||
PrintfMess();
|
||||
if(SGCP.BroadCmd == true)
|
||||
|
||||
+1
-1
@@ -647,7 +647,7 @@ void TimeGet(struct tm *cTime)
|
||||
cTime->tm_year = BCDToDec(RtcDateTime.u8Year) + 100;
|
||||
cTime->tm_mon = BCDToDec(RtcDateTime.u8Month) - 1;
|
||||
cTime->tm_mday = BCDToDec(RtcDateTime.u8Day);
|
||||
cTime->tm_hour = BCDToDec(RtcDateTime.u8Hour) + 8;
|
||||
cTime->tm_hour = BCDToDec(RtcDateTime.u8Hour);
|
||||
cTime->tm_min = BCDToDec(RtcDateTime.u8Minute);
|
||||
cTime->tm_sec = BCDToDec(RtcDateTime.u8Second);
|
||||
cTime->tm_isdst = 0;
|
||||
|
||||
+81
-14
@@ -132,12 +132,15 @@ static void AppInit(void)
|
||||
App.Para.Layout.ReportInterval = 40;
|
||||
App.Para.Layout.ERInterval = 4;
|
||||
App.Para.Layout.ERTime = 40;
|
||||
|
||||
App.Para.Layout.FPOTime = 0;
|
||||
App.Para.Layout.FPOTimeStart = 0;
|
||||
}
|
||||
|
||||
if(App.Para.BLPara.LoraFreq < 410000000 || App.Para.BLPara.LoraFreq > 525000000)
|
||||
if(App.Para.BLPara.LoraFreq < 470100000ul || App.Para.BLPara.LoraFreq > 492600000ul)
|
||||
App.Para.BLPara.LoraFreq = CH0;
|
||||
App.Para.Lora.FreqCent = App.Para.BLPara.LoraFreq;
|
||||
SX1276LoRaWriteFreq(App.Para.Lora.FreqCent); //Lora频率:433100000ul + 200000*N
|
||||
SX1276LoRaWriteFreq(App.Para.Lora.FreqCent); //Lora频率:470100000ul + 500000*N
|
||||
|
||||
if(App.Para.Rs485Ch1.Addr > 16 || App.Para.Rs485Ch1.Addr < 1){
|
||||
App.Para.Rs485Ch1.Addr = 1;
|
||||
@@ -157,8 +160,14 @@ static void AppInit(void)
|
||||
if(App.Para.Layout.ERTime > 240 || App.Para.Layout.ERTime < 20) {
|
||||
App.Para.Layout.ERTime = 40;
|
||||
}
|
||||
if(App.Para.Layout.FPOTimeStart > 23 || App.Para.Layout.FPOTimeStart < 0) {
|
||||
App.Para.Layout.FPOTimeStart = 0;
|
||||
}
|
||||
if(App.Para.Layout.FPOTime > 24 || App.Para.Layout.FPOTime < 0) {
|
||||
App.Para.Layout.FPOTime = 0;
|
||||
}
|
||||
if(App.Para.LaserTimerMinutes < 0 || App.Para.LaserTimerMinutes > 240)
|
||||
App.Para.LaserTimerMinutes = 10;
|
||||
App.Para.LaserTimerMinutes = 1;
|
||||
SGCP.LaserTimerMinutes = App.Para.LaserTimerMinutes;
|
||||
|
||||
SAVE_APP_PARA((uint32_t *)&App.Para);
|
||||
@@ -226,8 +235,8 @@ static void ReadDataLoopHandler(void)
|
||||
break;}
|
||||
|
||||
case READDATA_STATUS_UPDAING:{
|
||||
DATA_DBG_LOG("<------------ Sensor Data Updaing ------------> \r\n");
|
||||
App.UpdateOk = false;
|
||||
//持续采集模式下UpdateOk不在启动时清零:上一轮数据仍有效,拿到新数据后才覆盖
|
||||
//否则在两轮数据的间隙(约100ms)键入up/coll会误报"Device data is not ready"
|
||||
Lsm6dsStart();
|
||||
MMC5983Start();
|
||||
App.ReadData1mSDelayCnt = 2000;
|
||||
@@ -240,6 +249,7 @@ static void ReadDataLoopHandler(void)
|
||||
DATA_DBG_LOG("Lsm6dsl Get Data TimeOut...\r\n");
|
||||
if(App.MagRead_EndFlag == false)
|
||||
DATA_DBG_LOG("MMC5983 Get Data TimeOut...\r\n");
|
||||
App.UpdateOk = false; //超时:数据不可信
|
||||
App.RDStatus = READDATA_STATUS_DATA_HANDLE;
|
||||
}
|
||||
else if(App.MagRead_EndFlag == true
|
||||
@@ -250,9 +260,8 @@ static void ReadDataLoopHandler(void)
|
||||
|
||||
case READDATA_STATUS_DATA_HANDLE:{
|
||||
if(App.MagRead_EndFlag == false || App.AccRead_EndFlag == false){
|
||||
DATA_DBG_LOG("<------------ Sensor Data Upda End ------------> \r\n");
|
||||
App.RDStatus = READDATA_STATUS_IDLE;
|
||||
App.UpdateOk = false;
|
||||
//有传感器超时未出数:回到采集状态持续重试(启动函数幂等,不会重复初始化)
|
||||
App.RDStatus = READDATA_STATUS_UPDAING;
|
||||
break;
|
||||
}
|
||||
App.MagRead_EndFlag = false;
|
||||
@@ -262,7 +271,6 @@ static void ReadDataLoopHandler(void)
|
||||
App.ConvertedData.Pitch = (int16_t)(App.AHRSData.Deg.pitch * 10);
|
||||
App.ConvertedData.Roll = (int16_t)(App.AHRSData.Deg.roll * 10);
|
||||
App.ConvertedData.Yaw = (int16_t)(App.AHRSData.Deg.yaw * 10);
|
||||
DATA_DBG_LOG("PitchAngle:%06.1f, RollAngle:%06.1f, YawAngle:%06.1f\r\n",App.AHRSData.Deg.pitch, App.AHRSData.Deg.roll, App.AHRSData.Deg.yaw);
|
||||
|
||||
if(SGCP.MasterCaliOk == true)
|
||||
{
|
||||
@@ -308,14 +316,69 @@ static void ReadDataLoopHandler(void)
|
||||
#endif
|
||||
|
||||
memcpy(LocalDataPack, &SGCP.DevData.LaserTracing, sizeof(LocalDataPack));
|
||||
DATA_DBG_LOG("<------------ Sensor Data Upda End ------------> \r\n");
|
||||
//DATA_DBG_LOG("<------------ Sensor Data Upda End ------------> \r\n"); //10Hz循环打印会阻塞9600调试串口,屏蔽
|
||||
//App.RDStatus = READDATA_STATUS_UPDAING;//持续工作
|
||||
App.RDStatus = READDATA_STATUS_IDLE;
|
||||
App.RDStatus = READDATA_STATUS_UPDAING;//持续采集,姿态数据保持10Hz更新(上传网关节奏不变,仍由UploadFlag定时器控制)
|
||||
App.UpdateOk = true;
|
||||
break;}
|
||||
}
|
||||
}
|
||||
|
||||
bool IsFullPowerTime(void)
|
||||
{
|
||||
uint8_t Duration = App.Para.Layout.FPOTime;
|
||||
uint8_t Start = App.Para.Layout.FPOTimeStart;
|
||||
uint8_t Hour;
|
||||
struct tm cTime;
|
||||
|
||||
if(Duration == 0)
|
||||
return false;
|
||||
|
||||
TimeGet(&cTime);
|
||||
Hour = (uint8_t)(cTime.tm_hour % 24);
|
||||
|
||||
if(Start + Duration <= 24)
|
||||
{
|
||||
if(Hour >= Start && Hour < Start + Duration)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t WrapEnd = Start + Duration - 24;
|
||||
if(Hour >= Start || Hour < WrapEnd)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
* 函数名称: LoraPowerHandler
|
||||
* 功能描述: LoRa按需供电管理(设备为主动上报模式):
|
||||
* 仅在与网关通信期间(GWStatus非IDLE,含注册/上传/信号查询/激光响应)开启LoRa接收,
|
||||
* 通信结束回到IDLE立即休眠LoRa,平时不耗电。
|
||||
* 单片机/加速度/地磁不受影响,保持持续采集。
|
||||
* 参 数: 无
|
||||
* 返 回 值: 无
|
||||
*****************************************************************************************/
|
||||
static void LoraPowerHandler(void)
|
||||
{
|
||||
static bool LoraPowerOn = true; //开机BspInit已开启,初值true
|
||||
bool NeedLora;
|
||||
|
||||
NeedLora = (SGCP.GWStatus != GW_STATUS_IDLE);
|
||||
|
||||
if(NeedLora == true && LoraPowerOn == false) {
|
||||
LoraPowerOn = true;
|
||||
Sx1276LoRaWakeup(); //进入接收模式
|
||||
LORAIntEnable(); //开启LORA中断
|
||||
}
|
||||
else if(NeedLora == false && LoraPowerOn == true) {
|
||||
LoraPowerOn = false;
|
||||
LORAIntDisable(); //关闭LORA中断
|
||||
Sx1276LoRaSleep(); //LoRa休眠,平时不耗电
|
||||
}
|
||||
}
|
||||
|
||||
static void AppLoopHandler(void)
|
||||
{
|
||||
switch(App.Status) {
|
||||
@@ -357,14 +420,16 @@ static void AppLoopHandler(void)
|
||||
SGCP.GWStatus = GW_STATUS_LOGIN;//注册
|
||||
App.Status = APP_STATUS_WAIT_LOGIN;
|
||||
}
|
||||
else if(SGCP.TimingAcquisition == true && App.RDStatus == READDATA_STATUS_IDLE)//设备数据获取
|
||||
else if(SGCP.TimingAcquisition == true)//设备数据获取(持续采集模式下RDStatus常驻非IDLE,采集请求视为已被满足)
|
||||
{
|
||||
PrintfMess();
|
||||
SGCP.TimingAcquisition = false;
|
||||
if(App.RDStatus == READDATA_STATUS_IDLE){
|
||||
PrintfMess();
|
||||
App.RDStatus = READDATA_STATUS_UPDAING;
|
||||
App.Status = APP_STATUS_ACTION;
|
||||
App.TD1mSDelayCnt = 1000;
|
||||
}
|
||||
}
|
||||
else if(SGCP.LoginOk == true && App.UploadFlag == true && SGCP.GWStatus == GW_STATUS_IDLE && App.UpdateOk == true)
|
||||
{
|
||||
PrintfMess();
|
||||
@@ -385,7 +450,8 @@ static void AppLoopHandler(void)
|
||||
&& App.TD1mSDelayCnt == 0
|
||||
&& App.ReadData1mSDelayCnt == 0
|
||||
&& SGCP.LaserOnOff == false
|
||||
&& App.AttTestMode == false)
|
||||
&& App.AttTestMode == false
|
||||
&& IsFullPowerTime() == false)
|
||||
{
|
||||
//App.Status = APP_STATUS_ACTION;
|
||||
App.Status = APP_STATUS_OFF;
|
||||
@@ -524,6 +590,7 @@ int32_t main(void)
|
||||
//09 00 01 00 00 00
|
||||
|
||||
while (1) {
|
||||
LoraPowerHandler();//LoRa按需供电:通信时开,平时休眠
|
||||
#if(USE_VBAT_AD == 1)
|
||||
ADCLoopHandler();
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user