stm32数码管显示实时时间并有闹钟功能

  • 功能描述
  • 数码管介绍
    • 数码管芯片
    • 段选与位选
    • 驱动数码管显示代码
  • 实验思路
  • 完整代码
    • Led.h
    • Led.c
    • Key.h
    • Key.c
    • beep.h
    • beep.c
    • smg.h
    • smg.c
    • timer.h
    • timer.c
    • main.c
  • 实验难点
  • 解决方法
  • 总结

功能描述

通过stm32开发板上面的按键来实现时钟的调节和闹钟调节并响铃

数码管介绍

2个74HC595来驱动8位共阳数码管
共阳数码管0-9编码表:0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90

数码管芯片

74HC595是串行输入,并行输出的锁存器
DS:14脚,串行数据输入引脚
OE:13脚,输出使能控制脚,它是低电才使能输出,所以接GND
ST_CP:12脚,存储寄存器时钟输入引脚。上升沿时,数据从移位寄存器转存带存储寄存器。
SH_CP:11脚,移位寄存器时钟引脚,上升沿时,移位寄存器中的数据整体后移,并接受新的数据(从DS输入)
MR:10脚,低电平时,清空移位寄存器中已有的数据,一般不用,接高电平即可。
Q7’:9脚,串行数据输出引脚。当移位寄存器中的数据多于8位时,会把已有的位“挤出去”,就是从这里出去的。用于595的级联
Q1-Q7:1到7脚,并行输出引脚
74HC595具体介绍

段选与位选

位选:选择哪一个数码段点亮
段选:选择点亮的数码管显示什么数字
进行位选和段选时,要先进行透明在进行锁存,这样才能进行显示。

驱动数码管显示代码

void Smg_Diaplay()
{u8 i;for(i=0;i<8;i++){GPIOA->ODR=~(1<<i);//选择哪一个数码管亮GPIO_SetBits(GPIOA,GPIO_Pin_8);//位透明模式GPIO_ResetBits(GPIOA,GPIO_Pin_8);//段锁存模式GPIOA->ODR=DisPlayData[i];//数据输入GPIO_SetBits(GPIOA,GPIO_Pin_9);//位透明GPIO_ResetBits(GPIOA,GPIO_Pin_9);//段锁存}
}

实验思路

1、让数码管亮,能直接在代码中设置数字让其显示
2、让数码管的1、2,4、5,7、8位分别显示秒,分,时的数字;3、5位显示短线表示分割
3、设置定时器3,让其定时1秒,控制秒的改变,进而控制分和时
4、设置按键,控制分和时的增加,从而改变当前时间。此时应该停止定时器3的计数,方便进行调整
5、在设置一个定时器2定时1秒来控制闹钟的计数
6、设置按键,控制闹钟分和时的改变,此时应该让定时器2停止定时,定时器3继续计数
7、设置一个函数来计算设置的闹钟时间与当前时间的差值,让定时器进行计数,当计数值达到差值时,蜂鸣器响,否则不响

完整代码

Led.h

#ifndef __LED_H
#define __LED_H  void LED_Init(void);//初始化#endif

Led.c

#include "led.h"
#include "stm32f10x.h"//LED IO初始化
void LED_Init(void)
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//LED0GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       GPIO_Init(GPIOB, &GPIO_InitStructure);          GPIO_SetBits(GPIOB,GPIO_Pin_5);//输出高GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//LED1GPIO_Init(GPIOE, &GPIO_InitStructure);  GPIO_SetBits(GPIOE,GPIO_Pin_5);  //输出高
}

Key.h

#ifndef __KEY_H
#define __KEY_H  void Key_Init(void);#endif

Key.c

#include "stm32f10x.h"
#include "key.h"extern u8 sec,min,hour;void Key_Init(void)
{ GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOE,ENABLE);GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_4 | GPIO_Pin_3;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入GPIO_Init(GPIOE, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉   GPIO_Init(GPIOA, &GPIO_InitStructure);}

beep.h

#ifndef __BEEP_H
#define __BEEP_H        void Beep_Init(void);   //初始化#endif

beep.c

#include "beep.h"
#include "stm32f10x.h"   void Beep_Init(void)
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_ResetBits(GPIOB,GPIO_Pin_8);//关闭蜂鸣器输出
}

smg.h

#ifndef __SMG_H
#define __SMG_H         #include "stm32f10x.h"//#define RCLK PBout(10)//时钟脉冲信号——上升沿有效
//#define SCLK PBout(11)//打入信号————上升沿有效
//#define DIO  PAout(8)//串行数据输入void Smg_Init(void);
void Smg_DisPlay(void);
void Display_Data(u8 hour,u8 min,u8 sec);// Smg显示
void Smg_OUT(u8 X);// Smg单字节串行移位函数#endif

smg.c

#include "smg.h"
#include "stm32f10x.h"
#include "delay.h"extern u8 sec,min,hour;
u16 smgduan[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//u16 smgduan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
u8 DisPlayData[8];void Smg_Init(void) //IO初始化
{ GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB,ENABLE);//使能PORTA,PORTB时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;GPIO_Init(GPIOA, &GPIO_InitStructure);
}   void Smg_DisPlay(void)
{u8 i;for(i=0;i<8;i++){Smg_OUT(DisPlayData[i]);           Smg_OUT(0x01<<i); //RCLKGPIO_SetBits(GPIOB,GPIO_Pin_10);//位透明模式GPIO_ResetBits(GPIOB,GPIO_Pin_10);//锁存模式delay_ms(1);}
}void Display_Data(u8 hour,u8 min,u8 sec)
{DisPlayData[0] = smgduan[sec%10];//秒DisPlayData[1] = smgduan[sec/10];DisPlayData[2] = 0xbf;DisPlayData[3] = smgduan[min%10];//分DisPlayData[4] = smgduan[min/10];DisPlayData[5] = 0xbf;DisPlayData[6] = smgduan[hour%10];//时DisPlayData[7] = smgduan[hour/10];
}void Smg_OUT(u8 x)
{u8 i;for(i=8;i>=1;i--){if(x&0x80) GPIO_SetBits(GPIOA,GPIO_Pin_8);else GPIO_ResetBits(GPIOA,GPIO_Pin_8);x<<=1;//SCLKGPIO_SetBits(GPIOB,GPIO_Pin_11);//段透明模式GPIO_ResetBits(GPIOB,GPIO_Pin_11);}
}/*
void Showtime()//时间显示
{u8 i;delay_init();for(i=0;i<8;i++){GPIOA->ODR=~(1<<i);//选位GPIO_SetBits(GPIOA,GPIO_Pin_8);//透明模式GPIO_ResetBits(GPIOA,GPIO_Pin_8);//锁存模式GPIOA->ODR=DisPlayData[i];GPIO_SetBits(GPIOA,GPIO_Pin_9);//透明模式GPIO_ResetBits(GPIOA,GPIO_Pin_9);delay_ms(1);}
}
*/

timer.h

#ifndef __TIMER_H
#define __TIMER_H#include "stm32f10x.h"void Timer3_Init(u16 arr,u16 pse);
void Timer2_Init(u16 arr,u16 pse);
void TimeZJ();
int CountTime(u8 h,u8 m);#endif

timer.c

#include "timer.h"
#include "delay.h"
#include "stm32f10x.h"
#include "smg.h"extern u8 sec,min,hour;
extern u16 count;//定时1s 4999 7199
void Timer3_Init(u16 arr,u16 pse)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;NVIC_InitTypeDef NVIC_InitStruct;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);TIM_TimeBaseInitStruct.TIM_Period =  arr;TIM_TimeBaseInitStruct.TIM_Prescaler =  pse;TIM_TimeBaseInitStruct.TIM_CounterMode =  TIM_CounterMode_Up;TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority =2;NVIC_Init(&NVIC_InitStruct);TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);TIM_Cmd(TIM3,ENABLE);
}void Timer2_Init(u16 arr,u16 pse)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;NVIC_InitTypeDef NVIC_InitStruct;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);TIM_TimeBaseInitStruct.TIM_Period =  arr;TIM_TimeBaseInitStruct.TIM_Prescaler =  pse;TIM_TimeBaseInitStruct.TIM_CounterMode =  TIM_CounterMode_Up;TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority =2;NVIC_Init(&NVIC_InitStruct);TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);TIM_Cmd(TIM2,DISABLE);
}//时钟定时
void TIM3_IRQHandler()
{   sec++;TimeZJ();TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}//闹钟定时
void TIM2_IRQHandler()
{   count++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}void TimeZJ()
{if(sec >= 60){sec=0;min++;if(min >= 60) {min=0;hour++;if(hour >= 24) {hour = 0;}}   }
}int CountTime(u8 h,u8 m)
{if(h > hour)return (h - hour - 1) * 3600 + (60 - min + m) * 60;else if(h < hour)return (23 - hour + h) * 3600 + (60 - min + m) * 60;elseif(m >= min)return (m - min) * 60;elsereturn (23 - hour + h) * 3600 + (60 - min + m) * 60;
}

main.c

#include "stm32f10x.h"
#include "Key.h"
#include "Led.h"
#include "delay.h"
#include "smg.h"
#include "timer.h"
#include "delay.h"
#include "beep.h"u8 sec,min,hour;//时钟
u8 h,m,s;//闹钟
u8 setflag;//时间设置
u8 a = 0;
u16 count;
u8 countflag;//闹钟设置
u8 flag;//响铃int main()
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);Timer3_Init(9999,7199);Timer2_Init(9999,7199);LED_Init();Key_Init();delay_init();Smg_Init();Beep_Init();hour = 12;min = 14;sec = 15;h = 0;m = 0;s = 0;while(1){       //实时时间显示Smg_DisPlay();Display_Data(hour,min,sec);//时间设置if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1)//WK_UP{delay_ms(10);if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1){while((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)));setflag = 1;TIM_Cmd(TIM3,DISABLE);}}while(setflag){GPIO_ResetBits(GPIOB,GPIO_Pin_5);//亮 LED0if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1){//退出delay_ms(10);if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1){//消抖while((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)));setflag = 0;TIM_Cmd(TIM3,ENABLE);GPIO_SetBits(GPIOB,GPIO_Pin_5);//灭break;}}if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0)//KEY1 hour{delay_ms(10);if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0){while(!(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)));hour++;if(hour == 24)hour = 0;}}if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0)//KEY0 min{delay_ms(10);if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0){while(!(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)));min++;if(min == 60)min = 0;}}Smg_DisPlay();Display_Data(hour,min,sec);}//闹钟设置if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0)//KEY0{delay_ms(10);if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0){while(!(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)));countflag = 1;//进入设置闹钟模式if(a == 0){a = 1;TIM_Cmd(TIM2,DISABLE);}else{a = 0;countflag = 0;//退出定时模式TIM_Cmd(TIM2,ENABLE);//开启定时器count = 0;}}}while(countflag){GPIO_ResetBits(GPIOE,GPIO_Pin_5);//亮 LED1if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0)//KEY0{//退出设置闹钟模式 进入时钟运行模式delay_ms(10);if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0){while(!(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)));countflag = 0;flag = 1;TIM_Cmd(TIM2,ENABLE);//开启定时器2定时GPIO_SetBits(GPIOE,GPIO_Pin_5);//灭break;}}if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0)//KEY1 h{delay_ms(10);if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0){while(!(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)));m++;if(m == 60)m = 0;}}if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1)//WK_UP m{delay_ms(10);if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1){while((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)));h++;if(h == 24)h = 0;}}Smg_DisPlay();Display_Data(h,m,s);}//响铃while(flag){Smg_DisPlay();Display_Data(hour,min,sec);if(count == CountTime(h,m)){GPIO_SetBits(GPIOB,GPIO_Pin_8);//开GPIO_ResetBits(GPIOB,GPIO_Pin_5);//LED0 亮delay_ms(100);if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0)//KEY1{delay_ms(10);if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0){while(!(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)));flag = 0;GPIO_ResetBits(GPIOB,GPIO_Pin_8);//关GPIO_SetBits(GPIOB,GPIO_Pin_5);//灭 LED0TIM_Cmd(TIM2,DISABLE);break;}}}}}return 0;
}

实验难点

1、在进行闹钟设置时,会与当前的时钟产生矛盾,设置闹钟会改变时钟;
2、如何让闹钟的时间与当前时间进行比较;
3、当闹钟响铃时,按下按键还会响不会停或者闹钟响铃关闭时钟时间回到初始状态。

解决方法

1、在进行闹钟设置时在使用一个定时器来专门控制闹钟;一个定时器控制时钟。
2、使用一个函数来计数当前时间到闹钟的时间一共有多少秒,用一个定时器来进行计数并于这个时间进行比较,当两则相等时则表示闹钟一个响铃。在遇到闹钟问题时去询问了同学。
3、闹钟响铃时与时钟设置和闹钟设置时一样放入一个while()函数,但是在进入此函数和退出此函数是要进行变量设置,而且闹钟响铃后关闭闹钟的定时器。

总结

在进行时钟定时时,定时器的预分频系数和重装载值要设置正确,要为1秒。遇到问题时要去询问同学或查找相关资料。闹钟设置时一个难点,进行设置时要与时钟的设置区分开,否则很容易两则产生矛盾。

stm32数码管显示实时时间并有闹钟功能相关推荐

  1. C# CRC16 在textbox中显示实时时间

    PC环境win10,编译器visual studio2015 CRC16的源码 static int crc16(byte[] data, int size) {int crc = 0x0;byte ...

  2. 微信开发者工具中显示实时时间

    在wxml中设置显示时间的标签 <text>{{nowDate}}</text> <text>{{nowTime}}</text> 在js中data中设 ...

  3. 【组件封装】显示实时时间和星期几·附文字特效

    目录 前言 1.显示实时时间无星期版 1.1 效果如下: 1.2 封装的代码如下(适用vue) 2.显示实时时间带星期几 2.1 效果图 2.2 封装的代码如下(适用vue) 3.流光效果 4.文字发 ...

  4. WT588F02KD-24SS语音芯片(数码管显示驱动ic)在多功能烧水壶的应用设计方案

    WT588F02KD-24SS语音芯片(数码管显示驱动ic)在多功能烧水壶的应用设计方案 现代人除了写字楼及个别家庭在使用饮水机消费纯净水或蒸馏水外,大多数的家庭仍然是饮用烧开的自来水.而早前流行于欧 ...

  5. python七段数码管创新_Python绘制七段数码管显示当前时间

    利用Python中的turtle图形库绘制七段数码管,显示当前时间 代码 # coding:utf-8 # 绘制七段数码管,显示当前时间 import time import turtle as tt ...

  6. vs2008C#网页实现显示实时时间

    第一次接触这个东西,什么都不懂,好在看过几天的html5,对一些通用标签还是了解一点的. 在实现功能之前,查阅了很多代码,结果发现根本跑不起来,由于不懂C#这东西,在实现时间功能时遇到了很大的困难,在 ...

  7. STM32 数码管显示

    一 认识二级管 常用的二级管分为两种 1,(b)图共阴极结构:是把所有 LED 的阴极作为公共端(COM) 连起来,接低电平,通常接地.通过控制每一个 LED 的阳极电平使其发光或熄灭,阳极为高电平时 ...

  8. 【蓝桥杯嵌入式】【STM32】7_RTC之实时时间显示和硬件闹钟设置

    文章目录 1.RTC的三个可用时钟源 2.RTC框图 3.写代码前需要知道的一些标志位 4.配置流程 5.源代码 6.关于设置闹钟这件事  6.1.配置流程  6.2.实验源代码   下载工程文件: ...

  9. winform中显示实时时间和星期

    做winform项目发现需要添加一个时间显示功能,现记录如下: 1.首先新建一个Timer,命名为timer,并在属性中修改Interval为1000: 2.在需要显示时间的地方添加一个label(假 ...

最新文章

  1. 第一次作业+105032014116
  2. 第六十一节,html超链接和路径
  3. Python计算机视觉:第八章 图像类容分类
  4. 昨天,面试了一个安全工程师,她的回答让我耳目一新
  5. 用python编写密码安全性_密码安全性
  6. 很好的一篇讲解sql优化的文章
  7. ❤️java多线程并发编程入门 教程合集❤️
  8. 赋值语句、变量、数学表达式、位运算详解(C++)
  9. MySQL的详细安装教程和配置过程(附安装包)
  10. 【笔记】QCA9531无线校准
  11. MATLAB伽罗域是什么,利用伽罗华域的运算来计算生成矩阵
  12. 【vue】imitate-beautiful-thing
  13. IDE、SCSI、SATA几种常见的硬盘接口
  14. 新南威尔士大学纯硅量子计算机,重磅!!新南威尔士大学澳洲工程学院到访
  15. 电感器饱和的简单说明
  16. C#【必备技能篇】VS2019 使用C/C++ 生成DLL 文件,并用 C/C++、C#调用DLL
  17. JSP+Struct+MySql基于BBS管理系统设计与实现(源代码+论文+中英资料+开题报告+答辩PPT)
  18. 基于STM32震动感应灯
  19. 上饶师范学院数学与计算机科学学院,第4章-上饶师范学院数学与计算机科学学院.doc...
  20. 使用MakeMKV将DVD和ISO文件转换为MKV

热门文章

  1. oracle 自治事物,自治事务 - 努力创造未来! - BlogJava
  2. mysql中engine是什么意思_mysql中engine=innodb和engine=myisam的区别
  3. spring 扫描所有_自定义Spring事件监听机制
  4. fdfs往服务器上传文件超时,FastDFS 实现大文件分片上传
  5. php mysql 地理位置_MySQL版中国省市区地址地区信息数据表
  6. php编程实现水仙花数,php实现水仙花数的4个示例分享
  7. sha java 应用_Java中常用的加密算法应用MD5,SHA,RSA
  8. 设计素材|美丽的几何和多边形背景纹理
  9. 让版面充满空间感的海报PSD分层模板,你一定要看看!
  10. Web UI套件模板|设计师的好帮手