嵌入式智能万年历设计.docx
- 文档编号:5104586
- 上传时间:2022-12-13
- 格式:DOCX
- 页数:18
- 大小:19.12KB
嵌入式智能万年历设计.docx
《嵌入式智能万年历设计.docx》由会员分享,可在线阅读,更多相关《嵌入式智能万年历设计.docx(18页珍藏版)》请在冰豆网上搜索。
嵌入式智能万年历设计
任务要求:
用ARM—M3芯片设计一个智能万年历,要求能够正确显示近100年时间,星期几,时间格式为****年**月**日(星期**)**:
**:
**(时:
分:
秒),能够识别出闰年(计时范围能够从1970年1月1日到2100年左右)。
该程序设计工程里包含有main.c(相关配置、和终端联系,提醒输出初始时间、输出实时时间)/date.c(计算实时时间)/stm32f10x_it.c三个文件,各文件内容如下。
Main.c文件:
#include"stm32f10x.h"
#include"stdio.h"
#include"date.h"
__IOuint32_tTimeDisplay=0;
voidRCC_Configuration(void);
voidNVIC_Configuration(void);
voidGPIO_Configuration(void);
voidUSART_Configuration(void);
intfputc(intch,FILE*f);
voidRTC_Configuration(void);
voidTime_Regulate(structrtc_time*tm);
voidTime_Adjust(void);
voidTime_Display(uint32_tTimeVar);
voidTime_Show(void);
u8USART_Scanf(u32value);
#defineRTCClockSource_LSE
u8const*WEEK_STR[]={"日","一","二","三","四","五","六"};
structrtc_timesystmtime;
intmain()
{
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration();
USART_Configuration();
/*在启动时检查备份寄存器BKP_DR1,如果内容不是0xA5A5,则需重新配置时间并询问用户调整时间*/
if(BKP_ReadBackupRegister(BKP_DR1)!
=0xA5A5)
{
printf("\r\n\nRTCnotyetconfigured....");
RTC_Configuration();
printf("\r\nRTCconfigured....");
Time_Adjust();
BKP_WriteBackupRegister(BKP_DR1,0xA5A5);
}
else
{
/*启动无需设置新时钟*/
/*检查是否掉电重启*/
if(RCC_GetFlagStatus(RCC_FLAG_PORRST)!
=RESET)
{
printf("\r\n\nPowerOnResetoccurred....");
}
/*检查是否Reset复位*/
elseif(RCC_GetFlagStatus(RCC_FLAG_PINRST)!
=RESET)
{
printf("\r\n\nExternalResetoccurred....");
}
printf("\r\nNoneedtoconfigureRTC....");
/*等待寄存器同步*/
RTC_WaitForSynchro();
/*允许RTC秒中断*/
RTC_ITConfig(RTC_IT_SEC,ENABLE);
/*等待上次RTC寄存器写操作完成*/
RTC_WaitForLastTask();
}
#ifdefRTCClockOutput_Enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_TamperPinCmd(DISABLE);
BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);
#endif
RCC_ClearFlag();
Time_Show();
}
voidRCC_Configuration()
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);
}
voidNVIC_Configuration()
{
NVIC_InitTypeDefNVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel=RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
voidGPIO_Configuration()
{
GPIO_InitTypeDefGPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
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);
}
voidUSART_Configuration()
{
USART_InitTypeDefUSART_InitStructure;
USART_InitStructure.USART_BaudRate=115200;
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);
}
intfputc(intch,FILE*f)
{
/*将Printf内容发往串口*/
USART_SendData(USART1,(unsignedchar)ch);
while(!
(USART1->SR&USART_FLAG_TXE));
return(ch);
}
voidRTC_Configuration()
{
/*允许PWR和BKP时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
/*允许访问BKP域*/
PWR_BackupAccessCmd(ENABLE);
/*复位备份域*/
BKP_DeInit();
#ifdefRTCClockSource_LSI
/*允许LSI*/
RCC_LSICmd(ENABLE);
/*等待LSI准备好*/
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)==RESET)
{
}
/*选择LSI作为RTC时钟源*/
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
#elifdefinedRTCClockSource_LSE
/*允许LSE*/
RCC_LSEConfig(RCC_LSE_ON);
/*等待LSE准备好*/
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET)
{
}
/*选择LSE作为RTC时钟源*/
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
#endif
/*EnableRTCClock*/
RCC_RTCCLKCmd(ENABLE);
#ifdefRTCClockOutput_Enable
/*禁止Tamper引脚*/
BKP_TamperPinCmd(DISABLE);/*为了将RTCCLK/64在Tamper引脚输出,Tamper功能必须被禁止*/
/*允许RTC时钟在Tamper引脚上输出*/
BKP_RTCCalibrationClockOutputCmd(ENABLE);
#endif
/*等待寄存器同步*/
RTC_WaitForSynchro();
/*等待上次RTC寄存器写操作完成*/
RTC_WaitForLastTask();
/*允许RTC秒中断*/
RTC_ITConfig(RTC_IT_SEC,ENABLE);
/*等待上次RTC寄存器写操作完成*/
RTC_WaitForLastTask();
#ifdefRTCClockSource_LSI
/*设置分频系数*/
RTC_SetPrescaler(31999);/*RTC周期=RTCCLK/RTC_PR=(32.000kHz/(31999+1))*/
#elifdefinedRTCClockSource_LSE
RTC_SetPrescaler(32767);/*RTC周期=RTCCLK/RTC_PR=(32.768kHz/(31767+1))*/
#endif
/*等待上次RTC寄存器写操作完成*/
RTC_WaitForLastTask();
}
voidTime_Regulate(structrtc_time*tm)
{
u32Tmp_YY=0xFF,Tmp_MM=0xFF,Tmp_DD=0xFF,Tmp_HH=0xFF,Tmp_MI=0xFF,Tmp_SS=0xFF;
printf("\r\n=========================TimeSettings==================");
printf("\r\n请输入年份(PleaseSetYears):
20");
while(Tmp_YY==0xFF)
{
Tmp_YY=USART_Scanf(99);
}
printf("\n\r年份被设置为:
20%0.2d\n\r",Tmp_YY);
tm->tm_year=Tmp_YY+2000;
Tmp_MM=0xFF;
printf("\r\n请输入月份(PleaseSetMonths):
");
while(Tmp_MM==0xFF)
{
Tmp_MM=USART_Scanf(12);
}
printf("\n\r月份被设置为:
%d\n\r",Tmp_MM);
tm->tm_mon=Tmp_MM;
Tmp_DD=0xFF;
printf("\r\n请输入日期(PleaseSetDates):
");
while(Tmp_DD==0xFF)
{
Tmp_DD=USART_Scanf(31);
}
printf("\n\r日期被设置为:
%d\n\r",Tmp_DD);
tm->tm_mday=Tmp_DD;
Tmp_HH=0xFF;
printf("\r\n请输入时钟(PleaseSetHours):
");
while(Tmp_HH==0xFF)
{
Tmp_HH=USART_Scanf(23);
}
printf("\n\r时钟被设置为:
%d\n\r",Tmp_HH);
tm->tm_hour=Tmp_HH;
Tmp_MI=0xFF;
printf("\r\n请输入分钟(PleaseSetMinutes):
");
while(Tmp_MI==0xFF)
{
Tmp_MI=USART_Scanf(59);
}
printf("\n\r分钟被设置为:
%d\n\r",Tmp_MI);
tm->tm_min=Tmp_MI;
Tmp_SS=0xFF;
printf("\r\n请输入秒钟(PleaseSetSeconds):
");
while(Tmp_SS==0xFF)
{
Tmp_SS=USART_Scanf(59);
}
printf("\n\r秒钟被设置为:
%d\n\r",Tmp_SS);
tm->tm_sec=Tmp_SS;
}
voidTime_Adjust()
{
RTC_WaitForLastTask();
Time_Regulate(&systmtime);
GregorianDay(&systmtime);
RTC_SetCounter(mktimev(&systmtime));
RTC_WaitForLastTask();
}
voidTime_Display(uint32_tTimeVar)
{
to_tm(TimeVar,&systmtime);
printf("\r当前时间为:
%d年%d月%d日(星期%s)%0.2d:
%0.2d:
%0.2d",
systmtime.tm_year,systmtime.tm_mon,systmtime.tm_mday,
WEEK_STR[systmtime.tm_wday],systmtime.tm_hour,
systmtime.tm_min,systmtime.tm_sec);
}
voidTime_Show()
{
printf("\n\r");
/*Infiniteloop*/
while
(1)
{
/*每过1s*/
if(TimeDisplay==1)
{
Time_Display(RTC_GetCounter());
TimeDisplay=0;
}
}
}
u8USART_Scanf(u32value)
{
u32index=0;
u32tmp[2]={0,0};
while(index<2)
{
while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET)
{
}
tmp[index++]=(USART_ReceiveData(USART1));
if((tmp[index-1]<0x30)||(tmp[index-1]>0x39))/*数字0到9的ASCII码为0x30至0x39*/
{
if((index==2)&&(tmp[index-1]=='\r'))
{
tmp[1]=tmp[0];
tmp[0]=0x30;
}
else
{
printf("\n\rPleaseentervalidnumberbetween0and9-->:
");
index--;
}
}
}
/*计算输入字符的相应ASCII值*/
index=(tmp[1]-0x30)+((tmp[0]-0x30)*10);
/*Checks*/
if(index>value)
{
printf("\n\rPleaseentervalidnumberbetween0and%d",value);
return0xFF;
}
returnindex;
}
Date.c文件内容如下:
#include"date.h"
#defineFEBRUARY2
#defineSTARTOFTIME1970
#defineSECDAY86400L
#defineSECYR(SECDAY*365)
#defineleapyear(year)((year)%4==0)
#definedays_in_year(a)(leapyear(a)?
366:
365)
#definedays_in_month(a)(month_days[(a)-1])
staticintmonth_days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
/*计算公历*/
voidGregorianDay(structrtc_time*tm)
{
intleapsToDate;
intlastYear;
intday;
intMonthOffset[]={0,31,59,90,120,151,181,212,243,273,304,334};
lastYear=tm->tm_year-1;
/*计算到计数的前一年之中一共经历了多少个闰年*/
leapsToDate=lastYear/4-lastYear/100+lastYear/400;
/*如若计数的这一年为闰年,且计数的月份在2月之后,则日数加1,否则不加1*/
if((tm->tm_year%4==0)&&((tm->tm_year%100!
=0)||(tm->tm_year%400==0))&&(tm->tm_mon>2))
{
day=1;
}
else
{
day=0;
}
day+=lastYear*365+leapsToDate+MonthOffset[tm->tm_mon-1]+tm->tm_mday;/*计算从计数元年元旦到计数日期一共有多少天*/
tm->tm_wday=day%7;
}
u32mktimev(structrtc_time*tm)
{
if(0>=(int)(tm->tm_mon-=2))
{
tm->tm_mon+=12;
tm->tm_year-=1;
}
return((((u32)(tm->tm_year/4-tm->tm_year/100+tm->tm_year/400+367*tm->tm_mon/12+tm->tm_mday)
+tm->tm_year*365-719499)*24+tm->tm_hour)*6+tm->tm_min)*60+tm->tm_sec;
}
voidto_tm(u32tim,structrtc_time*tm)
{
registeru32i;
registerlonghms,day;
day=tim/SECDAY;
hms=tim%SECDAY;
tm->tm_hour=hms/3600;
tm->tm_min=(hms%3600)/60;
tm->tm_sec=(hms%3600)%60;
/*算出当前年份,起始的计数年份为1970年*/
for(i=STARTOFTIME;day>=days_in_year(i);i++)
{
day-=days_in_year(i);
}
tm->tm_year=i;
/*计算当前的月份*/
if(leapyear(tm->tm_year))
{
days_in_month(FEBRUARY)=29;
}
for(i=1;day>=days_in_month(i);i++)
{
day-=days_in_month(i);
}
days_in_month(FEBRUARY)=28;
tm->tm_mon=i;
/*计算当前日期*/
tm->tm_mday=day+1;
GregorianDay(tm);
}
stm32f10x_it.c文件内容:
#include"stm32f10x_it.h"
externuint32_tTimeDisplay;
voidNMI_Handler(void)
{
}
/**
*@briefThisfunctionhandlesHardFaultexception.
*@paramNone
*@retval:
None
*/
voidHardFault_Handler(void)
{
/*GotoinfiniteloopwhenHardFaultexceptionoccurs*/
while
(1)
{
}
}
/**
*@briefThisfuncti
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 嵌入式 智能 万年历 设计