作息時間提示控制項目

来源:https://www.cnblogs.com/Lavender-edgar/archive/2023/11/19/17842438.html
-Advertisement-
Play Games

目錄前言一、使用的元器件二、模擬圖三、項目分析四、代碼編寫總結 前言 這個項目主要針對於選擇的人們作息不規律而設計的一個項目,這個項目是使用stm32f103系列的晶元來製作的(R6和C8)都可以使用。 一、使用的元器件 DS1302時鐘晶元 STM32F103R6 按鍵 LCD1602顯示屏 蜂鳴 ...


目錄

前言

這個項目主要針對於選擇的人們作息不規律而設計的一個項目,這個項目是使用stm32f103系列的晶元來製作的(R6和C8)都可以使用。

一、使用的元器件

  • DS1302時鐘晶元
  • STM32F103R6
  • 按鍵
  • LCD1602顯示屏
  • 蜂鳴器
  • 藍牙模塊HC-05

二、模擬圖

這個可以添加一個藍牙手機連接功能,但是我這個模擬有問題所以等實物的時候我會添加一個藍牙模塊上去實現遠程停止定時和設置時間等內容。

三、項目分析

首先先實現LCD顯示時間內容,這裡需要寫一個DS1302的驅動來進行讀取內容,然後將讀取的內容顯示到屏幕上面即可。然後需要寫一個判斷來判斷獲取到的時間與設計的時間進行一個比較,然後如果時間到了那就可以啟動蜂鳴器報警模塊來提醒用戶該休息了。

然後需要對按鍵進行判斷,當按下KEY1按鍵那就將提醒關閉,KEY2按鍵是設置內容的。

四、代碼編寫

這裡就開始寫代碼了,首先要編寫一個驅動模塊,先實現DS1302的讀取和設置,這裡已經寫好了,直接使用即可:

#include "ds1302.h"

// 設置命令
u8 gREAD_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; 
u8 gWRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};

// 用來設置時鐘的數組,秒 分 時 日 月 年,都是BCD碼
u8 gDS1302_TIME[7] = {0x57, 0x59, 0x21, 0x20, 0x04, 0x05, 0x21};

void MX_Init_DS1302(){
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_InitStruct.GPIO_Pin = RST | CLK | IO;         
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStruct);
}

void ds1302_write_byte(u8 addr,u8 dat)
{
	u8 i=0;
	
	GPIO_WriteBit(GPIOC, RST, Bit_RESET);
		
	GPIO_WriteBit(GPIOC, CLK, Bit_RESET);
	
	GPIO_WriteBit(GPIOC, RST, Bit_SET);
	

	for(i=0;i<8;i++){
		GPIO_WriteBit(GPIOC, IO, addr&0x01);
		addr>>=1;
		GPIO_WriteBit(GPIOC, CLK, Bit_SET);
		
		GPIO_WriteBit(GPIOC, CLK, Bit_RESET);
	}
	for(i=0;i<8;i++){
		GPIO_WriteBit(GPIOC, IO, dat&0x01);
		dat>>=1;
		GPIO_WriteBit(GPIOC, CLK, Bit_SET);
		
		GPIO_WriteBit(GPIOC, CLK, Bit_RESET);
				
	}
	GPIO_WriteBit(GPIOC, RST, Bit_RESET);
		
}

u8 ds1302_read_byte(u8 addr)
{
	u8 i=0;
	u8 temp=0;
	u8 value=0;

	GPIO_WriteBit(GPIOC, RST, Bit_RESET);
		
	GPIO_WriteBit(GPIOC, CLK, Bit_RESET);
	
	GPIO_WriteBit(GPIOC, RST, Bit_SET);
	
	
	for(i=0;i<8;i++){
		GPIO_WriteBit(GPIOC, IO, addr&0x01);
		addr>>=1;	
		GPIO_WriteBit(GPIOC, CLK, Bit_SET);
		
		GPIO_WriteBit(GPIOC, CLK, Bit_RESET);
				
	}
	for(i=0;i<8;i++){
		temp=GPIO_ReadInputDataBit(GPIOC, IO);
		value=(temp<<7)|(value>>1);
		GPIO_WriteBit(GPIOC, CLK, Bit_SET);
		
		GPIO_WriteBit(GPIOC, CLK, Bit_RESET);
				
	}
	GPIO_WriteBit(GPIOC, RST, Bit_RESET);
		
	GPIO_WriteBit(GPIOC, CLK, Bit_SET);
	
	GPIO_WriteBit(GPIOC, IO, Bit_RESET);
	
	GPIO_WriteBit(GPIOC, IO, Bit_SET);
		
	return value;		
}

void ds1302_init(void)
{
	u8 i=0;
	ds1302_write_byte(0x8E,0X00);
	for(i=0;i<7;i++)
	{
		ds1302_write_byte(gWRITE_RTC_ADDR[i],gDS1302_TIME[i]);	
	}
	ds1302_write_byte(0x8E,0X80);	
}

void ds1302_read_time(void)
{
	u8 i=0;
	for(i=0;i<7;i++)
	{
		gDS1302_TIME[i]=ds1302_read_byte(gREAD_RTC_ADDR[i]);	
	}	
}
#ifndef __DS1302_H
#define __DS1302_H

#include "stm32f10x.h"

#define RST GPIO_Pin_1
#define CLK GPIO_Pin_2
#define IO GPIO_Pin_3

extern u8 gDS1302_TIME[7];  // 讀取時間的數組

void MX_Init_DS1302();
void ds1302_init(void);
void ds1302_read_time(void);


#endif

也可以直接到我的gitee中進行下載:DS1302

然後就可以進行讀取其中的內容了,這裡使用的就是一個全局數組進行接收數據,接收的順序是秒,分,時,讀取的代碼如下:

ds1302_read_time();
time = gDS1302_TIME[2]/16 * 10 + (gDS1302_TIME[2]&0x0f);
minute = gDS1302_TIME[1]/16 * 10 + (gDS1302_TIME[1]&0x0f);
second = gDS1302_TIME[0]/16 * 10 + (gDS1302_TIME[0]&0x0f);

這裡需要轉換一下,因為讀取的是BCD碼,然後就可以進行顯示了:

sprintf((char*)time_buf, "%2d:%2d:%2d", time, minute, second);
show_string(0, 0, time_buf);

這裡使用的是LCD1602的驅動程式中的顯示字元串的函數,下載鏈接:led1602模塊

然後就可以進行時間的判斷了:

if ((time == TIME) && ((minute < MINUTE + response) && (minute >= MINUTE)) && (flag == 1)){
    // 時間到了開始警報
    alarm();
}
else {
    // 如果還在定時的範圍中就不複位flag
    if ((time == TIME) && ((minute < MINUTE + response) && (minute >= MINUTE))){
        flag = 0;
    }
    else{
        // 如果不在這個範圍中就複位flag
        flag = 1;
    }
}

這裡添加了一個flag變數,這個變數是當按下了KEY1後就會停止響應,如果按下了,但是還是在定時的範圍中,那麼不會複位,因為你停止了就沒必要繼續響了。

然後就是按鍵的功能實現:

if (GPIO_ReadInputDataBit(GPIOA, KEY1) == Bit_RESET){
    // 按下了停止按鍵
    flag = 0;
    stopSound();
}
if (GPIO_ReadInputDataBit(GPIOA, KEY2) == Bit_RESET){
    // 設置和確認
    delay_ms(20);
    while(GPIO_ReadInputDataBit(GPIOA, KEY2) == Bit_RESET);
    // 清屏
    show_string(0, 0, (unsigned char*)"                ");
    show_string(0, 1, (unsigned char*)"                ");
    while(1){
        sprintf((char*)buf, "TIME:%2d", TIME);
        show_string(3, 0, buf);
        sprintf((char*)buf, "MINUTE:%2d", MINUTE);
        show_string(3, 1, buf);
        if (select == 0){
            show_string(0, 0, (unsigned char*)"->");
            show_string(0, 1, (unsigned char*)"  ");
        }
        else{
            show_string(0, 1, (unsigned char*)"->");
            show_string(0, 0, (unsigned char*)"  ");
        }
        if (GPIO_ReadInputDataBit(GPIOA, KEY1) == Bit_RESET){
            // 選擇
            delay_ms(20);
            while(GPIO_ReadInputDataBit(GPIOA, KEY1) == Bit_RESET);
            select = ~select & 0x01;
        }
        else if (GPIO_ReadInputDataBit(GPIOA, KEY3) == Bit_RESET){
            // 增加
            delay_ms(20);
            while(GPIO_ReadInputDataBit(GPIOA, KEY3) == Bit_RESET);
            if (select == 0){
                if (++TIME >= 24){
                    TIME = 0;
                }
            }
            else{
                if (++MINUTE >= 60){
                    MINUTE = 0;
                }
            }
        }
        else if (GPIO_ReadInputDataBit(GPIOA, KEY4) == Bit_RESET){
            // 減少
            delay_ms(20);
            while(GPIO_ReadInputDataBit(GPIOA, KEY4) == Bit_RESET);
            if (select == 0){
                if (--TIME == 255){
                    TIME = 23;
                }
            }
            else{
                if (--MINUTE == 255){
                    MINUTE = 59;
                }
            }
        }
        if (GPIO_ReadInputDataBit(GPIOA, KEY2) == Bit_RESET){
            delay_ms(20);   // 消抖
            // 清屏
            show_string(0, 0, (unsigned char*)"                ");
            show_string(0, 1, (unsigned char*)"                ");
            break;
        }
    }
}

這裡的按鍵功能比較複雜,因為涉及到一個按鍵判斷功能的一個內容,所以在KEY2中又添加了一個死迴圈,在死迴圈中進行設置,當然這個功能不會影響DS1302時鐘的。

總結

其實這個項目還是很簡單的,等後面有時間我會改寫一下這個項目,讓單片機中插入一個系統,然後再用系統進行控制。大家有什麼想法可以在下麵留言,我這都會看到的。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在 Go 語言中,panic、recover 和 defer 是用於處理異常情況的關鍵字。它們通常一起使用來實現對程式錯誤的處理和恢復。 1. defer 語句 defer 用於在函數返回之前執行一段代碼。被 defer 修飾的語句或函數會在包含 defer 的函數執行完畢後執行。defer 常用於 ...
  • 建議看看電腦科學速成課,一門很全面的電腦原理入門課程,短短10分鐘可以把大學老師十幾節課講的東西講清楚!整個系列一共41個視頻,B站上有中文字幕版。 每個視頻都是一個特定的主題,例如軟體工程、人工智慧、操作系統等,主題之間都是緊密相連的,比國內很多大學電腦課程強太多! 這門課程通過生動形象的講 ...
  • ✨前言✨ 本片文章,主要在於C#連接MySQL資料庫,由於這之間無法建立直接聯繫,這時候就涉及到了第三方連接工具.NET,以此來建立C#與MySQL資料庫的連接 🍒歡迎點贊 👍 收藏 ⭐留言評論 📝私信必回喲😁 🍒博主將持續更新學習記錄收穫,友友們有任何問題可以在評論區留言 目錄🍊 一, ...
  • SciPy庫的optimize模塊主要用於執行各種優化任務。優化是尋找特定函數的最小值或最大值的過程,通常用於機器學習、數據分析、工程和其他領域。 scipy.optimize提供了多種優化演算法,包括梯度下降法、牛頓法、最小二乘法等,可以解決各種複雜的優化問題。該模塊還包含一些特定的函數,用於解決某 ...
  • .NET8發佈後,Blazor支持四種渲染方式 靜態渲染,這種頁面只可顯示,不提供交互,可用於網頁內容展示 使用Blazor Server托管的通過Server交互方式 使用WebAssembly托管的在瀏覽器端交互方式 使用Auto自動交互方式,最初使用 Blazor Server,併在隨後訪問時 ...
  • AOT介紹 .Net8的本地預編機器碼AOT,它幾乎進行了100%的自舉。微軟為了擺脫C++的鉗制,做了很多努力。也就是代碼幾乎是用C#重寫,包括了虛擬機,GC,記憶體模型等等。而需要C++做的,也就僅僅是引導程式,本篇通過代碼來看下這段至關重要的引導程式的運作模式。 支持功能 SqlSugar OR ...
  • 關於Anolis8/Centos8系統重啟後ip地址不顯示的原因 版權聲明:原創作品,謝絕轉載!否則將追究法律責任。 ————— 作者:kirin #、今天把之前在VMware安裝的Anolis8系統重啟了,啟動之後發現Xshell連接不上。在VMware上登錄後執行ip a命令發現ip地址不見了 ...
  • DX後臺截圖C++實現代碼 文章僅發佈於https://www.cnblogs.com/Icys/p/DXGI.html和知乎上。 傳統的GDI API (BitBlt)雖然可以完美的完成後臺截圖的任務,但是歸根結底效率還是太低。 直接使用DXGI方法截圖只能完成前臺視窗的截圖,而DX HOOK的截 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...