فهرست منبع

实现rtc计时发送sos。(基础框架)

xuxinyi 2 ماه پیش
والد
کامیت
8ff2fccaa9
5فایلهای تغییر یافته به همراه173 افزوده شده و 20 حذف شده
  1. 3 0
      Core/Inc/E52.h
  2. 26 0
      Core/Inc/RTC_SLEEP.h
  3. 55 15
      Core/Src/RTC_SLEEP.c
  4. 46 2
      Core/Src/main.c
  5. 43 3
      Core/Src/stm32f1xx_it.c

+ 3 - 0
Core/Inc/E52.h

@@ -117,6 +117,9 @@ typedef struct __attribute__((packed)){
     //lora发生成功标志
     uint8_t loraSendSuccessFlag;
 
+    //SOS触发标志
+    uint8_t SOS_Flag;
+
     //定时器相关
     uint8_t  timerEnable;           //定时器使能
     uint16_t timeCount;             //定时器计数

+ 26 - 0
Core/Inc/RTC_SLEEP.h

@@ -11,5 +11,31 @@
 #include "E52.h"
 #include "E104-BT5005A.h"
 
+
+// 定义结构体一个结构体用于存储读取到的日期时间
+typedef struct {
+    uint8_t hours;
+    uint8_t minutes;
+    uint8_t seconds;
+    uint8_t weekday;
+    uint8_t month;
+    uint8_t date;
+    uint8_t year;
+} RTC_DateTimeTypeDef;
+
+typedef struct {
+    uint8_t SOS_key_Duration;
+    uint8_t SOS_key_Count;
+    uint8_t sosCheckActive;// 标志位,表示正在检测中
+} RTC_SOS_key_struct;
+
+extern RTC_DateTimeTypeDef firstPressTime;
+extern RTC_SOS_key_struct SOS_key_struct;
+
+void RTC_GetDateTime(RTC_HandleTypeDef *hrtc, RTC_DateTimeTypeDef *datetime);
+
+void RTC_SetDateTime(RTC_HandleTypeDef *hrtc, uint8_t hours, uint8_t minutes, uint8_t seconds,
+                     uint8_t weekday, uint8_t month, uint8_t date, uint8_t year);
+
 void RTC_Sleep_Enter_Fun(void);
 #endif //RTC_SLEEP_H

+ 55 - 15
Core/Src/RTC_SLEEP.c

@@ -4,29 +4,68 @@
 
 #include "../Inc/RTC_SLEEP.h"
 
+RTC_SOS_key_struct SOS_key_struct = {
+    .SOS_key_Count = 0,
+    .SOS_key_Duration = 0,
+    .sosCheckActive = FALSE
+};
 
+RTC_DateTimeTypeDef firstPressTime;
 
-void RTC_Sleep_Enter_Fun() {
-    /* 设置初始时间 */
+// 单独的RTC时间和日期设置函数
+void RTC_SetDateTime(RTC_HandleTypeDef *hrtc, uint8_t hours, uint8_t minutes, uint8_t seconds,
+                     uint8_t weekday, uint8_t month, uint8_t date, uint8_t year) {
+    RTC_TimeTypeDef sTime = {0};
+    RTC_DateTypeDef sDate = {0};
+
+    // 设置时间
+    sTime.Hours = hours;
+    sTime.Minutes = minutes;
+    sTime.Seconds = seconds;
+    HAL_RTC_SetTime(hrtc, &sTime, RTC_FORMAT_BCD);
+
+    // 设置日期
+    sDate.WeekDay = weekday;
+    sDate.Month = month;
+    sDate.Date = date;
+    sDate.Year = year;
+    HAL_RTC_SetDate(hrtc, &sDate, RTC_FORMAT_BCD);
+}
+
+// 读取RTC当前时间和日期
+void RTC_GetDateTime(RTC_HandleTypeDef *hrtc, RTC_DateTimeTypeDef *datetime) {
     RTC_TimeTypeDef sTime = {0};
     RTC_DateTypeDef sDate = {0};
 
-    sTime.Hours = 0x12;
-    sTime.Minutes = 0x00;
-    sTime.Seconds = 0x00;
-    HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD);
+    // 读取当前时间
+    HAL_RTC_GetTime(hrtc, &sTime, RTC_FORMAT_BCD);
+    // 读取当前日期
+    HAL_RTC_GetDate(hrtc, &sDate, RTC_FORMAT_BCD);
+
+    // 存储到自定义结构体中
+    datetime->hours = sTime.Hours;
+    datetime->minutes = sTime.Minutes;
+    datetime->seconds = sTime.Seconds;
+    datetime->weekday = sDate.WeekDay;
+    datetime->month = sDate.Month;
+    datetime->date = sDate.Date;
+    datetime->year = sDate.Year;
+}
+
+void RTC_Sleep_Enter_Fun() {
+    /* 调用独立的函数设置初始时间 */
+    RTC_SetDateTime(&hrtc, 0x12, 0x00, 0x00,
+                   RTC_WEEKDAY_MONDAY, RTC_MONTH_SEPTEMBER, 0x16, 0x25);
 
-    sDate.WeekDay = RTC_WEEKDAY_MONDAY;
-    sDate.Month = RTC_MONTH_SEPTEMBER;
-    sDate.Date = 0x16;
-    sDate.Year = 0x25;
-    HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD);
+    /* 获取当前时间用于设置闹钟 */
+    RTC_TimeTypeDef currentTime = {0};
+    HAL_RTC_GetTime(&hrtc, &currentTime, RTC_FORMAT_BCD);
 
-    /* 设置闹钟:20 秒后触发 */
+    /* 设置闹钟:50秒后触发 */
     RTC_AlarmTypeDef sAlarm = {0};
-    sAlarm.AlarmTime.Hours = sTime.Hours;
-    sAlarm.AlarmTime.Minutes = sTime.Minutes;
-    sAlarm.AlarmTime.Seconds = (sTime.Seconds + 50) % 60;
+    sAlarm.AlarmTime.Hours = currentTime.Hours;
+    sAlarm.AlarmTime.Minutes = currentTime.Minutes;
+    sAlarm.AlarmTime.Seconds = (currentTime.Seconds + 50) % 60;
     sAlarm.Alarm = RTC_ALARM_A;
 
     HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD);
@@ -37,3 +76,4 @@ void RTC_Sleep_Enter_Fun() {
 
     // MCU 唤醒后会从 main() 重新开始运行
 }
+

+ 46 - 2
Core/Src/main.c

@@ -104,6 +104,7 @@ uint16_t randomFun() {
 
 void Device_Info_Init_Fun() {
   deviceInfo.isOnline = FALSE;
+  deviceInfo.SOS_Flag = FALSE;
   deviceInfo.broadcast_type = BROADCAST_ALL;
   deviceInfo.loraDeviceAddress_H = 0xFE; //默认地址高位
   deviceInfo.loraDeviceAddress_L = 0xEF; //默认地址低位
@@ -175,6 +176,18 @@ void powerOff() {
   HAL_GPIO_WritePin(POWER_ON_GPIO_Port, POWER_ON_Pin, GPIO_PIN_SET);
 }
 
+uint32_t RTC_CalcDiffSeconds(RTC_DateTimeTypeDef *t1, RTC_DateTimeTypeDef *t2)
+{
+  uint32_t s1 = t1->hours * 3600 + t1->minutes * 60 + t1->seconds;
+  uint32_t s2 = t2->hours * 3600 + t2->minutes * 60 + t2->seconds;
+
+  if (s2 >= s1)
+    return s2 - s1;
+  else
+    return 24*3600 - (s1 - s2);  // 跨零点的情况
+}
+
+
 /* USER CODE END 0 */
 
 /**
@@ -210,8 +223,6 @@ int main(void)
   // 将GPIO引脚拉高
   // HAL_GPIO_WritePin(POWER_ON_GPIO_Port, POWER_ON_Pin, GPIO_PIN_SET);
   // HAL_GPIO_WritePin(POWER_ON_GPIO_Port, CTL_LORA_POWER_Pin, GPIO_PIN_RESET);
-  powerOn();
-  E52_CtlPowerOn_Fun();
   MX_DMA_Init();
   MX_USART1_UART_Init();
   MX_USART2_UART_Init();
@@ -219,6 +230,20 @@ int main(void)
   MX_TIM4_Init();
   MX_RTC_Init();
   /* USER CODE BEGIN 2 */
+
+  powerOn();
+  E52_CtlPowerOn_Fun();
+  // 在需要设置RTC时间的地方直接调用
+  // 参数依次为:小时、分钟、秒、星期、月份、日期、年份(均为BCD格式)
+  RTC_SetDateTime(&hrtc,
+                 0x12,  // 12时
+                 0x30,  // 30分
+                 0x00,  // 00秒
+                 RTC_WEEKDAY_WEDNESDAY,  // 星期三
+                 RTC_MONTH_OCTOBER,      // 10月
+                 0x17,  // 17日
+                 0x25); // 25年(2025年)
+
   // 启动 USART2 DMA 接收
   HAL_UART_Receive_DMA(&huart3, rx_buf, sizeof(rx_buf));
   // // HAL_UART_Receive_IT(&huart2, uart2_rx_byte, 7);
@@ -287,6 +312,25 @@ int main(void)
       HAL_Delay(3000);
     }
 
+    if (SOS_key_struct.sosCheckActive) {
+      RTC_DateTimeTypeDef now;
+      RTC_GetDateTime(&hrtc, &now);
+
+      uint32_t diffSec = RTC_CalcDiffSeconds(&firstPressTime, &now);
+      if (diffSec > 60) {
+        // 超过5秒,停止检测
+        if (SOS_key_struct.SOS_key_Count >= 5) {
+          printf("SOS TRIGGERED!!!\r\n");
+          // TODO: 触发SOS逻辑
+        }
+        // 重置状态
+        SOS_key_struct.sosCheckActive = FALSE;
+        SOS_key_struct.SOS_key_Count = 0;
+      }else {
+
+      }
+    }
+
     // 03:请求蓝牙数据
     if (GET_CMD( deviceInfo.commandFromCloud)  == REQUEST_BLUETOOTH_DATA && deviceInfo.isOnline) {
 

+ 43 - 3
Core/Src/stm32f1xx_it.c

@@ -28,6 +28,11 @@
 #include "E52.h"
 /* Private includes ----------------------------------------------------------*/
 /* USER CODE BEGIN Includes */
+
+#include <locale.h>
+
+#include "RTC_SLEEP.h"
+
 /* USER CODE END Includes */
 
 /* Private typedef -----------------------------------------------------------*/
@@ -368,17 +373,52 @@ void USART3_IRQHandler(void)
 /**
   * @brief This function handles EXTI line[15:10] interrupts.
   */
-void EXTI15_10_IRQHandler(void)
-{
+void EXTI15_10_IRQHandler(void) {
   /* USER CODE BEGIN EXTI15_10_IRQn 0 */
 
   /* USER CODE END EXTI15_10_IRQn 0 */
   HAL_GPIO_EXTI_IRQHandler(SOS_KEY_Pin);
   printf("I AM SOS KEY\r\n");
+  RTC_DateTimeTypeDef currentDT;
+  // 读取当前时间日期
+  RTC_GetDateTime(&hrtc, &currentDT);
+
+  if (SOS_key_struct.sosCheckActive == 0) {
+    // 第一次触发,记录时间
+    firstPressTime = currentDT;
+    SOS_key_struct.SOS_key_Count = 1;
+    SOS_key_struct.sosCheckActive = TRUE;
+  } else {
+    // 后续触发,只计数
+    SOS_key_struct.SOS_key_Count++;
+  }
+
+  printf("当前时间: %02X:%02X:%02X\n",
+     currentDT.hours, currentDT.minutes, currentDT.seconds);
+  // printf("当前日期: 20%02X年%02X月%02X日 星期%d\n",
+  //        currentDT.year, currentDT.month, currentDT.date, currentDT.weekday);
+
+  printf("第一次按下时间: %02X:%02X:%02X\n",
+       firstPressTime.hours, firstPressTime.minutes, firstPressTime.seconds);
+  // printf("第一次按下日期: 20%02X年%02X月%02X日 星期%d\n",
+  //        firstPressTime.year, firstPressTime.month, firstPressTime.date, firstPressTime.weekday);
+
+  // 触发第一次中断 ,记录第一次按压时间
+  // 通知主函数,开始计时
+  // 主函数中循检测,当前时间与第一次时间间隔是否超过5秒
+  // 如果超过五秒停止检测,并判断按压次数,如果超过5次,则认为是SOS,并停止检测
+}
+
+  // 打印当前时间日期
+  // printf("当前时间: %02X:%02X:%02X\n",
+  //        currentDT.hours, currentDT.minutes, currentDT.seconds);
+  // printf("当前日期: 20%02X年%02X月%02X日 星期%d\n",
+  //        currentDT.year, currentDT.month, currentDT.date, currentDT.weekday);
+
   /* USER CODE BEGIN EXTI15_10_IRQn 1 */
 
   /* USER CODE END EXTI15_10_IRQn 1 */
-}
+
 
 /**
   * @brief This function handles RTC alarm interrupt through EXTI line 17.