これは、PICチュートリアルシリーズの5番目のチュートリアルであり、PIC16F877Aでタイマーを学習して使用するのに役立ちます。以前のチュートリアルでは、PICとMPLABX IDEの概要から始め、PICを使用してLEDを点滅させる最初のPICプログラムを作成し、PICマイクロコントローラーの遅延機能を使用してLED点滅シーケンスを作成しました。ここで、前のチュートリアルハードウェアで使用したのと同じLED点滅シーケンスを使用してみましょう。これを使用して、PICMCUでタイマーを使用する方法を学習します。このチュートリアルでは、LEDボードにボタンをもう1つ追加しました。詳細については、チュートリアルをご覧ください。
タイマーは、組み込みプログラマーにとって重要な主力製品の1つです。私たちが設計するすべてのアプリケーションには、指定された時間間隔の後に何かをオンまたはオフにするなど、何らかのタイミングアプリケーションが含まれます。さて、しかし、同じことを行う遅延マクロ(__delay_ms())がすでにあるのに、なぜタイマーが必要なのですか?
Delay()があるのになぜタイマーなのか?
遅延マクロは「ダンプ」遅延と呼ばれます。なぜならディレイ機能の実行中にMCUはちょうど遅延を作成することにより、ダンプを座っています。このプロセス中、MCUはADC値をリッスンしたり、レジスタから何かを読み取ったりすることはできません。したがって、時間遅延が正確または長い必要がないLED点滅などのアプリケーションを除いて、遅延機能を使用することはお勧めできません。
遅延マクロには、次の欠点もあります。
- delayマクロの場合、delayの値は定数でなければなりません。プログラム実行中に変更することはできません。したがって、プログラマーが定義したままです。
- タイマーを使用する場合と比較して、遅延は正確ではありません。
- マクロを使用して、より大きな値の遅延を作成することはできません。たとえば、遅延マクロを使用して30分の遅延を作成することはできません。使用できる最大遅延は、使用する水晶発振器に基づいています。
PICマイクロコントローラータイマー:
物理的には、タイマーは値が継続的に255に増加するレジスタであり、その後、最初からやり直します:0、1、2、3、4… 255…. 0、1、2、3….。..等。
PIC16F877A PIC MCUは、3つのタイマーモジュールがあります。それらは、Timer0、Timer1、Timer2という名前です。タイマー0とタイマー2は8ビットタイマーで、タイマー1は16ビットタイマーです。このチュートリアルでは、アプリケーションにタイマー0を使用します。タイマー0を理解すると、タイマー1とタイマー2でも簡単に作業できるようになります。
Timer0モジュールのタイマー/カウンターには次の機能があります。
- 8ビットタイマー/カウンター
- 読み取り可能および書き込み可能
- 8ビットソフトウェアプログラマブルプリスケーラ
- 内部または外部クロック選択
- FFhから00hへのオーバーフロー時に割り込み
- 外部クロックのエッジ選択
タイマーの使用を開始するには、8ビット/ 16ビットタイマー、プリスケーラー、タイマー割り込み、フォーカスなどのいくつかの凝った用語を理解する必要があります。それでは、それぞれが実際に何を意味するのかを見てみましょう。先に述べたように、PIC MCUには8ビットタイマーと16ビットタイマーの両方がありますが、それらの主な違いは、16ビットタイマーの解像度が8ビットタイマーよりもはるかに優れていることです。
プリスケーラは、タイマーのステータスを上げるロジックに到達する前にオシレータクロックを分割するマイクロコントローラの一部の名前です。プリスケーラIDの範囲は1〜256で、プリスケーラの値はOPTIONレジスタ(プルアップ抵抗に使用したものと同じ)を使用して設定できます。たとえば、プリスケーラの値が64の場合、64番目のパルスごとにタイマーが1ずつ増加します。
タイマーが増加し、最大値の255に達すると、割り込みがトリガーされ、再び0に初期化されます。この割り込みはタイマー割り込みと呼ばれます。この割り込みは、この特定の時間がラップしたことをMCUに通知します。
fOSCは発振器の周波数を表し、それが使用する水晶の周波数です。タイマレジスタにかかる時間は、プリスケーラの値とFoscの値によって異なります。
プログラミングと作業の説明:
このチュートリアルでは、2つのボタンを2つの入力として設定し、8つのLEDを8つの出力として設定します。最初のボタンは時間遅延(プッシュごとに500ms)を設定するために使用され、2番目のボタンはタイマーシーケンスの点滅を開始するために使用されます。たとえば、最初のボタンを3回押すと(500 * 3 = 1500ms)、遅延は1.5秒に設定され、ボタン2を押すと、各LEDが事前定義された時間遅延でオンとオフになります。このチュートリアルの最後にあるデモンストレーションビデオを確認してください。
さて、これらの基本を念頭に置いて、コードセクションの最後にあるプログラムを見てみましょう。
プログラムを取得しなくても大丈夫ですが、取得した場合は!! あなた自身にクッキーを与えて、あなたの出力を楽しむためにプログラムを捨ててください。他の人のために、私はプログラムを意味のある部分に分割し、各ブロックで何が起こっているかを説明します。
コードの最初の数行は常に構成設定とヘッダーファイルであるため、以前のチュートリアルですでに行っているため、これについては説明しません。
次に、すべての行をスキップして、void main関数に直接ジャンプします。この関数内には、Timer0のPORT構成があります。
void main(){/ *****タイマーのポート構成****** / OPTION_REG = 0b00000101; //外部周波数と64をプリスケーラとして持つTimer0 //プルアップも有効にしますTMR0 = 100; //0.0019968sの時間値をロードします; delayValueは、TMR0IE = 1のみで0〜256の範囲にすることができます。// PIE1レジスタのタイマー割り込みビットを有効にするGIE = 1; //グローバル割り込みを有効にするPEIE = 1; //ペリフェラル割り込みを有効にする/ *********** ______ *********** /
これを理解するには、PICデータシートのOPTIONレジスタを確認する必要があります。
前のチュートリアルで説明したように、ビット7は、PORTBの弱いプルアップ抵抗を有効にするために使用されます。上の図を見ると、ビット3が0になっており、設定されている次のプリスケーラをWatchDogTimer(WDT)ではなくタイマーに使用するようにMCUに指示しています。タイマーモードは、ビット5T0CSをクリアすることで選択されます。
(OPTION_REG <5>)
ここで、bits2-0を使用して、タイマーのプリスケーラー値を設定します。上記の表に示すように、プリスケーラ値を64に設定するには、ビットを101に設定する必要があります。
次に、Timer0に関連付けられているレジスタを調べてみましょう。
タイマーは一度設定されるとインクリメントを開始し、256の値に達した後にオーバーフローします。この時点でタイマー割り込みを有効にするには、レジスタTMR0IEをハイに設定する必要があります。タイマー0自体はペリフェラルであるため、PEIE = 1にしてペリフェラル割り込みを有効にする必要があります。最後に、グローバル割り込みを有効にして、操作中に割り込みについてMCUに通知されるようにする必要があります。これは、GIE = 1にすることで実行されます。
遅延=((256-REG_val)*(Prescal * 4))/ Fosc
上記の式は、Delayの値を計算するために使用されます。
どこ
REG_val = 100;
プリスケール= 64
Fosc = 20000000
これを計算すると、
遅延= 0.0019968s
次の一連の行は、I / Oポートを設定することです。
/ ***** I / Oのポート構成****** / TRISB0 = 1; // PORTBピン0がボタン1の入力として使用されることをMCUに指示します。TRISB1= 1; // PORTBピン1がボタン1の入力として使用されることをMCUに指示します。TRISD= 0x00; //ポートDのすべてのピンが出力されるようにMCUに指示しますPORTD = 0x00; //すべてのピンを0に初期化します/ *********** ______ *********** /
同じハードウェアを使用しているため、これは前のチュートリアルと同じです。入力として別のボタンを追加したことを除いて。これは、行TRISB1 = 1によって実行されます。
次に、無限の while ループの裏返しに、2つのコードブロックがあります。1つはユーザーからタイマー入力を取得するために使用され、もう1つはLEDを介して遅延のシーケンスを実行するために使用されます。各行にコメントを付けて説明しました。
while(1){カウント= 0; //メインループ中にタイマーを実行しない// *******ユーザーから番号遅延を取得する**** ////// if(RB0 == 0 && flag == 0)//いつ与えられた入力{get_scnds + = 1; // get_scnds = get_scnds + http:// Increment variable flag = 1; } if(RB0 == 1)//連続インクリメントを防ぐためflag = 0; / *********** ______ *********** /
get_scndsという変数は、ユーザーがボタン1を押すたびにインクリメントされます。フラグ(ソフトウェア定義)変数は、ユーザーがボタンから指を離すまでインクリメントプロセスを保持するために使用されます。
// *******シーケンスを遅延で実行**** ////// while(RB1 == 0){PORTD = 0b00000001 <
ボタン2が押されると、次のブロックが実行されます。ユーザーはボタン1を使用して必要な時間遅延をすでに定義しており、変数get_scndsに保存されているためです。hscndと呼ばれる変数を使用します。この変数は、ISR(割り込みサービスルーチン)によって制御されます。
割り込みサービスルーチンは、タイマ0がオーバーフローするたびに呼び出されること割り込みです。次のブロックでISRによってどのように制御されているかを見てみましょう。 たとえば 、ボタンを押すたびに時間遅延を0.5秒(0.5秒)インクリメントし、変数 hscnd を0.5秒ごとにインクリメントする必要があります。 0.0019968秒(〜2ms)ごとにオーバーフローするようにタイマーをプログラムしたので、250 * 2ms = 0.5秒であるため、0.5秒の カウント 変数を カウント するには250にする必要があります。したがって、カウントが250(250 * 2ms = 0.5秒)になると、それは0.5秒であるため、 hscnd を1インクリメントし、カウントをゼロに初期化します。
void interrupt timer_isr(){if(TMR0IF == 1)//タイマーオーバーフローが原因でタイマーフラグがトリガーされました{TMR0 = 100; //タイマー値をロードしますTMR0IF = 0; //タイマー割り込みフラグカウントをクリアします++; } if(count == 250){hscnd + = 1; // hscndは、0.5秒ごとにインクリメントされますcount = 0; }}
したがって、この値を使用して hscnd と比較し、ユーザー定義の時間に基づいてLEDをシフトします。また、前回のチュートリアルと非常によく似ています。
これで、プログラムを理解して機能させることができました。
回路図とプロテウスシミュレーション:
いつものように、最初にProteusを使用して出力を確認しましょう。ここに、Proteusの回路図ファイルをリンクしました。
以前のLEDボードにボタンを追加すると、ハードウェアの準備が整います。次のようになります。
接続が完了したら、コードをアップロードして出力を確認します。問題がある場合は、コメントセクションを使用してください。また、プロセス全体を理解するには、以下のビデオを確認してください。