分享到plurk 分享到twitter 分享到facebook

版本 e70864d38f90ccce1d4b336be6c93b499c4fe049

embedded/RTC

Introduction

Real-Time Clock(RTC)是負責記錄時間的元件,出現在需要長期使用時鐘的電子設備中。例如學校定時關閉冷氣的裝置,以及手機上的鬧鈴功能。

System Overview

基本上RTC(Real-time clock)本身就是一個真正的時鐘,利用原本STM本身所內建的振盪器再利用Prescaler降成1Hz讓RTC使用。利用硬體達成的binary-coded decimal (BCD) format,可以把下列與時間有關的資訊儲存,而且不需要任何軟體轉換,因為硬體就已經把資料轉成一般的日期格式。

  • sub-seconds
  • seconds
  • minutes
  • hours in 12-hour or 24-hour format
  • day of the week (day)
  • day of the month (date)
  • month
  • year

可用的功能

  • Alarm A & Alarm B
  • Auto wakeup
  • Timestamp
  • Tamper detection

Block Diagram

[#]_

.. [#] Block Diagram <http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_ p.780 .. image:: /rtc_block.png

Functional Description

Clock Source

.. image:: /clocksource2.png

STM32的 Clock 有分成「SYSCLK」和「RTCCLK」:

SYSCLK為系統的clock有三種來源:

  1. HSI (High-Speed Internal) :16MHz,RC電路
  2. HSE (Low-Speed External):4-26MHz (一般選用8MHz),石英震盪
  3. Main PLL clock

RTCCLK為設備的clock有兩種來源:

  1. LSI (Low-Speed Internal) :40kHz,RC電路震盪
  2. LSE (High-Speed External):32.768kHz,石英震盪

—-> RTC 主要是使用 HSE , LSI , LSE 三種來源 [#]_

.. [#] Clock Source <http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_ p.150


比較 「HSE」, 「LSI」 , 「LSE」三種輸入來源:

  • HSE - 較為耗能, 可以處理像是USB或TV訊號的clock,需要和和另一個clock穩定同步。
  • LSI - 是一個低功耗的clock,可以再停機或待機模式下保持運行,用在auto-wakeup(簡稱AWU)與 watchdog看門狗(簡稱IMDG)。
  • LSE - 它是一個低功耗且“精準”的clock,適合用在時間的精確計算。

Prescaler

.. image:: /stm32 RTC prescaler.png

ck_spre一般而言要降為1Hz的頻率,因為省電的因素STM設計了兩個Prescaler。7 bit非同步prescaler(PREDIV_A)和15 bit同步的prescaler(PREDIV_S)。這兩個prescaler要在RTC_PRER的暫存器設定。ST在Reference有說明當兩個Prescaler都使用時,建議讓非同步的Prescaler讓他有較大的值,以讓系統更省電

所以ck_spre與兩個prescaler的關係為:

.. image:: /ck_spre2.png

例如:

LSE: 32.768kHz / (127+1) / (255+1) = 1Hz

LSI: 32kHz / (127+1) /(249+1) =1Hz

[#]_

.. [#] prescaler <http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_ p.781


Calibration

RTC裡面有兩個校正功能,一個是coarse calibration另一個是smooth calibration。[#]_

.. [#] Calibration <http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_ p.787

這兩個校正不能同時被使用,而前者只能固定修正,後者則可以動態的校正。後者也可以較大範圍及更精準的校正。

1、RTC coarse calibration :

  • 被使用在補償石英震盪器的校正。

  • 在非同步分頻器(ck_apre)的輸出,藉由增加或減少時間的週期達到校正,最大範圍的校正為63ppm~126ppm。

  • 只能在初始化Calendar時候修改,是一個非回授控制系統(opened loop control)。

  • 可以利用AFO_CALIB去計算clock deviation。不能以圖中512Hz的訊號去確認coarse calibration的輸出結果,只能使用ck_spre確認校正的結果。

  • reference clock calibration 和 coarse calibration 不能同時使用。


.. image:: /coarse cal.png

2、RTC smooth calibration:

  • 可以補償石英震盪器的偏差,此偏差可能是晶體老化或者溫度所造成。

  • 利用每個RTCCLK pulse為單位做出小幅調整,來修正RTC的clock頻率。

  • 最大範圍的校正為-487.1ppm~+488.5ppm。

  • 與coarse calibration不同,是一個閉迴路的控制系統(closed loop control)。

  • 可以使用AFO_CALIB來計算時間偏差,而且可直接檢查512Hz和1Hz的校正輸出。


.. image:: /smooth cal.png

3、RTC reference clock detection:

  • 利用外部時鐘校正,其時鐘源必須要比LSE的時鐘還精準。[#]_

.. [#] RTC reference clock <http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_ p.786

RTC Calendar

.. image:: /RTC_calendar.png

讀取Calendar:

當在讀取Calendar時其實並不是真正直接讀取calendar register,其實是在讀shadow register,如果想要直接讀取calendar必須

要設BYPSHAD控制位元為1(在RTC_C Rregister)才能繞過shadow register而直接讀取calender register。

Shadow Register:

  • 通常初始化和讀取的動作採用Shadow Register。

  • 每兩個RTCCLK時間週期,RTC的calendar register (RTC_SSR, RTC_TR, and RTC_DR)的值會被自動更新到Shadow Register。

[#]_

.. [#] Calendar <http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_ p.780


Alternate Function Outputs & Inputs

Alternate function 可以將RTC某些功能對應到輸出的接腳(GPIO Pin),這些輸出可以被選擇成tamp eventtime stamp event

甚至RTC Calibration 的訊號都可以藉由這個功能輸出。 [#]_

可以選擇兩個輸出:

  • 輸出接腳 RTC_AF1(PC13) :

    • RTC_ALARM output: 1. RTC Alarm A 2. RTC Alarm B 3. RTC Wakeup

    • RTC_CALIB output

    • RTC_TAMP1

    • RTC_TS

  • 輸出接腳 RTC_AF2 (PI8) :

    • RTC_TAMP1

    • RTC_TAMP2

    • RTC_TS

.. [#] Alternate Function Outputs & Inputs <http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_ p.227

PI8接腳參考: datasheet p.10

Low Power Modes

  • RTC 設計為最小的耗能,在休眠模式下,RTC將繼續動作。 [#]_

  • 當clock 的來源是LSE 或 LSI,在停止模式與待機模式下,RTC仍然活躍的動作。

  • 在低功率( low power mode)模式下,Alarm, tamper event, time stamp event, and wakeup 依然會被中斷所啟動。

.. image:: /Power.png

比較三種低功耗

  • 睡眠模式(sleep mode):CPU內核停止工作,週邊設備繼續工作。

  • 停機模式(stop mode):CPU內核停止工作,HSI、HSE進入關閉模式,STM32工作狀態仍然保留。(RTC正常運行)

  • 待機模式(standby mode):STM32所有SRAM與暫存器內容,全部丟失,(RTC正常運行)從待機模式喚醒相當於重新復位。

電流消耗

  • 一般運行模式 : 8.5mA

  • 低功耗模式

    • 睡眠模式 : 0.5mA

    • 停機模式 :24uA

    • 待機模式:2uA

.. [#] Low Power Modes <http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_ p.126



Interrupt Application

Alarm

  • 有兩個時鐘Alarm A及Alarm B,可以當作鬧鐘使用。而且相關的register也都會有兩組。[#]_

  • 可利用Mask達成不同時間的鬧鈴效果。

.. image:: /embedded/RTC/alarm_pass.png


.. image:: /Alarm3.png

.. [#] Alarm <http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_ p.781

利用MSKx bits設定遮罩改變Alarm的行為: [#]_

As an example, to configure the alarm time to 23:15:07 on Monday (預設MSK是0000)

.. image:: /MSK2.png

.. [#] Alarm application note <http://www.st.com/st-web-ui/static/active/cn/resource/technical/document/application_note/DM00025071.pdf>_ p.11


Periodic Wakeup Unit

  • 周期性的喚醒(wakeup)可以達成類似一個定時倒數的timer,一個downcounting且會auto-reload 的timer。當它的counter數到0的時候,在打開中斷的情況下會定時觸發中斷。

  • 與Alarm不同,Wakeup是定時觸發中斷,Alarm則是在特定時間才會觸發。

  • 會有兩個因素影響wakeup unit的中斷觸發週期,一個是timer儲存數字的大小,一個是clock source。

設定wakeup period [#]_

有三種組態:

Configuration 1:short wakeup periods

Configuration 2:medium wakeup periods

Configuration 3: long wakeup periods

Configuration 1:

Prescalers connected to the timebase/wakeup unit

.. image:: /wuck1.png

在這個設定中,wakeup unit,會接受由RTCCLK再經過Prescaler的clock。RTC_WUTR(RTC Wakeup Timer Register)為一個

auto-reload的down counting timer,這表示當使用者在初始化時設了一個值x,會在x數到0的時候觸發wakeup flag。

EX:當RTCCLK= 32768 Hz,代表著最小的timebase resolution為61.035μs(數一次的時間),最大則是488.28 μs。

  • 所以這代表著最小可觸發wakeup flag時間為(0x0001 + 1) x 61.035 μs = 122.07 μs

  • 最大可觸發wakeup flag時間為 (0xFFFF+ 1) x 488.28 μs = 2 s

註:STM32禁止timer初始值設為0


Prescalers connected to the wakeup unit for configurations 2 and 3

.. image:: /wuck2.png

2和3的clock source相同,都是用來計算calendar的ck_spre。

Configuration 2:

  • The minimum timebase/wakeup period is (0x0000 + 1) x 61.035 µs = 122.07 µs.

  • The maximum timebase/wakeup period is(0xFFFF+ 1) x 32 s = 131072 s (more than 36 hours).

Configuration 3:

其Clock Source與 Configuration 2 一樣,差在2最大可以從0xFFFF倒數至0x0000,3則是0x1FFFF至0x00000

  • The minimum timebase/wakeup period is: (0x10000 + 1) x 61.035 µs = 250.06 ms

  • The maximum timebase/wakeup period is: (0x1FFFF+ 1) x 32 s = 4194304 s (more than 48 days).

Min. and max. timebase/wakeup period when RTCCLK= 32768Hz

.. image:: /MaxMin.png

.. [#] Periodic Wakeup Unit <http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_ p.782


Time-stamp Function

實體世界裡有「郵戳為憑」來證明信件的時間,在網路世界裡如何來證明電子文件或交易的時間?

利用Time-stamp function 可以為任何電子文件或電子交易提供準確的時間證明,並且驗證其內容自蓋上時戳後是否曾被人修改過。[#]_

Time-stamp function 提供自動幫你儲存日曆的功能

RTC_TSDR register : 會去讀取RTC_DR 裡面的年、月、日、周的資料並儲存

RTC_TSTR register : 會去讀取RTC_TR 裡面的秒、時、分的資料並儲存

RTC_TSSR register : 會去讀取RTC_SSR 裡面的Sub-second 的資料並儲存

.. image:: /timestamp.png

.. [#] Time-stamp Function<http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_ p.790


Tamper Detection Function

Tamper Detection是一個可以檢測系統是否有被竄改的功能。在Tamper發生時,RTC Backup Register會全部自動reset,

達到保護系統的作用。而也可以在Tamper發生時,讓Timestamp發生。 [#]_

Backup registers

在主電源 VDD(1.8~3.6V) 關掉以後,這個backup registers會動作在 VBAT (1.65~3.6V)的低功率電源( low power mode),

所以它不會被system reset重設,它只會被tamper detection重設。或者因為backup domain reset。


如先前提到的,RTC_AF1和RTC_AF2可以被對映成不同接腳的輸入(alternate function )以偵測Tamper Event。

  • TAMPER1 可以被對映到: RTC_AF1(PC13) 或RTC_AF2 (PI8).

  • TAMPER 2可以被對映到: RTC_TAMP2 pin(PI8).

.. [#] Tamper Detection Function<http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_ p.792


補充 : 何謂 Backup Domain ? [#]_

Backup Domain 有下列幾個主要裝置:

  • The RTC

  • The LSE oscillator

  • The backup SRAM when the low power backup regulator is enabled

PC13 to PC15 I/Os, plus PI8 I/O (when available)

當VDD停止供應電源時,Backup Domain會切到standby mode的電壓,換電池供電。在reset後,RTC registers, RTC backup register and backup SRAM會被保護以避免寫入。

SRAM:靜態隨機存取存儲器(Static Random-Access Memory, SRAM)是隨機存取儲存器的一種。所謂的「靜態」,是指這種存儲器只要保持通電,裡面儲存的數據就可以恆常保。

.. image:: /backupdomain.PNG

.. [#] Tamper Detection Function<http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_ p.115

Example of code

下面的範例為先初始化RTC的Calendar再去設定Alarm A。一開始開機時時間為8:29:55,LED3,4,5會在開機五秒前輪流閃爍。但是在第五秒後也就是8:30:00,Alarm A觸發中斷將所有LED燈都關掉。LED6 為auto-wakeup 每秒閃爍直到alarm觸發中止。

.. image:: /RTCdemo.png

Initialize RTC

.. code-block:: prettyprint

RTC_InitTypeDef RTC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);    /* Enable the PWR clock */
PWR_BackupAccessCmd(ENABLE);                          /* Allow access to RTC */

RCC_LSICmd(ENABLE);                                   /* Enable the LSI OSC */
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);   /* Wait till LSI is ready */  
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);               /* Select the RTC Clock Source */

RCC_RTCCLKCmd(ENABLE);                                /* Enable the RTC Clock */
RTC_WaitForSynchro();                  /* Wait for RTC APB registers synchronisation */

/* Configure the RTC data register and RTC prescaler */
RTC_InitStructure.RTC_AsynchPrediv = 127;
RTC_InitStructure.RTC_SynchPrediv = 249;
RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
RTC_Init(&RTC_InitStructure);

[#]_

.. [#] Device overview <http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00037051.pdf>_ p.18


setting time

.. code-block:: prettyprint

   /* set 8:29:55 */
   RTC_TimeTypeDef RTC_TimeStruct;
   RTC_TimeStruct.RTC_Hours = 0x08;
   RTC_TimeStruct.RTC_Minutes = 0x29;
   RTC_TimeStruct.RTC_Seconds = 0x55;

   RTC_SetTime(RTC_Format_BCD, &RTC_TimeStruct);

initialize RTC alarm

.. code-block:: prettyprint

EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

/* EXTI configuration */
EXTI_ClearITPendingBit(EXTI_Line17);
EXTI_InitStructure.EXTI_Line = EXTI_Line17;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

/* Enable the RTC Alarm Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);


setting alarm time

.. code-block:: prettyprint

RTC_AlarmTypeDef RTC_AlarmStructure;
RTC_AlarmCmd(RTC_Alarm_A, DISABLE);   /* disable before setting or cann't write */

/* set alarm time 8:30:0 everyday */
RTC_AlarmStructure.RTC_AlarmTime.RTC_H12     = RTC_H12_AM;
RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours   = 0x08;
RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes = 0x30;
RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds = 0x0;
RTC_AlarmStructure.RTC_AlarmDateWeekDay = 0x31; // Nonspecific
RTC_AlarmStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay; // Everyday 
RTC_SetAlarm(RTC_Format_BCD, RTC_Alarm_A, &RTC_AlarmStructure);

/* Enable Alarm */
RTC_ITConfig(RTC_IT_ALRA, ENABLE);
RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
RTC_ClearFlag(RTC_FLAG_ALRAF);

RTC_Alarm_IRQHandler

.. code-block:: prettyprint

vTaskSuspend( pvLEDTask );
RTC_ClearITPendingBit(RTC_IT_ALRA);
EXTI_ClearITPendingBit(EXTI_Line17);
STM_EVAL_LEDOff(LED4);
STM_EVAL_LEDOff(LED3);
STM_EVAL_LEDOff(LED5);

RTC_WKUP_IRQHandler

.. code-block:: prettyprint

if(RTC_GetITStatus(RTC_IT_WUT) != RESET) { RTC_ClearITPendingBit(RTC_IT_WUT); EXTI_ClearITPendingBit(EXTI_Line22); STM_EVAL_LEDToggle(LED6); }

complete code

LCD的程式碼, 有介紹LCD的腳位, 可顯示字串在畫面上

.. code-block:: c

git clone https://github.com/zxc2694/stm32f4_LCD.git
cd stm32f4_LCD
make
make flash

利用LCD來做RTC的應用, 可以實現時間和日期的顯示

.. code-block:: c

git clone https://github.com/fboris/stm32_RTC_demo.git
cd stm32_RTC_demo
make
make flash

LCD introduction

Pin connection

Specification :http://www.sdec.com.tw/products.php?no=50

It has 14 pin to be used.

  • LCD pin 1 = ground

  • LCD pin 2 = v+

  • LCD pin 3 = ground (or use variable resistor)

  • LCD pin 4 ~ 13 connection :

    • RS = PD.08 (PIN 8 of GPIOD)

    • R/W = PD.09

    • E = PD.10

    • DB0 = PD.00

    • DB1 = PD.01

    • DB2 = PD.02

    • DB3 = PD.03

    • DB4 = PD.04

    • DB5 = PD.05

    • DB6 = PD.06

    • DB7 = PD.07

control method

.. image:: /lcdcontrol.PNG

Reference

RTC application note<http://www.st.com/st-web-ui/static/active/cn/resource/technical/document/application_note/DM00025071.pdf>_

STM32F405xx/07xx, STM32F415xx/17xx, STM32F42xxx and STM32F43xxx Reference Manual <http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>_

LCD introduction (選左邊清單的"LCD控制")<http://faculty.stust.edu.tw/~wjshieh/>_