#include "stm32f10x_lib.h"
#include "stdio.h"
void RCC_Config(void);
void NVIC_Config(void);
void GPIO_Config(void);
void USART_Config(void);
void RTC_Config(void);
u32 USART1_GetTime(void);
void RTC_ReSetTime(void);
void RTC_Display(void);
u32 RTCTime = 0xFFFF;//时钟数据变量
u8 TimeDisplayFlag = 0;//显示时钟标志位
int main(void)
{
RCC_Config();
NVIC_Config();
GPIO_Config();
USART_Config();
printf("\r\n 开始");
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
if(BKP_ReadBackupRegister(BKP_DR1) != 0xFAFA)//初次使用RTC时钟未配置
{
printf("\r\n RTC时钟还没有配置没有配置");
RTC_ReSetTime();
}
else//时钟已配置过
{
if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)//检查是否上电复位
{
printf("\r\n\ 电源上电复位");
}
else if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)//检查是否手动复位
{
printf("\r\n\ 系统复位");
}
RTC_WaitForSynchro();//等待RTC寄存器和APB时钟同步
RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC秒中断
RTC_WaitForLastTask();//等待写操作完成
}
RCC_ClearFlag();//清楚复位标志
while(1)//循环显示RTC时间
{
printf("\r\n 显示时间啊。");
RTC_Display();
if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET)
{
if(USART_ReceiveData(USART1) == 'S')
{
RTC_ReSetTime();
}
}//等待数据到来
}
}
void RCC_Config(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC, ENABLE);
//打开GPIOD和AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//使能串口2时钟
}
void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;//定义NVIC初始化结构体变量
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//配置优先级组为1位
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQChannel;//中断通道为RTC全局中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//1位优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//0位子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//中断通道使能
NVIC_Init(&NVIC_InitStructure);//初始化NVIC结构体
}
void RTC_IRQHandler(void)
{
if(RTC_GetITStatus(RTC_IT_SEC) != RESET)
{
RTC_ClearITPendingBit(RTC_IT_SEC);//必须软件清零RTC秒中断
TimeDisplayFlag = 1;//使能更新显示时间
RTC_WaitForLastTask();//等待写操作完成
//当RTC时钟为23:59:59时复位计数器
if(RTC_GetCounter() == 0x00015180)
{
RTC_SetCounter(0x0); //RTC计数器清零
RTC_WaitForLastTask();//等待写操作完成
}
}
}
void GPIO_Config(void)
{
//设置Tx(PA9)为推拉输出模式
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//选择PIN4 PIN5
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //引脚频率50M
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//引脚设置推拉输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
//=========== PA8=====
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //引脚频率50M
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//引脚设置推拉输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
//配置USART1 Rx (PA10)为悬浮输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void USART_Config(void)
{
USART_InitTypeDef USART_InitStructure; //定义串口初始化结构体
USART_InitStructure.USART_BaudRate = 115200;//波特率115200
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位数据
USART_InitStructure.USART_StopBits = USART_StopBits_1;//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);//初始化串口2
USART_Cmd(USART1, ENABLE);//串口2使能
/* Enable PWR and BKP clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
/* Allow access to BKP Domain */
PWR_BackupAccessCmd(ENABLE);
}
u32 USART1_GetTime(void)
{
u8 i = 0;
u8 j = 0;
u8 Hour = 0;
u8 Min = 0;
u8 Sec = 0;
u32 Temp[3][2] = {{0, 0}, {0, 0}, {0, 0}};
while(j < 3)
{
while(i < 2)
{
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)//等待数据到来
{
}
Temp[j][i++] = (USART_ReceiveData(USART1));//将从串口接收到数据存放数据
printf("%d" , Temp[j][i-1] - 0x30);
}
i = 0;
j++;
}
Hour = (Temp[0][1] - 0x30) + ((Temp[0][0] - 0x30) * 10);//计算小时
Min = (Temp[1][1] - 0x30) + ((Temp[1][0] - 0x30) * 10);//计算分
Sec = (Temp[2][1] - 0x30) + ((Temp[2][0] - 0x30) * 10);//计算秒
if(Hour > 23 || Min > 59 || Sec > 59)//检查输入的时钟数据是否正确
{
return 0xFFFF;
}
return (Hour *3600 + Min * 60 + Sec);
}
void RTC_ReSetTime(void)
{
while(1)
{
printf("\r\n\ 按HHMMSS格式输入时钟数据");
RTCTime = USART1_GetTime();
if(RTCTime == 0xFFFF)
{
printf("\r\n\ 输入非法数据,请重新输入");
}
else
{
RTC_WaitForLastTask();
printf("\r\n 正在设置RTC计数器的值");
RTC_SetCounter(RTCTime);//设置 RTC 计数器的值
RTC_WaitForLastTask();
printf("\r\n\ 时钟配置完成");
break;
}
}
}
void RTC_Config(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
//打开电源管理和备份寄存器时钟
PWR_BackupAccessCmd(ENABLE);//使能RTC和备份寄存器的访问(复位默认关闭)
BKP_DeInit();//BKP外设复位
RCC_LSEConfig(RCC_LSE_ON);//打开外部低速晶体
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)//等待LSE准备好
{
}
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//选择LSE位RTC时钟
RCC_RTCCLKCmd(ENABLE);//使能RTC时钟
RTC_WaitForSynchro();//等待RTC寄存器和APB时钟同步
RTC_WaitForLastTask();
//等待RTC寄存器写操作完成(必须在对RTC寄存器写操作钱调用)
RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC秒中断
RTC_WaitForLastTask(); //等待RTC寄存器写操作完成
RTC_SetPrescaler(32767);
//设置RTC预分频器值产生1秒信号计算公式 fTR_CLK = fRTCCLK/(PRL+1)
RTC_WaitForLastTask();//等待RTC寄存器写操作完成
}
void RTC_Display(void)
{
if(TimeDisplayFlag == 1)//时钟更新
{
u32 THH = 0, TMM = 0, TSS = 0;
RTCTime = RTC_GetCounter();//获取当前RTC计数值
THH = RTCTime/3600;//计算时钟数据
TMM = (RTCTime % 3600)/60;
TSS = (RTCTime % 3600)% 60;
printf("\r\n 当前时间: %0.2d:%0.2d:%0.2d",THH, TMM, TSS);
TimeDisplayFlag = 0;
}
}
int fputc(int ch, FILE *f)
{
USART_SendData(USART1, (u8) ch);
/* Loop until the end of transmission */
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{
}
return ch;
}
//好像是无法进入中断函数,蛋碎了。麻烦高手帮忙看看,可能还有其他问题。 |