作息時間提示控制項目

来源: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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...