基于ARM的时钟闹钟设计.docx
《基于ARM的时钟闹钟设计.docx》由会员分享,可在线阅读,更多相关《基于ARM的时钟闹钟设计.docx(20页珍藏版)》请在冰豆网上搜索。
![基于ARM的时钟闹钟设计.docx](https://file1.bdocx.com/fileroot1/2023-1/21/6944a996-c757-44e2-b9b3-99adef22c311/6944a996-c757-44e2-b9b3-99adef22c3111.gif)
基于ARM的时钟闹钟设计
基于ARM的时钟系统
摘要:
本设计选择STM32为核心控制元件,设计了用RTC定时器实现时钟的控制与设计,本设计能作为普通时钟用,而且能设置闹钟。
程序使用C语言进行编程,能动态显示当前时间,包括时、分、秒,并且用串口助手显示。
关键词:
STM32ARM时钟闹钟
目录
1引言1
2STM32单片机RTC介绍1
3总体设计框图2
4硬件电路2
4.1STM32芯片管脚介绍2
4.2STM32复位和时钟电路设计3
4.3闹钟提醒电路4
5程序流程图4
5.1主程序流程图4
5.2中断程序流程图6
6总结与体会6
参考文献:
7
附录:
8
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的状态。
3总体设计框图
本电路主要由3大部分电路组成:
ARM最小系统电路、时钟显示电路和闹钟警报电路(本设计用LED灯指示)。
其中ATM最小系统主要由复位电路和时钟电路组成。
在该设计中,闹钟提醒由LED灯代替,当闹钟时间到的话,LED灯亮,延时设定的时间后自动关闭。
总体设计方框图,如图1所示。
STM32
液晶显示电路
复位电路
闹铃提醒电路
时钟电路
图1总体设计方框图
4硬件电路
该设计分为软件设计和硬件设计两大模块,硬件电路由ARM最小系统电路、时钟显示电路和闹钟提醒电路组成。
4.1STM32芯片管脚介绍
STM32F103R6T6管脚示意图,如图2所示。
图2STM32F103R6T6管脚示意图
4.2STM32复位和时钟电路设计
此电路主要是复位电路和时钟电路两部分,其中复位电路采用按键手动复位和上电自动复位组合,电路如图2(右)所示:
其中7脚为STM32的复位端。
时钟电路如图2(左)所示:
晶振采用的是8MHz和32.786KHz,8MKz分别接STM32的5脚和6脚,32.786KHz分别接STM32的3脚和4脚。
图3STM32复位和时钟电路
4.3闹钟提醒电路
本设计的闹钟提醒电路没有采用蜂鸣器,为了调试方便用实验板上的发光二极管LED1—LED4指示,其与实验板对应接口为PC0—PC3。
电路如图4所示。
图4闹钟提醒电路
5程序流程图
5.1主程序流程图
主程序流程图,如图5所示。
图5主程序流程图
5.2中断程序流程图
中断程序流程图,如图6所示。
图6中断程序流程图
6总结与体会
通过这次时钟的设计,使我对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]
附录
1总体电路图
2串口助手演示效果
3源程序
/*
*函数名:
NVIC_Configuration
*描述:
配置RTC秒中断的主中断优先级为1,次优先级为0
*输入:
无
*输出:
无
*调用:
外部调用
*/
voidNVIC_Configuration(void)
{
NVIC_InitTypeDefNVIC_InitStructure;
/*Configureonebitforpreemptionpriority*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/*EnabletheRTCInterrupt*/
NVIC_InitStructure.NVIC_IRQChannel=RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel=RTCAlarm_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_InitStructure);
}
/*
*函数名:
GPIO_Configuration
*描述:
配置GPIO
*输入:
无
*输出:
无
*调用:
外部调用
*/
voidGPIO_Configuration(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDefGPIO_InitStructure;
/*开启GPIOC的外设时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
/*选择要控制的GPIOC引脚*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz*/
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
/*调用库函数,初始化GPIOC*/
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_SetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
}
/*
*函数名:
RTC_Configuration
*描述:
配置RTC
*输入:
无
*输出:
无
*调用:
外部调用
*/
voidRTC_Configuration(void)
{
/*EnablePWRandBKPclocks*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
/*AllowaccesstoBKPDomain*/
PWR_BackupAccessCmd(ENABLE);
/*ResetBackupDomain*/
BKP_DeInit();
/*EnableLSE*/
RCC_LSEConfig(RCC_LSE_ON);
/*WaittillLSEisready*/
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET)
{}
/*SelectLSEasRTCClockSource*/
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
/*EnableRTCClock*/
RCC_RTCCLKCmd(ENABLE);
/*WaitforRTCregisterssynchronization*/
RTC_WaitForSynchro();
/*WaituntillastwriteoperationonRTCregistershasfinished*/
RTC_WaitForLastTask();
/*EnabletheRTCSecond*/
RTC_ITConfig(RTC_IT_SEC,ENABLE);
RTC_ITConfig(RTC_IT_ALR,ENABLE);
/*WaituntillastwriteoperationonRTCregistershasfinished*/
RTC_WaitForLastTask();
/*SetRTCprescaler:
setRTCperiodto1sec*/
RTC_SetPrescaler(32767);/*RTCperiod=RTCCLK/RTC_PR=(32.768KHz)/(32767+1)*/
/*WaituntillastwriteoperationonRTCregistershasfinished*/
RTC_WaitForLastTask();
}
/*
*函数名:
Time_Regulate
*描述:
返回用户在超级终端中输入的时间值,并将值储存在
*RTC计数寄存器中。
*输入:
无
*输出:
用户在超级终端中输入的时间值,单位为s
*调用:
内部调用
*/
uint32_tTime_Regulate(void)
{
uint32_tTmp_HH=0xFF,Tmp_MM=0xFF,Tmp_SS=0xFF;
printf("\r\n==============TimeSettings=====================================");
printf("\r\nPleaseSetHours");
while(Tmp_HH==0xFF)
{
Tmp_HH=USART_Scanf(23);
}
printf(":
%d",Tmp_HH);
printf("\r\nPleaseSetMinutes");
while(Tmp_MM==0xFF)
{
Tmp_MM=USART_Scanf(59);
}
printf(":
%d",Tmp_MM);
printf("\r\nPleaseSetSeconds");
while(Tmp_SS==0xFF)
{
Tmp_SS=USART_Scanf(59);
}
printf(":
%d",Tmp_SS);
/*ReturnthevaluetostoreinRTCcounterregister*/
return((Tmp_HH*3600+Tmp_MM*60+Tmp_SS));
}
/*
*函数名:
Time_Adjust
*描述:
时间调节
*输入:
无
*输出:
无
*调用:
外部调用
*/
voidTime_Adjust(void)
{//uint32_tAAAA;
/*WaituntillastwriteoperationonRTCregistershasfinished*/
RTC_WaitForLastTask();
//AAAA=Time_Regulate();
/*Changethecurrenttime*/
RTC_SetCounter(Time_Regulate());
RTC_SetAlarm(Time_Regulate());
/*WaituntillastwriteoperationonRTCregistershasfinished*/
RTC_WaitForLastTask();
}
/*
*函数名:
Time_Display
*描述:
显示当前时间值
*输入:
-TimeVarRTC计数值,单位为s
*输出:
无
*调用:
内部调用
*/
voidTime_Display(uint32_tTimeVar)
{
uint32_tTHH=0,TMM=0,TSS=0;
/*Computehours*/
THH=TimeVar/3600;
/*Computeminutes*/
TMM=(TimeVar%3600)/60;
/*Computeseconds*/
TSS=(TimeVar%3600)%60;
printf("Time:
%0.2d:
%0.2d:
%0.2d\r",THH,TMM,TSS);
}
/*
*函数名:
Time_Show
*描述:
在超级终端中显示当前时间值
*输入:
无
*输出:
无
*调用:
外部调用
*/
voidTime_Show(void)
{
printf("\n\r");
/*Infiniteloop*/
while
(1)
{
/*If1shaspaased*/
if(TimeDisplay==1)
{
/*Displaycurrenttime*/
Time_Display(RTC_GetCounter());
TimeDisplay=0;
}
}
}
/*
*函数名:
USART_Scanf
*描述:
串口从超级终端中获取数值
*输入:
-value用户在超级终端中输入的数值
*输出:
无
*调用:
内部调用
*/
uint8_tUSART_Scanf(uint32_tvalue)
{
uint32_tindex=0;
uint32_ttmp[2]={0,0};
while(index<2)
{
/*LoopuntilRXNE=1*/
while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET)
{}
tmp[index++]=(USART_ReceiveData(USART1));
//从串口终端里面输进去的数是ASCII码值
if((tmp[index-1]<0x30)||(tmp[index-1]>0x39))
{
printf("\n\rPleaseentervalidnumberbetween0and9");
index--;
}
}
/*CalculatetheCorrespondingvalue*/
index=(tmp[1]-0x30)+((tmp[0]-0x30)*10);
/*Checks*/
if(index>value)
{
printf("\n\rPleaseentervalidnumberbetween0and%d",value);
return0xFF;
}
returnindex;
}
/**************************************************************************/
/*STM32F10xPeripheralsInterruptHandlers*/
/*AddheretheInterruptHandlerfortheusedperipheral(s)(PPP),forthe*/
/*availableperipheralinterrupthandler'snamepleaserefertothestartup*/
/*file(startup_stm32f10x_xx.s).*/
/*************************************************************************/
/**
*@briefThisfunctionhandlesRTCglobalinterruptrequest.
*@paramNone
*@retval:
None
*/
voidRTC_IRQHandler(void)
{
if(RTC_GetITStatus(RTC_IT_SEC)!
=RESET)
{
/*CleartheRTCSecondinterrupt*/
RTC_ClearITPendingBit(RTC_IT_SEC);
/*ToggleGPIO_LEDpin6each1s*/
//GPIO_WriteBit(GPIO_LED,GPIO_Pin_6,(BitAction)(1-GPIO_ReadOutputDataBit(GPIO_LED,GPIO_Pin_6)));
/*Enabletimeupdate*/
TimeDisplay=1;
/*WaituntillastwriteoperationonRTCregistershasfinished*/
RTC_WaitForLastTask();
/*ResetRTCCounterwhenTimeis23:
59:
59*/
if(RTC_GetCounter()==0x00015180)
{
RTC_SetCounter(0x0);
/*WaituntillastwriteoperationonRTCregistershasfinished*/
RTC_WaitForLastTask();
}
}
if(RTC_GetITStatus(RTC_IT_ALR)!
=RESET)
{
RTC_ClearITPendingBit(RTC_IT_ALR);
printf("\r\nRTCalarmbegin!
");
GPIO_ResetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
Delay_nms(3000);
GPIO_SetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
}
}
/*
*函数名:
Delay_nus(int16)
*描述:
微秒级延时n<32767
*输入:
无
*输出:
无
*/
voidDelay_nus(u16n)
{
u16j;
while(n--)
{
j=8;
while(j--);
}
}
/***************************************************************************/
/*
*函数名:
Delay_nms(int16)
*描述:
毫秒级延时n<32767
*输入:
无
*输出:
无
*/
voidDelay_nms(u16n)
{
while(n--)
{
Delay_nus(1100);
}
}
/***********************《嵌入式系统》课程设计报告*************************
*文件名:
main.c
*描述:
利用STM32的RTC实现一个简易的电子时钟。
在串口助手中显示时间值。
*显示格式为Time:
XX:
XX:
XX(时:
分:
秒),当时间
*计数为:
23:
59:
59时将刷新为:
00:
00:
00。
*另外还能设置闹钟
****************************基于ARM的时钟系统****************************/
intmain(void)