1、嵌入式智能万年历设计任务要求:用ARMM3芯片设计一个智能万年历,要求能够正确显示近100 年时间,星期几,时间格式为*年*月*日(星期*) *:*:*(时:分:秒),能够识别出闰年(计时范围能够从1970年1月1日到2100年左右)。该程序设计工程里包含有main.c(相关配置、和终端联系,提醒输出初始时间、输出实时时间)/date.c(计算实时时间)/stm32f10x_it.c三个文件,各文件内容如下。Main.c文件:#include stm32f10x.h#include stdio.h #include date.h_IO uint32_t TimeDisplay = 0;void
2、 RCC_Configuration(void);void NVIC_Configuration(void);void GPIO_Configuration(void);void USART_Configuration(void);int fputc(int ch, FILE *f);void RTC_Configuration(void);void Time_Regulate(struct rtc_time *tm);void Time_Adjust(void);void Time_Display(uint32_t TimeVar);void Time_Show(void);u8 USART
3、_Scanf(u32 value);#define RTCClockSource_LSE u8 const *WEEK_STR = 日, 一, 二, 三, 四, 五, 六;struct rtc_time systmtime;int main() RCC_Configuration(); NVIC_Configuration(); GPIO_Configuration(); USART_Configuration(); /*在启动时检查备份寄存器BKP_DR1,如果内容不是0xA5A5,则需重新配置时间并询问用户调整时间*/ if (BKP_ReadBackupRegister(BKP_DR1)
4、 != 0xA5A5) printf(rnn RTC not yet configured.); RTC_Configuration(); printf(rn RTC configured.); Time_Adjust(); BKP_WriteBackupRegister(BKP_DR1, 0xA5A5); else /*启动无需设置新时钟*/ /*检查是否掉电重启*/ if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET) printf(rnn Power On Reset occurred.); /*检查是否Reset复位*/ else if (R
5、CC_GetFlagStatus(RCC_FLAG_PINRST) != RESET) printf(rnn External Reset occurred.); printf(rn No need to configure RTC.); /*等待寄存器同步*/ RTC_WaitForSynchro(); /*允许RTC秒中断*/ RTC_ITConfig(RTC_IT_SEC, ENABLE); /*等待上次RTC寄存器写操作完成*/ RTC_WaitForLastTask(); #ifdef RTCClockOutput_Enable RCC_APB1PeriphClockCmd(RCC_
6、APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE); BKP_TamperPinCmd(DISABLE); BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock); #endif RCC_ClearFlag(); Time_Show();void RCC_Configuration() SystemInit(); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, E
7、NABLE);void NVIC_Configuration() NVIC_InitTypeDef NVIC_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_IR
8、QChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);void GPIO_Configuration() GPIO_InitTypeDef GPIO_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_
9、InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure);void USART_Configuration() USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b;
10、 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
11、_Cmd(USART1, ENABLE);int fputc(int ch, FILE *f) /* 将Printf内容发往串口 */ USART_SendData(USART1, (unsigned char) ch); while (!(USART1-SR & USART_FLAG_TXE); return (ch);void RTC_Configuration() /*允许PWR和BKP时钟*/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); /*允许访问BKP域*/ PWR_BackupA
12、ccessCmd(ENABLE); /*复位备份域*/ BKP_DeInit(); #ifdef RTCClockSource_LSI /*允许LSI*/ RCC_LSICmd(ENABLE); /*等待LSI准备好*/ while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)=RESET) /*选择LSI作为RTC时钟源*/ RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); #elif defined RTCClockSource_LSE /*允许LSE*/ RCC_LSEConfig(RCC_LSE_ON); /*等待LSE准备好*/
13、while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)=RESET) /*选择LSE作为RTC时钟源*/ RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); #endif /* Enable RTC Clock */ RCC_RTCCLKCmd(ENABLE); #ifdef RTCClockOutput_Enable /*禁止Tamper引脚*/ BKP_TamperPinCmd(DISABLE);/*为了将RTCCLK/64在Tamper引脚输出,Tamper功能必须被禁止*/ /*允许RTC时钟在Tamper引脚上输出*/ BKP_R
14、TCCalibrationClockOutputCmd(ENABLE); #endif /*等待寄存器同步*/ RTC_WaitForSynchro(); /*等待上次RTC寄存器写操作完成*/ RTC_WaitForLastTask(); /*允许RTC秒中断*/ RTC_ITConfig(RTC_IT_SEC, ENABLE); /*等待上次RTC寄存器写操作完成*/ RTC_WaitForLastTask(); #ifdef RTCClockSource_LSI /*设置分频系数*/ RTC_SetPrescaler(31999); /*RTC周期=RTCCLK/RTC_PR=(32.0
15、00kHz/(31999+1)*/ #elif defined RTCClockSource_LSE RTC_SetPrescaler(32767); /*RTC周期=RTCCLK/RTC_PR=(32.768kHz/(31767+1)*/ #endif /*等待上次RTC寄存器写操作完成*/ RTC_WaitForLastTask(); void Time_Regulate(struct rtc_time *tm) u32 Tmp_YY = 0xFF, Tmp_MM = 0xFF, Tmp_DD = 0xFF, Tmp_HH = 0xFF, Tmp_MI = 0xFF, Tmp_SS = 0
16、xFF; printf(rn=Time Settings=); printf(rn 请输入年份(Please Set Years): 20); while (Tmp_YY = 0xFF) Tmp_YY = USART_Scanf(99); printf(nr 年份被设置为: 20%0.2dnr, Tmp_YY); tm-tm_year = Tmp_YY+2000; Tmp_MM = 0xFF; printf(rn 请输入月份(Please Set Months): ); while (Tmp_MM = 0xFF) Tmp_MM = USART_Scanf(12); printf(nr 月份被设
17、置为: %dnr, Tmp_MM); tm-tm_mon= Tmp_MM; Tmp_DD = 0xFF; printf(rn 请输入日期(Please Set Dates): ); while (Tmp_DD = 0xFF) Tmp_DD = USART_Scanf(31); printf(nr 日期被设置为: %dnr, Tmp_DD); tm-tm_mday= Tmp_DD; Tmp_HH = 0xFF; printf(rn 请输入时钟(Please Set Hours): ); while (Tmp_HH = 0xFF) Tmp_HH = USART_Scanf(23); printf(
18、nr 时钟被设置为: %dnr, Tmp_HH ); tm-tm_hour= Tmp_HH; Tmp_MI = 0xFF; printf(rn 请输入分钟(Please Set Minutes): ); while (Tmp_MI = 0xFF) Tmp_MI = USART_Scanf(59); printf(nr 分钟被设置为: %dnr, Tmp_MI); tm-tm_min= Tmp_MI; Tmp_SS = 0xFF; printf(rn 请输入秒钟(Please Set Seconds): ); while (Tmp_SS = 0xFF) Tmp_SS = USART_Scanf(
19、59); printf(nr 秒钟被设置为: %dnr, Tmp_SS); tm-tm_sec= Tmp_SS;void Time_Adjust() RTC_WaitForLastTask(); Time_Regulate(&systmtime); GregorianDay(&systmtime); RTC_SetCounter(mktimev(&systmtime); RTC_WaitForLastTask();void Time_Display(uint32_t TimeVar) to_tm(TimeVar, &systmtime); printf(r 当前时间为: %d年 %d月 %d日
20、 (星期%s) %0.2d:%0.2d:%0.2d, systmtime.tm_year, systmtime.tm_mon, systmtime.tm_mday, WEEK_STRsystmtime.tm_wday, systmtime.tm_hour, systmtime.tm_min, systmtime.tm_sec);void Time_Show() printf(nr); /* Infinite loop */ while (1) /* 每过1s */ if (TimeDisplay = 1) Time_Display(RTC_GetCounter(); TimeDisplay =
21、 0; u8 USART_Scanf(u32 value) u32 index = 0; u32 tmp2 = 0, 0; while (index 2) while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) = RESET) tmpindex+ = (USART_ReceiveData(USART1); if (tmpindex - 1 0x39) /*数字0到9的ASCII码为0x30至0x39*/ if(index = 2) & (tmpindex - 1 = r) tmp1 = tmp0; tmp0 = 0x30; else print
22、f(nrPlease enter valid number between 0 and 9 -: ); index-; /* 计算输入字符的相应ASCII值*/ index = (tmp1 - 0x30) + (tmp0 - 0x30) * 10); /* Checks */ if (index value) printf(nrPlease enter valid number between 0 and %d, value); return 0xFF; return index;Date.c文件内容如下:#include date.h#define FEBRUARY 2#define STA
23、RTOFTIME 1970#define SECDAY 86400L#define SECYR (SECDAY * 365)#define leapyear(year) (year) % 4 = 0)#define days_in_year(a) (leapyear(a) ? 366 : 365)#define days_in_month(a) (month_days(a) - 1)static int month_days12 = 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ; /*计算公历*/void GregorianDay(struct
24、 rtc_time * tm) int leapsToDate; int lastYear; int day; int MonthOffset = 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
25、!=0) | (tm-tm_year%400=0) & (tm-tm_mon2) day=1; else day=0; day += lastYear*365 + leapsToDate + MonthOffsettm-tm_mon-1 + tm-tm_mday; /*计算从计数元年元旦到计数日期一共有多少天*/ tm-tm_wday=day%7;u32 mktimev(struct rtc_time *tm) if (0 = (int) (tm-tm_mon -= 2) tm-tm_mon += 12; tm-tm_year -= 1; return (u32) (tm-tm_year/4
26、- 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; void to_tm(u32 tim, struct rtc_time * tm) register u32 i; register long hms, day; day = tim / SECDAY; hms = tim % SECDAY; tm-tm_hour = hms / 3600; tm-tm_min
27、= (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
28、_in_month(FEBRUARY) = 28; tm-tm_mon = i;/*计算当前日期*/ tm-tm_mday = day + 1; GregorianDay(tm); stm32f10x_it.c文件内容:#include stm32f10x_it.hextern uint32_t TimeDisplay;void NMI_Handler(void)/* * brief This function handles Hard Fault exception. * param None * retval : None */void HardFault_Handler(void) /* Go to infinite loop when Hard Fault exception occurs */ while (1) /* * brief This functi
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1