女人荫蒂被添全过程13种图片,亚洲+欧美+在线,欧洲精品无码一区二区三区 ,在厨房拨开内裤进入毛片

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

零知開源——基于STM32F407VET6零知增強板的四路獨立計時器

PCB56242069 ? 來源:PCB56242069 ? 作者:PCB56242069 ? 2025-07-01 10:13 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

項目概述

教程將指導你如何使用STM32F407VET6零知增強板實現一個功能強大的四路獨立計時器。每個計時器可以獨立控制,支持開始、暫停和重置功能,并具備定時報警功能(4小時或每小時觸發)。項目結合了TFT顯示屏、蜂鳴器按鈕控制,提供了一個直觀的用戶界面。

目錄

一、硬件準備

二、軟件環境配置

三、核心代碼解析

四、項目演示效果

五、常見問題解答

六、完整源碼獲取

核心功能

>四路獨立計時器:每個計時器獨立運行,互不影響
>多種控制模式: 開始、暫停、重置功能
>智能報警系統: 4小時及以上每小時報警提示
>直觀的用戶界面:TFT顯示屏顯示計時器狀態
>聲音提示: 蜂鳴器提供報警音效
>長/短按操作:按鈕支持不同時長的操作

一、硬件準備

1.1 硬件清單

主控板:STM32F407VET6零知增強板<
顯示屏:1.54英寸TFT顯示屏(ST7789驅動)<
蜂鳴器:有源蜂鳴器模塊<

LED: LED燈珠<
按鈕: 4個輕觸開關<
連接線:杜邦線若干<
電源: 5V電源適配器或USB供電<

1.2硬件連接

模塊 零知增強板引腳
TFT_CS 53
TFT_DC 2
TFT_MOSI 51
TFT_SCLK 52
TFT_RST 4
蜂鳴器&LED 3
按鈕1 14
按鈕2 15
按鈕3 16
按鈕4 17

1.3 連接硬件圖

主控零知增強板和ST7789顯示屏:

wKgZO2hjPhKAVo0KAAQTV3O3XsU175.png

蜂鳴器和按鍵電路:

wKgZO2hjPhyAWmKeAAUo-vriXic137.png

1.4 連接實物圖

wKgZO2hjPjKAOY3sACCnm6yIGvA709.png

二、軟件環境配置

1.零知開源開發工具(Lingzhi IDE)

2.安裝必要的庫:

Adafruit_GFX

Adafruit_ST7789

3.配置開發板類型:STM32F407VET6

三、核心代碼解析

1. 引腳定義與初始化

#include 
#include 
#include 

// 屏幕引腳配置
#define TFT_CS         53
#define TFT_RST        4
#define TFT_DC         2
#define TFT_MOSI       51
#define TFT_SCLK       52

// 使用硬件SPI
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

// 蜂鳴器引腳
#define BUZZER_PIN 3

// 按鈕引腳 - 高電平觸發
#define BUTTON_PIN1 14
#define BUTTON_PIN2 15
#define BUTTON_PIN3 16
#define BUTTON_PIN4 17

// 計時器結構
typedef struct {
  unsigned long totalSeconds;
  bool isRunning;
  bool isReset;
  unsigned long lastUpdateTime; // 每個計時器獨立的更新時間戳
  unsigned long lastHourAlarm;  // 上次小時報警時間戳
  bool alarmTriggered;          // 計時器報警狀態
} Timer;

Timer timers[4]; // 四個計時器

2. 按鈕狀態檢測

// 按鈕狀態
enum ButtonState {
  BUTTON_RELEASED,
  BUTTON_PRESSED
};

// 按鈕結構
typedef struct {
  uint8_t pin;
  ButtonState state;
  ButtonState lastState;
  unsigned long pressStartTime;
} Button;

Button buttons[4];

// 當前選中的計時器
int selectedTimer = 0;
bool alarmActive = false;       // 報警激活狀態
bool alarmSilenced = false;     // 報警被靜音
unsigned long lastBeepTime = 0; // 上次蜂鳴器響的時間
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50; // 消抖時間(毫秒)

// 報警參數
const unsigned long ALARM_INTERVAL = 800; // 蜂鳴器報警間隔(ms)
const unsigned long HOUR_SECONDS = 3600;   // 1小時的秒數
const unsigned long ALARM_HOURS = 4;       // 報警小時數

// PWM參數
const int TONE_FREQUENCY = 2500; // 蜂鳴器頻率 (Hz)
const int TONE_DURATION = 300;   // 蜂鳴器單次響聲持續時間 (ms)

3. 初始化設置

void setup() {
  Serial.begin(9600);
  
  // 初始化蜂鳴器
  pinMode(BUZZER_PIN, OUTPUT);
  digitalWrite(BUZZER_PIN, LOW);
  
  // 初始化按鈕
  buttons[0] = {BUTTON_PIN1, BUTTON_RELEASED, BUTTON_RELEASED, 0};
  buttons[1] = {BUTTON_PIN2, BUTTON_RELEASED, BUTTON_RELEASED, 0};
  buttons[2] = {BUTTON_PIN3, BUTTON_RELEASED, BUTTON_RELEASED, 0};
  buttons[3] = {BUTTON_PIN4, BUTTON_RELEASED, BUTTON_RELEASED, 0};
  
  for (int i = 0; i < 4; i++) {
    pinMode(buttons[i].pin, INPUT);
  }
  
  // 初始化屏幕
  tft.init(240, 320);
  tft.setRotation(1);
  tft.fillScreen(ST77XX_BLACK);
  
  // 初始化計時器
  for (int i = 0; i < 4; i++) {
    timers[i].totalSeconds = 0;
    timers[i].isRunning = false;
    timers[i].isReset = true;
    timers[i].lastUpdateTime = 0;
    timers[i].lastHourAlarm = 0;
    timers[i].alarmTriggered = false;
  }
  
  // 繪制初始界面
  drawTimers();
}

4. 主循環控制

void loop() {
  unsigned long currentMillis = millis();
  
  // 更新所有正在運行的計時器
  for (int i = 0; i < 4; i++) {
    if (timers[i].isRunning) {
      // 每個計時器獨立更新
      if (currentMillis - timers[i].lastUpdateTime >= 1000) {
        timers[i].totalSeconds++;
        timers[i].lastUpdateTime = currentMillis;
        
        // 檢查報警條件
        checkAlarmConditions(i);
        
        // 只更新這個計時器的顯示
        drawTimer(i);
      }
    }
  }
  
  // 處理按鈕事件
  pollButtons();
  handleButtonEvents();
  
  // 處理報警聲音
  updateAlarmSound();
  
  delay(10);
}

5. 報警系統實現

// 檢查報警條件
void checkAlarmConditions(int index) {
  // 檢查是否達到4小時或每小時
  if (timers[index].totalSeconds >=  ALARM_HOURS * HOUR_SECONDS) { 
    // 檢查是否達到新的小時
    if (timers[index].totalSeconds % HOUR_SECONDS == 0) {
      // 避免連續觸發
      if (timers[index].totalSeconds != timers[index].lastHourAlarm) {
        timers[index].alarmTriggered = true;
        alarmActive = true;
        alarmSilenced = false;
        timers[index].lastHourAlarm = timers[index].totalSeconds;
      }
    }
  }
}

// 更新報警聲音
void updateAlarmSound() {
  if (alarmActive && !alarmSilenced) {
    unsigned long currentMillis = millis();
    
    // 每秒響一次(300ms開,800ms關)
    if (currentMillis - lastBeepTime >= ALARM_INTERVAL) {
      lastBeepTime = currentMillis;
      
      // 播放悅耳音調
      tone(BUZZER_PIN, TONE_FREQUENCY, TONE_DURATION);
    }
  } else {
    noTone(BUZZER_PIN);
  }
}

// 輪詢按鈕狀態(帶消抖)
void pollButtons() {
  unsigned long currentMillis = millis();
  
  for (int i = 0; i < 4; i++) {
    // 讀取按鈕狀態(高電平表示按下)
    ButtonState reading = (digitalRead(buttons[i].pin) == HIGH) ? BUTTON_PRESSED : BUTTON_RELEASED;
    
    // 如果狀態改變,重置消抖計時器
    if (reading != buttons[i].lastState) {
      lastDebounceTime = currentMillis;
    }
    
    // 如果狀態穩定時間超過消抖延遲
    if ((currentMillis - lastDebounceTime) > debounceDelay) {
      // 更新按鈕狀態
      if (reading != buttons[i].state) {
        buttons[i].state = reading;
        
        // 記錄按下開始時間
        if (buttons[i].state == BUTTON_PRESSED) {
          buttons[i].pressStartTime = currentMillis;
        }
      }
    }
    
    // 保存當前狀態用于下次比較
    buttons[i].lastState = reading;
  }
}

// 靜音報警并清除報警狀態
void silenceAlarm() {
  alarmActive = false;
  alarmSilenced = true;
  noTone(BUZZER_PIN);
  
  // 清除所有計時器的報警狀態
  for (int i = 0; i < 4; i++) {
    timers[i].alarmTriggered = false;
    // 重繪計時器以清除"ALARM"顯示
    drawTimer(i);
  }
}

6. 按鈕事件處理

void handleButtonEvents() {
  unsigned long currentMillis = millis();
  bool buttonEventOccurred = false;
  int previousSelectedTimer = selectedTimer; //跟蹤之前的選擇  
  
  for (int i = 0; i < 4; i++) {
    if (buttons[i].state == BUTTON_PRESSED) {
      // 長按檢測(超過1秒)
      if (currentMillis - buttons[i].pressStartTime > 1000) {
        // 長按 - 只復位當前選中的計時器
        if (i == selectedTimer) {
          timers[i].totalSeconds = 0;
          timers[i].isRunning = false;
          timers[i].isReset = true;
          timers[i].lastUpdateTime = 0;
          timers[i].lastHourAlarm = 0;
          timers[i].alarmTriggered = false;
          drawTimer(i);
          silenceAlarm();
        }
        buttonEventOccurred = true;
      }
    } else if (buttons[i].state == BUTTON_RELEASED) {
      // 按鈕釋放時檢測短按
      if (buttons[i].pressStartTime > 0 && 
          currentMillis - buttons[i].pressStartTime > debounceDelay && 
          currentMillis - buttons[i].pressStartTime <= 1000) {
        
        buttonEventOccurred = true;
        
        // 短按 - 開始/暫停計時器或切換計時器
        if (i == selectedTimer) {
          timers[i].isRunning = !timers[i].isRunning;
          timers[i].isReset = false;
          timers[i].lastUpdateTime = millis();
        } else {
          previousSelectedTimer = selectedTimer;
          selectedTimer = i;
          // 重繪所有計時器以更新選中框
          drawTimer(previousSelectedTimer);
          drawTimer(selectedTimer);
        }
        
        // 只更新當前計時器的顯示
        drawTimer(i);
      }
      
      // 重置按下開始時間
      buttons[i].pressStartTime = 0;
    }
  }
  
  // 如果有按鈕事件,靜音報警并清除報警狀態
  if (buttonEventOccurred) {
    silenceAlarm();
  }
}

7. 用戶界面設計

void drawTimers() {
  tft.fillScreen(ST77XX_BLACK);
  
  // 繪制四個計時器區域
  tft.drawRect(0, 0, 160, 120, ST77XX_WHITE);    // 左上
  tft.drawRect(160, 0, 160, 120, ST77XX_WHITE);  // 右上
  tft.drawRect(0, 120, 160, 120, ST77XX_WHITE);   // 左下
  tft.drawRect(160, 120, 160, 120, ST77XX_WHITE); // 右下
  
  // 繪制所有計時器
  for (int i = 0; i < 4; i++) {
    drawTimer(i);
  }
}

void drawTimer(int index) {
  int x, y;
  
  // 確定位置
  switch (index) {
    case 0: x = 30; y = 50; break; // 左上
    case 1: x = 190; y = 50; break; // 右上
    case 2: x = 30; y = 170; break; // 左下
    case 3: x = 190; y = 170; break; // 右下
    default: return;
  }
  
  // 清除時間顯示區域(避免殘留字符)
  tft.fillRect(x, y, 100, 20, ST77XX_BLACK);
  
  // 設置文本顏色和大小
  tft.setTextSize(2);
  tft.setTextColor(index == selectedTimer ? ST77XX_YELLOW : ST77XX_WHITE);
  
  // 計算時間
  int hours = timers[index].totalSeconds / 3600;
  int minutes = (timers[index].totalSeconds % 3600) / 60;
  int seconds = timers[index].totalSeconds % 60;
  
  // 格式化時間
  char timeStr[12];
  sprintf(timeStr, "%02d:%02d:%02d", hours, minutes, seconds);
  
  // 顯示時間
  tft.setCursor(x, y);
  tft.print(timeStr);
  
  // 清除狀態顯示區域
  tft.fillRect(x, y + 30, 60, 10, ST77XX_BLACK);
  
  // 顯示狀態
  tft.setTextSize(1);
  tft.setCursor(x, y + 30);
  if (timers[index].isReset) {
    tft.print("Reset");
  } else if (timers[index].isRunning) {
    tft.setTextColor(ST77XX_GREEN);
    tft.print("Running");
  } else {
    tft.setTextColor(ST77XX_ORANGE);
    tft.print("Paused");
  }
  
  // 顯示報警狀態(僅在報警觸發且未靜音時顯示)
  tft.fillRect(x + 60, y + 30, 40, 10, ST77XX_BLACK);
  if (timers[index].alarmTriggered && !alarmSilenced) {
    tft.setCursor(x + 60, y + 30);
    tft.setTextColor(ST77XX_MAGENTA);
    tft.print("ALARM");
  }

  //優化選擇高亮繪圖
  static int lastSelected = -1;
  
  //顯示選中框
  if (index == selectedTimer || index == lastSelected) {
    int rectX, rectY;
    switch (index) {
      case 0: rectX = 2; rectY = 2; break;
      case 1: rectX = 162; rectY = 2; break;
      case 2: rectX = 2; rectY = 122; break;
      case 3: rectX = 162; rectY = 122; break;
    }

  //通過繪制黑色清除先前的選擇
    tft.drawRect(rectX, rectY, 156, 116, ST77XX_BLACK);
    tft.drawRect(rectX+1, rectY+1, 154, 114, ST77XX_BLACK);
    
    //如果這是選定的計時器,則繪制新選區
    if (index == selectedTimer) {
      tft.drawRect(rectX, rectY, 156, 116, ST77XX_YELLOW);
      tft.drawRect(rectX+1, rectY+1, 154, 114, ST77XX_YELLOW);
    }

  }
  lastSelected = selectedTimer;
}

使用說明

>選擇計時器:短按對應按鈕選擇要操作的計時器(黃色邊框表示選中)
>開始/暫停:短按當前選中計時器的按鈕
>重置計時器:長按(>1秒)當前選中計時器的按鈕
>報警靜音:任意按鈕操作可暫時靜音報警
>報警條件:
計時達到4小時及以上時,每小時觸發一次報警
顯示屏顯示"ALARM"狀態
蜂鳴器發出提示音

四、項目演示效果

1. 四小時報警功能演示

當任意一個計時器達到4小時或以上時,系統會觸發報警功能:

計時器區域顯示"ALARM"文字、報警狀態會持續顯示直到用戶操作、蜂鳴器發出悅耳的2500Hz提示音

2. 報警靜音操作演示

報警觸發后,用戶可以通過以下方式關閉報警:

按下任意一個計時器按鈕(短按)、蜂鳴器立即停止發聲、屏幕上"ALARM"提示消失、系統進入靜音狀態

長按當前選中計時器的按鈕(>1秒)、除了停止報警,還會重置該計時器、計時器歸零并顯示"Reset"狀態

3. 多計時器獨立運行演示

四個計時器可完全獨立操作:

四個計時器可同時開始計時、每個計時器獨立記錄時間、顯示屏分區顯示各自狀態
>選擇計時器1:短按按鈕1
>開始/暫停:再次短按
>按鈕1重置:長按按鈕1(>1秒)
其他計時器操作類似

4. 項目視頻演示

https://blog.csdn.net/lingzhilab/article/details/148974172?spm=1001.2014.3001.5502#t18

達到四小時計數后持續報警,按下任意鍵清除報警聲,在四個小時基礎上每過一個小時報警一次。

五、常見問題解答

Q1: 報警聲音可以調整嗎?
A: 可以,在代碼中修改以下參數:

const int TONE_FREQUENCY = 2500; // 頻率(Hz),范圍0-5000
const int TONE_DURATION = 300;   // 單次響聲持續時間(ms)
const unsigned long ALARM_INTERVAL = 800; // 報警間隔(ms)

Q2: 為什么我的報警沒有觸發?
A: 請檢查:

計時器是否達到4小時(顯示04:00:00)
ALARM_HOURS參數設置是否正確(默認為4)
蜂鳴器接線是否正確(正負極)

Q3: 如何改變報警的小時閾值?
A: 修改代碼中的常量定義:

const unsigned long ALARM_HOURS = 2; // 2小時觸發報警

Q4: 按鈕按下后沒有響應怎么辦?
A: 檢查:

按鈕是否正常連接(用萬用表測試通斷)
按鈕引腳配置是否正確
消抖參數是否合適(可調整debounceDelay)

六、完整源碼獲取

百度網盤獲取鏈接,通過網盤分享的文件:STM32-Multi-Timer.zip
https://pan.baidu.com/s/1v9NuKp690DUWvqAC73VV8Q?pwd=3wv2

壓縮包內容:

/STM32-Multi-Timer
├── TIM_NVIC.ino // 主程序
├── Adafruit-ST7735-Library-master/ // 所需庫文件
├── SPI/ // 電路圖

^_^本教程詳細展示了四路獨立計時器的報警功能和操作演示,并提供了完整的源碼獲取方式。這個項目不僅具有實際應用價值,還涵蓋了嵌入式開發的多個關鍵技術點:

>多任務處理(四個獨立計時器)>用戶界面設計(TFT顯示)
>中斷處理(按鈕響應) >報警系統設計(聲光提示)
>狀態機實現(計時器狀態管理)

?零知開源是一個真正屬于國人自己的開源軟硬件平臺,在開發效率上超越了Arduino平臺并且更加容易上手,大大降低了開發難度。
?零知開源在軟件方面提供了完整的學習教程和豐富示例代碼,讓不懂程序的工程師也能非常輕而易舉的搭建電路來創作產品,測試產品。快來動手試試吧!

?訪問零知開源平臺,獲取更多實戰項目和教程資源吧!
www.lingzhilab.com


審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 計時器
    +關注

    關注

    1

    文章

    432

    瀏覽量

    33636
  • STM32F407VET6
    +關注

    關注

    2

    文章

    6

    瀏覽量

    3218
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    STM32F407VET6STM32F407IET6有什么區別?

    STM32F407VET6STM32F407IET6,除了引腳上數量不同之外,還有什么區別嗎? 我的CAN驅動,在STM32F407VET6可正常運行。在STM32F407IET6
    發表于 07-03 07:06

    開源——STM32F4驅動MAX31865實現PT100高精度測溫

    材料增強STM32F407VET6) MAX31865模塊(支持三線制PT100) 三線制PT100傳感
    發表于 05-26 18:52

    開源——基于STM32F407VET6增強獨立計時器

    本帖最后由 PCB56242069 于 2025-7-1 11:24 編輯 項目概述本教程將指導你如何使用STM32F407VET6增強板實現一個功能強大的
    發表于 07-01 10:31

    基于STM32F407VET6增強獨立計時器

    計時器
    PCB56242069
    發布于 :2025年07月01日 09:41:44

    stm32f407vet6原理圖

    請問誰有stm32f407vet6引腳圖,求分享,謝謝。。。。。。。。。。
    發表于 12-24 12:35

    STM32F407VET6數據手冊

    STM32F407VET6數據手冊
    發表于 05-04 08:09

    STM32F407VET6的片上資源描述

    前言在ST官網看到了STM32F407VET6的片上資源描述,記錄一下。實驗STM32F407VET6片上資源產品型號STM32F407VET6主頻(MHz)168內核ARM
    發表于 08-04 06:18

    STM32F103VET6/STM32F407VET6原理圖相關資料分享

    STM32F103VET6/STM32F407VET6 原理圖看不清楚就到這來免費下載吧 不用積分點擊下載pdf檔 不用積分點擊下載SCH檔
    發表于 08-05 06:59

    如何對STM32F407VET6的串口進行回環測試呢

    如何對STM32F407VET6的串口進行初始化呢?如何對STM32F407VET6的串口進行回環測試呢?
    發表于 12-06 06:54

    可以使用ST Link對STM32F407VET6黑板進行編程嗎?

    回家后我從當地市場購買了一塊 stm32f407vet6 黑板,令我驚訝的是我找不到任何教程或任何解釋如何對該進行編程的內容。這是我從當地市場購買的開發,我提供鏈接只是為了更好地理解我認為這塊
    發表于 01-03 08:06

    STM32F407VET6數據手冊

    STM32F407VET6數據手冊。
    發表于 04-13 14:10 ?637次下載

    STM32F407VET6核心的電路原理圖免費下載

    本文檔的主要內容詳細介紹的是STM32F407VET6核心的電路原理圖免費下載。
    發表于 03-18 08:00 ?530次下載
    <b class='flag-5'>STM32F407VET6</b>核心<b class='flag-5'>板</b>的電路原理圖免費下載

    基于STM32F407VET6的CS1237驅動程序

    基于STM32F407VET6的CS1237驅動程序,親測可用,歡迎大家一起交流
    發表于 08-28 11:22 ?189次下載

    STM32F407VET6

    STM32F407VET6規格書
    發表于 02-07 15:59 ?100次下載

    stm32f407vet6原理介紹

    STM32F407VET6是一款基于ARM Cortex-M4內核的高性能微控制,由STMicroelectronics公司生產。它具有豐富的外設和功能,廣泛應用于各種嵌入式系統開發。本文將介紹
    的頭像 發表于 01-03 16:49 ?1.4w次閱讀
    <b class='flag-5'>stm32f407vet6</b>原理介紹
    主站蜘蛛池模板: 海兴县| 朝阳区| 平果县| 修水县| 赤城县| 安化县| 独山县| 香港| 临朐县| 宜宾市| 灵山县| 体育| 射阳县| 天门市| 兴宁市| 隆昌县| 谢通门县| 绵竹市| 拉萨市| 定襄县| 溧阳市| 鸡东县| 曲沃县| 岐山县| 沾益县| 长宁县| 潍坊市| 绥滨县| 平遥县| 柯坪县| 剑河县| 南漳县| 安徽省| 晋州市| 安康市| 吉首市| 闽侯县| 综艺| 广南县| 鹤峰县| 肃北|