解決済み

PICのEQUでつまづいてしまいました

  • 困ってます
  • 質問No.7337990
  • 閲覧数410
  • ありがとう数5
  • 気になる数0
  • 回答数4
  • コメント数0

お礼率 70% (54/77)

PICを習い始めた者です。EQUの理解でつまづいてしまいました。どなたか入門者向けの説明が上手な方、宜しくお願いします。なお、勉強させていただいているページは↓こちらです。
http://www.k3.dion.ne.jp/~digikoma/swf/flpic.html

PICの「EQU」と「equ」は、
「大小文字の違いだけで、BULIDしたときは同じ働き」
と理解していたのですが、下記の記述でこんがらかってしまいました。

;;(ここから引用→ http://www.k3.dion.ne.jp/~digikoma/shoho/shoho11.html#top);;
INDF   EQU 0x00
TMR0  EQU 0x01
PCL   EQU 0x02
STATUS EQU 0x03
FSR   EQU 0x04
TRIS_A EQU 0x05
TRIS_B EQU 0x06
TRIS_C EQU 0x07
PORT_A EQU 0x08;PORT_A,4がマイクロ SW4
PORT_B EQU 0x09;7セグメント表示器へ(Hで点灯)
PORT_C EQU 0x0A;PORTC_0=LED1を点滅用にする

FLG equ PORT_C+1
;Bit0をSW4の検知状態フラグとして使用する

;↓↓ SW4のON期間の経過値
C_CNT equ FLG+1

;↓↓ スイッチが押して離した回数
SW_CNT equ C_CNT+1

;↓↓ LEDタスクへの侵入カウンター
LED_RC equ SW_CNT+1

;↓↓ LEDの点灯(ON)期間のカウンタ
LED_ON equ LED_RC+1

;↓↓ LEDの消灯(OFF)期間のカウンタ
LED_OF equ LED_ON+1
;;(ここまで引用 );;

↑ここでは「INDF」~「LED_OF」のラベルにアドレスを与えているわけですね。(質問1)
で、次のところからがわからないんです。

;;(ここから引用);;
CHAT equ 0x07;チャタリング時間(0xFD)
JOBCNT equ 0x04;点滅タスク侵入カウンタ(0x00)
ON_TIM equ 0x02;LEDの点灯期間(0x25)
OF_TIM equ 0x08;LEDの消灯期間(0x60)
;;(ここまで引用 );;

↑ここであたかもラベルのようにみえる「CHAT」~「OF_TIM」にはアドレスが与えられなくてもいいんでしょうか? 小文字の「equ」の後に16進数がありますけど、これはSFRの領域をしてるのではないんでしょうか?(質問2)

この後に↓次の記述が来てます・・・

;;(ここから引用);;
; *** SW4検知の初期化
 bcfFLG,0
 clrfSW_CNT;スイッチ検知初期化
 clrfC_CNT;チャタ検知用のカウンタ初期

; *** LED点滅の初期化(CPU速度で調整必要)
 movlwON_TIM;点灯期間の時間をセット
 movwfLED_ON
(略)
;;(ここまで引用 );;

↑この部分に相当するところをBULIDの後、逆コンパイラで確認すると、次のようになっています。

0x008  0x018D clrf  SW_CNT
0x009  0x018C clrf  C_CNT
0x00A  0x3002 movlw  0x02
0x00B  0x008F movwf  LED_ON

つまり「ON_TIM」に「equ」をつかって「0x02」を代入しているから、
上の「0x00A  0x3002 movlw 0x02」のところでは自動的に16進数「0x02」が入っているのですね。
EQU,equ はアドレスを指定したり、数値を指定したりと、両方が出来るのですか?(質問3)

このこんがらかりをナンとか直してください。お願いします!

質問者が選んだベストアンサー

  • 回答No.4

ベストアンサー率 45% (763/1670)

そうそう、ついでにいえば、逆アセンブルした内容で、

0x008  0x018D clrf  SW_CNT
0x009  0x018C clrf  C_CNT
0x00A  0x3002 movlw  0x02
0x00B  0x008F movwf  LED_ON

となっていて、(おそらく)movlw ON_TIM だけが、movlw 0x02 という表記になってしまっているのは、おそらくは、開発環境が気を利かせただけでしょう。
アセンブラした時点で、equ で割り当てた、名前と数値の対照表を持っていますので、
clrf 0x0d を、0x0d = SW_CNT というテーブルを引いて、clrf SW_CNT と表示するのは可能です。
この場合、アドレッシングモードから、clrf 0x0d の 0x0d は「アドレス」だとわかりますから、名前で表示した方がわかりやすいし、かつ、0x0d という数値がアドレスとして使用されているのなら、それは、SW_CNT だというのは、ほぼ決定できます。

ただ、
movlw 0x02
のほうは、数値の 0x02 を何というラベルで表したらいいのか、はっきり決められないことが多いです。
もちろん、ON_TIM という名前に割り当たっている数値が 0x02 だというのはわかっていますが、逆に、ほかに 0x02 というデータが存在していないかというのがなかなか判断できないと。
しかも、一度は、
0x00A  0x3002 movlw  0x02
の、0x3002 という数字になってしまったものから、元に戻しているわけですから、本当に、movlw 0x02 という書き方をしている可能性もあるわけです。

というわけで、アドレッシングモードから判断して、アドレスを指定している部分だけを、名前で置き換えたということだと思います。
お礼コメント
chy_farm

お礼率 70% (54/77)

2度もご丁寧にありがとうございました。こちらの方の上の方が一度読んだだけだとまだ理解できていないので、よーーーく読み直してみます!
本当にありがとうございました。
投稿日時 - 2012-03-02 16:18:38
感謝経済

その他の回答 (全3件)

  • 回答No.3

ベストアンサー率 12% (16/128)

EQUの宣言は、アッセンブルする前にラベルを定義した値に置き換えます。


以下の例では、

>PORT_C EQU 0x0A;PORTC_0=LED1を点滅用にする

>FLG equ PORT_C+1
>;Bit0をSW4の検知状態フラグとして使用する

FLG equ 0x0A+1 と置き換え、FLGを宣言し、


>;↓↓ SW4のON期間の経過値
>C_CNT equ FLG+1

C_CNT equ 0x0A+1 +1 と置き換え、C_CNTを宣言します。

すなわち、アドレスでも数値でもなく、それらを示す文字の宣言です。
したがって、EQUの記述がいくらあってもアッセンブル後のコードサイズは増えません。
お礼コメント
chy_farm

お礼率 70% (54/77)

ご丁寧に解答してくださってありがとうございました。感謝いたします。今後とも宜しくお願いいたします。
投稿日時 - 2012-03-02 16:20:47
  • 回答No.2

ベストアンサー率 45% (763/1670)

equ という疑似命令は、「数値を名前で呼べるようにする」という働きだけしかありません。
あと、普通のアセンブラでは、アドレスもデータも「単なる数字」と思った方がいいです。
アドレスは、「その数値で表される場所」を操作するし、
データは、「その数値で表されるもの」対象自体が操作の対象になります。

さて、

PORT_C EQU 0x0A;PORTC_0=LED1を点滅用にする
これは、PORT_C という名前に、0x0a という値を割り当てているだけです。
FLG equ PORT_C+1
これは、FLG という名前に、PORT_C + 1 という値を割り当てています。
ちなみに、PORT_C には、0x0a という値が割り当てられていますので、具体的には、FLG に 0x0b が割り当てられます。
以下同様。
ラベルにアドレスを割り当てているわけではなくて、単に、「名前に数値を割り当てている」だけです。

CHAT equ 0x07;チャタリング時間(0xFD)
JOBCNT equ 0x04;点滅タスク侵入カウンタ(0x00)

この二つの文も、それぞれ、CHAT に 0x07 という数値を、JOBCNT に0x04 という数値を割り当てているだけです。

で、ここまでは、PORT_C というのも単なる名前ですし、CHAT というのも単なる名前です。
どちらかが定数で、どちらかがアドレスという切り分けはないです。

というわけで、まずは、ここまでのところで、

● ↑ここでは「INDF」~「LED_OF」のラベルにアドレスを与えているわけですね。(質問1)
 いいえ、アドレスを与えているのではなく、単に、「名前に数値」を割り当てているだけです

● ↑ここであたかもラベルのようにみえる「CHAT」~「OF_TIM」にはアドレスが与えられなくてもいいんでしょうか? 小文字の「equ」の後に16進数がありますけど、これはSFRの領域をしてるのではないんでしょうか?(質問2)
 単に、CHAT とかの名前に数値を割り当てているだけです。
 その数値を保持する領域などはありませんので、領域をつぶしたりしません。

で、ここまででさらに混乱させてしまったかもしれませんが、ある数値が、「アドレス」だったり、「データ」だったりするのは、実は、アセンブラの「アドレッシングモード」の話です。

clrf SW_CNT で、SW_CNT というアドレスの中身が操作できるのは、「clrf は、次にある数値をアドレスと見なして実行する」からですし、
movlw 0x02 で、数値の0x02 を代入しようとするのは、「movlw は、次にある数値をデータと見なして実行する」からです。

なので、

● EQU,equ はアドレスを指定したり、数値を指定したりと、両方が出来るのですか?(質問3)

 これは、equ は、名前に数値を割り当てます。
 その数値を、データと見なすか、アドレスとして見なすかは、アセンブラのここの命令(のアドレッシングモード)によります。

ということになります。
お礼コメント
chy_farm

お礼率 70% (54/77)

なるほどーー、そう言うモードがあったのですか!
分かり易く読ませていただきました。ありがとうございます。
投稿日時 - 2012-03-02 16:22:11
  • 回答No.1

ベストアンサー率 42% (403/951)

EQU は定数を設定します、レジスタに代入すれば数値になり
データメモリのアドレスに名前をつけてわかりやすくします
0x00 と書くより INDF としたほうが判りやすいです、またPICの種類によりINDFのアドレスも変化
するので、INCファイルで設定されています
お礼コメント
chy_farm

お礼率 70% (54/77)

初心者の質問におつきあい下さってありがとうございました。今後とも宜しくお願いいたします。
投稿日時 - 2012-03-02 16:19:34
AIエージェント「あい」

こんにちは。AIエージェントの「あい」です。
あなたの悩みに、OKWAVE 3,500万件のQ&Aを分析して最適な回答をご提案します。

関連するQ&A
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する

特集


感謝指数によるOK-チップ配布スタート!

ピックアップ

ページ先頭へ