一、STM32日历读取,设置和输出
1、实验目标
读取STM32F103C8T6 内部的时钟(年月日时分秒),日历(星期x),1秒周期,通过串口输出到PC上位机。
2、时钟RTC
一、什么是RTC
RTC(Real-time Clock):实时时钟,本质上是一个支持BCD编码的定时器/计数器。主电源断电后能够由电池供电,使其时钟跳转依然正常。
二、STM32F4芯片内的RTC功能
①日历时钟(时分秒、年月日、星期)
②两个闹钟——闹钟动作出发可支持中断
③定时唤醒功能(周期性唤醒)
④自动唤醒
⑤可以使用数字校准功能对晶振精度的偏差进行补偿。
⑥上电复位后,所有RTC寄存器都会受到保护,以防止可能的非正常写访问。
三、官方文档
1、RTC框图
LSE配置——RCC配置
异步通道分频器:1-128分频(RTC_PRER)
同步通道分频器:1-256分频(RTC_PRER)
日历寄存器:RTC_TR(时间寄存器),RTC_DR(日期寄存器)
RTC_SSR本质上是一个递减计数器:辅助更新日历
2、RTC初始化和配置(官方文档截取)
3、日历初始化配置
3、实验步骤
1、创建CubeMX
创建STM32F103C8工程
配置RCC(设置高速外部时钟,使能外部晶振LSE)
配置RTC(激活时钟源(Activate Clock Source)和日历(Activate Calendar))
设置时间为创建时间2023/11/25 20:26
使能串口
时钟树配置
之后正常创建keil项目
2、打开Keil项目,添加代码
在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;
}
在main.c中定义时间和日期的结构体用来获取时间和日期
RTC_DateTypeDef GetData; //获取日期结构体
RTC_TimeTypeDef GetTime; //获取时间结构体
在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);
添加输出星期几,在后面添加以下代码:
/* 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");
}
编译运行,效果如下:
二、数字温湿度计
1、实验目标
读取AHT20的温度和湿度,通过OLED,把年月份时分秒、日历和实时温度、湿度显示出来,2秒周期。
2、代码撰写
1、工程建立
本实验采用标准库进行操作,首先打开Keil建立工程,在工程文件中添加文件。
2、编写代码
(1)dht11.c代码:
#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;
Delay_ms(20);
dht11_high;
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++)
{
while( Read_Data == 0);
Delay_us(30);
data <<= 1;
if( Read_Data == 1 )
{
data |= 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 )
{
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();
dht11_low;
Delay_us(55);
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;
}
dht11.h代码:
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h" // Device header
#define dht11_high GPIO_SetBits(GPIOB, GPIO_Pin_12) //GPIOB,GPIO_PIN_13
#define dht11_low GPIO_ResetBits(GPIOB, GPIO_Pin_12)
#define Read_Data GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12)
void DHT11_GPIO_Init_OUT(void);
void DHT11_GPIO_Init_IN(void);
void DHT11_Start(void);
unsigned char DHT11_REC_Byte(void);
void DHT11_REC_Data(void);
#endif
(2)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=15;
int min=40;
int s=0;
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[2]-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);
}
}