volatile 与レジスタ:SysTick->VAL 女性在读什么 – Zw-awa
このキーワードはよく出てきます。volatile。
電影写空電影延時,少长长长新:
volatile uint32_t i;
for (i = 0; i < 72000U; i++)
{
}
見た目は大丈夫です i この単語は実際にはバインドされており、コンパイラーに、この変数は毎回読み取られ、再度読み取ることができることを伝えます。
volatile がない場合は、空のループが残ります。
先掴み volatile 去掉:
uint32_t i;
for (i = 0; i < 72000U; i++)
{
}
このサイクルには点亮 LED はなく、後で使用される変数は変更されず、関数も呼び出されません。
Compiler 在电影可以会想:結果に変化がないのに、これを 72000 回プラス 1 回する必要は何ですか?サイクル全体を削除できます。
プラス volatile 後:
volatile uint32_t i;
for (i = 0; i < 72000U; i++)
{
}
i++ もはや単なるコンパイラではありません i 現実的な読み書きのサイクルをそのまま捨てることはできません。
コードにいくつかの変更が発生する可能性があります
変数を 1 つ見る:
static uint32_t tick_ms = 0U;
単一の割り込みを入力するためにタイマーが 1ms であると仮定します。割り込み関数里力加一:
void TIM1_UP_IRQHandler(void)
{
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
{
tick_ms++;
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
}
}
反対側のメインループは、1000 に変更されるのを待ちます。
while (tick_ms < 1000U)
{
}
メインサイクルだけを見て、tick_ms 在 while パス上の別の実行パスに割り込み関数が与えられるため、実際に変更される可能性があります。
static volatile uint32_t tick_ms = 0U;
各判定のメインループです tick_ms < 1000U いいえ、それは可能です。 volatile 時、電器性利得は電制の 0 に達することができ、また新しい値を確認することができます。 tick_ms 1000 に追加すると、ホスト発行前、つまり古いものは 0 になります。
それで、volatile 二米地で常用:
| 状況 | なぜ? volatile |
|---|---|
| 空のループ回数変数 | 这几次读写それ自体が循環存在の意味であり、削除することはできない |
| 割り込みと共通アクセス変数のメインサイクル | 安全な最高のコードを一目で確認できる方法名 |
-O0 問題が存在しないのではなく、問題を静かにしておきます。
この言葉を書き写すのは私の不愉快なことであり、私は心の中でこれを手就握报机等搧舧冒 -O0,设设デザイナー不是動我的存储;少書 volatile コードも正常に実行できます。
ただし、同じコードをチームの友人と共有する場合、最適化レベルを変更したり、将来的にプログラムのサイズを削減するために最適化が開かれた後、コンパイラの処理方法を変更することができます。 volatile の変数、またはそれを明確にマークする必要があります。作業活動のために、表現のコードは意味を意味します。
2 段階の操作を分割できない 1 段階にする、複数の場所で同じ変数を同時に変更する、順序を自動的にソートする、または抖力ボタンを解決するなどの機能はありません。 volatile 提供できる。
SysTick->VAL 会用会自由可
volatile その後、関数内のこの行をもう一度見てみましょう。
current_val = SysTick->VAL;
current_val は普通说明、右へ SysTick->VAL ないです。VAL SysTick の旅行安全技です。 SysTick の起動後、カーネル クロックは 1 秒ずつ進み、ハンドマシンが VAL 凯一;凯0に達したら、再インストールを再起動します。
一行 C コードはありません VAL 1 未満であっても、その変更はこのハードウェアの SysTick であるため、永久に変更されます。
ビデオのファイルが SysTick の決定分方に排列される一情加体:
typedef struct
{
__IO uint32_t CTRL;
__IO uint32_t LOAD;
__IO uint32_t VAL;
__I uint32_t CALIB;
} SysTick_Type;
電影またつか SysTick これは、このレジスタのグループを指すポインタとして定義されます。したがって:
SysTick->VAL
最後の「コンテンツ SysTick はこの組織美丽、再读任么的」 VAL」。-> これは C 言語のポインタ メンバ アクセスの構造のままですが、これは異なり、通常のメモリ上にあるのではなく、チップによって指定されたハードウェア アドレス内にあります。
標準 core_cm3.h 中国__IO 定義済み volatileつまり、ファイルはすでにそこにあります VAL よくマークされています: 毎回読んでください SysTick->VAL,都は実際に現在のハードウェア カウント値を読み取る必要があります。
したがって、これら 2 行の意味は同じではありません。
start_val = SysTick->VAL;
current_val = SysTick->VAL;
右側は2つの時間が同じです start_val、current_val これは 2 つの回答を保存するために使用される単純な変数です。初めて 30000 を読み取ると、初めて 28000 を読み取り、SysTick レジスタが変化します。プログラムは再び 2 つの保存された値を使用します。
SysTick レジスタだけではありません
レジスタはソフトウェアの監視やハードウェアの制御を行うための窓口であり、SysTick独自のものではありません。これはすでに GPIO ではなく、ソフトウェアの監視とハードウェアの制御のためのウィンドウであり、それぞれに一連のレジスタがあります。
| 写法 | 誰が変えたのか | 何を読むのですか? |
|---|---|---|
SysTick->VAL |
SysTickカウンター | 残りのカウント |
TIM2->CNT |
TIM2タイマー | 現在のカウント値 |
GPIOB->IDR |
电影上海电影电影 | PB電視合電の入力状態 |
ボタンを押すとPB11のレベルが低くなります GPIOB->IDR これらが発生すると、GNDに電圧がかかります。TIM2->CNT 画加加一または宇一、さえない main 送信中に書き込みを書きました。
標準ライブラリ関数はこれらのレジスタの関数そのものです。例えば:
GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)
それが最後の読み物です GPIOB->IDR 中 PB11 に対応しています。 機能名 動作私はいくつかの詳細を省略しています、ハードウェア レジスタ レジスタはまだまだ地傷がありますが、いくつかの詳細は省いています
設定を書き込むために使用されるメインレジスタもあります。SysTick->LOAD Tell SysTick 每轮从多就名种倒数、タイマーの構成レジスタが次の動作を決定します。
最後に彼はこう言いました
volatile 先电影者“电影器会不可ハンドル安全读書省掉”;登録再再论我们“なぜ最も多くは何が最もですか?SysTick->VAL 会食数、TIM2->CNT ミーティングGPIOB->IDR 1 つの登録名を見た後は、「誰が変更しても変更できます」というように、それぞれの場所の名前を覚えておくことがより重要です。
最後に彼はこう言いました
初见端倪……