#include
#include "system.h"
#include "usart.h"
#include "rtc.h"
#define LED1 PAout(4)
#define LED2 PAout(5)
void Gpio_Init(void);
extern const u8* Week_Table[7];
int main(void)
{
Rcc_Init(9); //系统时钟设置
Usart1_Init(72,9600);
Nvic_Init(0,0,RTC_IRQChannel,0); //设置中断
Gpio_Init();
Rtc_Init();
//Rtc_TIME_AutoSet(); //将当前编译时间作为RTC开始时间
Rtc_TIME_Set(2012,7,7,20,50,0); //设定开始时间 参数说明:年,月,日,时,分,秒
Rtc_ALARM_Set(2012,7,7,20,50,30); //设定闹钟事件时间
LED1 = 1;
while(1);
}
void Gpio_Init(void)
{
RCC->APB2ENR|=1<<2; //使能PORTA时钟
GPIOA->CRL&=0x0000FFFF; // PA0~3设置为浮空输入,PA4~7设置为推挽输出
GPIOA->CRL|=0x33334444;
//USART1 串口I/O设置
GPIOA -> CRH&=0xFFFFF00F; //设置USART1 的Tx(PA.9)为第二功能推挽,50MHz;Rx(PA.10)为浮空输入
GPIOA -> CRH|=0x000008B0;
}
#include "stm32f10x_it.h"
#include "system.h"
#include "stdio.h"
#include "rtc.h"
#define LED1 PAout(4)
#define LED2 PAout(5)
#define LED3 PAout(6)
#define LED4 PAout(7)
//extern void Wwdg_Feed(void);
//extern u16 Read_Bkp(u8 reg);
extern void Rtc_Get(void);
extern const u8* Week_Table[7];
void RTC_IRQHandler(void)
{
if(RTC->CRL&0x0001) //秒钟中断
{
LED4 = !LED4;
Rtc_Get();
printf("\r\n Time : %d - %d - %d,%d : %d : %d ,Today is %s \r\n",
timer.year,
timer.month,
timer.date,
timer.hour,
timer.minute,
timer.second,
Week_Table[timer.week]
);
}
if(RTC->CRL&0x0002) //闹钟中断
{
LED3 = 1;
printf("\r\nIt's time to do sth.\r\n");
RTC->CRL &= ~(0x0002); //清除闹钟中断
}
RTC->CRL &= 0x0FFA; //清除溢出,秒钟中断
while(!(RTC->CRL &(1<<5))); //等待RTC寄存器操作完成
}
#include
#include "rtc.h"
#include "stdio.h"
tm timer; //定义时钟结构体,主函数直接可以调用此结构体读出时间
//平年的月份日期表,月份缩写表
const u8 Days_Table[12]={31,28,31,30,31,30,31,31,30,31,30,31};
const u8 Month_Table[12][3]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
const u8* Week_Table[7]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
//月修正数据表
u8 const _Week[12]={0,3,3,6,1,4,6,2,5,0,3,5};
void Rtc_Init(void)
{
RCC->APB1ENR |= 1<<28; //使能PWR时钟
RCC->APB1ENR |= 1<<27; //使能BKP时钟,RTC校准在BKP相关寄存器中
PWR->CR |= 1<<8; //取消BKP相关寄存器写保护
//RCC->BDCR |= 1<<16; //备份区域软复位
//RCC->BDCR |= ~(1<<16); //备份区域软复位结束
RCC->BDCR |= 1<<0; //外部低速时钟(LSE)使能
while(!(RCC->BDCR & 0x02)); //等待外部时钟就绪
RCC->BDCR |= 1<<8; //LSE作为RTC时钟
RCC->BDCR |= 1<<15; //RTC时钟使能
while(!(RTC->CRL & (1<<5))); //等待RTC寄存器最后一次操作完成
while(!(RTC->CRL & (1<<3))); //等待RTC寄存器同步完成
RTC->CRH |= 0x07; //允许溢出中断[2],闹钟中断[1],秒中断[0],CRH寄存器低三位有效
while(!(RTC->CRL & (1<<5))); //等待RTC寄存器最后一次操作完成
RTC->CRL |= 1<<4; //进入配置模式
RTC->PRLH = 0x0000;
RTC->PRLL = 32767; //设定分频值
//Rtc_TIME_AutoSet(); //将当前编译时间写入寄存器
//Rtc_TIME_Set(2012,7,7,20,50,0); //年,月,日,时,分,秒
RTC->CRL &= ~(1<<4); //退出配置模式,开始更新RTC寄存器
while(!(RTC->CRL & (1<<5))); //等待RTC寄存器最后一次操作完成
}
//设定RTC开始计时时间
void Rtc_TIME_Set(u16 year,u8 month,u8 date,u8 hour,u8 minute, u8 second)
{
u32 sec;
sec = Date_TO_Sec(year,month,date,hour,minute,second);
//printf("\nRtc TIME Set Sec = %x\n",sec);
RCC->APB1ENR |= 1<<28; //使能PWR时钟,方便独立调用此函数
RCC->APB1ENR |= 1<<27; //使能BKP时钟
PWR->CR |= 1<<8; //取消写保护
RTC-> CRL |= 1<<4; //允许配置
RTC-> CNTL = sec&0xffff; //取低16位
RTC-> CNTH = sec>>16; //取高16位
RTC-> CRL &= ~(1<<4); //开始RTC寄存器更新
while(!(RTC->CRL&(1<<5))); //等待RTC寄存器操作完成
}
//判断是否是闰年函数
//
//判断方法:
// 普通年能整除4且不能整除100的为闰年。(如2004年就是闰年,1900年不是闰年)
// 世纪年能整除400的是闰年。(如2000年是闰年,1900年不是闰年)
//
//返回: 1,是闰年 0,不是闰年
u8 Is_LeapYear(u16 year)
{
if(year%4==0) //必须能被4整除
{
if(year%100==0)
{
if(year%400==0)
return 1; //如果以00结尾,还要能被400整除
else
return 0;
}else{
return 1;
}
}else{
return 0;
}
}
//将时间转化为到1970年1月1日的总秒数
//Bugs:此函数秒数会多20左右,所以函数返回值做了校正,校正后没有问题
//待优化
u32 Date_TO_Sec(u16 year,u8 month,u8 date,u8 hour,u8 minute, u8 second)
{
u16 t;
u32 sec;
if(year >= 1970 && year<= 2106) //判断是否为合法年份,RTC的时间是从1970开始,只能由32位表示秒数,最大只能到2106年左右
{
for(t= 1970 ;tCNTH; //读取RTC的当前时间值(距1970年的总秒数)
secs <<= 16;
secs += RTC->CNTL;
//printf("\nRtc_Get Sec = %x\n",secs);
days = secs/86400;
if(days > 0) //超过一天
{
temp = days;
while(temp >= 365)
{
if(Is_LeapYear(years)) //是闰年
{
if(temp >= 366)
temp -= 366; //闰年的天数
else
break;
}else{
temp -= 365;
}
years++;
}
timer.year = years; //得到年份
while(days >= 28)
{
if(Is_LeapYear(years) && months ==1) //判断是否为闰年的第二月
{
if(temp >= 29)
temp -= 29;
else
break;
}else{
if(temp >= Days_Table[months])
temp -= Days_Table[months];
else
break;
}
months++;
}
timer.month = months+1; //得到月数
timer.date = temp+1; //得到日期
}
temp = secs % 86400; //得到剩余秒数
timer.hour = temp/3600; //得到小时
timer.minute = (temp%3600)/60;
timer.second = (temp%3600)%60;
timer.week = Rtc_DAY_Get(timer.year,timer.month,timer.date);
}
//判断当前为星期几
u8 Rtc_DAY_Get(u16 year,u8 month,u8 day)
{
u16 temp;
u8 yearH,yearL;
yearH = year/100;
yearL = year%100;
// 如果为21世纪,年份数加100
if( yearH > 19 ) yearL += 100;
// 所过闰年数只算1900年之后的
temp = yearL+yearL/4;
temp = temp%7;
temp = temp + day + _Week[month-1];
if( yearL%4 == 0 && month < 3 ) temp--;
return(temp%7);
}
//设定闹钟时间
void Rtc_ALARM_Set(u16 year,u8 month,u8 date,u8 hour,u8 minute, u8 second)
{
u32 sec;
sec = Date_TO_Sec(year,month,date,hour,minute,second);
RTC-> CRL |= 1<<4; //允许配置
//while(!(RTC->CRL&(1<<5))); //RTOFF为1 才可以写入ALRL和ALRH寄存器
RTC-> ALRL = sec&0xffff; //取低16位
RTC-> ALRH = sec>>16; //取高16位
RTC-> CRL &= ~(1<<4); //开始RTC寄存器更新
while(!(RTC->CRL&(1<<5))); //等待RTC寄存器操作完成
}
#include
typedef struct
{
u8 hour;
u8 minute;
u8 second;
u16 year;
u8 month;
u8 date;
u8 week;
}tm;
extern tm timer;
void Rtc_Init(void);
void Rtc_TIME_Set(u16 year,u8 month,u8 date,u8 hour,u8 minute, u8 second);
u8 Is_LeapYear(u16 year);
u32 Date_TO_Sec(u16 year,u8 month,u8 date,u8 hour,u8 minute, u8 second);
void Rtc_TIME_AutoSet(void);
void Rtc_Get(void);
void Rtc_ALARM_Set(u16 year,u8 month,u8 date,u8 hour,u8 minute, u8 second);
u8 Rtc_DAY_Get(u16 year,u8 month,u8 day);
#include "stm32f10x.h"
#include "stdio.h"
#include "time.h"
#define PRINTF_ON 1
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void USART_Configuration(void);
void RTC_Configuration(void);
void TimeShow(void);
void SetAlarm(struct tm t);
void SetCalendarTime(struct tm t);
void SetUnixTime(time_t);
struct tm ConvUnixToCalendar(time_t t);
u32 ConvCalendarToUnix(struct tm t);
u32 GetUnixTime(void);
vu32 Display;
struct tm CurrentTime = {0,30,10,11,4,2011};
struct tm AlarmTime = {5,30,10,11,4,2011};
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
NVIC_Configuration();
USART_Configuration();
RTC_Configuration();
SetCalendarTime(CurrentTime);
SetAlarm(AlarmTime);
while(1){ TimeShow(); }
}
void TimeShow(void)
{
u32 Time = 0;
if(Display)
{
Time = GetUnixTime();
CurrentTime = ConvUnixToCalendar(Time);
printf("\r\n Time : %d - %d - %d,%d : %d : %d \r\n",
CurrentTime.tm_year,
CurrentTime.tm_mon,
CurrentTime.tm_mday,
CurrentTime.tm_hour,
CurrentTime.tm_min,
CurrentTime.tm_sec);
Display = 0;
}
}
void SetCalendarTime(struct tm t)
{
SetUnixTime(ConvCalendarToUnix(t));
}
void SetUnixTime(time_t t)
{
RTC_WaitForLastTask();
RTC_SetCounter((u32)t);
RTC_WaitForLastTask();
}
void SetAlarm(struct tm t)
{
RTC_WaitForLastTask();
RTC_SetAlarm(ConvCalendarToUnix(t));
RTC_WaitForLastTask();
}
u32 GetUnixTime(void)
{
return (u32)RTC_GetCounter();
}
u32 ConvCalendarToUnix(struct tm t)
{
t.tm_year -=1900;
return mktime(&t);
}
struct tm ConvUnixToCalendar(time_t t)
{
struct tm *t_tm;
t_tm = localtime(&t);
t_tm->tm_year += 1900;
return *t_tm;
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
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);
}
void RTC_Configuration(void)
{
PWR_BackupAccessCmd(ENABLE);
BKP_DeInit();
RCC_LSEConfig(RCC_LSE_ON);
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro();
RTC_WaitForLastTask();
RTC_ITConfig(RTC_IT_SEC|RTC_IT_ALR,ENABLE);
RTC_WaitForLastTask();
RTC_SetPrescaler(32767);
RTC_WaitForLastTask();
}
void RCC_Configuration(void)
{
/* 定义枚举类型变量 HSEStartUpStatus */
ErrorStatus HSEStartUpStatus;
/* 复位系统时钟设置*/
RCC_DeInit();
/* 开启HSE*/
RCC_HSEConfig(RCC_HSE_ON);
/* 等待HSE起振并稳定*/
HSEStartUpStatus = RCC_WaitForHSEStartUp();
/* 判断HSE起是否振成功,是则进入if()内部 */
if(HSEStartUpStatus == SUCCESS)
{
/* 选择HCLK(AHB)时钟源为SYSCLK 1分频 */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* 选择PCLK2时钟源为 HCLK(AHB) 1分频 */
RCC_PCLK2Config(RCC_HCLK_Div1);
/* 选择PCLK1时钟源为 HCLK(AHB) 2分频 */
RCC_PCLK1Config(RCC_HCLK_Div2);
/* 设置FLASH延时周期数为2 */
FLASH_SetLatency(FLASH_Latency_2);
/* 使能FLASH预取缓存 */
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
/* 选择锁相环(PLL)时钟源为HSE 1分频,倍频数为9,则PLL输出频率为 8MHz * 9 = 72MHz */
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
/* 使能PLL */
RCC_PLLCmd(ENABLE);
/* 等待PLL输出稳定 */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
/* 选择SYSCLK时钟源为PLL */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* 等待PLL成为SYSCLK时钟源 */
while(RCC_GetSYSCLKSource() != 0x08);
}
/* 打开APB2总线上的GPIOA时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP, ENABLE);
}
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStructure;
USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
USART_ClockInit(USART1 , &USART_ClockInitStructure);
USART_InitStructure.USART_BaudRate = 9600;
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);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
#if PRINTF_ON
int fputc(int ch,FILE *f)
{
USART_SendData(USART1,(u8) ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
return ch;
}
#endif
#include "stm32f10x_it.h"
#include "stdio.h"
extern vu32 Display;
void RTC_IRQHandler(void)
{
if(RTC_GetFlagStatus(RTC_FLAG_ALR) != RESET){
printf("\r\nIt's time to do sth.\r\n");
}else{
Display =1 ;
}
RTC_ClearITPendingBit(RTC_IT_ALR|RTC_IT_SEC);
}