打印
[STM32F1]

STM32F103C8T6配置RTC显示年月日时分秒(日历)

[复制链接]
1082|38
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
g36xcv|  楼主 | 2023-11-24 00:13 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
RTC介绍一、主要框图




使用特权

评论回复
沙发
g36xcv|  楼主 | 2023-11-24 00:14 | 只看该作者
二、介绍
RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。
RTC 模块和时钟配置系统 (RCC_BDCR 寄存器 ) 处于后备区域,即在系统复位或从待机模式唤醒
后, RTC 的设置和时间维持不变。
系统复位后,对后备寄存器和 RTC 的访问被禁止,这是为了防止对后备区域 (BKP) 的意外写操
作。执行以下操作将使能对后备寄存器和 RTC 的访问:
● 设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备接口时钟
● 设置寄存器PWR_CR的DBP位,使能对后备寄存器和RTC的访问。
● 可以选择以下三种 RTC 的时钟源:
─ HSE 时钟除以 128 ;
─ LSE振荡器时钟;
─ LSI 振荡器时钟 ( 详见 6.2.8
308/754
节 RTC 时钟 ) 。
● 2 个独立的复位类型:
─ APB1 接口由系统复位;
─ RTC 核心 ( 预分频器、闹钟、计数器和分频器 ) 只能由后备域复位 。
● 3 个专门的可屏蔽中断:
─ 闹钟中断,用来产生一个软件可编程的闹钟中断。
─ 秒中断 ,用来产生一个可编程的周期性中断信号 ( 最长可达 1 秒 ) 。
─ 溢出中断,指示内部可编程计数器溢出并回转为 0 的状态。

使用特权

评论回复
板凳
g36xcv|  楼主 | 2023-11-24 00:14 | 只看该作者
2、主要模块
一、rtc文件
RTC初始化配置
RTC_NVIC配置
备份区域识别--BKP
设置时间
将时间放进Setcounter()---Time_Adjust()函数
获取时间
把参数放进时间结构体
显示时间
判断闰年
RTC中断服务函数
printf重定向,重写fputc函数

使用特权

评论回复
地板
g36xcv|  楼主 | 2023-11-24 00:15 | 只看该作者
系统文件
系统文件system

使用特权

评论回复
5
g36xcv|  楼主 | 2023-11-24 00:15 | 只看该作者
库文件

使用特权

评论回复
6
g36xcv|  楼主 | 2023-11-24 00:16 | 只看该作者
用户文件

使用特权

评论回复
7
g36xcv|  楼主 | 2023-11-24 00:16 | 只看该作者
自编程序

使用特权

评论回复
8
g36xcv|  楼主 | 2023-11-24 00:16 | 只看该作者
3、代码框架
4个,主函数,延时,串口,rtc
4个.h文件中实现函数的声明,定义
将printf重写函数写进rtc.c中
主函数只有初始化函数调用和时间显示函数,时间显示函数在while(1)里

使用特权

评论回复
9
g36xcv|  楼主 | 2023-11-24 00:17 | 只看该作者
4、RTC配置
如果忘记如何配置查看STM32f103固件库参考手册和数据手册实例,有详细的步骤

使能电源PWR,后备区域BKP
允许访问备份区域
备份域复位
使能外部低速时钟LSE
等待LSE稳定(这里while循环可能会被卡死)
选择LSE作为RTC时钟源
使能RTC时钟
等待上一次操作完成
等待寄存器与APB1时钟同步,因为RTC时钟是低速的,内环时钟是高速的,所以要同步(这里很可能会卡死)
等待上一次操作完成
使能RTC秒中断
等待上一次操作完成
设置预分配寄存器周期1s
等待上一次操作完成

使用特权

评论回复
10
g36xcv|  楼主 | 2023-11-24 00:17 | 只看该作者
5、重写printf
#include <stdio.h>
#if 1
//关闭半主机模式
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE{
int handle;
};
FILE __stdin, __stdout, __stderr;
//FILE __stdin;
//避免使用半主机模式
void _sys_exit(int x)
{
x=x;
}


/*重写fputc*/
int fputc(int ch, FILE *f)
{
       
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);  //通过串口把ch给发送出去
        USART_SendData(USART1,ch);
        return ch;
}

使用特权

评论回复
11
g36xcv|  楼主 | 2023-11-24 00:18 | 只看该作者
6、时间设置Set
时间是从1970年1月1日00:00: 00开始

1970-到现在经过的天数,一天60*60*24=86400秒

不足一天的按,时*3600+分*60+秒=second

second+经过的天数*86400=所有的秒

?那一年经过多少天呢 ?是365还是366?             答:就需要一个判断年是不是闰年的函数

用一个临时自增变量记录年份,每判断一个年份就自增,直到2023

剩下不足一年的按照月份统计天数

?二月 ?是28还是29于是又一次用判断闰年函数,每一次加数字太繁琐,使用数组装下每个月的天数,用一个for循环方便。month_table[12]={31,28,31,30,31,30,31,31,30,31,30,31}

返回类型uint32_t,将此函数放于RTC_SetCounter(时间设置函数Set) ,后面请看代码

使用特权

评论回复
12
g36xcv|  楼主 | 2023-11-24 00:18 | 只看该作者
7、时间Get获取
通过RTC_GetCounter()获得放在寄存器的秒,将所有秒/86400得到所有的天数days,从1970判断是不是闰年直到2023,是闰年days-366不是就days-365。不足一天的秒如何得到?答:所有秒%86400.一天中的时就(秒%86400)/3600=时,((秒%86400)%3600)/60=分,(秒%86400)%3600)%60=second,将获得的年月日放进我们设置的结构体时间里

使用特权

评论回复
13
g36xcv|  楼主 | 2023-11-24 00:18 | 只看该作者
8、核心代码
1、rtc.h
#ifndef _RTC_H
#define _RTC_H
#include <stm32f10x.h>
#include <stdio.h>

//时间结构体
typedef struct{
     uint16_t year;
           uint8_t month;
           uint8_t day;
           uint8_t hour;
           uint8_t minute;
           uint8_t second;

}cal;
extern cal calendar;
extern int const month_table[12] ;


void clockinit_RTC(void);
void RTC_NVIC_Config(void);
void rtc_init(void);
uint32_t rtc_timeSet(uint16_t syear,uint8_t smonth,uint8_t sdays,uint8_t shour,uint8_t sminute,uint8_t ssecond);
void Time_Adjust(void);
uint8_t rtc_timeGet(void);
int IS_temp_year(uint16_t year);
void Time_Show(void);
void Time_Display(uint32_t time);
void Time_Display2(void);
#endif

使用特权

评论回复
14
g36xcv|  楼主 | 2023-11-24 00:18 | 只看该作者
2、rtc.c
#include "rtc.h"
#if 1
//关闭半主机模式
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE{
int handle;
};
FILE __stdin, __stdout, __stderr;
//FILE __stdin;
//避免使用半主机模式
void _sys_exit(int x)
{
x=x;
}


/*重写fputc*/
int fputc(int ch, FILE *f)
{
       
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);  //通过串口把ch给发送出去
        USART_SendData(USART1,ch);
        return ch;
}

int fgetc(FILE *f){
   char ch;
         while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET);
   ch=USART_ReceiveData(USART1);
         return (int)ch;
}
int ferror(FILE * f){
  return EOF;
}
void _ttywrch(int ch){
   while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
         USART_SendData(USART1,ch);
}
//void _sys_exit(int return_code){
//  while(1);
//}
#endif

cal calendar;
int const month_table[12] ={31,28,31,30,31,30,31,31,30,31,30,31};
__IO uint8_t TimeDisplay;
//RTC内设配置
void rtc_init(){
          uint32_t t;
    //使能rcu_bkpi时钟,pwr电源,bkp后备区域
          RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP,ENABLE);
          //使能备份区域,允许访问备份(Backup)区域
          PWR_BackupAccessCmd(ENABLE);
       
    //备份域复位
          BKP_DeInit();
          //使能外部低速时钟,32.768k
          RCC_LSEConfig(RCC_LSE_ON);       
          //等待外部低速时钟稳定  
          while((RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)&& (t<10)){
                   t++;
                }
          //选择LSE作为RTC的时钟源       
          RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);       
          //使能RTC时钟
          RCC_RTCCLKCmd(ENABLE);
               
          //等待RTC最后一次操作完成
    RTC_WaitForLastTask();       
               
          //等待寄存器与APB1时钟同步,因为RTC时钟是低速的,内环时钟是高速的,所以要同步
          RTC_WaitForSynchro();
          //等待RTC最后一次操作完成
    RTC_WaitForLastTask();       
          //使能RTC的秒中断
                RTC_ITConfig(RTC_IT_SEC,ENABLE);
                //等待RTC最后一次操作完成
                RTC_WaitForLastTask();
                //设置预分频寄存器,时间周期是1秒 = 32.768k/32768+1--------(RTCCLK/RTC_PR)
                RTC_SetPrescaler(32768-1);
                //等待RTC最后一次操作完成
                RTC_WaitForLastTask();
}

void RTC_NVIC_Config(void){
        NVIC_InitTypeDef NVIC_InitStructure;
        //设置优先级组为1,抢占1位(0-1),从3位(0-7)
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
        //设置优先级通道
        NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
}

void clockinit_RTC(){
        RTC_NVIC_Config();
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP,ENABLE);
        PWR_BackupAccessCmd(ENABLE);
        //识别是不是后背备份区域
  if(BKP_ReadBackupRegister(BKP_DR1)!=0XA5A5){
                //通过判断后背寄存器的值来判断是否是系统第一次上电
                printf("RTC没有被配置过");
                //是的话就进行RTC配置,设置初试时间
          rtc_init();
                printf("RTC正在配置");
                Time_Adjust();
                BKP_WriteBackupRegister(BKP_DR1,0xA5A5);

        }else{
                //看是否是系统掉电
                if(RCC_GetFlagStatus(RCC_FLAG_PORRST)!=RESET){
                  printf("Power On Resetm occurred...");
                }
                //看是否是复位引脚引起的复位
                else if(RCC_GetFlagStatus(RCC_FLAG_PINRST)!=RESET){
                  printf("External Reset occured...");
                }
                printf("No need to configure RTC...");
          RTC_WaitForSynchro();
                RTC_ITConfig(RTC_IT_SEC,ENABLE);
                RTC_WaitForLastTask();
        }
                RCC_ClearFlag();
                Time_Show();       
}
//RTC初始化(配置函数,Set引参,Get获得时间)

//设置时间函数
void Time_Adjust(void){
   //等待RTC最后一次操作完成
    RTC_WaitForLastTask();
                 //将秒数存取寄存器
          RTC_SetCounter(rtc_timeSet(2023,9,22,14,30,0));
          //等待RTC最后一次操作完成
    RTC_WaitForLastTask();
}
//用设置的时间去获得秒,我们使用秒中断       
uint32_t rtc_timeSet(uint16_t syear,uint8_t smonth,uint8_t sdays,uint8_t shour,uint8_t sminute,uint8_t ssecond){
                         
    uint16_t old_year=1970;
         //uint32_t all_second=0;
          uint16_t days=0;
          uint8_t month=0;
          uint32_t second=0;
        //时间大于一年的计算
        while(old_year<syear){
          if(IS_temp_year(old_year)){
            days +=        366;                       
          }else{
            days +=365;
          }       
                old_year++;
        }
        //时间不足一年的计算
  for(;month<smonth;month++){
                if(!IS_temp_year(syear)){
                   days += month_table[month];
                }else{
                   if(month==1){
                            days = days + month_table[month]+1;
                         }else{
                            days += month_table[month];
                         }
                }   
        }
        days += sdays;
        //得到年月日的秒数,一天有86400秒
        second = days * 86400;
        //不足一天的秒数--时
        second +=shour * 3600;
  //不足一天的秒数--分
        second += sminute * 60;
        //不足一天的秒数--秒
        second += ssecond;
  return second;
       
}
//用得到的秒数去计算现在的日期
uint8_t rtc_timeGet(){
  uint32_t getsecond = RTC_GetCounter();
        uint16_t gyear = 1970;
        uint16_t gdays = 0;
        uint8_t gmonth = 0;
        uint8_t ghour = 0;
        uint8_t gminute = 0;
        uint16_t gsecond = 0;
       
        gdays = getsecond / 86400;
        while(gdays < 365){
           if(IS_temp_year(gyear)){
                    gdays -= 366;
                 }else{
                    gdays -= 365;
                 }
                 gyear++ ;
        }
       
        while(gdays >= 28){
                        if(IS_temp_year(gyear)){
                           gdays = gdays - month_table[gmonth]-1;
                        }else{
                           gdays -= month_table[gmonth];
                        }
            gmonth++ ;
         }
        calendar.year = gyear;
        calendar.month = gmonth;
        calendar.day = (uint8_t)gdays;
        //不足一天的秒数
        gsecond = getsecond % 86400 ;
        ghour = gsecond / 3600;
        gminute = (gsecond % 3600) / 60;
        gsecond = (gsecond % 3600) %60 ;
  calendar.hour = ghour;
        calendar.minute = gminute;
        calendar.second = (uint8_t)gsecond;
        return 0;

}
//判断现在的年份是不是闰年
int IS_temp_year(uint16_t year){
   if(year%4==0){
            if(year%100!=0){
                            return 1;
                        }else{
                            return 0;
                        }
         
         }else{
           if(year%400==0){
                    return 1;
                 }else{
                    return 0;
                 }
         }
}
void Time_Show(void){
        printf("\n\r");
   while(1){
                 //秒标志位
           if(TimeDisplay == 1){
                         //Time_Display(RTC_GetCounter());
                         Time_Display2();
                         TimeDisplay = 0;
                 }
         
         }

}

void Time_Display(uint32_t time){
    uint32_t hh=0,mm=0,ss=0;
        /*当时间走到23:59:59,RTC复位,计数值清零*/
        if(RTC_GetCounter() == 0x0001517f){  //(23*3600=82800)+(59*60=3540)+(59)=86399变十六进制是0x0001517f
           RTC_SetCounter(0x0);
                RTC_WaitForLastTask();
        }
        hh=time/3600;
        mm=(time%3600)/60;
        ss=(time%3600)%60;
}
void RTC_IRQHandler(void){
        //秒中断是否开启
   if(RTC_GetITStatus(RTC_IT_SEC)==SET){
                 /*清除秒中断标识位*/
                 RTC_ClearITPendingBit(RTC_IT_SEC);
                 /*置1s标志位*/
                 TimeDisplay=1;
                 RTC_WaitForLastTask();
//                 //显示时间
//                 Time_Display2();
                 
         }
         RTC_WaitForLastTask();

}
void Time_Display2(void){
   rtc_timeGet();
   printf("Now time is: %d-%d-%d %d:%d:%d\r\n", calendar.year, calendar.month, calendar.day, calendar.hour, calendar.minute, calendar.second);
}

使用特权

评论回复
15
g36xcv|  楼主 | 2023-11-24 00:19 | 只看该作者
2、rtc.c
#include "rtc.h"
#if 1
//关闭半主机模式
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE{
int handle;
};
FILE __stdin, __stdout, __stderr;
//FILE __stdin;
//避免使用半主机模式
void _sys_exit(int x)
{
x=x;
}


/*重写fputc*/
int fputc(int ch, FILE *f)
{
       
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);  //通过串口把ch给发送出去
        USART_SendData(USART1,ch);
        return ch;
}

int fgetc(FILE *f){
   char ch;
         while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET);
   ch=USART_ReceiveData(USART1);
         return (int)ch;
}
int ferror(FILE * f){
  return EOF;
}
void _ttywrch(int ch){
   while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
         USART_SendData(USART1,ch);
}
//void _sys_exit(int return_code){
//  while(1);
//}
#endif

cal calendar;
int const month_table[12] ={31,28,31,30,31,30,31,31,30,31,30,31};
__IO uint8_t TimeDisplay;
//RTC内设配置
void rtc_init(){
          uint32_t t;
    //使能rcu_bkpi时钟,pwr电源,bkp后备区域
          RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP,ENABLE);
          //使能备份区域,允许访问备份(Backup)区域
          PWR_BackupAccessCmd(ENABLE);
       
    //备份域复位
          BKP_DeInit();
          //使能外部低速时钟,32.768k
          RCC_LSEConfig(RCC_LSE_ON);       
          //等待外部低速时钟稳定  
          while((RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)&& (t<10)){
                   t++;
                }
          //选择LSE作为RTC的时钟源       
          RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);       
          //使能RTC时钟
          RCC_RTCCLKCmd(ENABLE);
               
          //等待RTC最后一次操作完成
    RTC_WaitForLastTask();       
               
          //等待寄存器与APB1时钟同步,因为RTC时钟是低速的,内环时钟是高速的,所以要同步
          RTC_WaitForSynchro();
          //等待RTC最后一次操作完成
    RTC_WaitForLastTask();       
          //使能RTC的秒中断
                RTC_ITConfig(RTC_IT_SEC,ENABLE);
                //等待RTC最后一次操作完成
                RTC_WaitForLastTask();
                //设置预分频寄存器,时间周期是1秒 = 32.768k/32768+1--------(RTCCLK/RTC_PR)
                RTC_SetPrescaler(32768-1);
                //等待RTC最后一次操作完成
                RTC_WaitForLastTask();
}

void RTC_NVIC_Config(void){
        NVIC_InitTypeDef NVIC_InitStructure;
        //设置优先级组为1,抢占1位(0-1),从3位(0-7)
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
        //设置优先级通道
        NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
}

void clockinit_RTC(){
        RTC_NVIC_Config();
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP,ENABLE);
        PWR_BackupAccessCmd(ENABLE);
        //识别是不是后背备份区域
  if(BKP_ReadBackupRegister(BKP_DR1)!=0XA5A5){
                //通过判断后背寄存器的值来判断是否是系统第一次上电
                printf("RTC没有被配置过");
                //是的话就进行RTC配置,设置初试时间
          rtc_init();
                printf("RTC正在配置");
                Time_Adjust();
                BKP_WriteBackupRegister(BKP_DR1,0xA5A5);

        }else{
                //看是否是系统掉电
                if(RCC_GetFlagStatus(RCC_FLAG_PORRST)!=RESET){
                  printf("Power On Resetm occurred...");
                }
                //看是否是复位引脚引起的复位
                else if(RCC_GetFlagStatus(RCC_FLAG_PINRST)!=RESET){
                  printf("External Reset occured...");
                }
                printf("No need to configure RTC...");
          RTC_WaitForSynchro();
                RTC_ITConfig(RTC_IT_SEC,ENABLE);
                RTC_WaitForLastTask();
        }
                RCC_ClearFlag();
                Time_Show();       
}
//RTC初始化(配置函数,Set引参,Get获得时间)

//设置时间函数
void Time_Adjust(void){
   //等待RTC最后一次操作完成
    RTC_WaitForLastTask();
                 //将秒数存取寄存器
          RTC_SetCounter(rtc_timeSet(2023,9,22,14,30,0));
          //等待RTC最后一次操作完成
    RTC_WaitForLastTask();
}
//用设置的时间去获得秒,我们使用秒中断       
uint32_t rtc_timeSet(uint16_t syear,uint8_t smonth,uint8_t sdays,uint8_t shour,uint8_t sminute,uint8_t ssecond){
                         
    uint16_t old_year=1970;
         //uint32_t all_second=0;
          uint16_t days=0;
          uint8_t month=0;
          uint32_t second=0;
        //时间大于一年的计算
        while(old_year<syear){
          if(IS_temp_year(old_year)){
            days +=        366;                       
          }else{
            days +=365;
          }       
                old_year++;
        }
        //时间不足一年的计算
  for(;month<smonth;month++){
                if(!IS_temp_year(syear)){
                   days += month_table[month];
                }else{
                   if(month==1){
                            days = days + month_table[month]+1;
                         }else{
                            days += month_table[month];
                         }
                }   
        }
        days += sdays;
        //得到年月日的秒数,一天有86400秒
        second = days * 86400;
        //不足一天的秒数--时
        second +=shour * 3600;
  //不足一天的秒数--分
        second += sminute * 60;
        //不足一天的秒数--秒
        second += ssecond;
  return second;
       
}
//用得到的秒数去计算现在的日期
uint8_t rtc_timeGet(){
  uint32_t getsecond = RTC_GetCounter();
        uint16_t gyear = 1970;
        uint16_t gdays = 0;
        uint8_t gmonth = 0;
        uint8_t ghour = 0;
        uint8_t gminute = 0;
        uint16_t gsecond = 0;
       
        gdays = getsecond / 86400;
        while(gdays < 365){
           if(IS_temp_year(gyear)){
                    gdays -= 366;
                 }else{
                    gdays -= 365;
                 }
                 gyear++ ;
        }
       
        while(gdays >= 28){
                        if(IS_temp_year(gyear)){
                           gdays = gdays - month_table[gmonth]-1;
                        }else{
                           gdays -= month_table[gmonth];
                        }
            gmonth++ ;
         }
        calendar.year = gyear;
        calendar.month = gmonth;
        calendar.day = (uint8_t)gdays;
        //不足一天的秒数
        gsecond = getsecond % 86400 ;
        ghour = gsecond / 3600;
        gminute = (gsecond % 3600) / 60;
        gsecond = (gsecond % 3600) %60 ;
  calendar.hour = ghour;
        calendar.minute = gminute;
        calendar.second = (uint8_t)gsecond;
        return 0;

}
//判断现在的年份是不是闰年
int IS_temp_year(uint16_t year){
   if(year%4==0){
            if(year%100!=0){
                            return 1;
                        }else{
                            return 0;
                        }
         
         }else{
           if(year%400==0){
                    return 1;
                 }else{
                    return 0;
                 }
         }
}
void Time_Show(void){
        printf("\n\r");
   while(1){
                 //秒标志位
           if(TimeDisplay == 1){
                         //Time_Display(RTC_GetCounter());
                         Time_Display2();
                         TimeDisplay = 0;
                 }
         
         }

}

void Time_Display(uint32_t time){
    uint32_t hh=0,mm=0,ss=0;
        /*当时间走到23:59:59,RTC复位,计数值清零*/
        if(RTC_GetCounter() == 0x0001517f){  //(23*3600=82800)+(59*60=3540)+(59)=86399变十六进制是0x0001517f
           RTC_SetCounter(0x0);
                RTC_WaitForLastTask();
        }
        hh=time/3600;
        mm=(time%3600)/60;
        ss=(time%3600)%60;
}
void RTC_IRQHandler(void){
        //秒中断是否开启
   if(RTC_GetITStatus(RTC_IT_SEC)==SET){
                 /*清除秒中断标识位*/
                 RTC_ClearITPendingBit(RTC_IT_SEC);
                 /*置1s标志位*/
                 TimeDisplay=1;
                 RTC_WaitForLastTask();
//                 //显示时间
//                 Time_Display2();
                 
         }
         RTC_WaitForLastTask();

}
void Time_Display2(void){
   rtc_timeGet();
   printf("Now time is: %d-%d-%d %d:%d:%d\r\n", calendar.year, calendar.month, calendar.day, calendar.hour, calendar.minute, calendar.second);
}

使用特权

评论回复
16
g36xcv|  楼主 | 2023-11-24 00:20 | 只看该作者
3、usart.h
#ifndef _USART_H
#define _USART_H

#include <stm32f10x.h>
#include <stdio.h>

void usart_init(uint32_t bound);
void USART_SendString(uint8_t *ch);
void usart_byte(uint8_t ch);
void usart_buf(uint8_t *buf,uint8_t len);
#endif

使用特权

评论回复
17
g36xcv|  楼主 | 2023-11-24 00:20 | 只看该作者
3、usart.h
#ifndef _USART_H
#define _USART_H

#include <stm32f10x.h>
#include <stdio.h>

void usart_init(uint32_t bound);
void USART_SendString(uint8_t *ch);
void usart_byte(uint8_t ch);
void usart_buf(uint8_t *buf,uint8_t len);
#endif

使用特权

评论回复
18
g36xcv|  楼主 | 2023-11-24 00:20 | 只看该作者
4、usart.c
#include <usart.h>

//FILE _stdout;
//_sys_exit(int x)
//{
//  x=x;

//}
//int fputc(int ch,FILE *f)
//{
//   while((USART1->SR&0x40)==0);
//        USART1->DR=(u8) ch;
//        return ch;
//}
//int fputc(int ch, FILE *f)
//{
//        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);  //通过串口把ch给发送出去
//        USART1_SendData(USART1,ch);
//        return ch;
//}



void usart_init(uint32_t bound)
{
   GPIO_InitTypeDef GPIO_InitStructure;
         USART_InitTypeDef USART_InitStructure;
   NVIC_InitTypeDef NVIC_InitStructure;
       
         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1|RCC_APB2Periph_AFIO,ENABLE);
   
         GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
         GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
         GPIO_Init(GPIOA,&GPIO_InitStructure);
       
         GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;;
         GPIO_Init(GPIOA,&GPIO_InitStructure);
       
         USART_InitStructure.USART_BaudRate=bound;
         USART_InitStructure.USART_WordLength=USART_WordLength_8b;
         USART_InitStructure.USART_StopBits=USART_StopBits_1;
         USART_InitStructure.USART_Parity=USART_Parity_No;
         USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
         USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
         USART_Init(USART1,&USART_InitStructure);
         USART_Cmd(USART1,ENABLE);
         USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
         USART_ClearFlag(USART1,USART_FLAG_TC);
         
         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
         NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn ;
         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
         NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
         NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
         NVIC_Init(&NVIC_InitStructure);
         
}
void usart_byte(uint8_t ch){
   USART_SendData(USART1,ch);
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
}
//void USART_SendString(uint8_t *ch){
//  uint16_t k=0;
//        while(*(ch+k) !='\0'){
//                k++;
//                usart_byte(*(ch+k));
//        }
//}
void USART_SendString(uint8_t *ch){
    while((*ch)!='\0')
                {
                   usart_byte(*ch++);
                }
}
void usart_buf(uint8_t *buf,uint8_t len){
   uint16_t i;
        for(i=0;i<len;i++){
            usart_byte(buf[i]);
        }
}
uint16_t usart_rx_buf[8]={0};
uint8_t USART_RX_CNT=0;
/*
void USART1_IRQHandler(void)
{
  if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)//接收中断(接收到的数据必须是0x0d)
        {
                USART_ClearITPendingBit(USART1,USART_IT_RXNE);
          usart_rx_buf[USART_RX_CNT]=USART_ReceiveData(USART1);//读取接收到的
                USART_RX_CNT++;         
                   if((usart_rx_buf[USART_RX_CNT-1]=='\r')||(usart_rx_buf[USART_RX_CNT-1]=='\n'))
                                 {
                                          USART_SendString((uint8_t *)usart_rx_buf);
                                          //遇到\r或\n就保存一次数据到队列中
                                          USART_RX_CNT=0;//重新开始接收数据       
                                 }
                                                                   
        }               
}*/

void USART1_IRQHandler(void)
{
        uint16_t  temp;
  if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)//接收中断(接收到的数据必须是0x0d)
        {
          temp = USART_ReceiveData(USART1);//读取接收到的
          usart_byte((uint8_t)temp);       
        }       
        USART_ClearITPendingBit(USART1,USART_IT_RXNE);

}
/*
void USART1_IRQHandler(void)
{
  if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)//接收中断(接收到的数据必须是0x0d)
        {
                USART_ClearITPendingBit(USART1,USART_IT_RXNE);
          usart_rx_buf[USART_RX_CNT]=USART_ReceiveData(USART1);//读取接收到的
                USART_RX_CNT++;
                   if(usart_rx_buf[USART_RX_CNT] == '\0'&&  (USART_RX_CNT >= 7)){
                                   usart_buf((uint8_t *)usart_rx_buf,8);       
                                         //遇到\r或\n就保存一次数据到队列中
                                         USART_RX_CNT=0;//重新开始接收数据
                          }
  }                                
}*///(usart_rx_buf[usart_rx_len-1]=='\r')||(usart_rx_buf[usart_rx_len-1]=='\n')

使用特权

评论回复
19
g36xcv|  楼主 | 2023-11-24 00:20 | 只看该作者
5、main.c
#include "led.h"
#include "delay.h"
#include "rtc.h"
#include <stm32f10x.h>
#include "usart.h"
#include <stdio.h>

int main(void){
        usart_init(115200);
        printf("串口配置.\r\n");
        led_init();
        printf("led灯配置\r\n");
        USART_SendString("你好\r\n");
        clockinit_RTC();
        printf("This is a RTC test.\r\n");

        while(1){
     Time_Show();
        }
}

使用特权

评论回复
20
g36xcv|  楼主 | 2023-11-24 00:20 | 只看该作者
9、本实验卡在了等待时钟死循环,也验证不出其他的问题,暂时终止

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

25

主题

262

帖子

0

粉丝