基于STM32设计的指针式电子钟与万年历

发布者:喜茶我要七分糖最新更新时间:2022-10-09 来源: csdn关键字:STM32  万年历 手机看文章 扫描二维码
随时随地手机看文章

1. 项目简介

这是基于STM32设计的一个指针式电子钟+万年历小项目,采用3.5寸的LCD屏显示时钟,日历、温度、天气,支持触摸屏调整设置时间,设置闹钟,查看日历等等。整体项目主要是技术点就是LCD屏的图形绘制。比如: 时钟的时针绘制、分针、秒针、表盘、日历绘制等等。


时钟的时间是直接采用STM32本身的RTC时钟,室内的室温数据采用DS18B20温度传感器获取,STM32芯片的具体型号是STM32F103ZET6,只要是STM32F1系列的开发板,代码都是可以通用的。


LCD显示屏采用的正点原子的3.5寸TFT显示屏,支持8080时序,自带触摸屏功能,触摸屏是电阻屏驱动芯片是XPT2046,SPI接口,通信非常方便。


STM32F103ZET6带有FSMC功能,可以输出8080时序,本项目里驱动LCD屏就采用FSMC控制的,效率比较高。


主界面如下:

image-20211231110615969

项目源码下载地址: https://download.csdn.net/download/xiaolong1126626497/63897554


项目视频演示地址:

基于STM32设计的指针式电子钟与日历


2. 项目功能介绍

下面对每个子功能页面做详细讲解。


2.1 实时时钟页面

在LCD屏上方显示表盘、分针、时针、 秒针、刻度、更改时钟时间方块,并实现分针、时针、秒针的移动,在实时时钟下方同步显示数字时钟。

image-20211231112132730

运用触摸屏功能实现时钟设置功能,点击“+” “-”至设置时钟方块,跳出设置时钟界面,即可开始设置时钟与日期;点击“+”“-”至设置闹钟方块,跳出设置闹钟界面,即可开始设置闹钟。

image-20211231112305798

2.2 日历页面

在LCD屏中部显示日期、星期、天气、实时温度,在LCD屏下方显示日历、左右两边显示黄历,并在日历上重点突出今天的日期。


image-20211231112355785

3. 项目实现主要程序讲解

3.1 流程图

image-20211231112512719

3.2 ds18b2.c 代码

下面列出DS18B20温度传感器主要代码.


#include "ds18b20.h"

#include "delay.h"  

//复位DS18B20

void DS18B20_Rst(void)     

{                 

    DS18B20_IO_OUT();   //SET PG11 OUTPUT

    DS18B20_DQ_OUT=0;   //拉低DQ

    DelayUs(750);       //拉低750us

    DS18B20_DQ_OUT=1;   //DQ=1 

    DelayUs(15);        //15US

}

//等待DS18B20的回应

//返回1:未检测到DS18B20的存在

//返回0:存在

u8 DS18B20_Check(void)     

{   

    u8 retry=0;

    DS18B20_IO_IN();    //SET PG11 INPUT     

    while (DS18B20_DQ_IN&&retry<200)

    {

        retry++;

        DelayUs(1);

    };   

    if(retry>=200)return 1;

    else retry=0;

    while (!DS18B20_DQ_IN&&retry<240)

    {

        retry++;

        DelayUs(1);

    };

    if(retry>=240)return 1;     

    return 0;

}

//从DS18B20读取一个位

//返回值:1/0

u8 DS18B20_Read_Bit(void)    

{

    u8 data;

    DS18B20_IO_OUT();   //SET PG11 OUTPUT

    DS18B20_DQ_OUT=0; 

    DelayUs(2);

    DS18B20_DQ_OUT=1; 

    DS18B20_IO_IN();    //SET PG11 INPUT

    DelayUs(12);

    if(DS18B20_DQ_IN)data=1;

    else data=0;     

    DelayUs(50);           

    return data;

}

//从DS18B20读取一个字节

//返回值:读到的数据

u8 DS18B20_Read_Byte(void)     

{        

    u8 i,j,dat;

    dat=0;

    for (i=1;i<=8;i++) 

    {

        j=DS18B20_Read_Bit();

        dat=(j<<7)|(dat>>1);

    }                           

    return dat;

}

//写一个字节到DS18B20

//dat:要写入的字节

void DS18B20_Write_Byte(u8 dat)     

 {             

    u8 j;

    u8 testb;

    DS18B20_IO_OUT();   //SET PG11 OUTPUT;

    for (j=1;j<=8;j++) 

    {

        testb=dat&0x01;

        dat=dat>>1;

        if (testb) 

        {

            DS18B20_DQ_OUT=0;   // Write 1

            DelayUs(2);                            

            DS18B20_DQ_OUT=1;

            DelayUs(60);             

        }

        else 

        {

            DS18B20_DQ_OUT=0;   // Write 0

            DelayUs(60);             

            DS18B20_DQ_OUT=1;

            DelayUs(2);                          

        }

    }

}

//开始温度转换

void DS18B20_Start(void) 

{                                          

    DS18B20_Rst();     

    DS18B20_Check();     

    DS18B20_Write_Byte(0xcc);   // skip rom

    DS18B20_Write_Byte(0x44);   // convert

//初始化DS18B20的IO口 DQ 同时检测DS的存在

//返回1:不存在

//返回0:存在         

u8 DS18B20_Init(void)

{

    RCC->APB2ENR|=1<<8;         //使能PORTG口时钟 

    GPIOG->CRH&=0XFFFF0FFF;     //PORTG.11 推挽输出

    GPIOG->CRH|=0X00003000;

    GPIOG->ODR|=1<<11;          //输出1

    DS18B20_Rst();

    return DS18B20_Check();

}  

//从ds18b20得到温度值

//精度:0.1C

//返回值:温度值 (-550~1250) 

short DS18B20_Get_Temp(void)

{

    u8 temp;

    u8 TL,TH;

    short tem;

    DS18B20_Start ();           // ds1820 start convert

    DS18B20_Rst();

    DS18B20_Check();     

    DS18B20_Write_Byte(0xcc);   // skip rom

    DS18B20_Write_Byte(0xbe);   // convert      

    TL=DS18B20_Read_Byte();     // LSB   

    TH=DS18B20_Read_Byte();     // MSB  

              

    if(TH>7)

    {

        TH=~TH;

        TL=~TL; 

        temp=0;                 //温度为负  

    }else temp=1;               //温度为正        

    tem=TH;                     //获得高八位

    tem<<=8;    

    tem+=TL;                    //获得底八位

    tem=(float)tem*0.625;       //转换     

    if(temp)return tem;         //返回温度值

    else return -tem;    

}

3.3 lcd屏图形绘制核心算法

整个项目的功能都是在LCD显示屏上,需要绘制线段、绘制圆、绘制矩形、绘制角度线段、绘制中文、绘制数字等等,下面列出这部分的核心代码。

 

/*

函数功能:画横直线

函数形参:x,y:坐标

        length:长度

*/

void LcdDrawThwartLine(u16 x,u16 y,u16 length,u16 color)

{

    u16 i;

    for(i=0;i    {

        LcdDrawPoint(x+i,y,color);

    }

}

/*

函数功能:画竖直线

函数形参:x,y:坐标

         length:长度

*/

void LcdDrawVerticalLine(u16 x,u16 y,u16 length,u16 color)

{

    u16 i;

    for(i=0;i    {

        LcdDrawPoint3(x,y+i,color);

    }

}

/*

函数功能:画矩形

函数形参:x,y:坐标

         length:长

                 width:宽

*/

void LcdDrawRectangle(u16 x,u16 y,u16 length,u16 width,u16 color)

{

    LcdDrawThwartLine(x,y,length,color);

    LcdDrawVerticalLine(x,y,width,color);

    LcdDrawThwartLine(x,y+width,length,color);

    LcdDrawVerticalLine(x+length,y,width,color);

}

//两点画线

//x1,y1:起点坐标

//x2,y2:终点坐标  

void LcdDrawLine(u16 x1, u16 y1, u16 x2, u16 y2,u16 color)

{

    u16 t; 

    int xerr=0,yerr=0,delta_x,delta_y,distance; 

    int incx,incy,uRow,uCol; 

    delta_x=x2-x1; //计算坐标增量 

    delta_y=y2-y1; 

    uRow=x1; 

    uCol=y1; 

    if(delta_x>0)incx=1; //设置单步方向 

    else if(delta_x==0)incx=0;//垂直线 

    else {incx=-1;delta_x=-delta_x;} 

    if(delta_y>0)incy=1; 

    else if(delta_y==0)incy=0;//水平线 

    else{incy=-1;delta_y=-delta_y;} 

    if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 

    else distance=delta_y; 

    for(t=0;t<=distance+1;t++ )//画线输出 

    {  

        LcdDrawPoint(uRow,uCol,color);//画点 

        xerr+=delta_x ; 

        yerr+=delta_y ; 

        if(xerr>distance) 

        { 

            xerr-=distance; 

            uRow+=incx; 

        } 

        if(yerr>distance) 

        { 

            yerr-=distance; 

            uCol+=incy; 

        } 

    }  

//在指定位置画一个指定大小的圆

//(x,y):中心点

//r    :半径

void LcdDraw_Circle(u16 x0,u16 y0,u8 r,u16 color)

{

    int a,b;

    int di;

    a=0;b=r;      

    di=3-(r<<1);             //判断下个点位置的标志

    while(a<=b)

    {

        LcdDrawPoint(x0+a,y0-b,color);             //5

        LcdDrawPoint(x0+b,y0-a,color);             //0           

        LcdDrawPoint(x0+b,y0+a,color);             //4               

[1] [2]
关键字:STM32  万年历 引用地址:基于STM32设计的指针式电子钟与万年历

上一篇:基于STM32设计的环境检测设备
下一篇:基于STM32+ESP8266+华为云IoT设计的云端绿化管理系统

推荐阅读最新更新时间:2024-11-18 16:14

STM32基础知识:串口通信-DMA方式
1 DMA概述 直接存储器访问 (DMA) : 用于在外设与存储器之间以及存储器与存储器之间进行高速数据传输。DMA传输过程的初始化和启动由CPU完成,传输过程由DMA控制器来执行,无需CPU参与,从而节省CPU资源,提高利用率。 DMA数据传输的四个要素: 传输源 :DMA数据传输的来源 传输目标:DMA数据传输的目的 传输数量:DMA传输数据的数量 触发信号:启动一次DMA数据传输的动作 STM32的DMA控制器特点 每个DMA控制器有8个数据流,每个数据流可以映射到8个通道(或请求); 每一个DMA控制器用于管理一个或多个外设的存储器访问请求,并通过总线仲裁器来协调各个DMA请求的优先级; 数据流(st
[单片机]
<font color='red'>STM32</font>基础知识:串口通信-DMA方式
STM32一键下载电路导致的单片机不能正常运行
使用的正点原子精英版的电路,直接使用那种4线的stlink给单片机供电+下载程序,发现能够正常下载,但死活不运行程序。 一键下载电路如图~ 当时没有使用USB串口功能,所以没有接入5V供电,导致了RTS和DTR引脚悬空,测量电压均为2.69V,即BOOT0被拉高,单片机的启动模式变成了从ISP下载。 插上5V供电一切正常~
[单片机]
<font color='red'>STM32</font>一键下载电路导致的单片机不能正常运行
keil下生成与使用库文件
写过系统级程序的同学对库(lib,dll)都不陌生把,一个是静态库一个是动态库。 库大家都知道是不需要编译的,而且别人是无法看到源代码的,这样的好处就是编译快,并且方便移植,更安全。 但是keil好像只能用静态库,这里就简单的说一下把。 例如我有一个LED的文件,可以实现点灯的功能,并且是c++开发的,我想把它做成静态库方便以后使用。 等我搭建一个c++的keil工程....................... 终于搭建好了,烧录后可以正常运行。 下面直接把led.cpp生成led.lib 编译一下,下面看到已经生成led.lib文件了 下面看看怎么使用 我们去上面那个目录找到led.lib文
[单片机]
keil下生成与使用库文件
STM32入门——寄存器
GPIO学习: 引脚的分类:1.电源引脚 2.晶振引脚 3.复位引脚 4.下载引脚 5.BOOT引脚 6.GPIO引脚 GPIO的结构:1.保护二极管 --引脚两端连接上两个二极管,设置好高低电压,这样超过这个电压之后二极管导通就会保护里面的电路。这能处于两端电压设置的中间值。2.上下拉电阻--上下拉电阻在输入方向门口,用于稳定电压 3.P-MOS和N-MOS管 --- 这是输出模式的门口,推挽输出和开漏输出,推挽输出3.3V ,靠命令传来的电压,激活开关,使他们链接对应的高低电压传出去。 开漏输出能输出5V电压,开漏输出就是控制开关开或者关,上边要接上一个上拉电阻,关掉就是低电压,开开就是高电压。 4.输出寄存器---输出寄存器
[单片机]
stm32 SPI通信 操作寄存器
SPI(Serial Peripheral Interface--串行外设接口) 总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息。 SPI是Freescale(原 Motorola)公司首先在其处理器上定义的。 SPI是一种高速、主从式、全双工、同步传输的通信总线,SPI总线在物理层体现为四根传输线: MOSI (Master Output Slaver Input) – 主器件数据输出,从器件数据输入 MISO (Master Input Slaver Output) – 主器件数据输入,从器件数据输出 SCLK – 时钟信号,由主器件产生 NSS – 从器件使能信号,由主器
[单片机]
STM32中的位带(bit-band)操作
//位带操作,实现51类似的GPIO控制功能 //具体实现思想,参考 CM3权威指南 第五章(87页~92页). //IO口操作宏定义 #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF) 5)+(bitnum 2)) #define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) //IO口地址映射 #define GPIOA_ODR_Addr
[单片机]
基于STM32的嵌入式数字示波器设计
  嵌入式数字示波器是近年来发展起来的一种集显示、测量、运算、分析、记录等多种功能于一体的智能化测量终端设备。凭借其强大的性能优势,己逐步取代传统模拟示波器。当前国内通用的数字示波器多数采用51单片机、FPGA、DSP等结构。但是51单片机处理能力有限,无法实现数字示波器的基本指标,FPGA虽然能深入开发数字示波器,然而,其成本偏高,即使加入SOPC软核,其软件压力也很大。   本设计选用ARM处理器中基于Cortex-M3内核的32位STM32F103VCT6作为主控芯片。该芯片内部集成了16通道的12位高精度A/D转换器,转换时间仅为1μs,而且STM32芯片具省电模式,功耗低,与传统MCU相比,其在性能和处理能力上都比较
[测试测量]
基于<font color='red'>STM32</font>的嵌入式数字示波器设计
X-CUBE-STL:支持更多STM32, 揭开功能安全的神秘面纱
X-CUBE-STL 目前支持 STM32MP1、STM32U5、STM32L5、STM32H5和 STM32WL。实际上,这个最大的通用微控制器产品家族还在不断扩大,将会有更多的产品支持SIL2和SIL3系统。客户的开发团队可以在ST最新的产品上开发满足 IEC 61508、ISO 13849 和 IEC 61800 等要求 的应用。此外,在ST网站的功能安全网页上,开发者很容易找到各种资源,轻松快速通过工业或家电安全认证。网页上还列出了ST 授权合作伙伴以及他们提供的实时操作系统、开发工具、工程服务和培训课程,确保客户团队能够完成从概念验证到商品的市场转化。 o观看ST的功能安全网络研讨会 国际电工委员会对安全的定
[单片机]
X-CUBE-STL:支持更多<font color='red'>STM32</font>, 揭开功能安全的神秘面纱
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved