基于ARM的万年历 精品.docx
《基于ARM的万年历 精品.docx》由会员分享,可在线阅读,更多相关《基于ARM的万年历 精品.docx(19页珍藏版)》请在冰豆网上搜索。
![基于ARM的万年历 精品.docx](https://file1.bdocx.com/fileroot1/2023-2/23/72132965-dafe-41d6-8a04-2b080ab19045/72132965-dafe-41d6-8a04-2b080ab190451.gif)
基于ARM的万年历精品
《嵌入式系统》课程设计报告
基于ARM的万年历系统
院系:
机电学院
学生姓名:
专业:
应用电子技术教育
班级:
指导教师:
田丰庆杜留锋
付广春陈艳锋
完成时间:
2013年3月29日
摘要
现在是一个知识爆炸的新时代,新产品、新技术层出不穷,电子技术的发展更是日新月异。
可以毫不夸张的说,电子技术的应用无处不在,电子技术正在不断地改变我们的生活,改变着我们的世界。
在这快速发展的年代,时间对人们来说是越来越宝贵,在快节奏的生活时,人们往往忘记了时间,一旦遇到重要的事情而忘记了时间,这将会带来很大的损失。
因此我们需要一个定时系统来提醒这些忙碌的人,而数字化的钟表给人们带来了极大的方便。
电子万年历是一种非常广泛日常计时工作,对现代社会越来越流行。
它可以对年、月、日、周、时、分、秒进行计时。
由于单片机具有灵活性强、成本低、功耗低、保密性好等特点,所以电子日历时钟一般都以单片机为核心,外加一些外围设备来实现,可以显示年月日时分秒和温度信息,具有可调整日期和时间功能。
近些年,随着科技的发展和社会的进步,人们对数字钟的要求也越来越高,传统的时钟已不能满足人们的需求。
多功能数字钟不管在性能还是在样式上都发生了质的变化,有电子闹钟、数字闹钟等等。
单片机在多功能数字钟中的应用已是非常普遍的,人们对数字钟的功能及工作顺序都非常熟悉。
但是却很少知道它的内部结构以及工作原理。
由单片机作为数字钟的核心控制器,可以通过它的时钟信号进行计时实现计时功能,将其时间数据经单片机输出,利用显示器显示出来,通过按键可以进行定时、校时功能。
输出设备显示器可以用液晶显示技术和数码管显示技术。
目录
1ARMCortex-M简介1
2电子万年历的发展状况1
3万年历硬件系统设计1
3.1单片机内部主电路如图一所示1
3.2时钟电路如图二所示2
4程序流程图3
5程序运行结果如图五所示4
6研究目的与意义4
参考文献6
附录7
源程序7
1ARMCortex-M简介
ARMCortex-M系列主要用于微控制器单片机(MCU)领域,是为了那些对功耗和成本非常敏感,同时对性能要求不断增加的嵌入式应用(如微控制器系统、汽车电子与车身控制系统、各种家电、工业控制、医疗器械、玩具和无线网络等)所设计与实现的。
随着在各种不同领域应用需求的增加,微处理器市场也在趋于多样化。
Cortex-M3是一个32位的单片机核,在传统的单片机领域中,有一些不同于通用32位CPU应用的要求,结合了多种创新性突破技术,使得芯片供应商可以提供超低费用的芯片。
M3处理器还集成了许多紧耦合系统外设,合理利用了芯片空间,使系统能满足下一代产品的控制需求。
Cortex的优势在于低功耗、低成本、高性能的结合,凭借缩小的内核尺寸、出色的中断延迟、集成的系统部件、灵活的硬件配置、快速的系统调试和简易的软件编程,Cortex-M3处理器将成为广大嵌入式系统(从复杂的片上系统到低端微控制器)的理想解决方案。
2电子万年历的发展状况
随着人们生活水平的提高和生活节奏的加快,对时间的要求越来越高,精准数字计时的消费需求也是越来越多。
二十一世纪的今天,最具代表性的计时产品就是电子万年历,它是近代世界钟表业界的第三次革命。
第一次是摆和摆轮游丝的发明,相对稳定的机械振荡频率源使钟表的走时差从分级缩小到秒级,代表性的产品就是带有摆或摆轮游丝的机械钟或表。
第二次革命是石英晶体振荡器的应用,发明了走时精度更高的石英电子钟表,使钟表的走时月差从分级缩小到秒级。
第三次革命就是单片机数码计时技术的应用(电子万年历),使计时产品的走时日差从分级缩小到1/600万秒,从原有传统指针计时的方式发展为人们日常更为熟悉的夜光数字显示方式,直观明了,并增加了全自动日期、星期、温度以及其他日常附属信息的显示功能,它更符合消费者的生活需求!
因此,电子万年历的出现带来了钟表计时业界跨跃性的进步!
3万年历硬件系统设计
3.1单片机内部主电路如图1所示
图1单片机内部主电路
3.2时钟电路如图2所示
图2时钟电路
3.3内部串口电路如图3所示
图3内部串口电路
4程序流程图
图4程序流程图
5程序运行结果如图5所示
程序通过宏定义来设置当前时间,对开发板进行初始化后,进行设置和串口初始化,并打开中断,当设置时间到时,程序读取可编程计数器的值以或许信息,通过串口发送数据显示时钟。
图5程序运行结果
6研究目的与意义
二十一世纪是数字化技术高速发展时代,而单片机在数字化高速发展的时代扮演者极为重要的角色。
电子万年历的开发与研究在信息化时代的今天亦是当务之急,因为它应用在学校、机关、企业、部队等单位礼堂、训练场地、教学室、公共场地等场合,可以说遍及人们生活的每一个角落。
所以说电子万年历的开发是国家之所需,社会之所需,人民之所需。
由于社会对信息交换不断提高的要求及高新技术的逐步发展,促进电子万年历发展并且投入市场得到广泛应用。
参考文献
1、李佳.ARM系列处理器应用技术完全手册[M].人民邮电出版社,2006.
2、彭刚,秦志强.基于ARMCortes-M3的STM32系列嵌入式微控制器应用实践[M].北京:
电子工业出版社.2011.1
3、李佳.ARM系列处理器应用技术完全手册[M].人民邮电出版社,2006.
4、赖于树.ARM微处理器与应用开发[M].电子工业出版社,2007.
张绮文,谢建雄,谢劲心.ARM嵌入式常用模块与中和系统设计实例精讲[M].电子工业出版社,2007.
5、张绮文,谢建雄,谢劲心.ARM嵌入式常用模块与中和系统设计实例精讲[M].电子工业出版社,2007.
6、刘岚尹勇李京蔚.基于ARM的嵌入式系统开发[M].电子工业出版社,2008.
附录
源程序:
#include"stm32f10x.h"
#include"stdio.h"
#include"calendar.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[]={"日","一","二","三","四","五","六"};
u8const*zodiac_sign[]={"猪","鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗"};
structrtc_timesystmtime;
intmain()
{
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration();
USART_Configuration();
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....");
}
elseif(RCC_GetFlagStatus(RCC_FLAG_PINRST)!
=RESET)
{
printf("\r\n\nExternalResetoccurred....");
}
printf("\r\nNoneedtoconfigureRTC....");
RTC_WaitForSynchro();
RTC_ITConfig(RTC_IT_SEC,ENABLE);
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)
{
USART_SendData(USART1,(unsignedchar)ch);
while(!
(USART1->SR&USART_FLAG_TXE));
return(ch);
}
voidRTC_Configuration()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_DeInit();
#ifdefRTCClockSource_LSI
RCC_LSICmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)==RESET)
{
}
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
#elifdefinedRTCClockSource_LSE
RCC_LSEConfig(RCC_LSE_ON);
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET)
{
}
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
#endif
RCC_RTCCLKCmd(ENABLE);
#ifdefRTCClockOutput_Enable
BKP_TamperPinCmd(DISABLE);
BKP_RTCCalibrationClockOutputCmd(ENABLE);
#endif
RTC_WaitForSynchro();
RTC_WaitForLastTask();
RTC_ITConfig(RTC_IT_SEC,ENABLE);
RTC_WaitForLastTask();
#ifdefRTCClockSource_LSI
RTC_SetPrescaler(31999);
#elifdefinedRTCClockSource_LSE
RTC_SetPrescaler(32767);
#endif
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)
{
staticuint32_tFirstDisplay=1;
u8str[15];
to_tm(TimeVar,&systmtime);
if((!
systmtime.tm_hour&&!
systmtime.tm_min&&!
systmtime.tm_sec)||(FirstDisplay))
{
GetChinaCalendar((u16)systmtime.tm_year,(u8)systmtime.tm_mon,(u8)systmtime.tm_mday,str);
printf("\n\r\n\r今天农历:
%0.2d%0.2d,%0.2d,%0.2d",str[0],str[1],str[2],str[3]);
GetChinaCalendarStr((u16)systmtime.tm_year,(u8)systmtime.tm_mon,(u8)systmtime.tm_mday,str);
printf("%s",str);
}
printf("\r当前时间为:
%d年(%s年)%d月%d日(星期%s)%0.2d:
%0.2d:
%0.2d",
systmtime.tm_year,zodiac_sign[(systmtime.tm_year-3)%12],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");
while
(1)
{
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))
{
if((index==2)&&(tmp[index-1]=='\r'))
{
tmp[1]=tmp[0];
tmp[0]=0x30;
}
else
{
printf("\n\rPleaseentervalidnumberbetween0and9-->:
");
index--;
}
}
}
index=(tmp[1]-0x30)+((tmp[0]-0x30)*10);
if(index>value)
{
printf("\n\rPleaseentervalidnumberbetween0and%d",value);
return0xFF;
}
returnindex;
}