定时器与日历时钟

一、STM32通过hal库使用定时器

1.实验目的

设置一个5秒的定时器,每隔5秒从串口发送“hello windows!”;同时设置一个2秒的定时器,让LED灯周期性地闪烁。

2.实验材料

软件:
Keil5
STM32CubeMx

硬件:
STM32F103C8T6最小板
CH340模块
LED灯一个
面包板
杜邦线

3.实验过程

(1)配置时钟

使用STM32CubeMx创建项目后,先配置HSE,如下图
在这里插入图片描述
然后按下图配置Clock Configuration
在这里插入图片描述

(2)配置GPIO引脚

因为要用定时器来控制LED灯的亮灭,所以我们要配置一个输出引脚,引脚的选择,我这里选择PA5
在这里插入图片描述

(3)配置定时器

本次实验既要控制LED,又要串口输出,所以要用两个定时器。
我们不需要用到高级定时器,就用通用计时器TIM2~4即可。
下图是TIM2的配置
在这里插入图片描述
分频系数是71,但系统处理的时候会自动加上1,所以实际是72分频。
因为时钟我们的配置为72MHZ,所以72分频后得到1MHZ的时钟,即0.001ms记一次数,这里写成2000就是2ms触发一次中断。
后面我们只需要写代码让每触发1000次中断就闪烁一次LED灯,就满足了2s闪烁一次的条件。
然后我们还要开启中断以及生成优先级函数,如下图
在这里插入图片描述
在这里插入图片描述
TIM3用于串口通信,原理同上,就直接看图配置即可
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(4)配置串口

只要设置为异步即可,别的都是默认配置。
在这里插入图片描述

(5)配置项目

在这里插入图片描述
在这里插入图片描述

(6)配置代码

以下代码用于手动开启定时器,需要放到main函数里面

HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_Base_Start_IT(&htim3);

在这里插入图片描述
然后要编写中断函数,注意:
首先要声明两个静态变量,分别记录两个定时器触发中断的次数。

	static uint32_t time_cnt1 =0;
	static uint32_t time_cnt2 =0;

if(htim->Instance == TIM2)用于判断使用的定时器是TIM2
if(++time_cnt1 >= 1000)用于判断触发中断的次数,也就是前文说的1次中断的时间为2ms,1000次就为2s,然后就执行相应的操作。
TIM3同理。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	static uint32_t time_cnt1 =0;
	static uint32_t time_cnt2 =0;
	if(htim->Instance == TIM2)
	{
		if(++time_cnt1 >= 1000)
		{
			time_cnt1 =0;
			HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
		}
	}
	if(htim->Instance == TIM3)
	{
		if(++time_cnt2 >= 1000)
		{
			time_cnt2 =0;
			uint8_t hello[20]="hello windows!\n";
      HAL_UART_Transmit(&huart1,hello,20,100000);
		}
			
	}
}

在这里插入图片描述

(7)配置电路

LED短脚接PA5,长脚接正。按下图接即可:
在这里插入图片描述

4.实验效果

在这里插入图片描述

二、STM32通过hal库读取RTC数据发送给串口助手

1.实验目的

了解实时时钟RTC的原理。STM32芯片自带RTC,因此不须像其他MCU需外接RTC模块。请编程实现STM32的日历读取、设置和输出。
要求:
1)读取RTC初始时间,验证是否为 1970年1月1日零分零秒;
2)将RTC时间调整为当前时间,并以 2021年x月x日x分x秒的格式从串口输出(或输出到OLED屏),每1s改变一次;
3)如果输出内容中需加入“星期x”,请修改代码。

2.实验材料

软件:
Keil5
STM32CubeMx

硬件:
STM32F103C8T6最小板
CH340模块
LED灯一个
面包板
杜邦线

3.实验过程

(1)配置时钟

创建好项目后,按下图配置时钟使能RCC和HSE,下图第5步可能需要开启RTC后才能配置,这里等后面开启RTC后再配置。
在这里插入图片描述

(2)配置RTC

下面只需要勾选即可,框中的BCD码是用来设置RTC中的时间初值的,后面会用到,这里可以不管。
在这里插入图片描述

(3)配置串口

前文已经配置过了,只要设置成异步即可。
在这里插入图片描述

(4)配置项目

也同前文一样
在这里插入图片描述
在这里插入图片描述

(5)配置代码

首先要编写一个fputc函数,然后使能printf,代码和配置图如下,注意要勾选魔术棒里的Use Micro Lib

#include "stdio.h"

int fputc(int ch,FILE *f){
 uint8_t temp[1]={ch};
 HAL_UART_Transmit(&huart1,temp,1,2);
 return ch;
}

在这里插入图片描述
在这里插入图片描述
然后我们需要获取日期结构体和时间结构体。
GetDate用来接受日期,GetTime用来接收时间

  RTC_DateTypeDef GetDate;  
  RTC_TimeTypeDef GetTime;   

然后我们可以打开rtc.c文件,我们可以看到RTC中的时间都在这里被初始化
在这里插入图片描述
也就是说,如果我们不修改的话,默认的是00年1月1日,0时0分0秒。
同时要注意:HAL库的年是从2000年开始的,输入0x00,保存的是2000年,而星期是由年月日自动计算出来的,我们无法修改。所以我们如果要输出2021年的第一天的话就要把Year=0x21即可。
在这里插入图片描述

接下来就可以往while循环里写代码了,以下代码中,发送一次信息给串口的速度为1s,其中printf中的1,2,3,4,5,6,7代表的是星期一到星期日,:

	  HAL_RTC_GetTime(&hrtc,&GetTime,RTC_FORMAT_BIN);
		HAL_RTC_GetDate(&hrtc,&GetDate,RTC_FORMAT_BIN);
		printf("%02d-%02d-%02d %02d:%02d:%02d  ",GetDate.Year,GetDate.Month,GetDate.Date,GetTime.Hours,GetTime.Minutes,GetTime.Seconds);
		if(GetDate.WeekDay==1){
			printf(" 1\r\n");
		}else if(GetDate.WeekDay==2){
			printf(" 2\r\n");
		}else if(GetDate.WeekDay==3){
			printf(" 3\r\n");
		}else if(GetDate.WeekDay==4){
			printf(" 4\r\n");
		}else if(GetDate.WeekDay==5){
			printf(" 5\r\n");
		}else if(GetDate.WeekDay==6){
			printf(" 6\r\n");
		}else if(GetDate.WeekDay==7){
			printf(" 7\r\n");
		}
        HAL_Delay(1000);

(6)配置电路

前文的电路不用拆直接使用即可,多余的接线对本次实验并无影响,且不会导致短路。

4.实验效果

在不修改任何日期设置时,默认时间为00年1月1日 00:00:00,星期六
在这里插入图片描述
修改年份为0x21后,时间变为了21年1月1日00:00:00,星期五
在这里插入图片描述

三、总结

本次实验学到了挺多,一个是定时器,它的使用原理是计数个数到达一定值后触发中断,我们利用中断进行我们想要的操作,一个是RTC,要声明结构体来接受数据,还有日期的设定是用BCD码来进行设置,且默认为0x00就是2000年,0x21就是2022年,还有星期的计算是自动计算的,我们不能更改。

四、参考链接

STM32CUBEMX_定时器控制LED闪烁
【STM32】HAL库 STM32CubeMX教程十三—RTC时钟

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值