« 2014年5月 | トップページ | 2014年7月 »

2014年6月30日 (月)

「天文屋のためのマイコン入門」タイマープログラムの改良

前回出したタイマーのプログラムですが、ちょっと改良してみましょう。

まず、タイマーレジスタTMR0に-30を代入してカウントアップしていますが、単純に考えてこの値が大きいほど精度が良くなると想像できます。

値が30ということは、最大1/30の誤差を伴います。ただ、大きくすると言っても、8ビットレジスタなので、最大で255までです。それを考慮して、計算する必要があります。

プリスケーラーの分周比を現在の1/256から8倍の1/32にしてみたらどうでしょう。

この場合、TMR0に入力されるクロックの周波数は

31250÷4÷32 = 244Hz

したがって、TMR0レジスタに-244を代入してカウントアップすることにします。

分周比を1/32にするには、OPTION_REGのビット0とビット1を0にクリアします。したがって、以下の2行を初期化部に追加します。

BCF    81h,1
BCF    81h,0

もう一つの改良点

TMR0レジスタが0になったかどうかの判定ですが、TMR0レジスタの値をワーキングレジスタに転送し、ゼロフラグで判定しています。しかし、その間にもTMR0レジスタはカウントアップしていますので、0を読みすごしてしまう不安が生じます。

ただ、この不安はあたりません。なぜなら、TMR0に入力されるクロックは、命令のクロックを128分周しています。つまり、TMR0が0から1にカウントアップしている間にマイコンは、128命令も実行してしまいます。これなら読みすごしてしまうことはないでしょう。

ただ、後で説明しますが、割込みというのが発生するとプログラムが中断され、その間にもTMR0がカウントアップするので、まったく可能性がないともいえません。

そこで、もう少しましな方法を採用します。

実は、TMR0がオーバーフローすると、セットされるフラグがあるのです。INTCONというレジスタ(0bh番地)のビット2がそうです。ですから、このビットでオーバーフローを判定します。このビットをオーバーフローフラグといいます。

プログラムは以下のようになります。

まず、オーバーフローフラグを0にクリアします。なぜならオーバーフローフラグは自動ではクリアされず、プログラムでクリアする必要があるためです。

BCF  0bh,2   ;オーバーフローフラグクリア

16進数で先頭がアルファベットの場合は先頭に0をつけます。

次に、オーバーフローフラグを判定し、セットされているなら、つまりオーバーフローが発生しているなら、次のGOTO命令をスキップして、サブルーチンを終了します。

BTFSS 0bh,2       ;オーバーフローしたらスキップ
GOTO Wait1s_LOOP  ;オーバーフローしないならループ

プログラムの全部を掲載します。

1406303_3 

さて、この1秒待つサブルーチンですが、これは正確な1秒ではありません。確かに、TMR0は1秒でオーバーフローしますが、このサブルーチンを呼び出して処理する命令実行時間がかかりますので、1秒より長くなります。これをオーバーヘッドといいます。

正確に1秒にしたいなら、このオーバーヘッドも考慮してTMR0の初期値を決定する必要がありますが、今後説明する「割込み」という機構を利用する方が懸命です。

まとめ

これで一通り、タイマーの説明をしましたが、関連するレジスタが3つ出てきました。これを最後にまとめておきます。

TMR0 1h番地
タイマー0レジスタ 0から255までカウントアップしている

OPTION_REG 81h番地(バンク1の1h番地)
TMR0の入力クロック源を選択したり、プリスケーラーの分周比を選択するレジスタ

INTCON 0bh番地
TMR0のオーバーフローフラグがあるレジスタ

| | コメント (0)

「理想のポタ赤を作る」製図完成

こちらのほうも着々と進んでいます。

やっと、製図が完成しました。

1406301_2


3D製図も完成。

1406302_2


1406303


基本ユニットです。

1406304_2


これから試作機作りに入ります。

| | コメント (6)

「天文屋のためのマイコン入門」タイマーのプログラム

それでは実際にプログラムを作って見ましょう。

1406301

このプログラムをビルドして、書き込むと、LEDが一秒間隔で点滅します。

●初期化部

OPTION_REGのうち、クロック源の選択で、命令のクロックをクロック源とするため、ビット5をクリアします。また、プリスケーラーをウオッチドッグタイマーではなくタイマー0で使用するため、ビット3を0にクリアします。

よって次の2命令を初期化部分に加えます。

BCF   81h,5
BCF   81h,3

●メイン部

LEDを点灯する命令と消灯する命令を交互に実行しますが、間に1秒待つサブルーチンを呼び出しています。

●サブルーチン部

1秒待つサブルーチンです。タイマーレジスタTMR0に入力されるクロックは次のようになります。

1406302

プリスケーラーの分周比ですが、特に設定していないので、デフォルトの1/256になります。したがって、TMR0に入力されるクロック周波数は30Hzになります。

つまりTMR0が30カウントしたら1秒ということです。これを利用して1秒を作り出します。つまり、TMR0に-30を代入して、

MOVLW  -30
MOVWF  1h

次にTMR0の値をワーキングレジスタに読み込んで

MOVF     1h,W

0かどうか判定でします。0ならSTATUS(3番地)レジスタのビット2がセットされています。

BTFSS    3h,2

0なら、GOTOをスキップしてサブルーチンからリターンします。0でないなら、まだ一秒たっていないので、ループの先頭に戻って同じことを繰り返します。

GOTO    Wait1s_LOOP
RETURN

いかだでしょうか、タイマーの機能をわかっていたただけたでしょうか?次回このプログラムを少し改良するのと、問題点を検討してみます。

| | コメント (0)

2014年6月29日 (日)

「天文屋のためのマイコン入門」タイマーを使いこなそう

これから、LEDを1秒間隔ごとに点滅させるプログラムを作りたいのです。マイコンの命令だけでこれを実行するのは、けっこう大変です。また1秒というマイコンの感覚からすると超長い時間は命令だけでは作りづらい部分があります。

マイコンのプログラムはほとんどの場合、時間が絡んできます。マイコンで正確な時間管理ができるように、マイコンはタイマーという機能を内臓しています。タイマーは時間管理をするための機能で、マイコン内蔵機能としてはポートを除いてもっとも基本的なものです。

PIC16F88はこのタイマーを3つ内蔵していて、それぞれ特徴があります。今回はそのうちもっとも簡単なタイマー0(Timer0)について説明します。

タイマーとは

タイマーは時間管理機能というと難しそうですが、実は0から255までをクロックに応じてカウントアップしている8ビットのレジスタに過ぎません。

1406294この8ビットのレジスタはTMR0といい、番地はバンク0の1番地です。カウントアップは電源投入時から常に行われています。255までカウントアップされると、次に0に戻ります。これをオーバーフローといいます。

タイマーの本質はたったこれだけです。普通、レジスタというと値を書き込んでやらないとその値になりません。しかしタイマーレジスタは自動的に値を更新します。もちろんタイマーレジスタに値を書き込めばその値になりますが、すぐにカウントアップを始めます。

カウントアップのクロック源ですが、以下から選べます。

1 マイコンの命令を実行するのと同じクロックを1/4に分周したもの
2 タイマーのために外部から特別に入力したクロック

普通は1で十分です。特殊な値の周波数や精度が必要な場合は2を選びます。

また、タイマーはプリスケーラーと呼ばれるクロック周波数を分周(遅くする)する機能も内蔵しています。分周は1/2から1/256まで選べます。

1406295

これらの選択をするレジスタがOPTION_REGです。番地は81hです。つまりバンク1の1番地です。

このレジスタはタイマーだけでなく他の内蔵機能と共通になっていますので、タイマーの関連するビットだけ説明します。

1406296このレジスタの初期値は各ビット1なので、0にする必要があるビットだけ0にします。ちなみに今回の回路でタイマー0を動かすには、T0CS、PSAの各ビットを0にする必要があります。

次回は、このタイマーを使って、1秒間隔ごとにLEDを点滅させるプログラムを作ってみます。

| | コメント (0)

「天文屋のためのマイコン入門」クロック

久々の投稿です。すみません。今日はマイコンのクロックについてお話します。マイコンを動作させるには下図のように外部から、クロックという1と0の繰り返し信号を入力してやります。そしてこのクロックの周期を周波数といいます。

1406291

マイコンは命令をこのクロックに同調して実行しますので、周波数が高いほど処理スピードが速くなります。ただ、いくらでも周波数を高くできるわけではありません。PIC16F88の場合は8MHzに制限されています。

また、周波数が高いと、電源電圧の範囲が制限されたり、消費電流が増えることも留意しておく必要があります。

また、クロックは命令の実行だけでなく、マイコン内蔵機能の時間管理などに使われたりします。代表的なものにタイマーや、シリアル通信のボーレートなどがあります。

マイコンにクロックを入力する方法はいくつかあります。

一つはクロックオシレーターを使う方法です。クロックオシレーターは独立したクロック発生回路ですので、精度等必要に応じて選べて、そのマイコンに依存しません。コスト的には割高で、回路も多少複雑になります。下図の回路図では省略していますが、波形整形用にもう一つICを通す場合もあります。

1406292

もう少し安価な方法で一番ポピュラーなのは、水晶振動子を使う方法です。クロック生成回路はマイコン内蔵のものを利用させてもらいます。クロックの精度は主に水晶振動子にi依存しますので、必要で十分な精度と周波数のものを得られべます。

1406293_2 

ただ、この方式はマイコンのポートを2つ使ってしまいます。ちなみに水晶振動子を使わず、抵抗とコンデンサを使う方式もあります。これだともっと低コストになり、ポートも一本しか使いませんが、精度は悪いです。

PIC16F88の場合、抵抗とコンデンサを使ったクロック生成回路が完全に内蔵されていますので、外付け部品一切なしで、マイコンを動かすことができます。(だからこのマイコンを選んだ!) ただ、精度は数%であまりよくありません。インターバルシャッターくらいならこの精度でもいいですが、次回作るモータードライブではこの精度ではだめです。
したがって、モータードライブの場合は外付けの水晶振動子を使うことにします。

なお、どのようなクロック源を使うかは、前回説明したコンフィグレーションで設定します。
外部から供給の場合は、オシレーターか水晶振動子か抵抗・コンデンサか選べます。内蔵の場合は31.25Hzから、8MHzまで選択できます。ちなみに今までのサンプルプログラムの設定では31.25Hzです。

今日はここまで

| | コメント (0)

2014年6月28日 (土)

PRO-10初プリント

PRO-10で初プリントしてみました。

1406288

一発で、満足のいくプリントが出てきました。さすが、キャノン。紙を節約できます。

でも光沢感ないですね。G930よりもない感じです。

残念ながら応募できるレベルの作品はないですね。でもまだテストですから、来月頑張ります。

| | コメント (0)

α7s作品公開その2

引き続き、α7sの作品公開です。

実は今日公開する作品はすべて、カメラが出したJPG画像が元になってます。RAWをDNGに変換してフォトショップ現像では、なぜかうまく行かなかったんです。JPGのほうが、ノイズも少なく、色も良く出ています。なんとかJPGと同じになるようにがんばったのですが、超えられませんでした。それなら最初からJPGでやってしまえと、JPG画像を元にしました。

あとJPGだと、星の周りの色にじみも綺麗にとれてます。これに関しては異論もあるでしょう。

1406281

ISO6400 6秒

ISO6400の画像ありました。ちょっとざらついていますが、これくらいなら問題ないでしょう。

1406282
ISO25600 6秒

明るいレンズではないので、看板も星もピントが合います。

1406283
ISO25600 10秒×4枚

夏の大三角。いて座付近より明るくない部分ですが、たった40秒でこの写り。ポタ赤載せて、こんな安いレンズではなく普通のレンズで5分くらい時間かければ、すごい画像ができそうです。

1406284
EF100mmF2.8Lマクロ F2.8開放
ISO51200 4秒×4枚

ISO51200でもコンポすれば使えます。たった16秒でこの写り。ただし、ISO51200だとアンプノイズが出ます。この写真では、右下部分に出ますが、ちょうど木があります。あと右上の隅にも出ます。この写真でもうっすら赤紫になっているのがわかると思います。ノイズリダクションかダーク引きが必要です。

ここからはちゃんとしたレンズですが、やっぱ、高いレンズはそれなりのことがあります。機材はケチらないようにしましょう。

1406287

ISO25600 6秒

これがやりたかったんです。不思議なポーズをとってます。天の川からダークエナジーをもらっているのでしょうか?

1406286

ISO25600 6秒

おまけのJPG撮って出し画像。

●まとめ

さて、これで全部公開しました。個人的な感想をまとめてみたいと思います。

重要な感度ですが、

ISO3200までならまったく問題ないでしょう。ISO6400あたりから気になりますが、許容量は人によって違うでしょう。

個人的には、このカメラは星景写真より、コンポやモザイク前提の方が力量を発揮できそうな気がします。

ISO25600なら1分も露出すれば十分な露光量が得られるので、ノータッチの限界が上がるでしょう。また場合によっては赤道義さえ要らなくなるでしょう。

あと、暗いレンズや、絞って撮影する場合にも有効と思います。ミラーレンズなんかいいんじゃないでしょうか。

●次回遠征時の課題

まず、ノイズリダクションの効果を確かめたいです。

それと、こんどは赤道義に載せて、ミニボーグでじっくり撮ってみたいですね。

あと、やっぱ、このカメラ用にちゃんとしたレンズもほしいです。

| | コメント (0)

2014年6月26日 (木)

α7s作品公開その1

それでは、α7sのファーストライト作品公開です。

1406261

ISO12800 8秒

多少ノイズ除去処理しましたが、ノイジーですね。特に木のあたりがざらついてるのが分かると思います。

1406262

ISO12800 8秒

雲海に漂うカシオペアです。カシオペアから下に二重星団、ペルセウスと連なります。右上にM31もみえています。こういった写真はソフトフィルター必須ですね。画像処理で、ソフトフィルターを実現してみましたが、やっぱし、不自然です。

1406263

ISO25600 10秒×7枚

固定撮影です。夏の天の川を広角で撮るなら、ポタ赤いらいないですね。三脚だけで十分です。

1406264

ISO25600 6秒×12枚

中望遠でも固定撮影でここまで撮れてしまいます。ほんとポタ赤いらない。
それにしても、このレンズ酷いですね。上半分はほとんどボケボケ、下側はいいんですけど。方ボケというか、ほとんど不良品に近いような。安いから文句言わないけど。

明日も続きます。

| | コメント (2)

2014年6月25日 (水)

α7s感度別生データ公開

それでは、撮ってきた写真を公開します。まず画像処理していない素の画像を公開します。客観性重視のため、なんの処理もしていない画像です。

現像はDNG変換したのち、フォトショップで現像しています。現像時の明るさやコントラストのパラメータはすべて0です。

ノイズリダクションは長露出、高感度とも両方ともOFFです。

レンズですが、EF 28-105mm F3.5-4.5で、マウントアダプターで絞り開放で撮ってます。キタムラの中古で、8千円ちょっとで買った安物です。周辺部のものすごい収差と、かたボケがありますので星はあまり見ないください。

画像は各ISO別に3種類出しています。1素の画像、2レベル調整で255->150程度に強調した画像、3ピクセル等倍画像。

ISO3200(30秒)

1406251
赤い光は車のテールランプです。

1406252
1406253
なめらかですね。

ISO8000(4秒)

ISO6400で撮るの忘れました。そのかわし、ISO8000の画像がありました。

140625414062551406256
まだまだいけるかな。

ISO12800(8秒)

140625714062581406259
このへんから、急に荒くなります。

ISO25600(10秒)

140625101406251114062512

う~ん、苦しい。このままではA4プリントは厳しい。この感度だと強調処理はほとんどできないと思います。

ISO51200以上になると、突如アンプノイズが出ます。長露出ノイズリダクションをONにするか、ダーク減算やらないと使えないです。

さて、いかがだったでしょうか。個人的な感想ですが、星景写真で一枚勝負ならISO6400までかな、コンポジットするか、強力なノイズ除去処理をやるなら、ISO25600でもいけると思います。

EOS 5D Mark2よりは明らかに良いですが、一枚勝負の星景ならISO6400が実用ということを考えると、EOS 6Dでも良かったかなとも思います。

ただ、ノイズリダクションを効かせればまだよくなるかも知れません。この辺は次の遠征時に検証したいと思います。

次回はちゃんと画像処理した作品をたくさん公開したいと思います。

| | コメント (2)

α7sファーストインプレッション

火曜の夜は、買ったばかりのα7sをもって湯沢に遠征してきました。GPVの予報は曇りでところにより晴れ間もあったので、それに期待して出かけてきました。

ついてみると、厚い雲に覆われ、どんより。どこか晴れ間はないか探し、六日町、十日町、津南町と移動しましたが、どこも厚い雲。そこで湯沢にもどり山の上の高いところに移動することにしました。だめでも、夜景を撮って帰ってこうようというこんたんです。

で、途中、霧に覆われ、これは雲の上に出れる!と期待しながら、到着すると。快晴、見事な雲海が下に見えました。 

さっそく、α7sでパシャパシャとりまくりました。

一番驚いたのは、ライブビューとEVFです。どちらも星が見えます。ライブビューですが、高感度設定にして早いシャッタースピード(1/4秒とか)にすると、天の川がはっきり写ります。バンビやM8もしっかり見えます。シャッタースピードを遅くすると逆に暗くなってしまいます。

そしてEVFもすごい。星が、3~4等星くらいまで見えます。星座の形がはっきりわかります。こちらは小さな星を画像処理で大きくしてる感じです。おそらく星撮りを意識しての機能と思います。ただ、明るい星も、暗い星も同じくらいの大きさになってしまうので、なんか現実の星を見てる感じはなく星図を見てる感じです。

ピントあわせ時の拡大表示ですが、メニュー項目の中にあるので、カスタムキーで割り当てておくと便利だと思います。操作性は非常に良いと思います。録画ボタンの位置がちょっと考えもんで、誤って押してしまうことがありました。ダイヤルはあまり回しやすくありませんでした。あとは、直感的で特に困ることはありませんでした。

肝心の高感度性能ですが、あまり過度な期待はしないほうがいいかも知れません。これから現像して、結果を順次アップします。お楽しみに。

| | コメント (0)

2014年6月24日 (火)

いろいろ買って来た

さっそく、今夜出撃。

1406241

| | コメント (1)

2014年6月22日 (日)

よっちゃんとのトーク解説2

今日は、トークのうち、もう一つの話題、カラーバランスについて解説します。こちらの方が内容は簡単だと思います。初心者の方も容易に理解できると思います。

トークでは、まず、私が次のように切り出しています。「最近のみんなの作品はグリーンが良く出ていてうまい」

昔は、グリーンが出ていなくて、赤みががった作品が多かったということですが、たとえばこんな感じです。

1406221

天の川が全体に赤みがかっています。理由として考えられるのは、

1 改造デジカメは一般に赤かぶりになるがうまく補正できていない
2 カブリを目立たなくするため、グリーンのコントラストを下げている

で、グリーンをちゃんと出した作品が↓です。

1406222

どうでしょうか、立体感が出たと思います。この作品は星ナビの入選作品ですが、我ながらうまくできたと思います。私、昔の方がこの辺はうまかったです。

それで、私の天の川の色ととり方についても語っていますが、下図のように天の川の周辺がちょっとグリーン、またはシアンぽくなるのが私の基準です。

1406223

次にこの画像を、青をちょっと強めてみました。

1406224

寒色系なので、透き通るような透明感が出ます。各色の役割についてわかっていただけたと思います。

ここで、注意があります。たとえばグリーンが出ているとか強いとか表現していますが、これは色の絶対的な輝度が高いと言っているわけではありません。もし、そうなら、レベル調整で、いくらでも自由にカラーをコントロールできるからです。

そうではなく色の起伏です。(色のコントラストともいう) 色のコントラストが低いと、レベル調整でどんなに色の絶対値を上げてもやはりのっぺりした画像になります。一番分かりやすいのはヒストグラムの山の幅です。もし一色でも山の細いのがあると、美しい色表現はできません。過度にカブリ補正した画像などは、このような傾向になるので要注意です。

さて、トークですが、オリオン座南部の私の作品を例にいろいろしゃべっています。その作品です。

1406225

この作品は意図的にカラーバランスを崩してます。まず、背景はニュートラルグレーではなくグリーンを弱めにしてます。そして、赤い星雲の赤を弱めています。こうすることによって、色の重なり具合いを分かりやすく表現しています。それが功を奏してか、これも天ガに入選した作品です。

よっちゃんはこれを「GB遊び」といって、もう時代遅れと言っていましたので、そしてこの作品の場合は赤をかぶせればよいと言っていました。その通りにしてみました。

1406226

よっちゃん曰く、同じ赤でも、グリーンぽい赤もあれば、ブルーぽい赤もある、いろいろな赤があるので、十分色を表現できるとのことでした。いかがでしょうか。

さて、2回にわたってトーク解説をしましたが、トークの他の部分についてはたわいない会話なので、説明してもしょうがないでしょう。

それよりも、ほんまかは、α7sを買うのでしょうか?それが問題だ。

| | コメント (9)

2014年6月21日 (土)

よっちゃんとのトーク解説その1

お久しぶりです。

なんだかんだ、忙しく、ブログの更新が開いてしまいました。そんな中、よっちゃんのブログのトークコーナーにめでたく?出演することができました。パチパチパチ。

私、自分から出せと言っておきながら、何のネタの準備もなく望んだため、ダラダラ会話してしまい、よっちゃんや、聞いてくださる方に大変ご迷惑をおかけしました。すみません。

次回は必ず、ネタを準備して望みます。っていうか、また出るきか?

さて、ダラダラ会話でしたが、多少有意義な議論がありました。2つほどあったと思います。

1 強調処理におけるトーンカーブVSレベル調整
2 カラーバランスについて

強調処理とカラーバランスという天体写真のおける重要なテーマについて議論できたことは良かったと思います。ベテランの方なら話している内容はわかってくれたと思います。残念ながら何を言ってるか分からなかった人はすみません。そこで2回にわたって、上記議論の内容を解説していきたいと思います。

●トーンカーブについて

よっちゃんは強調処理ではトーンカーブは使わないそうです。私はしょっぱなから使います。

●トーンカーブの問題点

トーンカーブは接線の傾きが重要で、傾きが寝ている部分はコントラストが低く、眠たい感じになる。

●ほんまか反論

階調は256段階というように決まっており、どこかのコントラストを高くすれば、どこかが低くなるのはしょうがない。トーンカーブはそのことがはっきりわかって、分かりやすい。

で、トーンカーブを使わない場合、レベル調整を使用しますが、

●レベル調整の利点は

リニアで調整しやすく、コントラストが低くなることはない、高輝度部のトビはマスク併用で抑える。

●ほんまか反論

レベル調整だと全体的に均一に明るくなる(特に淡い部分だけというのではなく)、マスクとマスクのない部分で不連続になる。

さて、言葉で説明してみても分からないと思いますので、実際にやって見ましょう。お題の絵はこちら。

1406211

まず、私流にトーンカーブをかけてきます。かなりきついS字カーブです。

1406212

トーンカーブで重要なのはその傾きです。傾きが大きいとコントラストが高く、傾きが小さいと、コントラストが低くなります。これを寝かせるといいます。

1406213

ピクセル等倍画像です。トーンカーブが寝ているのは、星の回りのボーとしたところ、それから燃える木の中心部あたりです。確かにちょっと眠い感じがします。一度こうなってしまうと2度と元には戻りません。

1406214

それでは、次に、レベル調整で強調処理をしてみます。

ここで一言断っておきます。ここの説明は画像処理の結果を見て、どちらかの優劣を決めるものではありません。私は、よっちゃんが具体的にどのような処理をしているか知りません。私ならこうすると言うだけです。

また、私は普段、このような処理をしていないので、普段からやっている人と同じレベルの画像ををだすことなど絶対にできません。

ここでの説明は、トークの内容が理解できなった方のために、理解の手助けになるヒントを与えるだけです。

それでは説明します。こんどはレベル調整で下と上のスライダーを狭めます。真ん中のスライダーを動かしてはいけません。(真ん中動かすとリニアになりません)

1406215

このレベル調整は、トーンカーブでも再現できます。以下のような具合です。リニアというのはここから来ています。

1406216

ただ、ピクセル等倍で見ますと、高輝度部が飛んでいるのが分かると思います。

1406217

そこでマスクの登場です。このマスクをどう作るかが大問題です。私はレベル調整を切り詰めて作りましたが、作り方や、どの程度まで抽出するかの程度の問題。これで結果がまったく異なります。

14062182

このマスクを適用すると、高輝度部とトビが抑えられますが、次のように不自然な画像にあります。

1406218

拡大画像です。マスクが効きすぎています。そこでマスク自体にレベル調整をかけて、マスクをちょっと薄めてみます。

1406219

下のスライダーの出力レベルを右にスライドさせます。

14062110_2 

ちょうど良くなったと思いますが、トーンジャンプしてますね。実はここまでするのに凄い苦労しました。普段からやってる人なら問題なと思いますが。あと、星の周りにフリンジができてしまいました。これもだめですね。繰り返しますが、マスクなどの手法が悪いのではありません。私が悪いのです。

さて、マスクを使う、私の懸念ですが、マスクとマスクでない部分の境界で階調に不連続性が出るのではないかということです。図でイメージするとこんな感じです。

14062113_4

レベル調整の場合の最終画像を出しておきます。

14062111

トーンカーブの場合の画像ももう一度出しておきます。

14062112_2

あまり変わりありませんね。トーンカーブの方があきらかにコントラスト低いですが、本番ならもっとちゃんとやりますから。レベル調整の方も同じです。

いかがでしょうか、トークの内容が分からなかった方はもう一度と聞いてみてください。

次回はカラーバランスです。

| | コメント (0)

2014年6月16日 (月)

「天文屋のためのマイコン入門」PICマイコンのコンフィグレーション

今日は今まで説明を後回しにしてきた次の一行

__CONFIG H'2007', H'3F18'

について詳しく解説していきたいと思います。

16進数表記をレジスタと同じにすればこのようになります。

__CONFIG 2007h, 3F18h

この一行は、端的に言うと、PICマイコン16F88の初期設定(コンフィグレーション)を行っている一文です。機械的な説明をすると、番地2007hのプログラムメモリに値3F18hに設定していると見ることができます。

実は、16F88はプログラムを格納するためのプログラムメモリの一部を借りて、そこをPICのコンフィグレーションの設定場所としているのです。番地は決まっていて2007h番地と、2008h番地ですが、2008h番地は使用頻度は高くないので、今後省略します。

1406162 

次に__CONFIGの一文ですが、これはMOVLWなどと同じ命令でしょうか? NOです。これはマイコンが実行する命令ではありません。ENDなどと同じ擬似命令(開発ツールに対する指示)の部類です。

__CONFIGがマイコンの命令ではないことは明らかです。PICの命令の中にはプログラムメモリに書き込む命令はありません。(できない、ということではない) レジスタなどのデータメモリに書き込む命令はありますが、プログラムメモリに書き込む命令はありません。

また仮にそのような命令があったとしても、そもそもコンフィグレーションが終わっていないと、何の命令も実行できませんから、意味がありません。

ということで、2007h番地への書き込みは、ビルドしたプログラムを書き込むときに一緒にコンフィグレーション設定値も書き込んでおくほかありません。__CONFIGはそのための命令です。したがって、この一文は、

__CONFIG 2007h, 3F18h

プログラムを書き込むときに、2007h番地に3F18hも一緒に書き込んでおけという、MPLABに対する命令です(マイコンに対する命令ではない) つまり擬似命令ということができます。

それでは、このコンフィグレーションの設定値について詳しく説明します。

2007h番地の各ビットは数ビットづつのグループに分かれていて、次のような記号を持ちます。

1406161_2

記号の意味は後で出します。

この各ビットを1または0に設定するのが、コンフィグレーションです。

サンプルプログラムでは設定値を16進数に変換して書きましたが、16進数が苦手な人は、2進数でもかまいません。

__CONFIG 2007h, B'11111100011000'

さて、ここは1または0を正しく設定しないと、マイコンが動作しなかったり、ポートの一部が使えなかったりします。

ですから、非常に重要な設定です。それなのに、このコンフィグレーションについて分かりやすい説明はあまり見ません。そこで私が、3日ががりで作ったPDFがあるので、それをよく読んで利用してください。

「16F88コンフィグ説明書」をダウンロード

補足事項

●デフォルト値は'1'です。なぜなら、プログラムメモリはフラッシュメモリであり、何も書込みしなければ1だからです。

●どのビットも必ず、1か0か選択してください。この機能は利用しないから、どちらでもいいやと思うと、意図しない設定になって動作しません。

| | コメント (0)

2014年6月15日 (日)

「天文屋のためのマイコン入門」サブルーチンについて考える

今日は、サブルーチンについて、もう少し考えて見たいと思います。

まず、最初に問いです。

サブルーチンの処理の中で別のサブルーチンを呼べるか?

1406151

この問いに私が答えを言うのは簡単です。でも、せっかくなので、サブルーチンの動作の仕組みを考えながら、上記問いの答えを考えてみたいと思います。

まず、サブルーチンコール命令を良く見てみます。

CALL ラベル

この命令によって、ラベルの番地にジャンプします。しかし、似たような命令がありました。

GOTO ラベル

これも、ラベルの番地にジャンプします。CALLもGOTOも動作が同じように見えます。どこが違うのでしょうか? CALLをGOTOに変えたらプログラムは動くでしょうか? 当然ですが、動きません。では違いはどこにあるのでしょうか?

その違いの鍵はサブルーチンから戻るRETURN命令にあります。

RETURN

この命令、番地の指定は一切ありません。それなのになぜ、元の番地に戻れるのでしょうか?

さらに、次のような場合を考えてみてください。メイン処理の中で、同じサブルーチンを2回呼ぶとします。

1406152

図を見れば分かるように、2回RETURN命令が実行されますが、まったく同じ番地の同じRETURN命令なのに、1回目と2回目で戻る番地が違うのです。

これはちょっと考えると不思議です。RETURN命令はどうして戻り先が分かるのか?

勘のいい人ならもうわかると思いますが、答えは、

CALL命令が戻り番地をどこかに保存しておいて、RETURN命令はそれを参照している。

その通りです。CALL命令は戻り番地はたやすく分かります。なぜなら、自分自身の番地+1が戻り番地だからです。それをどこかに保存してからラベルの番地へジャンプします。

CALL命令=戻り番地の保存+GOTO命令

と考えられます。ここで最初の問いに戻ります。

サブルーチンの処理の中で別のサブルーチンを呼べるか?

答えはNOということになります。理由はこうです。戻り番地の保存先がどこかにあるとします。それをBUFと呼ぶことにします。

1 MAINからSUB1をコールするとき、MAINの戻り番地がBUFに保存される
2 SUB1からSUB2をコールするとき、SUB1の戻り番地がBUFに保存される

この時点で、MAINの戻り番地が上書きされますので、SUB1からMAINに戻ることはできなくなります。

1406153

ただし、これは戻り番地を保存する場所が一つしかないとした場合です。もし2つあるなら答えはYESになります。

1406154

実は、保存する場所は8つあります。したがって、サブルーチンの中でサブルーチンを呼ぶことをネストするといいますが、ネストレベル8まで許されるということです。

9回目ネストすると、最初の保存場所が上書きされるので、もう最初の位置に戻ることはできません。

ここで勘違いして欲しくないのは、サブルーチンが8回までしかコールできないと言っているのではないです。また、サブルーチンは8個までしか定義できないと言っているのでもありません。

サブルーチンは何個でも定義できますし、何回でも呼ぶことができます。ただ、サブルーチンの中から別のサブルーチンを呼ぶネスト構造が8レベルまでということです。ロシアのマトリョーシカ人形は8個までということです。ここは勘違いしないように注意してください。

中級者向け補足(ここの説明がわからなかったら、それはそれでいいです)

ここで言うネストレベルとは、実際ににCALL命令が実行された場合の問題です。単にプログラム中にCALL命令があるだけでは判断できません。もし、条件判定などでこのCALL命令が実行されないなら、これはネストレベルの中に含まれません。このように実行時にきまる問題を動的な問題といいます。(反対は静的な問題)ネストレベルは動的な問題です。

| | コメント (0)

2014年6月14日 (土)

「天文屋のためのマイコン入門」サブルーチンの導入

プログラムの7セグメントLEDを表示する部分ですが、長いですね。また7セグメントLEDを表示する処理は、今後、プログラム中で、いくつも出てきそうです。その度にこの長い処理を記述していたのでは大変です。またプログラムもわかり難くなります。

それにGOTO命令が多いと、プログラムを読み解くのも大変です。

もし、7セグメントLEDを表示する部分をメインの処理から切り離し、プログラムの端っこに記述しておいて、1命令でこの処理を代用できたら、便利そうです。

7セグメントLEDを表示する処理が必要な場合は、この一命令を記述すればよいのです。そうすればプログラムのメイン処理部分はすっきりとするでしょう。

このプログラムの一部分を切り離し別の処理とすることを、処理を「サブルーチン化する」といいます。そしてこの分離した処理を「サブルーチン」といいます。

サブルーチンの処理を実際に行いたいときは次の一命令を実行すればよいです。

CALL サブルーチンの番地

サブルーチンの番地にはラベルが使えますので、実際には次の一行になります。

CALL サブルーチン先頭のラベル

この命令の名称からわかるように、サブルーチン処理を要求することを、「サブルーチンを呼ぶ」といいます。

次に、サブルーチン本体の記述です。本体はどこかに記述しなければなりません。普通はプログラムのメイン処理の後に記述します。サブルーチンだからといって特別なことはありませんが、次の2点は必ず守ってください。

1 先頭にラベルを定義する
これによりサブルーチンをラベルで呼ぶことができます。

2 サブルーチンの処理が終わり、呼ばれた場所に戻るには、
RETURN命令を記述する

以上の決まり図示してみました。

1406141

それでは、このサブルーチンの決まりにしたがって、前のプログラムで7セグメントLEDを表示する部分をサブルーチン化してみましょう。

サブルーチンのラベルはDisp7Segとします。またサブルーチン本体ですが、GOTO LOOPのところをRETURNに変えます。

前半
1406142

後半
1406143_2
いかがでしょうか? プログラムのメインの処理の部分がすっきりしたのがわかります。

ところで、サブルーチンにすべき処理はどのような処理でしょうか? この例では、処理が長いのサブルーチンにしました。一般にサブルーチンにするべき処理は以下のような場合です。

●処理が長い
●使用頻度が高い(何回も同じことを繰り返す)
●汎用性がある(他のプログラムでも利用できる)
●回路などハードに依存している

このプログラムの例では、スイッチの状態を入力する次のたった2行もサブルーチン化してよさそうです。

MOVF 5h,W          ;ポートAをワーキングレジスタに格納
ANDLW B'00001111'    ;下位4ビットをマスク

たった2行ですが、これもサブルーチン化するとメリットがあります。もし、スイッチに関する回路が変更になった場合、このサブルーチンだけ変更すれば良いのです。メイン処理は変更する必要がありません。このようにハードに依存する部分をサブルーチン化し、メイン処理から分離することはよく行われます。

この2行をInputSWとしてサブルーチン化した例を示します。(後半部分は省略)

1406144

さて、InputSWと、Disp7Segの2つのサブルーチンを紹介しましたが、この2つのサブルーチンは次の特徴があります。

1 InputSWは、スイッチからデータを入力し、メイン処理側に値を返している。

2 Disp7Segは、メイン処理から値を20hに格納してもらい、呼ばれている。

InputSWはメインに値を返しています。これを戻り値といいます。InputSWは戻り値を持っているといいます。

Disp7Segは逆にメインから値をもらっています。これを引数またはパラメーターといいます。Disp7Segには引数があると言います。

1406145

もちろん、戻り値も、引数も両方あるサブルーチンもありますし、両方ないサブルーチンもあります。

引数も戻り値もその受け渡しにワーキングレジスタ(W)を使うのが理想です。

Disp7Segは引数に20hの汎用レジスタを使っていますが、これはあまり良くありません。汎用レジスタは番地があるので、その番地を覚えていなければなりませんし、番地が変われば、サブルーチンを書き直さないといけません。それになにより、汎用レジスタはバンクが異なれば同じ番地でも実体が異なりますから、違うバンクで使うことができません。(もちろろん全バンク共通の汎用レジスタを使う手もありますが)

次回はもうちょっとサブルーチンに関して考えてみたいと思います。

| | コメント (0)

「天文屋のためのマイコン入門」プログラム解説続き

ロータリースイッチのプログラム解説の続きですが、ここはほとんど説明の必要もないとこでしょう。

1406132_2
0から9までの表示をする処理を記述しています。そえぞれ、PA6とポートBにデータを出力して、最後に無限ループの先頭にジャンプします。

さて、今回の7セグメントLEDを表示するプログラムを見直して見ましょう。

スイッチからの10通りの入力を場合分けする部分、ここがキーポイントですね。このようにデータを片っ端から比較、選別する処理はわかりやすいですが、効率は悪そうです。

もし、スイッチからの入力が1なら、運よく一回の比較で、処理を選別できます。最悪は0の場合です。この場合、9回比較した後に、ようやく選別できます。

今、Nとおりのパターンを選別するときの比較回数を計算してみると、最良の場合は1回、最悪の場合はN-1回です。平均するとN/2回です。

もうちょと、効率の良い選別方法はないでしょうか?

2分検索という方法があります。方法は簡単です。データパターンを2つにわけ、どちらに入っているか調べます。そして入っているほうを更に2つに分けてどちらに入っているか調べます。これを繰り返していけば、すべてのパターンを検索できます。

2つに分けるというと、なにやら難しそうですが、2進法で考えるとわけないです。ビットパターンを端から順に、0か1の場合で場合分けしていけばよいのです。今回の場合はスイッチの入力は4ビットですから、上位のビットから1の場合と0の場合で場合分けしていきます。

b3=0
     b2=0
          b1=0
               b0=0   ->0
               b0=1   ->1
          b1=1
               b0=0   ->2
               b0=1   ->3
     b2=1
          b1=0       
               b0=0   ->4
               b0=1   ->5
          b1=1
               b0=0   ->6
               b0=1   ->7
b3=1
     b2=0
          b1=0
               b0=0   ->8
               b0=1   ->9
          b1=1
               ありえない
     b2=1
          ありえあない

場合分けは、BTFSC命令などでやっていけばよいでしょう。このアルゴリズムでは、N通りのパターンを場合分けする比較回数は√Nです。N=10くらいなら大差ないですが、Nが大きくなると、この差が効いてきます。

さて、実は、もっともっと効率の良い、そしてプログラムももっと小さくなる処理方法があります。間接参照というデータアクセス方法を使えば、比較処理など一切なしで一発で処理できる方法があります。

この間接参照というのは、マイコンではとても基本的なもので、必ず覚えなければならないものですが、当面必要ないので、また折をみて説明したいと思います。

今日はここまで。

| | コメント (0)

2014年6月13日 (金)

PRO-10買いました

PRO-10買いました。

1406136

実は、半年ほど前から愛用のプリンタPX-G930が故障して、そのままにしておいたのですが、そろそろ買わないと、フォトコンにも応募できないので、やっとのこと買いました。

候補はPro-100 Pro-10 PX-7V...とあったのですが、購入のポイントは2つ。

1顔料系であること

染料系は、色が安定するにに時間がかかるから嫌です。プリント直後は良かったのに、次の日に変わっていたらがっかりですからね。でも最近の染料系はちょっとよくなっているみたいです。

2キャノン製であること

エプソンは前機種PX-G930でICCプロファイルがまったく合わず苦労したので、もう二度とエプソンは買うまいと思っていたので、キャノン製ということになります。

以上2点を考慮するとこの機種くらいしかないのですが、かなり悩みました。高いですからね。最近まともな天体写真撮ってないので、そもそもプリンタ自体もう必要ないのではと思っていました。ただ、仕事でもA3プリンタがあるといいなと思っていたので、それが後押しになりました。

今日は、USB接続とWiFi接続の作業をして3台のパソコンからテストプリントしただけです。はやくこれで出力したやつ応募したいですね。

 
 
 

| | コメント (2)

「天文屋のためのマイコン入門」プログラム解説

ロータリースイッチのプログラム解説です。

このプログラムをビルドし、書込み、実行すると、ロータリースイッチの値(0~9)が7セグメントLEDに表示されます。スイッチを回すと7セグメントLEDの値も変化します。

前半部分

1406131

後半部分

1406132

今日は前半部分の解説です。

まず、初期化の部分ですが、ポートAの下位4ビットが今度は入力になりますので、以下のように変更します。

MOVLW B'00101111'    ;RA7 RA6 RA4出力、他入力
MOVWF 85h          ;TRISA=B'11010000' ポートA入出力セット

1に設定したビットは入力で、0び設定したビットは出力になります。RA7は未接続ですが、未使用のピンはハイインピーダンス状態になるのを避けるため、出力に設定しておいた方が良いでしょう。

初期化の他の部分は前回と同じです。

次に、ロータリースイッチからの入力部分です。

LOOP
MOVF 5h,W         ;ポートAをワーキングレジスタに格納
ANDLW B'00001111'   ;下位4ビットをマスク
MOVWF 20h         ;それを、汎用レジスタに格納

まず、MOVF 5h,Wで、ポートAの状態をワーキングレジスタに入力します。これでワーキングレジスタにはポートAの状態が入りました。

ただ、ポートAのうち、必要なのは下位4ビットで、上位4ビットは何が入っているか分かりません。正確に言えば、調べれば分かります。ただ、いちいち不要なビットのことを考えるのも無駄なので、上位4ビットを強制的に0にしてしまいます。

方法は論理積演算(AND)です。AND演算は、

1406133

0とのAND演算は相手が1であろうと0であろうと0になります。
1とのAND演算は相手の状態がそのまま反映されます。つまり相手が1なら1、0なら0です。

つまり、必要なビットは1とのANDをとり、
不要なビットは0とのANDをとります。

そうすると、不要なビットはすべて0になり、必要なビットのみ取り出せます。

ANDLW B'00001111'   ;下位4ビットをマスク
1406134このような理由からこのような演算をANDでマスクするといいます。

さて、これで純粋にスイッチの状態がワーキングレジスタに代入されました。次にこの値を汎用レジスタに保存します。

MOVWF 20h         ;それを、汎用レジスタに格納

汎用レジスタは、レジスタファイルの後ろの方にあるレジスタで、プログラマがプログラム中に自由に使うことができます。汎用レジスタは20h番地からありますので、一番最初の20h番地のレジスタを使うことにします。(他の番地でもかまいません)

次は、取り込んだスイッチの状態を値に応じて、場合分けしなければなりません。つまり、スイッチが0の場合、1の場合、2の場合、という具合です。

あまり効率的ではありませんが、分かりやすい方法をここで紹介します。

取り込んだ値を、デクリメント(-1)してみます。

DECF 20h,F  ;デクリメントする

もし、これが0なら、値は1だったことになります。したがって、0なら、GOTOで1を表示する部分にジャンプするようなプログラムにします。そうするには、0でないならGOTOをスキップする命令を書けば良いことになります。

ところで0でないということはZフラグがセットされないので0ということです。

演算結果が0  ->Zフラグが1
演算結果が0でない -> Zフラグが0

演算の結果が0でないなら、Zフラグが0という逆の状態になるのです。ややこしいですね。ここを注意して、Zフラグは3番地のビット2にありますから、次のような命令になります。

BTFSC 3h,2           ;0でないならGOTOをスキップ
GOTO disp_1          ;1を表示へ

disp_1は7セグメントLEDに1を表示するプログラムを記述している番地を示すラベルです。次回その部分の説明をします。

また、BTFSC命令ですが、次の2つの種類があります。

BTFSC      f  ,  b     f番地のbビットが0なら(Clear)スキップ
BTFSS      f  ,  b     f番地のbビットが1なら(Set)スキップ

区別は最後文字でします。最後がCならClearですから、0、
最後がSならSetですから1です。

1406135_2分かりましたか?

さて、これで1かどうかの判断は終わりましたので、またデクリメントします。今度0なら、最初の値は2だったということになります。これで2を表示する部分にジャンプできます。以下同様に繰り返していき、最後9まで比較し、どれにも当てはまらなければ、0だったということになります。

今日はここまで、次回、後半部分を説明します。

| | コメント (0)

2014年6月12日 (木)

「天文屋のためのマイコン入門」ロータリースイッチの取り付け

またまた説明漏れがありました。私の認識不足ですみません。

プログラムに記述する命令や擬似命令は先頭に空白かタブを入れてください。これがないと、ビルド時に警告メッセージ(Warning Message)が出ると思います。

なぜ、空白かタブを入れなければならないかですが、前回説明したラベルと区別するためだと思われます。ラベルは行の先頭に記述しなければなりません。

さて、今日はロータリースイッチの取付です。デジタルスイッチとも呼ばれます。このスイッチには0から9のポジションがあり、4本のピンから2進数として値を出力することができます。

マイコンからはポートAの下位4ビット(RA0~RA3)を使ってこの状態を入力することにします。

回路図は以下の通りです。

1406121

この回路図に描かれたスイッチの1,2,4,8の番号ですが、これはピン番号ではなく裏に書かれた記号です。2進数にした時の重みをあらわします。たとえばスイッチが5のポジションにある場合は、1と4がONになり、2と8がOFFになります。スイッチは正論理で取り付けています。

1406122

配線図は以下の通りです。

1406123_2 

完成写真です。

1406124

1406125

次回、プログラムの紹介と説明をします。

| | コメント (0)

2014年6月11日 (水)

「天文屋のためのマイコン入門」ラベルの使用

今日は、便利なラベルと言われる機能について説明します。

GOTO命令は、次のようにジャンプ先の番地を記述するのが決まりです。

GOTO 5

ただ、直接番地を記述しながらプログラミングするのは煩わしいです。その理由は、

1 どこへジャンプするか番地を数えないと分からない

2 プログラムの上のほうへジャンプ(後方参照という)する場合は、すでに番地が確定しているので良いが、下のほうにジャンプ(前方参照という)する場合は、番地が未確定である。そのため、番地を空欄にするか、仮の番地を記述し、後から修正する(この作業をフィックスアップという) 

3 プログラムが修正された場合、番地が変化するので、再度番地を記述しなおさなければならない。

以上3つは実際にプログラミングして見れば誰でも感じることです。で、この3つの不便をすべて解消してくれるのがラベルの機能です。

●ラベルとは
 
まず、ラベルの名前を決めます。ラベルの名前は英字、数字、下線などからなり、先頭は数字以外です。名前はプログラムする人が自由に決められます。たとえばプログラムの最初のを意味するSTARTと名付けることにします。

そしたら、このラベルを行のはじめ、命令の前に記述します。

START    BSF  3,5

または、途中に改行を入れてもいいです。

START
             BSF  3,5

どちらでもいいです。そうしておいてプログラムをビルドすると、MPLABは、BSF 3,5の命令の番地を計算してSTARTというラベルに割り当ててくれるのです。

たとえば、BSF 3,5という命令が5番地だとすれば、STARTは5番地と同等になります。

したがって、BSF  3,5という命令のところにジャンプしたければ、

GOTO START

と、記述すれば良いです。これがラベルです。簡単に言えば

ラベルとは
 その場所の番地である

このラベルを使用すればジャンプ先がはっきり分かりますし、番地の計算も必要ありません、またプログラムが変更されても、その都度MALABが再計算しますので、プログラマが考える必要はありません。

それでは、前回出したプログラムをラベルを使って書き直してみます。

1406111

どうですか、分かりやすくなったと思います。

| | コメント (0)

2014年6月10日 (火)

「天文屋のためのマイコン入門」プログラム解説

7セグメントLEDのプログラムの解説です。

1406096 

まず、以前と比べてプログラミングスタイルをちょっと変えてみました。レジスタの番地は16進数の通し番地で記述してあります。これはPICのマニュアルの記載に合わせたからです。

次に、コメントを追加しました。セミコロン(;)から行末までは、コメントといって、プログラム上は何の影響もありません。プログラムが読みやすくなるようにコメントを入れます。

それでは解説に入ります。4行目から8行目までは初期化ですが、前回のプログラムとほぼ同じで、ポートBの出力方向の設定が新たに加わっています。

10行目から無限ループが始まります。最初に

BTFSC 5h,5

でスイッチの状態を見ています。スイッチがONなら、つまりRA5が0なら次のGOTO命令をスキップするので、GOTO以下の命令が実行されます。

GOTO以下の命令は

BSF 5h,4  ;ポートAの4ビットを1にセットLEDが光る
BSF 5h,6  ;ポートAの6ビット
MOVLW B'11011011'
MOVWF 6h  ;ポートB出力

最初の一行目でLEDを光らせ、後の3行で7セグメントLEDをすべて光らせています。

そして最後に

GOTO 5  ;最初に戻る

で無限ループの先頭に戻ります。

20行目からは、スイッチOFFの場合の処理が記述されています。
 
BCF 5h,4  ;ポートAの4ビットを0にクリアLED消灯
BCF 5h,6  ;ポートAの6ビット
MOVLW B'00000000'
MOVWF 6h  ;ポートB出力

スイッチONの場合とは逆にLED、7セグメントLEDをすべて消灯させています。
そして最後に

GOTO 5  ;最初に戻る

によって、無限ループの先頭に戻ります。

ポートの1ビットのみを操作する時は、BSFやBCFなどのビット操作命令が便利です。

一方、ポートの中の複数のビットを操作する場合は、数値を一旦、ワーキングレジスタに入れて、それをポートのレジスタに転送する方式が便利です。

以上、プログラムを簡単に説明しました。

次回は、ロータリースイッチの取り付けです。

| | コメント (0)

2014年6月 9日 (月)

「天文屋のためのマイコン入門」7セグメントLEDを付ける

まず最初に、謝らなければならないことがあります。大事な設定の説明を忘れていました。それは、デフォルトの基数の設定です。

これから先、プログラムを記述するのにデフォルトの基数を10進数としたいのですが、それにはMPLIBの設定が必要なのです。これをしないと、たとえば、

10

と書いた場合、10進数の10ではなく16進数の10(つまり10進の16)と解釈されてしまうのです。

方法は次の通りです。

MPLIBを起動し、プロジェクトを新規作成、または開いたら、メニューの[Project]->[Build options]->[Project]を開き、[MPASM Assembler]のタブをクリックします。

1406091

Default RadixのところををDecimalとします。

ただ、この設定はプロジェクト毎に行う必要があり、忘れる可能性があります。(実際私は忘れた)

そこで、プログラム中で設定する方がいいと思います。プログラムの一番最初に次の一文を書けばOKです。

Radix DEC

なおデフォルト基数を10進数としましたが、この場合、16進数を書くには以下の方法があります。

●H'    'で囲う  例 H'9b'
●最後にhを付ける 例 9bh
●最初に0xを付ける 例 0x9b

どの方法でも良いのですが、PICのマニュアルの記述が最後にhを付ける方式なので、今後そうします。

それでは、7セグメントLEDを取り付けます。まず、回路図です。

1406092

ほんとは、7セグメントLEDの7個のLEDを全部、ポートBに接続したかったのですが、ポートBのRB2とRB5は、スマフォの無線通信のために使うので、どうしても空けておく必要があります。そこで泣く泣く、1本だけ、ポートAのRA6に接続しました。

ですから、この7セグメントLEDを操作するにはポートAとポートBの両方をアクセスする必要があります。

ただ、ポートAは1ビットしか使っていないので、ビット操作命令(BCF/BSF)を使うことにします。

この接続の場合の、ポートへ出力するデータと7セグメントLEDの数字の関係を次に示します。

1406097

配線図は次の通りです。

1406093

実際の完成写真です。

1406094

1406095

プログラムを作ります。MPLIBを起動したらプロジェクトを新規に作成し、以下のようなプログラムを記述します。

1406096

このプログラムは、スイッチを押すとLEDと7セグメントLEDが点灯し、離すと消灯するプログラムです。プログラムの解説は次回します。

| | コメント (0)

2014年6月 8日 (日)

「天文屋のためのマイコン入門」LEDプログラムの解説

それでは、必要な準備が整ったので、以前出したLEDのプログラムを解説します。こんな小さなプログラムでも、ちゃんと理解するにはこれだけの下準備が必要なのです。

1406081

回路図ももう一度、出しておきます。

1404121_2 

まず、このプログラムを見て、ちょっとPICのプログラムを知っている人なら、ちょっと様子がおかしいと思うかもしれません。シンボルを使っていなくて、やたら数字が多いです。

普通のPICプログラムはたとえば、こんな感じです。

1406082

数値をシンボルに置き換えて、数値の代わりにシンボルでプログラミングすることをシンボルプログラミングといいます。この鍵は、2行目の

INCLUDE P16F88.INC

にあります。この一文によって、シンボルの定義ファイルを取り込んでいるのです。この定義ファイルをヘッダファイルといいます。

この連載ではしばらくヘッダファイルは使わないことにします。つまりシンボルは使いません。(ラベルは使います)

このヘッダファイルというのはプログラミングを習熟した人が使うのは便利で良いのですが、これからプログラムを学ぼうとする人にとっては、なんの利益もありません。これはプログラムの本質をブラックボックス化し、本質を見えなくします。確かにシンボルを使わないと、番地とかいちいち調べなければなりませんが、それゆえ、マニュアルを見る癖がつくでしょう。

また、エラーが起きたとき、ヘッダファイルを使わないと、すべての問題が一つのファイル内で完結しますから、エラー原因がつかみやすいです。(ヘッダファイルをいきなり使うことは、小学生に筆算を教えないでいきなり電卓の使い方を教えるようなものです。)

それでは、元のプログラムにもどり解説します。

1406081_3 

1行目 __CONFIG H'2007', H'3F18'

この一行は、PIC16F88の初期状態、たとえば内部クロックを使うか、外部クロックを使うか、リセット信号はどうするかとかのコンフィグレーション情報を設定するものです。

この一文は非常に重要な文です。ですから、この一行は「おまじない」ですとか、この通り書いてくださいですむ一行ではありません。ちゃんと説明しないといけない一文です。もし、この文を理解していないと、このプログラムを他のシステムに流用したり、逆に他のシステムのプログラムをこの回路に流用する場合にプログラムが動かない可能性があります。

しかし、この説明をするとまた横道にそれるので、また改めて後日説明します。

3行目から6行目でポートAの初期設定をしています。

3行目  BSF  3,5

これは3番地のレジスタ(つまりSTATUSレジスタ)の5ビットを1にセットしています。つまりバンク1に設定しています。ビット6は初期値0のままでよいので、ビット6を操作する命令は要りません。

4行目  CLRF 27

バンク1の27番地のレジスタ、つまりANSELレジスタです。ポートAは初期状態でADコンバーターの入力ピンとなっていて、ポートの機能はありません。このANSELレジスタをすべて0にすることにより、ポートAをポート機能として利用できるようになります。

5行目  CLRF 5

バンク1の5番地のレジスタ、つまりTRISAレジスタを0にクリアしています。つまりポートAのすべてのビットを出力に設定しています。

6行目  BCF  3,5

STATUSレジスタのビット5を0にクリアして、バンクを0に戻しています。

7行目以降で実際にLEDを光らせます。

8行目 MOVLW b'00000000'

まず、ワーキングレジスタに0を書き込んでおきます。なぜ0を書き込んでおきかは後で分かります。

9行目 BTFSC 5,5

現在はバンク0の状態です。バンク0の5番地はポートAそのものです。ポートAの第5ビットを調べています。ポートAの第5ビットRA5はスイッチをつなげていましたね。

この命令はRA5の状態が0なら次の命令をスキップしろという命令です。

10行目 MOVLW B'11111111'

ワーキングレジスタに2進数で11111111を書き込んでいます。ただ、8行目により、もしRA5が0ならこの命令はスキップされます。したがって、ワーキングレジスタは0のままです。まとめると

RA5が0なら、すなわち、スイッチONなら、W=00000000
RA5が1なら、すなわち、スイッチOFFなら、W=11111111

11行目 MOVWF 5

ワーキングレジスタをバンク0の5番地、つまりポートAに出力します。ワーキングレジスタの値によって、'1'または'0'が出力されます。'1'の場合は、LEDが点灯し、'0'の場合は消灯します。

12行目 GOTO 4

プログラムは4番地、つまり5番目の命令のところにジャンプします。これにより4番地からのプログラムを繰り返し実行することになります。これによりプログラムは無限ループ構造になります。

つまり電源を切るまで同じことを繰り返します。

実はマイコンのプログラムでは、このようにプログラムを無限ループ構造にすることが重要です。つまりマイコンのプログラムには終わりがないのです。

もし、どうしても一回限りの処理でよく、無限ループ構造にならないなら、GOTOのジャンプ先番地を自分自身にします。

つまりひたすらGOTOを繰り返す命令です。

こうしないと、マイコンが暴走してしまうのです。つまり、プログラムが途中で終わってしまうと、人間から見ると、プログラムはそこで終わりに見えますが、マイコンから見ると、プログラムメモリに終わりの印はあるわけではないです。まだプログラムがあって、でたらめなデータをプログラム命令として実行し続けてしまうのです。ですから、かならず、最後は無限ループ構造にします。(あるいはスリープ状態にして終わらせる方法もあります)

14行目 END

END命令ですが、これはマイコンに対する命令ではありません。この命令はマイコンが実行するプログラムには含まれません。ですからこの命令があっても、マイコンは実行を停止しません。

では何に対するEND命令かというと、プログラムをビルドするMPLABソフトウェアに対する命令です。ここでプログラムは終了するから、翻訳作業を停止せよということです。

このようにマイコンに対する命令ではなく、開発ソフトウェアに対する命令を「擬似命令」といいます。

次回は、7セグメントLEDの取り付けです。

| | コメント (0)

2014年6月 7日 (土)

「天文屋のためのマイコン入門」IOポートの使い方を調べる

PICマイコンの命令とデータ構造を一通り学びました。さあ、これで、自由自在にプログラミングといきたいところですが、そう簡単にはいきません。

命令とデータの知識だけでは、マイコンにたとえば"1+2=3"の計算をやらせるようなもので、これだけは何の役にもたちません。

IOポートに代表されるマイコンの内蔵機能を使うことを覚えて、初めて役に立つプログラミングができます。

ただ、内蔵機能は覚えるものではなく、その都度調べる物です。内蔵機能はマイコンの機種によって使い方が違いますし、そもそも使わない機能を覚えても仕方ありません。ですから、覚えるのではなく、正確に言えば、使い方を調べる方法を覚える。と言ったほうがいいでしょう。

では、どうやって調べるか、それはメーカーから発行されるマイコンの「データシート」を読み解くことです。

ちなみにPIC16F88のデータシートはPIC16F88で検索すればすぐ見つかります。

とはいえ、マイコン初心者が、英文のマニュアルを読みながら使い方を調べるのはそう簡単にはいきません。最初はサンプルプログラムや解説本、ネットの解説などを頼りにやっていくしかないでしょう。しかし、大事なことはマニュアルを読む力をつけることです。サンプルプログラムを使うにしても、少なくてもこの一文は何をやっているかくらいは理解しておかなければなりません。

それでは最初に2つあるIOポートのうちAグループの方の使い方を調べて見ましょう。

データシートの51ページに、IOポートの記述があります。最初に次ページのTABLE5-2を見てみます。これはIOポートに関連したレジスタの一覧があります。

1406071

これらのレジスタに値を書いたり、読んだりして、ポートの操作を行います。マイコンに慣れてくると、この表を見ただけでだいたいどんな機能かわかるよういなります。ちなみに私が最初にこの表を見て思ったことは、

1 PORTAは、そのままポートのデータ入出力のレジスタ。
2 TRISAは、入出力方向を設定するレジスタ。
3 ADCON1、ANSELはたぶんADコンバーターに関するレジスタ。なぜ、ここに書いてある???

最初に、この表の見方を説明します。表の左側から説明していきます。

●Address
レジスタのレジスタファイルの中での番地です。最後にhの記号があるので、16進数で書かれています。ここで大事なのは、この番地は通し番地で書かれていることです。たとえば、TRISAは85hと書かれていますが、これは10進数に直すと、133ですから、バンク0ではありません。バンク1ということが分かります。

なお、16進数で書かれた番地からバンクを知る方法は次の通りです。

1 二桁目が0~7ならバンク0
2 二桁目が8~Fならバンク1
3 二桁目、三桁目が10~17ならバンク2
4 二桁目、三桁目が18~1Fならバンク3

また、プログラムを記述する場合は、ここで書かれた16進数をそのまま書いて大丈夫です。

例 MOVWF  85h

85hなどの番地は、通し番地なので、本来は5に直すべきですが、このままでもビルドできます。ただし、バンク0ではないとのメッセージが表示されます。

●Name
表の2カラム目は名称です。レジスタの名称です。プログラマにとって分かりやすい名称になっています。実はこの名称ですが、前述の番地の変わりにプログラム中で使用できるのですが、ちょっとした設定が必要です。これについてはまた後で説明します。

●Bit7~Bit0
Bit7からBit0はレジスタの各ビットの名称です。または機能説明です。ここはIOポートの説明の文章を読むとき参照します。

●Value on POR、BOR
ここの値は、マイコンを起動した時のレジスタの初期値です。0また1またはxで表現されています。0または1は分かると思います。xですが、これは初期値が不定であることを意味します。

この初期値は非常に重要です。なぜなら、初期値のままでよいなら、わざわざのその値に設定する命令を記述する必要がないからです。

●Value on all other Resets
ここもリセット後の初期値ですが、この初期値は電源投入後の初期値ではなく、ウオッチドックタイマと呼ばれる再起動システムによる再起動の場合など、電源投入以外のリセットによる初期値です。uと書かれている場合は、unchangedで値は以前の値を保持するという意味です。

さて、レジスタの使い方の実際の説明は、この表の前のページに書かれています。英文なので、日本語で要約だけ書いておきます。

1 IOポートのピンは他の内蔵機能のピンと共通に使用されている。他の機能が有効ならIOポートのピンとして使用できない。

2 TRISAレジスタはポートAの入出力方向をビット単位で設定する。'1'の場合は入力ポート、'0'の場合は出力ポートである。

3 PORTAレジスタは、ポートAのデータレジスタで、入力ポートの場合、ポートAに入力されたデータがPORTAレジスタから読み出される。出力ポートの場合は、PORTAに書き込んだデータがポートAに出力される

4 ポートAのビット0から5は初期状態でADコンバーターの入力ピンとしての機能になっている。したがって、IOポートとして使用できない

5 ポートAのビット5は入力専用レジスタで出力には設定できない

このうち、4番が重要です。初期状態ではIOポートとして使用できません。IOポートとして使用するには、ADコンバーターの機能をOFFにしなければなりません。そのため、ADコンバーターのレジスタが、ここの表に同時に載っていたのです。ADコンバーターの機能をOFFにするのはANSELというレジスタの各ビットを0にします。

また、ポートの入出力方向ですが、各ビットでバラバラでもかまいません。すべて同じにする必要はありません。

以上の準備のもと、ではポートAを使うにはどのような設定が必要か書いてみましょう。

●入力ポートとして使う場合

1 バンクを1に設定する
2 ANSELレジスタの対応するビットを0にする
3 バンクを0に戻す
4 PORTAレジスタを読み出す

ANSELレジスタはバンク1なので、バンク1に設定する必要があります。また入出力方向の設定は初期値のままでよいので不要です。

●出力ポートとして使う場合

1 PORTAレジスタに初期値のデータを書き込む
2 バンクを1に設定する
3 ANSELレジスタの対応するビットを0にする
4 TRISAレジスタの対応するビットを0にする
5 バンクを0に戻す
6 PORTAレジスタに出力したいデータを書き込む

TRISAレジスタでポートの入出力方向を出力に設定した瞬間に、ポートからデータが出力されます。したがって、それ以前にPORTAに初期値データを書き込んでおくのが正しい作法です。そうしないと、マイコンにつながれた機器が誤動作する可能性があります。ただ、出力がLEDなどの場合は、さほど気にする必要はありません。

ポートにはもう一つポートBがありますが、ほとんど同じなので説明は省略します。

次回は、以前作った簡単なプログラムの説明です。

| | コメント (0)

2014年6月 6日 (金)

「天文屋のためのマイコン入門」命令とデータのまとめ

●命令には、転送命令、演算命令、制御命令がある。

●命令の操作の対象には、ワーキングレジスタ、レジスタファイル、数値の3つがある。

●ワーキングレジスタは唯一つしかない一時的な演算領域、命令コストが少ない。記号W

●レジスタは、プログラムのデータメモリであり、128個あつまりレジスタファイルを形成する。レジスタの中には、マイコン内蔵機能をアクセスするためのレジスタや、プログラムで自由に使える汎用レジスタがある。レジスタは命令中に番地を指定するので命令コストは高い。

●ワーキングレジスタ、レジスタ、数値は8ビットのデータであり、0から255までの数値を格納できる。

●命令体系は、命令コストの概念を導入すると、なぜそうなっているか自然と理解できる。

●転送命令は、片方がワーキングレジスタの場合だけ許される。レジスタファイル間の転送は同一番地を除いて許されない。

●演算命令は算術演算命令と、論理演算命令がある。演算命令は片方がワーキングレジスタの場合だけ許される

●データに1を加算することをインクリメントといい、1を減算することをデクリメントという。インクリメント、デクリメント命令がある。

●マイコンが扱う数の特徴として、最大値がある(255)、整数しか扱えない、負数の概念がないなどがある。

●レジスタファイルは128個のレジスタからなり、0番地から127番地まである。ただこれだけでは足りない。バンクの概念を使い、この4倍まで増やしている。

●バンクは、ページと理解すると分かりやすい。ページ番号はSTATUSレジスタの第5、第6ビットになる。

●STATUSレジスタはレジスタファイルの中のレジスタであり、番地は3である。STATUSレジスタはすべてのバンクにある。

●バンクは、絶対番地(通し番地)の上位2ビットと考えることができる。

●よく使うバンクはバンク0とバンク1である。これしか使わない場合、以下の命令でバンクを切り替えることができる。

ページ0にする
BCF  3,5

ページ1にする
BSF  3,5

●制御命令には、無条件ジャンプ命令と条件ジャンプ命令がある。

●ジャンプ命令は命令コストが高いので、条件ジャンプ命令は条件スキップ命令と無条件ジャンプ命令を組み合わせて実現される

●演算結果がゼロかどうかを保存するビットがあり、これをゼロフラグという。記号Zであらわす。

●ゼロフラグはSTATUSレジスタのビット2にある

●ゼロフラグが1か0かによって次の命令をスキップするかどうかの条件スキップ命令がある。

●加算においては、負数も扱うことができる(例-10のように)

以下、今までの説明で出てきた命令を一覧にまとめました。これ以外にも命令がありますが、必要な時はその都度説明しますが、基本的にこれだけで十分です。

1406061

全部で30数個ありますが、格納先がワーキングレジスタの場合とレジスタの場合の2通りがあり、それらを一つの命令と考えれば、命令の数は20数個です。とりあえず、これだけ覚えればなんとかなります。

| | コメント (0)

2014年6月 5日 (木)

「天文屋のためのマイコン入門」負の数の扱い

マイコンの基本のまとめの前に、負の数の扱いについて説明したいと思います。前回の例題で次のような命令を出しました。

ADDLW     -10       ワーキングレジスタから10を引く

-10という負の数が出てきました。今まで、レジスタは8ビットなので、扱える数の範囲は0~255までと説明しました。また、マイコンでは負の数の概念がないといってきました。それと矛盾するようなプログラムですが、上記は正しいです。

なぜ、正しいのか、なぜ負の数も扱えるのか。それはマイコンで扱う数が、数学でいうところのモジュラー演算(256で割ったあまり)だからです。

以前説明したように、PICマイコンが扱う数は255が最大です。これを超えると0に戻ると説明しました。そしてそこからまた0、1、2、と増えていきます。つまりある数Nがあるとすればnを整数として、

N =N + 256n

が成り立ちます。256の倍数を足したり引いたりしても良い。式で書くと難しいですが、数直線で書くとわかりやすいです。

1406051

したがって、-10という数は256を足した246とまったく同じです。

ADDLW  -10
  || 同等
ADDLW  246

これで負の数が除去できました。でもなぜ、246を足すことと、10を引くことが同等なのでしょうか?

255に1を足すと、0に戻ります。逆に言えば、0から1を引けば255になります。つまり-1と255が同等ということになります。
254に2を足すと、0に戻ります。つまり-2と254は同等ということになります。

実際、計算で確かめてみましょう。例として、100に246を足してみます。

100
+246
----
346

256を超えたので、256を引きます。

346
-256
----
90

100が90になったので10を引いたことと同等です。

この原理が直感的にわかるように数直線であらわしてみます。先ほどの循環する数直線を輪にしてみます。で、その中にダイアルがあって、現在は0を指してします。

1406052

今、このダイアルを246の位置に合わせたいとします。そうすると二通りの方法があります。

方法1 時計回りに246まわす
方法2 反時計回りに10まわす

もうお分かりになったと思いますが、時計回りに回すことが足し算を表し、反時計回りに回すことが引き算を表します。なんとなくわかっていただけたでしょうか。

ADDLW -10

というのは人間から見ると引き算をやっているように見えます。ただ、マイコンから見るとこれは単純な正数の足し算なのです。

ところで、246という数字は2進数で表すと、11110110です。

今、レジスタの各ビットが次のようになっているとします。

1406053

これを、246と見るか、-10と見るか、これは人間の都合です。どちらでもわかりやすい方で考えればいいのです。どちらにしてもマイコンは正しい結果を出します。(途中で見方を変えることさえOKです)

これを246と見る考え方を「符号なし」といいます。

これを-10と見る考え方を「符号付き」といいます。

繰り返しますが、マイコンのデータ自体に符号付き、符号なしの区別があるわけではありません。あくまでも人間の考え方です。
(高級言語は違います。たとえばC言語は変数自体に符号なし、付きの区別があります。int xと定義されれば符号付きです)

| | コメント (0)

2014年6月 3日 (火)

「天文屋のためのマイコン入門」条件ジャンプ命令

さて、プログラム構成上、絶対必要なもののうち無条件ジャンプ命令については前回説明しました。しかし、まだ条件ジャンプ命令が残っています。

条件ジャンプ命令のうち、分かりやすい命令を一つ紹介します。

ある演算命令を実行した後に、演算結果が0でないなら、k番地にジャンプする。

このような命令があれば、ある処理を有限回数(無限でない)実行する処理が記述できます。

1405172

たとえば、ある処理を10回実行したいとします。

1 まず、汎用レジスに数値10をセットします。
2 そのレジスタの数値を一回処理するごとに1ずつ減らしていきます。
3 もし、その数が0でないなら、処理の最初の番地にジャンプして繰り返す。

さて、前述の条件ジャンプ命令ですが、k番地にジャンプする部分、ここが命令コストが高いのでした、なぜならジャンプ先の番地が必要だからです。そこで、次のような命令を考えます。

演算結果が0なら、次の命令をスキップする

次の命令をスキップとは、次の命令を実行しないで、次の次の命令を実行するということです。この命令は番地を含まないので命令コストは低いです。

このスキップ命令と前回説明した無条件ジャンプ命令を組み合わせれば、最初に説明した条件ジャンプとまったく同等のことができます。

演算結果が0でないなら、k番地にジャンプする。
         || 同等
演算結果が0なら次の命令をスキップ
GOTO k番地

演算結果が0なら、GOTO命令はスキップされます。
演算結果が0でないならGOTO命令が実行されk番地にジャンプします。

つまり、スキップ命令があれば、無条件ジャンプ命令と組み合わせて、様々な条件ジャンプが実現できるのです。

なにやら、面倒な話が続いてすみません。もう少し辛抱してください。さらに面倒なことが続きます。

ここで、演算結果が0かどうかの判断です。実は演算命令を実行した後に、その結果が0かどうかは非常に重要なので、0かどうかを保存して置く場所があります。それをフラグといいます。フラグとは旗という意味です。0なら旗を立てよということです。もっとも実際に立てるのは旗ではなく、ビットです。つまり'1'です。

演算結果が0なら'1'がセットされ、0でないなら'0'にクリアされる特別なビット

これをゼロフラグといい、Zの記号で示します。

さて、このゼロフラグはどこにあるのでしょうか? 実はバンクの説明で出てきたSTATUSレジスタの中にあるのです。

1406024_2   

この図の2番目のビットがゼロフラグです。ちなみにDC、Cも違う種類のフラグです。

演算命令を実行した結果が0の場合、Zは'1'にセットされます。
演算命令を実行した結果が0以外の場合は、'0'にクリアされます。

したがって、STATUSレジスタ(3番地でしたね)のビット2を判断できれば0か0でないか判断したことになります。そこで、条件スキップ命令にもどりますが、次のようなスキップ命令があれば0かどうかの判断ができることになります。

演算結果が0なら、次の命令をスキップ
   ||  同等
3番地のレジスタの2番目のビット1なら、次の命令をスキップ

やっと、ここで条件ジャンプ命令を定式化することができました。つまり、上の命令を汎用化して次の命令に到着します。

やっと完成した命令

●f番地のレジスタのbビットが1なら、次の命令をスキップ

これの論理を反転した命令も追加します。

●f番地のレジスタのbビットが0なら、次の命令をスキップ

この命令を記号化したのが、そのままPICの命令になります。

1406025_2 

これで条件ジャンプ命令が完成しました。これで理論上は何でもできます。例として、同じ処理を10回する例を示します。

番地1 MOVLW   10         ワーキングレジスタに10をセット
番地2 MOVWF   120       120番地の汎用レジスタに10をセット
番地3 処理A                  ここに繰り返したい処理を記述(何命令でも可)
番地4 DECF      120,F     120番地の汎用レジスタをデクリメント(1を減算)
番地5 BTFSS    3 , 2       STATUSレジスタ(3番地)のビット2が'1'なら、すなわち上記
                                   演算結果が0なら、次の命令をスキップ
番地6 GOTO      3          3番地にジャンプ

次に、120番地の汎用レジスタの値が10の時だけ、処理Aを実行する例を示します。

番地1 MOVF      120,W    120番地のレジスタをワーキングレジスタに転送
番地2 ADDLW     -10       ワーキングレジスタから10を引く
番地3 BTFSS     3 , 2      STATUSレジスタ(3番地)のビット2が'1'なら、すなわち上記
                                   演算結果が0なら、(つまりW=10なら)次の命令をスキップ
番地4  GOTO     6          6番地にジャンプ
番地5  処理A
番地6  .....

この例ですが、W=10なら、GOTO 6がスキップされますので、処理Aが実行されます。またこの例ですが、処理Aが1命令なら、次のように簡略化されます。

番地1 MOVF      120,W    120番地のレジスタをワーキングレジスタに転送
番地2 ADDLW     -10       ワーキングレジスタから10を引く
番地3 BTFSC     3 , 2      STATUSレジスタ(3番地)のビット2が'0'なら、すなわち上記
                                     演算結果が0でないなら、(つまりW=10でないなら)次の命令    をスキップ
番地4  処理A
番地5  .....

この場合、スキップされるのは、GOTO命令ではなく処理Aです。スキップ命令は何も、GOTO命令とセットで使う必要はまったくありません。
もっとも、処理Aが2命令以上なら、GOTOと併用しなければなりません。

最後に便利な命令を紹介しておきます。

スキップ命令は例題1のようにデクリメント命令の直後に利用されることが多いです。そこで、これら一連の命令を一つにした命令があります。

1406026

この便利な命令を使うと、例題1は次のようになります。

番地1 MOVLW   10         ワーキングレジスタに10をセット
番地2 MOVWF   120       120番地の汎用レジスタに10をセット
番地3 処理A                  ここに繰り返したい処理を記述(何命令でも可)
番地4 DECFSZ  120,F     120番地の汎用レジスタをデクリメント、結果が0なら次の
                 命令をスキップ

番地5 GOTO      3          3番地にジャンプ

DECFSZ命令には実は、インクリメントバージョンもありますが、あまり使用頻度は高くないと思い、紹介は割愛しました。

これでPICの命令とデータに関する基本のなが~い、なが~い説明が終わりました。お疲れ様でした。まだまだ説明不足のところもありますが、とりあえず終わりにします。それ以外に必要な知識は必要な時に説明します。

一通り基本の説明が終わったので、次回、まとめをします。その後、実際のプログラムの説明をしたいと思います。

| | コメント (0)

2014年6月 2日 (月)

「天文屋のためのマイコン入門」制御命令

さて、データについては一通り説明は終わりました。また命令の説明に戻りたいと思います。命令ですが、転送命令と演算命令は説明しました。ただ、これだけではマイコンのプログラムは組めません。

マイコンはプログラムメモリに格納された命令を上から順に実行していくだけでは複雑な処理はできません。

プログラムは同じ処理を繰り返したり、特定の場所を飛ばしたり、ジャンプしたり、条件によって処理を変えたりします。

これらのプログラムの流れを変える命令を制御命令といいます。これがないとプログラムは組めません。

制御命令は2種類あり、どちらも絶対に必要なものです。

1 無条件ジャンプ命令  無条件にプログラムの特定の番地にジャンプする。

2 条件ジャンプ命令 ある条件が満たされた場合のみ特定の番地にジャンプする。条件が満たされない場合は次の命令から実行される。

1の無条件ジャンプ命令は一個しかありませんが、2の条件ジャンプ命令は条件の数だけ複数あります。条件の種類としては、「0かどうか」とか、「桁上がりがあるかないか」などの条件があります。

それでは無条件ジャンプ命令を紹介します。無条件ジャンプ命令は次のようなものです。1405171

具体的な命令は次のようになります。

1406021

GOTOというのは天文屋には親しみやすい名称ですが、この命令によりプログラムはk番地にジャンプします。

ここでいう番地とは、レジスタファイルの番地とはまったく違います。プログラムは、データとはまったく別のプログラムメモリに格納されます。そのメモリの番地です。命令は通常、1命令1番地使いますので、k番地といったら、k番目の命令にジャンプすると言ってもいいでしょう。

レジスタファイルの番地は、0から127まででした。つまり14ビットの命令のうち、下位7ビットで番地を指定し、残り7ビットで命令の種類を指定すると説明しました。

14051710

プログラムメモリの番地ですが、127番地までしか許されないということは、命令が128個しか許されないということで全然足りないのです。実はプログラムメモリは2047番地まであります。つまり2048個まで命令を格納できます。ただし、番地を指定するのに11ビット必要になります。

しがたって、命令のフォーマットは以下のようになります。

1406022_2

これを見ると、データ命令と比べると、ジャンプ命令は命令の種類を指定するフィールドが3ビットしかありません。もし、PICのすべての命令がこのフォーマットであるなら、PICの命令は8個(2の3乗)しかないことになります。

何が言いたいかとうと、ジャンプする命令は、非常に命令コストが高いということです。もし、このような命令ばかりだと、PICの命令は少なくなってしまいます。だからジャンプする命令は、必要最小限にしなければなりません。

ところが、制御命令は無条件ジャンプ命令だけではありません。条件ジャンプ命令もあります。これらすべてを番地へジャンプする命令とすることはできないのです。

そこで、考え出されたのが、スキップ命令という概念です。次回説明する条件ジャンプ命令は、すべてスキップ命令として実現されています。

次回詳しく説明します。

| | コメント (0)

2014年6月 1日 (日)

へびつかい~さそりモザイク

久々の作品公開ですが、結論からいうとボツです。

1406011EF100mmF2.8Lマクロ F4 EOS 5D Mark2 ISO3200
南部 5分×24枚
北部 5分×19枚
2枚モザイク

2枚モザイクですが、南部は4月上旬に伊豆遠征で撮影したもの、北部は先週の湯沢遠征で撮影したものです。2ヶ月ががりのモザイクですが、露出不足、透明度不足、カブリ多しで、うまく処理できませんでした。

この構図ですが、実は最優秀を頂いた「おうし座付近の星雲」の次に狙っていたものですが、なかなかチャンスがなく撮影できませんでした。この構図の見所は、アンタレス付近から、蛇使いの散光星雲(SH2-27)に広がる茶色の分子雲です。

この写真からもSH2-27の下部に分子雲があるのが判別できます。これがどのように広がっているかとても興味がありました。

低空の対象でしかも、薄明の早い時期に狙うには難しい対象でした。来年以降にリベンジしたいですが、たぶん無理だな。っていうか、南半球行きたいです。

EF100mmF2.8Lマクロですが、このレンズは、まさにこの作品を撮る為に買ったといってもいいです。色収差も少なく素晴らしいレンズです。今まで、EF85mmF1.2L、マクロプラナー100mmF2と使ってきましたが、いずれも色収差が目立ちました。これはとても、すっきりした星像です。とても気に入りました。ただ周辺減光はちょっと多いかなと思います。また、非常にモザイクしやすいレンズです。歪が少ないのでしょうかね。

| | コメント (0)

« 2014年5月 | トップページ | 2014年7月 »