第8周-定时器与日历时钟

第8周作业


前言

第8周-定时器与日历时钟


一、定时器

1、LED周期闪烁

1)创建项目

1.打开外部时钟,点击“System Core”,选择RCC,在右侧弹出的菜单栏中选择“Crystal/Ceramic Resonator”。
在这里插入图片描述
2.选择调试接口,点击“System Core”,选择RCC。,在右侧弹出的菜单栏中选择“Serial Wire”。
在这里插入图片描述
3.配置IO。LED部分和实验2一样,配置PC15,并命名为D1。
在这里插入图片描述
4.配置定时器2。这里我们使用定时器2来实现定时的功能。如图所示,依次点击位置1,选中定时器2;位置2,配置定时器2的时钟源为内部时钟;位置3,分频系数为71,向上计数模式,计数周期为5000,使能自动重载模式。
在这里插入图片描述
分频系数那里虽然写的是71,但系统处理的时候会自动加上1,所以实际进行的是72分频。由于时钟我们一般会配置为72MHZ,所以72分频后得到1MHZ的时钟。1MHZ的时钟,计数5000次,得到时间5000/1000000=0.005秒。也就是每隔0.005秒定时器2会产生一次定时中断。
5.配置中断。如下图所示,开启定时器2的中断。
在这里插入图片描述
如下图所示,生成定时器2中断优先级配置代码。
在这里插入图片描述
6.时钟配置
在这里插入图片描述
7.进行相应配置,生成工程文件
在这里插入图片描述
在这里插入图片描述

2)配置keil

1.修改工程。生成工程后,打开,添加中断响应之后所需的一些代码。在main.c文件中添加如下内容
在这里插入图片描述
代码如下:

HAL_TIM_Base_Start_IT(&htim2);

在这里插入图片描述

代码如下:

//定时器回调函数

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	static uint32_t time_cnt =0;

	if(htim->Instance == TIM2)
	{
		if(++time_cnt >= 400)
		{
			time_cnt =0;
			HAL_GPIO_TogglePin(D1_GPIO_Port,D1_Pin);
		}
	}
}

该函数为定时器的中断回调函数,当产生定时中断的时候,会自动调用这个函数。在函数内部定义了一个静态变量:time_cnt。当它大于等于400的时候,才会执行if里面的代码。也就是说需要发生400次中断,才会让LED的状态翻转。前面已经算过了,一次定时中断的时间是0.005秒,所以400次中断的时间是0.005*400=2秒。也就是说每隔2秒,LED的状态翻转一次。

2.修改后,编译,烧录,重新上电。可以看到LED1差不多每隔2秒翻转一次,实现了我们想要的效果。

3)效果展示

TIMER2_LED

2、串口周期发送

1)配置项目

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

其他设置和1、中一样。

2)在keil配置代码

1.在main函数前定义全局变量
在这里插入图片描述
2.在main函数中设置接收中断
代码如下:

HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);

3.main函数中的while循环里面添加传输代码
在这里插入图片描述
4.在main函数下面重写中断处理函数
代码如下:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	
	//当输入的指令为0时,发送提示并改变flag
	if(c=='0'){
		flag=0;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2),0xFFFF); 
	}
	
	//当输入的指令为1时,发送提示并改变flag
	else if(c=='1'){
		flag=1;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips1, strlen(tips1),0xFFFF); 
	}
	
	//当输入不存在指令时,发送提示并改变flag
	else {
		flag=0;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips, strlen(tips),0xFFFF); 
	}

	//重新设置中断
		HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);  
}


5.打开野火助手发现每隔5s发送一次hello windows。

3)效果展示

hellowindows

二、日历时钟

1、了解时钟RTC并验证初始时间

1)RTC及其特征

RTC是个独立的定时器。RTC模块拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期 RTC还包含用于管理低功耗模式的自动唤醒单元。

RCT特征:
● 可编程的预分频系数:分频系数高为220。
● 32位的可编程计数器,可用于较长时间段的测量。
● 2个分离的时钟:用于APB1接口的PCLK1和RTC时钟(RTC时钟的频率必须小于PCLK1时钟 频率的四分之一以上)。
● 可以选择以下三种RTC的时钟源:
● HSE时钟除以128;
● LSE振荡器时钟;
● LSI振荡器时钟

● 2个独立的复位类型:
● APB1接口由系统复位;
● RTC核心(预分频器、闹钟、计数器和分频器)只能由后备域复位

● 3个专门的可屏蔽中断:
● 1.闹钟中断,用来产生一个软件可编程的闹钟中断。

● 2.秒中断,用来产生一个可编程的周期性中断信号(长可达1秒)。

● 3.溢出中断,指示内部可编程计数器溢出并回转为0的状态。

RTC时钟源:
三种不同的时钟源可被用来驱动系统时钟(SYSCLK):

● HSI振荡器时钟
● HSE振荡器时钟
● PLL时钟

这些设备有以下2种二级时钟源:

● 40kHz低速内部RC,可以用于驱动独立看门狗和通过程序选择驱动RTC。 RTC用于从停机/待机模式下自动唤醒系统。
● 32.768kHz低速外部晶体也可用来通过程序选择驱动RTC(RTCCLK)。

2)RTC原理框图

在这里插入图片描述

3)初始时间

在这里插入图片描述

4)验证

在这里插入图片描述

2、以 x年x月x日x分x秒的格式从串口输出

1)创建项目

1.配置RCC(设置高速外部时钟,使能外部晶振LSE)
在这里插入图片描述
2.配置RTC(激活时钟源(Activate Clock Source)和日历(Activate Calendar))
在这里插入图片描述
3.设置时间为2022/11/3 14:50
在这里插入图片描述
4.使能串口
在这里插入图片描述
5.时钟树配置
在这里插入图片描述
6.设置项目
在这里插入图片描述
在这里插入图片描述

2)添加代码

1.打开stm32f1xx_hal_rtc.h文件可以看到以下函数
在这里插入图片描述
在这里插入图片描述
2.在main.c文件中重写fputc函数,完成printf函数的重定向
代码如下:

//添加头文件#include "stdio.h"
int fputc(int ch,FILE *f){
 uint8_t temp[1]={ch};
 HAL_UART_Transmit(&huart1,temp,1,2);
 return ch;
}

3.在main.c中定义时间和日期的结构体用来获取时间和日期

RTC_DateTypeDef GetData;  //获取日期结构体

RTC_TimeTypeDef GetTime;   //获取时间结构体

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

4.在main函数的while循环中添加以下代码

/* Get the RTC current Time */
	    HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);
      /* Get the RTC current Date */
      HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN);

      /* Display date Format : yy/mm/dd */
      printf("%02d/%02d/%02d\r\n",2000 + GetData.Year, GetData.Month, GetData.Date);
      /* Display time Format : hh:mm:ss */
      printf("%02d:%02d:%02d\r\n",GetTime.Hours, GetTime.Minutes, GetTime.Seconds);

      printf("\r\n");

      HAL_Delay(1000);

如图:
在这里插入图片描述
接下来,编译并且烧录。
在这里插入图片描述

3)效果展示

在这里插入图片描述
输出的时间就是现在的时间。并且输出间隔是1s。

3、输出内容中加入“星期x”

1)添加代码

1.在下图所示位置后面加上以下代码
在这里插入图片描述
代码如下:

/* Display date Format : weekday */
		if(GetData.WeekDay==1){
			printf("星期一\r\n");
		}else if(GetData.WeekDay==2){
			printf("星期二\r\n");
		}else if(GetData.WeekDay==3){
			printf("星期三\r\n");
		}else if(GetData.WeekDay==4){
			printf("星期四\r\n");
		}else if(GetData.WeekDay==5){
			printf("星期五\r\n");
		}else if(GetData.WeekDay==6){
			printf("星期六\r\n");
		}else if(GetData.WeekDay==7){
			printf("星期日\r\n");
		}

2.编译烧录。

2)效果展示

在这里插入图片描述
正确输出了此时的星期数-----星期一。


总结

本次作业让我学会了如何通过定时器Timer方式实现时间的精准控制,了解了实时时钟RTC的原理,按年月日时分星期输出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值