本文例子參考《STM32單片機開發實體——基于Proteus虛擬仿真與HAL/LL庫》
源代碼:https://github.com/LanLinnet/STM33F103R6
專案要求
單片機每隔1s以“YYYY-MM-DD HH:MM:SS”的格式自動向串口輸出日期和時間資訊(“ASCII格式”),起始時間設為“2022-05-20 05:20:00”,自動走時,按下按鈕BTN,時間自動恢復為起始時間,串口通信引數:波特率為19200bit/s,無校驗,
硬體設計
-
在第一節的基礎上,在Proteus中添加電路如下圖所示,

除錯程序也可以添加一個虛擬儀器VIRTUAL TERMINAL,配置如下,用來查看單片機收到的串口資料,具體參考第11節,

-
RTC簡介:
1)RTC是Real Time Clock(實時時鐘)的首字母縮寫形式,是一種常用的電子功能模塊,有獨立的RTC芯片,也有集成于單片機內的獨立功能模塊,常用于制作電子鐘、電子表、電子萬年歷等計時工具,
2)STM32單片機的RTC可以看作特殊的定時器,它可以根據輸入的時鐘源自動計時,此外還提供了1個“鬧鐘”中斷源和1個“秒”中斷源, -
打開CubeMX,建立工程,
首先,設定PA5為GPIO_EXTI5,點擊“Categories”中的“GPIO”,將"GPIO mode"設定為External Interrupt Mode With Falling edge trigger detection,也就是下降沿觸發,

隨后,點擊“Timers”串列中的“RTC”進行實時時鐘配置,選中“Active Clock Source”和“Active Calendar”復選框,激活時鐘源和日歷,在“Parameter Settings”中設定時間和日期如下圖所示,其中,“Data Format”設定資料格式有2個選項:“Binary Data Format”(字面意思是二進制資料格式,實際是十進制資料格式)和“BCD Data Format”(BCD碼資料格式),實際設定時間時任意選其中一個即可,

然后,點擊“Connectivity”串列中的“USART”進行串口配置,將Mode設定為Asynchronous(異步),波特率設為19200Bits/s,字長設為8Bits,校驗設為None,停止位設為1,資料傳送設為Receive and Transmit(接收與發送),設定完成后,會看到右側的PA9和PA10引腳被自動設定為USART1_TX和USART1_RX,即USART1的發送端和接收端,

再點擊“NVIC Settings”,選中USART global interrupt和EXTI line[9:5] interrupts,使能Enabled串口1的中斷功能和GPIO的外部中斷,

最后,實踐中為了追求時間的精度,我們會采用外部低速晶振LSE作為RTC的時鐘源,由于本次采用Proteus進行仿真,我們選擇默認的LSI作為RTC的時鐘源,

-
點擊“Generator Code”生成Keil工程,
軟體撰寫
-
本次我們需要實作實時時鐘自動走時,并通過串口發送輸出,需要用到RTC相關函式其API檔案如下:
HAL_RTC_GetTime RTC時間獲取函式

HAL_RTC_GetDate RTC日期獲取函式

HAL_RTC_SetTime RTC時間設定函式

HAL_RTC_SetDate RTC日期設定函式

其中,介紹兩個結構體:
時間結構體sTime有以下3個元素- Hours(時),資料型別為uint8_t,
- Minutes(分),資料型別為uint8_t,
- Seconds(秒),資料型別為uint8_t,
日期結構體
sDate有以下4個元素- Year(年),資料型別為uint8_t,取值范圍為0-99(BIN格式)或0-0x99(BCD格式),
- Month(月),資料型別為uint8_t,取值范圍為1-12(BIN格式)或1-0x12(BCD格式),
- Date(日),資料型別為uint8_t,取值范圍為1-31(BIN格式)或1-0x31(BCD格式),
- WeekDay(星期),資料型別為uint8_t,取值范圍為1-7,
另外,
Format有以下2個宏定義選項- RTC_FORMAT_BIN:字面意思是二進制資料格式,實際是十進制資料格式
- RTC_FORMAT_BCD:BCD碼資料格式
-
點擊“Open Project”在Keil中打開工程,雙擊“main.c”檔案,
-
首先我們需要在main.c檔案中的最前面引入標準輸入輸出頭檔案
/* USER CODE BEGIN Includes */ #include "stdio.h" /* USER CODE END Includes */在main函式中定義日期結構體和時間結構體
/* USER CODE BEGIN 1 */ //定義日期結構體和時間結構體 RTC_DateTypeDef sDateStructure; RTC_TimeTypeDef sTimeStructure; char sYear[5]; char sMonth[3]; char sDate[3]; char sHour[3]; char sMin[3]; char sSec[3]; /* USER CODE END 1 */隨后,在
/* USER CODE BEGIN 4 */和/* USER CODE END 4 */中插入外部中斷回呼函式,代碼如下/* USER CODE BEGIN 4 */ //外部中斷回呼函式 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { //定義日期結構體和時間結構體 RTC_DateTypeDef sDateStructure; RTC_TimeTypeDef sTimeStructure; if(GPIO_Pin == GPIO_PIN_5) //檢測到EXTI5線產生外部中斷事件 { //設定日期 sDateStructure.Year = 22; sDateStructure.Month = 5; sDateStructure.Date = 20; sDateStructure.WeekDay = 5; //十進制格式 HAL_RTC_SetDate(&hrtc, &sDateStructure, RTC_FORMAT_BIN); //設定時間 sTimeStructure.Hours = 0x05; sTimeStructure.Minutes = 0x20; sTimeStructure.Seconds = 0; //BCD碼格格式 HAL_RTC_SetTime(&hrtc, &sTimeStructure, RTC_FORMAT_BCD); while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == GPIO_PIN_RESET); //直到按鍵松開 } } /* USER CODE END 4 */最后,在
while(1)中插入代碼如下,進行RTC和串口發送相關操作/* USER CODE BEGIN WHILE */ while (1) { //十進制格式 HAL_RTC_GetTime(&hrtc, &sTimeStructure, RTC_FORMAT_BIN); //RTC時間獲取函式 //BCD碼格式 HAL_RTC_GetDate(&hrtc, &sDateStructure, RTC_FORMAT_BCD); //RTC日期獲取函式 //格式轉換為字串 sprintf(sYear, "%04x", 0x2000+sDateStructure.Year); sprintf(sMonth, "%02x", sDateStructure.Month); sprintf(sDate, "%02x", sDateStructure.Date); sprintf(sHour, "%02d", sTimeStructure.Hours); sprintf(sMin, "%02d", sTimeStructure.Minutes); sprintf(sSec, "%02d", sTimeStructure.Seconds); //列印日期 HAL_UART_Transmit(&huart1, (uint8_t *)sYear, 4, 4); HAL_UART_Transmit(&huart1, (uint8_t *)&"-", 1, 1); HAL_UART_Transmit(&huart1, (uint8_t *)sMonth, 2, 2); HAL_UART_Transmit(&huart1, (uint8_t *)&"-", 1, 1); HAL_UART_Transmit(&huart1, (uint8_t *)sDate, 2, 2); HAL_UART_Transmit(&huart1, (uint8_t *)&" ", 1, 2); //列印時間 HAL_UART_Transmit(&huart1, (uint8_t *)sHour, 2, 2); HAL_UART_Transmit(&huart1, (uint8_t *)&":", 1, 1); HAL_UART_Transmit(&huart1, (uint8_t *)sMin, 2, 2); HAL_UART_Transmit(&huart1, (uint8_t *)&":", 1, 1); HAL_UART_Transmit(&huart1, (uint8_t *)sSec, 2, 2); HAL_UART_Transmit(&huart1, (uint8_t *)&"\n\r", 2, 2); //延時 HAL_Delay(1000); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
聯合除錯
- 點擊運行,生成HEX檔案,
- 在Proteus中加載相應HEX檔案,點擊運行,可以看到“Virtual Terminal”從“2022-05-20 05:20:00”開始自動走時,每秒輸出一個結果,按下BTN按鍵,又重新從“2022-05-20 05:20:00”開始自動走時,

轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/478739.html
標籤:嵌入式
