Archive
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
こんばんは!

金曜日でテンション上がりまくりなのにも関わらず、住んでるとこが田舎過ぎて何も出来ないゆってぃです。
西東京を世界最強のテクノロジーエリアにしたい…><

世界最強のテクノロジーエリアってどんなのだろう?
まず、動く歩道は必須ですね。
これが無いと話になりません
あとは、LED太陽電池とかね。
エコ且つキラキラして感じでお願いしたい。
是非お願いしたい!!


さて、今日は会社で新人の技術研修がありました。
私ことゆってぃが、まさかの講師(!?)を任されてしまいました。

とりあえずPWMとかPIDとか、微妙にモーター制御に偏ったの話をしましたが、皆さん熱心に聴いてくれました。
超氷河期に入ってきた人たちだけあって、優秀そうなオーラむんむんです。

コーディングに関する部分では、マイコンのプログラミングを行うときの注意点をお話しました。
たとえば、FM3_GPIO->PDORFレジスタの0ビット目と1ビット目を"1"に、2ビット目と3ビット目を"0"にしたい時

--

FM3_GPIO->PDORF &= 0xfffffff0;
FM3_GPIO->PDORF |= 0x00000003;

--

とやってはいけませんね

面倒ですが

--

unsigned long tmp;

tmp =  FM3_GPIO->PDORF;
tmp &= 0xfffffff0;
tmp |= 0x00000003;
FM3_GPIO->PDORF = tmp;

--

としなければなりません。

もちろん、最初のやり方でも、結果的には希望の信号が出力されます。
しかもたったの2行でコードが終わっているので、アプリ系のプログラマさんなら最初のコードの方が優れたコードだとおっしゃるかもしれません。

でも、組み込み系では少し事情が異なります。
最初の方法では
一瞬だけ0ビット目と1ビット目からもL信号が出力されてしまうからです。
この制御を行う前からLなら問題ありませんが、実際はそうとは限りませんからね。

レジスタは、他の変数と同じようにアクセスが出来てしまいます。
ですが、アクセスした以上、マイコンはその命令に従って何かしらの動作を行います。
ですから、マイコンのレジスタへのアクセスは必要十分に。
そして、くれぐれも慎重に。

マイコンのレジスタはね
とても神聖な場所
なんです。
目的も心構えも無しに
むやみやたらにアクセスしちゃいけないんです!

これはね。。。
むやみやたらにアクセスした結果・・・
過去にバグを出した僕だからわかるんです…(涙)

そのことを伝えたかったんですけど・・・

新入社員の皆さんには、多分全く伝わっていませんでした・・・(;_;)

けれども、彼らも配属後しばらくすれば、僕の作った渾身のテキストの内容が理解できると信じています。

・・・ダメだしされたらどうしよう・・・

さて、今日はここまでにしますね。
最後までお読みいただいて、ありがとうございました!(感謝)
関連記事
スポンサーサイト
こんばんは!

このところ、ブログの更新をさぼりっぱなしのゆってぃです(コラー!!!)

仕事でFM3に携わる機会があって、自己申告的にはもうFM3ネタはバッチリなんですよ!(汗)
マルチファンクションシリアルに関する記事とか、クロックに関する記事を書きたいんですよ!(大汗)
・・・え?そんなの信じないって?
そんなこと言わないで下さいよ~本当ですよ~(涙)
もう富士通の人も真っ青なくらい詳しくなりましたよ~(大嘘)

・・・本当にごめんさない。ごめんさない。

ボーナスが出たらオシロを買うので、そしたらガンガン記事を書いていきますから!!

さて、今日は組み込み現場におけるdefineの使い方を。

みなさんは、いつもdefineをどのように使われていますか?

たとえば、

#define BUF_MAX  (256)

みたいにして

unsigned char array[BUF_MAX] = {0};

みたいに使われることが多いのではないでしょうか?

あるいは

#define NELEMS(array) ((sizeof(array))/(sizeof(array[0])))

みたいなマクロ関数を作られる場合も多いでしょう。



組み込みソフトでは、レジスタ名にその役割を示すためにdefineを用いることが少なくありません。

たとえば、以前の記事でLEDの点滅は以下のように書きました。

FM3_GPIO->PDORF_f.P3 ^= 1;

確かにこれでもよいのですが、この記述方法では「ポートFの3ビット目」が何を目的として反転しているのかわかりません。
そこで

#define LED_PORT (FM3_GPIO->PDORF_f.P3)

とすれば

LED_PORT ^= 1;

と書けるので、ソースコードがずいぶん読みやすくなります。
また、仮に回路変更が入ってポートが変更になったとしても、define内を訂正すればそれですみます。
たとえば

FM3_GPIO->PDORF_f.P3 = 0;
FM3_GPIO->PDORF_f.P3 = 1;
FM3_GPIO->PDORF_f.P3 = 0;
FM3_GPIO->PDORF_f.P3 = 1;

というコードがあった場合、もしも回路でP3がP4になった場合、4行も直さなければなりません。

FM3_GPIO->PDORF_f.P4 = 0;
FM3_GPIO->PDORF_f.P4 = 1;
FM3_GPIO->PDORF_f.P4 = 0;
FM3_GPIO->PDORF_f.P4 = 1;

これはたまたま4行が並んでいたからよかったものの、複数のファイルであっちこっちに修正箇所があった場合、ちょっとばかしめんどうくさい作業が必要になりますね。

でも、もしもdefineでマクロ化されていたら、define内のみの修正ですみます。
たった1箇所変えるだけで、修正は完了です。

#define LED_PORT (FM3_GPIO->PDORF_f.P4)

LED_PORT = 0;
LED_PORT = 1;
LED_PORT = 0;
LED_PORT = 1;

ですので、レジスタ名はその役割毎にマクロ化することをオススメします。

今日はほとんど内容はありませんでしたが、ここまでにしましょう(汗)
最後までお読みいただいて、ありがとうございました!(感謝)
関連記事
こんばんは!

学生の頃から愛用してきた外付けHDDが不調になってきて、ちょっとドキドキなゆってぃです。
とりあえず必要なデータは新しいHDDに移しましたが、やはり寿命でしょうか(;_;)

さて、今日は趣向を変えて、Subversionについてお話したいと思います。
というほど僕自身も詳しくないですが・・・
ボロが出るといけないので、今回はサラっと終わらせます

Subversionとはなんぞや?
という方のために簡単にご説明すると、一言で言えば超便利なソースコード管理システムです。

たとえば、こんなことはございませんか?

デバッグしているうちに、なんだかコードがどんどんおかしくなって…昨日まではきちんと動いていた部分までおかしくなっちゃった!(涙)
でも、バックアップを取ってなかったから、どこをどう変更したのかもうわからない(;_;)

あるいは

複数人でソフト開発してるけど、うまくマージが出来ないよ!><

など。

そんな事態に陥らないためのツールがSubversionです。
一応バージョン管理システムですが、バックアップのためのツールと言うことも出来ますね。

ひとくちにSubversionと言っても複数あるのですが、Windowsで開発をされている方にはTortoiseSVNをオススメします。
このツールは、http://tortoisesvn.net/downloads.html から無料でダウンロードできます。
日本語のパックもあるので、本体をダウンロード&インストール後に日本語化パックをインストールしてください。

詳細は割愛しますが、ファイル上の任意の場所にリポジトリと呼ばれるバックアップデータを蓄積していく場所を作ります。
ソースコードを書いたら、こまめにリポジトリへバックアップを取っておけば、いつでもバックアップデータを取得することが出来ます。
チェックアウトは、リポジトリ作成後であれば右クリックでチョイチョイっと出来るので、とてもお手軽です。
本来なら、複数人でソフトウェアを開発する場合に使用するツールですが、お一人様でコードをガリゴリかく場合にもかな~り重宝します。

よければチェックしてみてくださいね^^

余談ですが、応用情報技術者試験などでも、ソースコードのリポジトリ管理の問題は出題されることがあります。
教科書だけではイメージが掴み辛い部分でもあるので、是非一度、ご自身でバージョン管理の便利さをご体験ください。

最後までお読みいただいて、ありがとうございました!(感謝)
関連記事
こんばんは!

長かったGWも今日でおしまい。。。
ああ、明日からまた仕事が始まってしまう(;_;)

さて、今日はFM3マイコンに内蔵されているベースタイマを使ってLEDを点滅させるプログラムを作ってみましょう。
FM3マイコンのベースタイマには、以下の4つの機能があります。

・PWMタイマ
・PPGタイマ
・リロードタイマ
・PWCタイマ

今回はLEDを点滅させるプログラムですので、リロードタイマを用いてコードを書いてみましょう。

--ここから--

#include "mcu.h"

static void initPort(void);
static void initBaseTimer(void);

int32_t main(void){

 initPort();
 initBaseTimer();

 while(1);

 return 1;

}

static void initPort(void){

 FM3_GPIO->PFRF_f.P3 = 0;
 FM3_GPIO->PZRF_f.P3 = 1;
 FM3_GPIO->DDRF_f.P3 = 1;
 FM3_GPIO->PDORF_f.P3 = 1;

}

static void initBaseTimer(void){

 FM3_BT3_RT->TMCR = 0x3030;
 FM3_BT3_RT->TMCR2 = 0x00;
 FM3_BT3_RT->STC = 0x50;

 NVIC_EnableIRQ(BTIM0_7_IRQn);

 FM3_BT3_RT->PCSR = 0xffff;
 FM3_BT3_RT->TMCR |= 0x03;

}

void BT0_7_IRQHandler(void){

 FM3_BT3_RT->STC &= 0xfe;
 FM3_GPIO->PDORF_f.P3 ^= 1;

}

--ここまで--

今回使用しているマイコンはMB9BF618Tですので、mb9b610t.hというデバイスヘッダファイルをプロジェクトフォルダに入れ、mcu.hをインクルードすれば、このコードの様に各レジスタのアドレスがFM3_xxx->xxxのようにマクロ経由で行えるようになります。
これはPICでも同じでしたね。

なお、FM3_BT3_RT->TMCRと書けばTMCRレジスタそのものに、FM3_BT3_RT->TMCR_f.xxx(xxxはビット名)と書けば、TMCRレジスタの各ビットにアクセスできます。詳細はヘッダファイルをご確認ください。

では、ソースコードの説明に入ります。

main関数では、initPort()関数とinitBaseTimer()関数を順番に呼び出し、無限ループに入っています。
無限ループ中はタイマ割り込みハンドラにてLEDの点滅を制御します。
その割り込みハンドラがBT0_7_IRQHandler()です。

まず、initPort()関数ではポートFの3ビット目をIO設定・出力設定とし、最後にHIを出力しています。
なお、インターフェース付属ボードではHIを出力した場合、LEDは消灯します。
CQ出版社のHPから回路図が入手できますのでご確認ください。

initBaseTimer()関数内では、ベースタイマのチャンネル3をリロードタイマとして初期化し、動作を開始させています。

まず、ベースタイマをリロードタイマとして使用する場合、以下のレジスタを設定する必要があります。

・TMCRレジスタ
・TMCR2レジスタ
・STCレジスタ
・PCSRレジスタ
(・TMRレジスタ)※このレジスタは読み出しのみ

各レジスタの詳細は、富士通さんのHPから入手できるペリフェラルマニュアルをご参照ください。
ありがたいことに日本語で書かれていますので、すぐにご理解いただけると思います。

ただし、各レジスタを設定しただけでは割り込みは発生しません。
ペリフェラルタイマは、割り込みが発生するとCortex-M3コアへ
(富士通ペリフェラル君)「割り込みが発生しました!!割り込みハンドラを呼び出して下さい!!」
という信号を送ることしか出来ないからです。
ですので、Cortex-M3コアが
(Cortex-M3様)「いやじゃ」
と言ったら、割り込みハンドラは呼ばれないのです。

そのため、タイマー初期化時などにあらかじめ「タイマ割り込みが発生するから、そのときはよろしくね」と伝えておかなければなりません。
それが、赤文字で書いた
NVIC_EnableIRQ(BTIM0_7_IRQn);
という部分です。
NVIC_EnableIRQ()はNVIC用の関数で、要はCortex-M3のもつ割り込みコントローラへアクセスするための関数です。
Interface6月号の第7章にとてもわかりやすい説明がありますので、詳細はそちらをご参照ください。
(記事を書かれているのもARM社の方です)

最後に、割り込みハンドラのBT0_7_IRQHandler()です。
この関数内では、割り込みフラグのクリアと、ポート出力の反転を行っています。
なお、使用する割り込みハンドラの関数名は、あらかじめスタートアップ用のアセンブリファイル内で登録をしておかなければなりません。
この内容もInterface6月号の第5章に詳しく書かれているので、ご確認ください。

駆け足でしたが、以上がペリフェラルタイマを用いた場合のLED点滅プログラムです。
本来であれば、割り込みハンドラ内の
if(i>2000000)
部分はカウントクロックによって変化させなければなりませんが、今回は大目に見てください(笑)

最後までお読みいただいて、ありがとうございました!!(感謝)
関連記事
ご訪問者様
プロフィール

ゆってぃ

Author:ゆってぃ
経歴7年の組み込み系・制御系エンジニアです。
("ど素人"という文言は取りました…笑)
ソフトウェア開発経験ゼロの状態から、なんとか実務がこなせるようになってきた現在に至るまでの経験を、備忘録代わりに綴っていきたいと思います。
入門者の方、大歓迎!
(上級者の方、ごめんなさい…)

あと、ブログには全然関係ないですが、Bumpy Headというバンドのギターをやっています。
ライブ情報なんかも書いたりすることがあるので、その時に「行ってもいいよ~」といった感じのコメントを戴けると、泣いて喜びます(泣)
ブログ読んでくださってる方なら、チケット代サービスしちゃいます!

最後に…滅多に流用することは無いでしょうが、このブログに書かれているソースは、特に指定の無い限りMITライセンスとします。ただし、一部それ以外のものもございますのでご注意下さい。
※ブログのリンク先にあるコードに関しては、リンク先のポリシーに従ってください。

最新記事
最新コメント
カテゴリ
RSSリンクの表示
メールフォーム

名前:
メール:
件名:
本文:

twitter
リンク
ブロとも申請フォーム
スポンサードリンク


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。