- 締切済み
ARM Cortex-M3のタイマー処理方法
<環境> ・WindowsXP SP2 ・デザインウェーブ2008年5月号付属のARM基板を知人より借用中 <開発ツール> ・デザインウェーブ2008年5月号付属CD-ROMの『IAR Embedded Workbench』 ・WindowsXP上でのC言語のデバック用にはCygwinのSetup.exeVersion2.573.2.2で 『Devel』のカテゴリー『Install』にして『gcc』を使えるようにしました。 こんにちは。 マイコンにお詳しいかた助けてください。 先日、デザインウェーブ2008年5月号を借用してきまして、その 113頁にありますLED点滅用プログラムを修正変更して、For文で 点滅させるのではなく、1秒毎に点滅させてあげようとしており ます。 プログラムは以下のように作成しておりまして、Windows上での デバッグではLED点滅文をprintf文に変更してあげて、Cygwin上 で1秒毎にprintf文が実行されることを確認しております。 しかし実際の基板では、万国標準時から現在までの時間差が 求められず、time関数で得た『start』も『end』も『ゼロ』では 無い何かしらの同じ値が入るようで、2つの値の差をとっても 常に『ゼロ』という結果の為に、1秒差を求めるには程遠い 状態にあります。 C言語・ARMにお詳しいかたがいらっしゃいましたら解決策を 教えて戴けると嬉しいです。 ※以下、作成済みプログラム --------------------------------------------- #include <stdio.h> #include <time.h> #include <ST\iostm32f10x.h> //unsigned int t; signed long t; int main(void) { time_t start, end; RCC_APB2ENR |= 0x10; // CPIOCを使用できるようにする。 GPIOC_CRL = 0x43444444; // PC6を出力にする。 while(1) { time( &start ); // スタート時刻の取得 while(1) { time( &end ); // 現在時刻の取得 // t = difftime( end, start ); // 現在時刻とスタート時刻の差をtに格納 t = end - start ; // 現在時刻とスタート時刻の差をtに格納 if ( t >= 1 ) { GPIOC_ODR ^= 0x40; // LEDの出力を反転させる。 break; // 一番内側のWhileループを抜ける } } } }
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- chie65536(@chie65535)
- ベストアンサー率44% (8757/19871)
time関数は「カレンダ&時計機能を持つシステムで動くプログラム」ででしか使えません。 デザインウェーブ付録のARM基板には「カレンダ&時計機能が無い」ので、time関数のような「カレンダ&時計機能に依存するライブラリ関数」は、正常には動きません。 カレンダ&時計機能に限らず「存在しないハードウェアに依存するライブラリ関数」はすべて使えません。 呼び出そうとすると「呼んでも何もしない」か「関数が存在せず、コンパイルが出来ない」か、どちらかです。 多分、質問者さんのケースでは、time関数は呼んでも何もせず、引数に与えたstart、endは「初期化されないままの不定な値」になっていると思われます。 そして「偶然、startもendも、初期化されないままの不定な値がゼロではなく、同じ値で、引き算したら0になっただけ」に過ぎません。 雑誌付録のARM基板には時計ICは無いですが、ADuC7026は運良くチップ内にRTC(タイマ)が組み込まれているようなので、RTCを使えば「1秒」が計測可能だと思われます。 てゆか、元々、付録のみの状態では基本のクロックが正確じゃないので、RTCを使っても「約1秒」になるだけで、正確に1秒を計る事はできないでしょう。 元となるクロックが不正確ならすべてが不正確になりますから、RTCに「1秒間隔」と設定しても、1000秒で999回点滅とか、1000秒で1001回点滅になっちゃうでしょう。 どうせ正確じゃないのなら for (i = 0;i < i_max;i++) { for (j = 0;j < j_max;j++) { for (k = 0;k < k_max;k++) {;} } } みたいな「何もしない空ループ」を書いて「約1秒待つ」で良いと思います。 なお、上記の「空ループ」を使う場合、i_max、j_max、k_maxは「ループに要する時間が約1秒になる」ような値にして下さい。多分、何度も試行錯誤して、自分で値を見付けないとなりません。 試行錯誤する場合、点滅が目で見て判るくらいの値で試し、何秒で何回点滅したかストップウォッチなどで計りましょう。 例えば、計った結果が「27秒で10回点滅」だったら、1回の点滅が「2.7秒」なので、i_max、j_max、k_maxのどれかを「2.7で割った値」にするとかで微調整します。 ちなみに、基板には、オプションで正確な水晶発振子を付けられるらしいので、それを付けた場合、RTCは「ほぼ正確」な計測をするようになるようです。
- D-Matsu
- ベストアンサー率45% (1080/2394)
RTCがあるはずなので、そっちから値を取ることを考えますね。 最終的にはタイマー割り込みを使った方がいいんじゃないかとは思いますが。
補足
RTCのキーワードを戴きましたのでデザインウエーブを見ていくと84頁に『RTC関係のコマンド』と『TIM、TIM1のコマンド』がありましたので、time関数の箇所を『RTC_GetCounter();』としてみたのですけど、事前に定義されてませんのでコンパイルエラーになってしまいました。 『タイマー割り込み』に関しましては、ごめんなさい、ど素人でしてまったく想像が出来ません。
補足
ありがとうございます。 デザインウエーブに書かれていました(CD-ROMの中に入っていました)プログラムもfor文でループさせる方法でしたので、そのループの中の数字を変更して点滅時間を変更させることは出来たのですね。 それで、約1秒よりは別の方法でキッチリ1秒が出来ないものかと思いましてfor文以外のプログラムを模索しておりまして。 仮にRTCを使用しても『不正確な為に約1秒』になってしまうのですか…。 水晶発振子は後に追加出来ることを考えますと『今は不正確でも構わないのでfor文とは異なるプログラム』を作ってみたいです。