feat: continuous sensor sampling (10Hz attitude) + LoRa on-demand power + I2C driver hardening

- LSM6DSL: ODR 12.5->52Hz high-performance, gyro FS 2000->500dps, FIFO stream mode,
  watermark 4 sets (24 words) interrupt driven, 4-sample average output 13Hz,
  1s no-data watchdog auto recovery
- MMC5983: enable 20Hz continuous measurement mode (was dead code), remove per-read SW_RST,
  STATUS polling + INT dual path, write-1-clear Meas_M_Done to release INT latch,
  2-sample average output 10Hz, timeout auto recovery
- I2C driver: add wait timeout and state machine retry limit to read/write,
  NACK fast-return FALSE, eliminate bus-stuck infinite loop
- main.c: continuous acquire loop (no IDLE dead-end on first failure),
  keep UpdateOk valid to fix up/coll command race, TimingAcquisition compatible with
  continuous mode, add LoraPowerHandler (LoRa RX during comm, sleep otherwise, saves ~10mA),
  remove 10Hz hot-path debug prints
- Attitude update ~10Hz (IMU 13Hz / mag 10Hz), gateway upload cadence unchanged
This commit is contained in:
2026-09-03 16:15:09 +08:00
parent 706eb1247e
commit 93e00b8b0a
5 changed files with 387 additions and 358 deletions
+45 -15
View File
@@ -235,20 +235,21 @@ 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;
App.RDStatus = READDATA_STATUS_WAIT_UPDAING;
break;}
case READDATA_STATUS_WAIT_UPDAING:{
if(App.ReadData1mSDelayCnt <= 0){
if(App.AccRead_EndFlag == false)
DATA_DBG_LOG("Lsm6dsl Get Data TimeOut...\r\n");
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
@@ -256,22 +257,20 @@ static void ReadDataLoopHandler(void)
App.RDStatus = READDATA_STATUS_DATA_HANDLE;
}
break;}
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;
App.AccRead_EndFlag = false;
IMU_Update(0, App.Sensor.acce, App.Sensor.mag, &App.AHRSData.Rad, &App.AHRSData.Deg);
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)
{
@@ -317,9 +316,9 @@ 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;}
}
@@ -352,6 +351,34 @@ bool IsFullPowerTime(void)
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) {
@@ -393,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,采集请求视为已被满足)
{
SGCP.TimingAcquisition = false;
if(App.RDStatus == READDATA_STATUS_IDLE){
PrintfMess();
SGCP.TimingAcquisition = false;
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();
@@ -561,6 +590,7 @@ int32_t main(void)
//09 00 01 00 00 00
while (1) {
LoraPowerHandler();//LoRa按需供电:通信时开,平时休眠
#if(USE_VBAT_AD == 1)
ADCLoopHandler();
#endif