作息時間提示控制項目

来源: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
  • 當使用Autofac處理一個介面有多個實現的情況時,通常會使用鍵(key)進行區分或者通過IIndex索引註入,也可以通過IEnumerable集合獲取所有實例,以下是一個具體的例子,演示如何在Autofac中註冊多個實現,並通過構造函數註入獲取指定實現。 首先,確保你已經安裝了Autofac Nu ...
  • 本篇將分享Prometheus+Grafana的監控平臺搭建,並監控之前文章所搭建的主機&服務,分享日常使用的一些使用經驗本篇將配置常用服務的監控與面板配置:包括 MySQL,MongoDB,CLickHouse,Redis,RabbitMQ,Linux,Windows,Nginx,站點訪問監控,已... ...
  • 使用Aspirate可以將Aspire程式部署到Kubernetes 集群 工具安裝 dotnet tool install -g aspirate --prerelease 註意:Aspirate 正在開發中,該軟體包將作為預覽版進行版本控制,--prelease 選項將獲得最新的預覽版。 容器註 ...
  • 前言 本文要說的這種開發模式,這種模式並不是只有blazor支持,js中有一樣的方案next.js nuxt.js;blazor還有很多其它內容,本文近關註漸進式開發模式。 是的,前後端是主流,不過以下情況也許前後端分離並不是最好的選擇: 小公司,人員不多,利潤不高,創業階段能省則省 個人開發者,接 ...
  • 在.NET中,Microsoft.Extensions.Logging是一個靈活的日誌庫,它允許你將日誌信息記錄到各種不同的目標,包括資料庫。在這個示例中,我將詳細介紹如何使用Microsoft.Extensions.Logging將日誌保存到MySQL資料庫。我們將使用Entity Framewo ...
  • chatgpt介面開發筆記3: 語音識別介面 1.文本轉語音 1、瞭解介面參數 介面地址: POST https://api.openai.com/v1/audio/speech 下麵是介面文檔描述內容: 參數: { "model": "tts-1", "input": "你好,我是饒坤,我是ter ...
  • 前面兩篇文章主要是介紹瞭如何解決高併發情況下資源爭奪的問題。但是現實的應用場景中除了要解決資源爭奪問題,高併發的情況還需要解決更多問題,比如快速處理業務數據等, 本篇文章簡要羅列一下與之相關的更多技術細節。 1、非同步編程:使用async和await關鍵字進行非同步編程,這可以避免阻塞線程,提高程式的響 ...
  • 大家好,我是棧長。 Nacos 2.3.0 前幾天正式發佈了,新增了不少實用性的新功能,真是史上最強版本。 Nacos 2.3.0 還真是一個比較重要的大版本,因為它涉及了太多重大更新,今天棧長給大家來解讀下。 Nacos 先掃個盲: Nacos 一個用於構建雲原生應用的動態服務發現、配置管理和服務 ...
  • IDEA的遠程開發功能,可以將本地的編譯、構建、調試、運行等工作都放在遠程伺服器上執行,而本地僅運行客戶端軟體進行常規的開發操作即可,舊版本IDEA目前不支持該功能.,本例使用的是IDEA2023.2.5版本 下麵介紹如何在IDEA中設置遠程連接伺服器開發環境並結合Cpolar內網穿透工具實現無公網 ...
  • 本文解釋為啥會有響應式編程,為什麼它在開發者中不太受歡迎,以及引入 Java 虛擬線程後它可能最終會消失。 命令式風格編程一直深受開發者喜愛,如 if-then-else、while 迴圈、函數和代碼塊等結構使代碼易理解、調試,異常易追蹤。然而,像所有好的東西一樣,通常也有問題。這種編程風格導致線程 ...