#include "stm32f10x_lib.h" #include"stdio.h" vu32 TimeDisplay = 0; void RCC_Configuration() { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1 , ENABLE); //打開APB2外設 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能電源時鐘和備份區時鐘 } void NVIC_Configuration( ) { NVIC_InitTypeDef NVIC_InitStructure; //定義一個中斷結構體 NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQChannel; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //無搶占式優先級 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //響應優先級為0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void GPIO_Configuration() { GPIO_InitTypeDef GPIO_InitStructure; //定義GPIO初始化結構體 //--------將USART1 的TX 配置為復用推挽輸出 AF_PP---------------------// GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; //管腳位置定義,標號可以是NONE、ALL、0至15。 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz; //輸出速度2MHz GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //推挽輸出模式 Out_PP GPIO_Init(GPIOA,&GPIO_InitStructure); //E組GPIO初始化 //--------將USART1 的RX 配置為浮空輸入 IN_FLOATING---------------------// GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; //管腳位置定義 //輸入模式下配置輸出速度無意義 //GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz; //輸出速度2MHz GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空輸入 IN_FLOATING GPIO_Init(GPIOA,&GPIO_InitStructure); //C組GPIO初始化 } void USART1_Configuration( ) { USART_InitTypeDef USART_InitStructure; //串口設置恢復默認參數 USART_ClockInitTypeDef USART_ClockInitStructure; 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; //打開Rx接收和Tx發送功能 USART_Init(USART1, &USART_InitStructure); //初始化 USART_Cmd(USART1, ENABLE); //啟動串口 //-----如下語句解決第1個字節無法正確發送出去的問題-----// USART_ClearFlag(USART1, USART_FLAG_TC); // 清標志 } void RTC_Configuration(void) { PWR_BackupAccessCmd(ENABLE); //取消備份區寫保護(寫保護在每次硬件復位后被使能) BKP_DeInit(); //備份區恢復默認 RCC_LSEConfig(RCC_LSE_ON); //LSE(外部低速振蕩時鐘)打開 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); //等待LSE準備就緒 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //將LSE作為RTC時鐘 RCC_RTCCLKCmd(ENABLE); //RTC時鐘打開 RTC_WaitForSynchro(); //等待RTC寄存器同步 RTC_WaitForLastTask(); //對RTC任何寄存器的操作,都必須在前一次寫操作完成后執行 RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能 秒中斷 RTC_WaitForLastTask(); //對RTC任何寄存器的操作,都必須在前一次寫操作完成后執行 RTC_SetPrescaler(32767); //對RTC時鐘分頻 32.768K/(32767+1)=1Hz RTC_WaitForLastTask(); //對RTC任何寄存器的操作,都必須在前一次寫操作完成后執行 } u8 USART_Scanf(u32 value) { u32 index = 0; u32 tmp[2] = {0, 0}; while(index < 2) { /* Loop until RXNE = 1 */ while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET); tmp[index++] = (USART_ReceiveData(USART1)); if((tmp[index - 1] < 0x30) || (tmp[index - 1] > 0x39)) { printf("\n\rPlease enter valid number between 0 and 9"); index--; } } /* Calculate the Corresponding value */ index = (tmp[1] - 0x30) + ((tmp[0] - 0x30) * 10); /* Checks */ if(index > value) { printf("\n\rPlease enter valid number between 0 and %d", value); return 0xFF; } return index; } u32 Time_Regulate(void) { u32 Tmp_HH = 0xFF, Tmp_MM = 0xFF, Tmp_SS = 0xFF; printf("\r\n==============Time Settings====================================="); printf("\r\n Please Set Hours"); while(Tmp_HH == 0xFF) { Tmp_HH = USART_Scanf(23); } printf(": %d", Tmp_HH); printf("\r\n Please Set Minutes"); while(Tmp_MM == 0xFF) { Tmp_MM = USART_Scanf(59); } printf(": %d", Tmp_MM); printf("\r\n Please Set Seconds"); while(Tmp_SS == 0xFF) { Tmp_SS = USART_Scanf(59); } printf(": %d", Tmp_SS); /* Return the value to store in RTC counter register */ return((Tmp_HH*3600 + Tmp_MM*60 + Tmp_SS)); } void Time_Adjust(void) { RTC_WaitForLastTask(); //對RTC任何寄存器的操作,都必須在前一次寫操作完成后執行 RTC_SetCounter(Time_Regulate()); //設置計數值 RTC_WaitForLastTask(); //對RTC任何寄存器的操作,都必須在前一次寫操作完成后執行 } void Time_Display(u32 TimeVar) { u32 THH = 0, TMM = 0, TSS = 0; THH = TimeVar/3600; //計算小時 TMM = (TimeVar % 3600)/60;//計算分 TSS = (TimeVar % 3600)% 60; //計算秒 printf("Time: %0.2d:%0.2d:%0.2d\r\n",THH, TMM, TSS); } void Time_Show(void) { while(1) //infinite loop { if(TimeDisplay == 1) //if 1s has passed { Time_Display(RTC_GetCounter()); //display current time TimeDisplay = 0; } } } int fputc(int ch, FILE *f) //在源代碼中添加fputc函數,可以用printf函數做為調試輸出 { /* 將Printf內容發往串口 */ USART_SendData(USART1, (u8) ch); /* 循環,直到傳送完成 */ while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); return ch; } int main() { RCC_Configuration(); GPIO_Configuration(); NVIC_Configuration( ); USART1_Configuration(); if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5){ //檢查是否第一次配置RTC printf("\r\n\n RTC not yet configured...."); RTC_Configuration(); printf("\r\n RTC configured...."); Time_Adjust(); BKP_WriteBackupRegister(BKP_DR1, 0xA5A5); } else{ if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET) //檢查是否是上電復位 { printf("\r\n\n Power On Reset occurred...."); } else if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET) //檢查是否是復位腳復位 { printf("\r\n\n External Reset occurred...."); } printf("\r\n No need to configure RTC...."); RTC_WaitForSynchro(); RTC_ITConfig(RTC_IT_SEC, ENABLE); RTC_WaitForLastTask(); } RCC_ClearFlag(); //清除復位標志 Time_Show(); } //秒中斷函數 ,在 stm32f10x_it.c 里 void RTC_IRQHandler(void) { if(RTC_GetITStatus(RTC_IT_SEC) != RESET) //判斷是否是秒中斷 { RTC_ClearITPendingBit(RTC_IT_SEC); //清除RTC秒中斷標志 TimeDisplay = 1; //將標志位置1,代表1s過去 RTC_WaitForLastTask(); //wait until last write operation on RTC regisiters has finished if(RTC_GetCounter() == 0x00015180) //reset RTC counter when time is 23:59:59 { RTC_SetCounter(0x0); RTC_WaitForLastTask(); //wait until last write operation on RTC regisiters has finished } } }
|