基于ARM的万年历1 精品Word文档格式.docx
《基于ARM的万年历1 精品Word文档格式.docx》由会员分享,可在线阅读,更多相关《基于ARM的万年历1 精品Word文档格式.docx(19页珍藏版)》请在冰点文库上搜索。
关键词:
STM32ARM时钟
1引言
随着科技的发展,嵌入式系统广泛应用于工业控制和商业管理领域,在多媒体手机、袖珍电脑,掌上电脑,车载导航器等方面的应用,更是极大地促进了嵌入式技术深入到生活和工作各个方面。
嵌入式系统主要由嵌入式处理器、相关支撑硬件及嵌入式软件系统组成。
本文介绍基于STM32F103R6T6的嵌入式微处理器的万年历设计,并且在液晶上显示。
2STM32芯片RTC时钟介绍
STM32的实时时钟(RTC)是一个独立的定时器。
RTC模块拥有一组连续计数的计数器,在相应软件配置下,可以提供时钟日历的功能,修改计数器的值可以重新设置系统当前的时间和日期。
STM32F10x系列微控制器片上内置的RTC模块,主要特性如下:
(1)可编程的预分频系数,分频系数最高位2^20。
(2)32位的可编程计数器,可用于长程时间段的测量。
(3)两个单独的时钟:
用于APB1接口的PLCK1和RTC时钟(此时RTC时钟的频率必须小于PCLK1时钟的四分之一以上)。
(4)可以选择一下三种RTC的时钟源:
HSE(highspeedexternal)时钟除以128,即高速外部时钟,接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4~16MHz。
LSI(lowspeedinternal)振荡器时钟,即低速内部时钟,频率为40kHz。
LSE(lowspeedexternal)振荡器时钟,即低速外部时钟,接石英晶体,频率为32.768kHz。
(5)2钟独立的复位类型:
APB1接口由系统复位。
RTC核(预分频器、闹钟、计数器和分频器)只能由备份域复位。
(6)3个专门的可屏蔽中断:
闹钟中断,用来产生一个软件可编程的闹钟中断。
秒中断,用来产生一个可编程的周期性中断信号(最长可达1s)。
溢出中断,检测内部可编程计数器溢出并回转为0的状态
(7)STM32侵入检测:
TPAL=0时启动侵入检测TAMPER引脚前已经为高电平,一旦启动检测功能,则会产生一个额外的侵入事件。
TPAL=1时启动侵入引脚TAMPER前该引脚为低电平,一旦启动检测功能,则会产生一个额外的侵入事件。
检测TAMPER上的点品变化,就会把备份寄存器的内容清空,以保护重要的数据不被非法盗取。
3STM32最小系统电路
3.1STM32芯片管脚介绍
STM32F103R6T6管脚示意图,如图1所示。
图1STM32F103R6T6管脚示意图
3.2STM32复位和时钟电路设计
此电路主要是复位电路和时钟电路两部分,其中复位电路采用按键手动复位和上电自动复位组合,电路如图2(右)所示:
其中7脚为STM32的复位端。
时钟电路如图2(左)所示:
晶振采用的是8MHz和32.786KHz,8MKz分别接STM32的5脚和6脚,32.786KHz分别接STM32的3脚和4脚。
图2STM32复位和时钟电路
4总体设计框图
本电路主要由3大部分电路组成:
ARM最小系统电路、时钟显示电路和闹钟警报电路(本设计用LED灯指示)。
其中ATM最小系统主要由复位电路和时钟电路组成。
在该设计中,闹钟提醒由LED灯代替,当闹钟时间到的话,LED灯亮,延时设定的时间后自动关闭。
总体设计方框图,如图3所示。
STM32
复位电路
串口显示
输入时间
时钟电路
图3总体设计方框图
5程序运行结果如图4所示
图4程序运行结果
6程序流程图
程序流程图,如图5所示。
图5程序主流程和时间程序流程图
7总结与体会
通过这次万年历的设计,使我对ARM有了更深的理解。
刚开始拿到题提目,我先是查找相关资料,从图书馆和网上找到相关的课题,参考借鉴别人的设计,从而理清我们设计的思路。
此次作业设计大致可以分为两部分,电路图部分和程序编程部分,其中最有难度的是程序的编写与调试。
在编写程序的过程中,我遇到了各种各样的问题,工程之间的结合,对于其中的错误怎样解决,需要配置什么,更改哪里等等。
对于ARM我学的很浅,编程遇到问题不知道如何解决,我知道这个是我的弱点,但在这两周的课程设计中,用KeiluVision4在ARM开发板上进行程序调试,遇到问题解决问题,在这个过程中我收获了不少。
参考文献
[1]彭刚、秦志强等.基于ARMCortex-M3的STM32系列嵌入式微控制器应用实践[M].北京:
电子工业出版社
[2]李宁.基于MDK的STM32处理器开发应用[M].北京航空航天大学出版社,2008.
[3]王永红、徐炜、赫立平.STM32系列ARMCortex-M3微控制器原理与实践[M].北京航空航天大学出版社,2008.
[4]ARMLimited.Cortex-M3TechnicalReferenceManual(r2p0).ARMDDI0037G2008.
[5]
总体电路图
程序
#include"
stm32f10x.h"
stdio.h"
calendar.h"
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)
{
\r\n\nPowerOnResetoccurred...."
}
elseif(RCC_GetFlagStatus(RCC_FLAG_PINRST)!
\r\n\nExternalResetoccurred...."
\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;
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()
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);
RCC_RTCCLKCmd(ENABLE);
BKP_RTCCalibrationClockOutputCmd(ENABLE);
RTC_WaitForSynchro();
RTC_WaitForLastTask();
RTC_ITConfig(RTC_IT_SEC,ENABLE);
RTC_SetPrescaler(31999);
RTC_SetPrescaler(32767);
voidTime_Regulate(structrtc_time*tm)
u32Tmp_YY=0xFF,Tmp_MM=0xFF,Tmp_DD=0xFF,Tmp_HH=0xFF,Tmp_MI=0xFF,Tmp_SS=0xFF;
\r\n=========================TimeSettings=================="
\r\n请输入年份(PleaseSetYears):
20"
while(Tmp_YY==0xFF)
Tmp_YY=USART_Scanf(99);
\n\r年份被设置为:
20%0.2d\n\r"
Tmp_YY);
tm->
tm_year=Tmp_YY+2000;
Tmp_MM=0xFF;
\r\n请输入月份(PleaseSetMonths):
"
while(Tmp_MM==0xFF)
Tmp_MM=USART_Scanf(12);
\n\r月份被设置为:
%d\n\r"
Tmp_MM);
tm_mon=Tmp_MM;
Tmp_DD=0xFF;
\r\n请输入日期(PleaseSetDates):
while(Tmp_DD==0xFF)
Tmp_DD=USART_Scanf(31);
\n\r日期被设置为:
Tmp_DD);
tm_mday=Tmp_DD;
Tmp_HH=0xFF;
\r\n请输入时钟(PleaseSetHours):
while(Tmp_HH==0xFF)
Tmp_HH=USART_Scanf(23);
\n\r时钟被设置为:
Tmp_HH);
tm_hour=Tmp_HH;
Tmp_MI=0xFF;
\r\n请输入分钟(PleaseSetMinutes):
while(Tmp_MI==0xFF)
Tmp_MI=USART_Scanf(59);
\n\r分钟被设置为:
Tmp_MI);
tm_min=Tmp_MI;
Tmp_SS=0xFF;
\r\n请输入秒钟(PleaseSetSeconds):
while(Tmp_SS==0xFF)
Tmp_SS=USART_Scanf(59);
\n\r秒钟被设置为:
Tmp_SS);
tm_sec=Tmp_SS;
voidTime_Adjust()
Time_Regulate(&
systmtime);
GregorianDay(&
RTC_SetCounter(mktimev(&
systmtime));
voidTime_Display(uint32_tTimeVar)
staticuint32_tFirstDisplay=1;
u8str[15];
to_tm(TimeVar,&
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);
\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);
%s"
str);
}
\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()
\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
\n\rPleaseentervalidnumberbetween0and9-->
:
index--;
index=(tmp[1]-0x30)+((tmp[0]-0x30)*10);
if(index>
value)
\n\rPleaseentervalidnumberbetween0and%d"
value);
return0xFF;
returnindex;