最後に、後退する場所は他になく、機械を組み立てて、ほとんど分割不可能なものにする時が来ました。 1つの小さな質問が残っています:このマシンはどのようにオン/オフになりますか? そして、前のテーマを次の投稿で続ける伝統についてはどうですか?
伝統を壊さないために、前の投稿からのトピックを続けます:LED点滅。 それらの何が問題になっていますか?
遅延時間の曲線から始まり、ひどいタイマー割り込みハンドラーで終わる、それらについてはそれほどではありません。
まず、通常の遅延関数を作成する必要があります。 TMR1を1ミリ秒間置いてコードに追加します
volatile uint16_t millis=0; void DelayMS(uint16_t m) { millis=0; while(millis<m); } ... void TMR1_ISR(void) { millis++; ...
このような簡単な方法では、最大65秒まで、別のコードの頻度/可用性に依存しない遅延関数を取得します(主なことはタイマーが作動することです)。 私たちの目的には十分なマージンがあります。
次に、LEDの点火コードを見てみましょう。 中断(およびループ)を遅らせることに加えて、良い方法で遠く離れた場所で行う必要がある比較の束を作成することは、何となくhowいものです。 いいえ、ホームプロジェクトにとってはそれ自体がかなりのものですが、産業プロジェクトにとっては良くありません。
アルゴリズムをもう一度変更しましょう。 ポイントは何ですか? 完全にLEDに渡されるポートCの例を考えてみましょう。
下位3ビットは色を担当します。 シニア3-最初の3つのLED用。 最初のLEDを赤、2番目を緑、3番目を「オレンジ」(または赤+緑)で精神的にオンにします。 港には何がありますか?
最初のステップ、赤チャンネル
0b00101001
2番目のステップ、「グリーン」チャンネル
0b00110010
3番目のステップ、「青」チャンネル
0b00000100
ご覧のとおり、原則として、同じ機能を得るためにポートごとに何度も送信するだけで十分です。 そして、これらのバイトの形成をsetLed関数に渡します。これは、割り込みのコードよりも頻繁に呼び出されず、あらゆる種類の計算、ループ、およびその他の過剰を許容できます。
すべてをポートCに押し込めることを知っているのは良いことです。ポートCには、どこにも接続されていない2つの高位ビットがあります(データシートとコードから判断します)。 しかし、ポートAをどうすればよいのでしょうか。ポートAでは、残りの部分に触れることなく1ビットだけ変更する必要があります。 これを行うには、素晴らしい機能「ビットAND」と「ビットOR」を使用できます。
より明確にするために、例を作成します。
0b00 0 01010ポートから現在の値を読み取ります。 必要なビットを選択しました-値を変更するだけです。 残りは誤って配置されました。
setLed関数によって事前に準備されたマスクを使用して、「ビット単位のOR」を作成します(1が存在する必要があるため、1も存在するはずです)。 ビットを有効にするには、0b00 1 00000にする必要があります。ビットを有効にする必要があるとします
0b00 0 01010 | 0b00 1 0000 = 0b00 1 01010
すべて、目的のビットが設定され、残りは変更されないため、受信した値をポートに書き戻すことができます。
そして、「ビットAND」を使用して同じビットをリセットします(両方とも1である必要があるため、出力も1になります)。
0b00101010および0b11011111 = 0b00 0 01010
すべてが論理的なようです。 コードを書き直してください。
一般に、setLed関数には、ポートに送信するものの6バイトを準備するタスクがあります。 led.cとled.hを変更します
// basic colors #define RED 1 #define GREEN 2 #define BLUE 3 #define OFF 0 extern volatile uint8_t lc[3]; extern volatile uint8_t la[3]; void setLed(uint8_t n,uint8_t c) { uint8_t b; if(n==0) b=0b11110111; if(n==1) b=0b11101111; if(n==2) b=0b11011111; if(c>0) { c--; if(n==3) { la[0]=1; la[1]=1; la[2]=1; la[c]=0; } else { lc[c]=lc[c]&b; } } else { // turn off channel N b=b^0xff; if(n==3) { la[0]=1; la[1]=1; la[2]=1; } else { lc[0]=lc[0]|b; lc[1]=lc[1]|b; lc[2]=lc[2]|b; } }
そして、割り込みハンドラーで規定します
LATC=lc[current_led]; _LED4_ = la[current_led]; current_led++; if(current_led==3) current_led=0;
以前のバージョンよりもはるかに短いことを認める必要があります(ただし、ポートCのビットを使用したままにし、ポートAは手動で「プル」しやすいことが判明しました)。 時間が短いほど高速になります。 そして、それがより速い場合、コントローラー全体のパフォーマンスも高くなります。 あらゆる面で堅実なボーナス。 確かに、「白」を取得するには、setLedを3回呼び出す必要がありますが、これらは些細なことです。
今、最も重要な問題を解決するために残っています:それをオンにする方法とオフにする方法?
原則として、マシンの元の作成者によって提案されたオプションがあります-ドアのボタン。 しかし、創造性を応用する前に、「それだけの価値があるのか」を理解する必要があります。
次のコードを書きます
setLed(3, RED); setLed(2, BLUE); PWM3_LoadDutyValue(49*2); TMR2_LoadPeriodRegister(49); uint8_t c,q; for(q=0;q<1;q++) { setLed(0, RED); setLed(1, OFF); DelayMS(100); for (c = 0; c < 10; c++) { setLed(0, OFF); DelayMS(50); setLed(0, RED); DelayMS(50); } setLed(1, BLUE); setLed(0, OFF); DelayMS(100); for (c = 0; c < 10; c++) { setLed(1, OFF); DelayMS(50); setLed(1, BLUE); DelayMS(50); } } PWM3_LoadDutyValue(0); TMR2_LoadPeriodRegister(0); setLed(0, OFF); setLed(1, OFF); setLed(2, OFF); setLed(3, OFF); DelayMS(10); SLEEP();
最後の命令に注意してください-SLEEP()は、すべてがオフになっているときにマイクロコントローラーを休止状態にし、一部の割り込みのみがこの状態から抜け出すことができます。 割り込みはまだ送信されていないので、測定時に手動でオンとオフを切り替えるだけです。
消費電流を測定するためにマルチメーターを接続します。 私が発行したのは、LEDが点灯し、スピーカーが痛むとき、消費電流は2.97-3mAです。 スピーカーを押し込まない場合、2.85-2.9。 そして、それがすべて終了したら、0.01mA以下になります(私のマルチメーターには0.01mAの測定下限があります)。 1 MHzと4 MHzのクロック周波数の差も最小限で、文字通り0.2 mAです。
12個の点滅するLEDのスマートな数字に同意しますか? 「通常どおり」それらを接続すると、30〜40mAの電流が流れます。
2本のAAAバッテリー(平均容量は1000mAh)があるため、マシンの寿命は簡単にわかります。
常にビープ音が鳴り、点滅する場合は、1000mAh / 3mA / 24h = 13日です。
そして、あなたが常に眠っているならば-1000 / 0.1 / 24 = 416日。
単一のバッテリーでは「ゼロ」まで放電することができないため、実際には数が少なくなることは明らかです。 しかし、そうであっても-タイプライターの冬眠の年は非常に良いです。 一般に、個別のスイッチは必要ないので、ボタンにすでに準備されているブランクを使用することにします。 RA4とマイナスの間にボタンを接続します。CodeConfiguratorで読み取り用にこのレッグをオンにし、プルアップ抵抗をオンにしてこのレッグの割り込みを生成することを忘れないでください。
何らかの理由で、Code Configuratorで割り込みを許可するコードを追加するのを忘れていました(チェックボックスはオンになっていますが)。そのため、プロセッサでデータシートを開いて、どのビットが何に責任があるのかを調べる必要があります(実際、これは非常に有用なアクティビティです)。 周辺からの割り込みの許可を有効にし、A4ポートに接続して生成されるようにします。
INTCONbits.IOCIE =1; IOCANbits.IOCAN4 =1;
もう一度確認してください。 その結果、ボタンを押すだけで、すべてが目覚め、点滅し、数回眠りに落ちます。
美しいフラッシャーはすでに存在し(上記のコード)、サイレンの周波数により、コメントで私を助けてくれました。 救急車のサイレン:850 Hzから1550 Hzの生成周波数が時間とともに変化する、三角形の周波数変調信号。 0.2ヘルツの速度で。 650 Hzからの警察のサイレン。 1350 Hzまで。 そして、速度をヘルツで測定する方法を私に聞かないでください:)しかし、音は非常に似ています。
今では、蓄積されたすべて(音、非常灯、睡眠)を1つのコードに集めることが残っています。 トレーナーの最高の伝統では、私はそれをあなたにお任せします。
ほぼ準備が整いました。multik.org/ pic / policecar.rarがあります。