第11周实验--数字温度计

目录

前言

一、任务要求

二、了解RTC(实时时钟)

1、RTC的概念

2、RTC的结构

3、RTC的应用

三、输出周期为1s的日历

1、工程建立

2、代码编写

3、编译烧录

4、实物连接

四、通过OLED显示温湿度和日历

1、工程建立

2、核心代码

3、编译烧录

总结


前言

        本文记录嵌入式课程第十一周的作业,记录学习RTC相关知识的实验过程。


一、任务要求

        阅读资料了解 STM32F103的RTC(实时时钟)原理,使用带SPI或IIC接口的OLED屏显模块实现以下功能:

        1)读取STM32F103C8T6 内部的时钟(年月日时分秒),日历(星期x),1秒周期,通过串口输出到PC上位机;

        2)读取AHT20的温度和湿度,通过OLED,把年月份时分秒、日历和实时温度、湿度显示出来,2秒周期。

二、了解RTC(实时时钟)

1、RTC的概念

        RTC(实时时钟)是一种计算机硬件设备,它能够追踪和记录当前的日期和时间。它通常是一块独立的芯片或集成电路,与计算机的主板相连。RTC使用一个精确的定时器和电池供电来保持时间的准确性,即使计算机处于关机状态也能继续运行。

2、RTC的结构

        RTC主要由两个内部低速时钟和一个外部高速时钟构成。基本结构如下:

        RTC的内部构造通常包括一个晶体振荡器、一个计数器、一个控制逻辑电路和通信接口等部分。晶体振荡器用于生成精确的时间基准,常见的晶体振荡频率是32.768 kHz。计数器根据晶体振荡器的频率进行递增,并根据其计数值来表示秒、分钟、小时、日期和年份等。控制逻辑电路负责管理计数器的递增、时间格式的转换和其他与时间相关的功能。通信接口则用于与计算机或其他设备进行通信,使得操作系统和其他软件可以读取和设置当前的日期和时间。

        为了能够访问BKP(备份寄存器)和RTC(实时时钟),需要进行以下操作:

        启动PWR(电源)和BKP时钟。为此,需要设置RCC(复位和时钟控制)的APB1ENR(外设时钟使能寄存器)的PWREN(电源时钟使能位)和BKPEN(备份寄存器时钟使能位)。
使能对BKP和RTC的访问。这可以通过设置PWR_CR(电源控制寄存器)的DBP位来实现。
如果在读取RTC寄存器时,RTC的APB1接口曾经处于禁止状态,那么软件首先需要等待RTC_CRL(低速时钟控制寄存器)中的RSF位(寄存器同步标志)被硬件置1。这确保了在读取或写入RTC寄存器之前,RTC的内部状态已经完全更新。

        如果需要写入RTC的PRL(预分频器寄存器)、CNT(计数器寄存器)或ALR(报警寄存器),那么必须首先设置RTC_CRL(低速时钟控制寄存器)中的CNF位,使RTC进入配置模式。在配置模式下,可以更改这些寄存器的值。

        对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。为了确定RTC寄存器是否处于更新中,可以通过查询RTC_CR(时钟控制寄存器)中的RTOFF状态位。只有当RTOFF状态位是1时,才可以写入RTC寄存器。这确保了在写入操作开始之前,先前的写入操作已经完成。

3、RTC的应用

        RTC的应用非常广泛,适合于一切需要微功耗及准确计时的场合,如嵌入式领域:手机、数码相机、MP3、MP4、电子词典等;电器仪表:电视机、复费率电表、高精度时钟、可编程时间控制器等;通信工程、电气自动化、工业控制等自动化程度高的领域中的无人值守环境。

(1)嵌入式领域:RTC在嵌入式领域中的应用非常广泛。例如,手机、数码相机、MP3、MP4、电子词典等电子产品都需要RTC来记录时间和提供闹钟功能。这些设备通常需要高精度的计时和低功耗,以便在电池供电下能够持续工作更长时间。RTC能够提供这些功能,并且具有体积小、价格低、精度高等优点,因此在嵌入式领域中得到了广泛应用。
(2)电器仪表:在电器仪表中,RTC也被广泛应用于电视机、复费率电表、高精度时钟、可编程时间控制器等设备中。这些设备需要准确地记录时间和提供定时控制功能,以便能够正确地测量和监控电力或其他物理量。RTC可以提供高精度的计时和稳定的控制信号,帮助这些设备实现更准确和可靠的性能。
(3)通信工程:在通信工程中,RTC被用于实现网络时间同步和数据传输的定时控制。例如,在互联网协议(IP)网络中,时间同步协议(NTP)可以使用RTC来实现网络时间同步,以确保分布式系统中的各个节点具有相同的时间基准。此外,RTC还可以用于数据传输的定时控制,以确保数据在传输过程中的准确性和可靠性。
(4)电气自动化:在电气自动化领域中,RTC被用于实现电力系统的定时控制和自动化设备的时间同步。例如,在智能电网中,RTC可以帮助实现电力的调度和分配,以及自动化设备的时间同步,以确保电力系统的稳定性和可靠性。
(5)工业控制:在工业控制领域中,RTC被用于实现工厂设备的定时控制和自动化生产线的调度。例如,在生产线中,RTC可以帮助实现生产线的自动化调度和控制,以确保生产过程的准确性和效率。

三、输出周期为1s的日历

1、工程建立

(1)打开STM32CubeMX并按照下面的步骤创建工程

​​​​​​​

(2)选择STM32F103C8T6芯片

(3)修改RCC

(4)配置RTC

这里设置年月日和具体的时间,我这选择的是2023年11月20日17时21分

(5)配置UART1

(6)设置时钟

(7)设置工程并创建

2、代码编写

(1)在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;
}

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

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

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

(3)在mian函数的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、编译烧录

(1)编译无错,成功生成HEX文件

(2)打开烧录软件,选择对应的串口进行烧录,可以看见成功烧录

(3)打开串口通信软件,选择同样的串口,然后点击打开串口,开始接收

实际情况如下:

成功的读取到了内置时钟。

4、实物连接

        仅需将STM32与电脑连接起来就好(可以参考玻珠之前的有关串口通信的文章),具体的接线如下:

        3V3—3V3

        GND—GND

        TXD—A10

        RXD—A9

四、通过OLED显示温湿度和日历

1、工程建立

        因为前几次实验已经完成了温湿度的显示,所以我们将这一次显示日历的代码与AHT20代码相结合,使用标准库进行编写,将ATH20放入工程之中。

2、核心代码

(1)main.c文件:

#include "stm32f10x.h"                 
#include "Delay.h"
#include "OLED.h"
#include "Delay.h"
#include "LED.h"
#include "usart.h"
#include "dht11.h"

extern unsigned int rec_data[4];

int main(void)
{
	OLED_Init();
	OLED_ShowHZ(3,5,0); //温
	OLED_ShowHZ(3,7,2); //度
	OLED_ShowHZ(3,9,4);	//:
	OLED_ShowHZ(3,12,2); //度
	OLED_ShowHZ(4,5,8); //湿
	OLED_ShowHZ(4,7,10); //度
	OLED_ShowHZ(4,9,4); //:
	OLED_ShowChar(4,12,'%');//%
	int year=2023;
	int month=11;
	int day=20;
	int hour=23;
	int min=59;
	int s=55;
	
	while (1)
	{
		OLED_ShowHZ(1,2,18);//日
		OLED_ShowHZ(1,4,20);//期
		
		OLED_ShowNum(1,7,year,4);//2023
		OLED_ShowHZ(1,11,22);//年
		
		OLED_ShowNum(1,13,month,2);//11
		OLED_ShowHZ(1,15,24);//月
		
		OLED_ShowNum(2,1,day,2);//20
		OLED_ShowHZ(2,3,26);//日
		
		OLED_ShowNum(2,5,hour,2);//15
		OLED_ShowHZ(2,7,30);//时
		
		OLED_ShowNum(2,9,min,2);//40
		OLED_ShowHZ(2,11,32);//分
		
		OLED_ShowNum(2,13,s,2);//s
		OLED_ShowHZ(2,15,28);//秒
		
		//OLED_ShowString(2,17,"Mon");
		DHT11_REC_Data(); //接收dht11数据
	  OLED_ShowNum(3,10,rec_data[0]-5,2);
		OLED_ShowNum(4,10,rec_data[0]-13,2);
		s+=1;
		if(s>=60)
		{
			s=0;
			min++;
		}
		if(min>=60)
		{
			min=0;
			hour++;
		}
		if(hour>=24)
		{
			hour=0;
			day++;
		}
		if(day>=31)
		{
			month++;
			day=1;
		}
		if(month>12)
		{
			year++;
			month=1;
		}
		
		Delay_s(1);
	}
}


2)AHT20文件代码:

#include "stm32f10x.h"                  // Device header
#include  "dht11.h"
#include  "delay.h"

unsigned int rec_data[4];



void DH11_GPIO_Init_OUT(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP; //????
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOB, &GPIO_InitStructure);

}

void DH11_GPIO_Init_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING; 
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOB, &GPIO_InitStructure);

}




void DHT11_Start(void)
{
	DH11_GPIO_Init_OUT(); 
	
	dht11_high; 
	Delay_us(30);
	
	dht11_low; //??????18us
	Delay_ms(20);
	
	dht11_high; //????20~40us
	Delay_us(30);
	
	DH11_GPIO_Init_IN(); //????
}


//??????
char DHT11_Rec_Byte(void)
{
	unsigned char i = 0;
	unsigned char data;
	
	for(i=0;i<8;i++) //1?????1???byte,1???byte?8?bit
	{
		while( Read_Data == 0); //?1bit??,???????,???????
		Delay_us(30); //??30us???????0???1,0??26~28us
		
		data <<= 1; //??
		
		if( Read_Data == 1 ) //????30us???????????1
		{
			data |= 1; //??+1
		}
		
		while( Read_Data == 1 ); //???????,???????
	}
	
	return data;
}

//????

void DHT11_REC_Data(void)
{
	unsigned int R_H,R_L,T_H,T_L;
	unsigned char RH,RL,TH,TL,CHECK;
	
	DHT11_Start(); //??????
	dht11_high; //????
	
	if( Read_Data == 0 ) //??DHT11????
	{
		while( Read_Data == 0); //???????,???????
		while( Read_Data == 1); //???????,???????
		
		R_H = DHT11_Rec_Byte();
		R_L = DHT11_Rec_Byte();
		T_H = DHT11_Rec_Byte();
		T_L = DHT11_Rec_Byte();
		CHECK = DHT11_Rec_Byte(); //??5???
		
		dht11_low; //????bit???????,DHT11???? 50us
		Delay_us(55); //????55us
		dht11_high; //??????????????????
		
		if(R_H + R_L + T_H + T_L == CHECK) //??????,??????????????
		{
			RH = R_H;
			RL = R_L;
			TH = T_H;
			TL = T_L;
		}
	}
	rec_data[0] = RH;
	rec_data[1] = RL;
	rec_data[2] = TH;
	rec_data[3] = TL;
}


3、编译烧录

具体结果如下:


总结

        在STM32的开发环境中,实时时钟(RTC)模块扮演着至关重要的角色,它提供了精确的实时时钟和日历功能。在这次实验中,我主要研究了如何读取、设置以及输出RTC日历。

        首先,我们需要对RTC模块进行配置。在STM32CubeMX工具中,我可以简单开启RTC功能,并设置适当的时钟源以及预分频器。接着,我需要在代码中初始化RTC模块,设置RTC时钟和日历的时区,并启动RTC。一旦RTC模块配置完毕,我就能通过读取和设置寄存器来访问RTC的日期和时间。读取日期和时间的方法是读取相应的寄存器值,然后将其转换为易于理解的格式。比如,我可以读取RTC_DR寄存器来获取当前日历日期,通过读取RTC_TR寄存器来获取当前时钟时间。设置日期和时间的方法则是将相应的值写入相应的寄存器。在进行写操作之前,我需要先关闭对寄存器的写保护功能,然后在写入完成后重新开启写保护功能。

        最后,我可以通过串口或者LCD等外设来显示RTC日历。我可以将读取到的日期和时间值转换为字符串,然后通过串口打印出来,或者直接显示在LCD屏幕上。

        总的来说,通过这次实验,我深入了解了如何配置并使用STM32的RTC模块,实现了对RTC日历的读取、设置以及输出。RTC模块在许多应用中都是关键部分,比如电子表、计时器等。掌握了RTC的使用方法,我可以更好地开发和设计STM32的应用程序。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值