- ベストアンサー
PIC18F2550・コンパイルできない(再掲)
初めて投稿します。 技術職(機械系)の会社員です。 マイコンプログラム作成歴:約3ヶ月のほぼド素人です。 現在、会社の技術研修でPIC18F2550を使ったライントレーサの動作プログラムを作成しています。先日までPIC16F84A&88でのプログラミングを行なっており、基本は理解できているつもりです。 …が、これまで見た事のないエラーコードが出てしまい、理由がわからず困っています。 エラーコードは、[1101]lvalue required と[1105]symbol '○○○' has not been defined というもので、コンパイラのユーザーガイドを見ると、変数(GIE,LATA0等)の認識ができない?エラーのようです。ヘッダーファイルのインクルードもしており、これまでの84A&88では出なかったエラーです。 webも調べましたが、わかりませんでした。 作成環境はMPLAB V8.36、MPLAB C18コンパイラV3.33 です。 エラーメッセージ画面添付、ソースコード掲載しますので、PICプログラムに精通されている方、間違い部分をご教授頂けないでしょうか? 何卒ご協力のほどよろしくお願いします。 --【以下、コード抜粋】-- //●使用マイコン:PIC18F2550 //===《初期設定》=== //---<ヘッダーファイル>--- #include<p18f2550.h> #include"delays.h" //---<コンフィグレーション>--- #pragma config PLLDIV = 5 #pragma config CPUDIV = OSC1_PLL2 #pragma config USBDIV = 2 #pragma config FOSC = HSPLL_HS #pragma config FCMEN = OFF #pragma config IESO = OFF #pragma config PWRT = ON #pragma config BOR = OFF #pragma config BORV = 3 #pragma config VREGEN = OFF #pragma config WDT = OFF #pragma config WDTPS = 1 #pragma config MCLRE = ON #pragma config LPT1OSC = OFF #pragma config PBADEN = OFF #pragma config CCP2MX = ON #pragma config STVREN = OFF #pragma config LVP = OFF #pragma config XINST = OFF #pragma config DEBUG = OFF #pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF #pragma config CPB = OFF, CPD = OFF #pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF #pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF #pragma config EBTRB = OFF //---<関数宣言>--- void ioport(void); void interr(void); void pwm_settei(void); void move_A(void); void move_B(void); void delay_ms(long); //---<変数宣言>--- int c_flg = 0; //変数「c_flg」を宣言 //------------------------------------------------------------ //===《動作プログラム》=== //---<メイン関数>--- void main() { ioport(); interr(); pwm_settei(); while(1) { move_A(); } } //---<サブルーチン>--- void ioport(void) //[入出力ポート初期設定] { ADCON1 = 0b00001111; //A/D設定:全ポートデジタル TRISA = 0b00000000; //ポートA・I/O設定 TRISB = 0b11111111; //ポートB・I/O設定 TRISC = 0b00110000; //ポートC・I/O設定 } void interr(void) //[割り込み初期設定] { GIE = 1; //グローバル割り込み設定:許可 TMR2IE = 1; //タイマ2割り込み設定:許可 } --【途中省略】-- void move_A(void) //[動作A(直線&曲線走行モード)] { switch(PORTB) { case 0b01000000 : //センサB(内左)認識 CCPR1L = 100; //CCP1 Duty値設定 CCPR2L = 30; //CCP2 Duty値設定 LATC7 = 1; //モータR1:正転 LATA0 = 1; //モータL1:正転 LATC6 = 1; //モータR2:ON LATA1 = 1; //モータL2:ON break; --【以下続く】--
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
こんにちは。 #3です。 > ちなみに、以前PIC16F84A&88でプログラムを記述した際には、上記対応 > (共用体名を付ける)は不要でしたが、マイコンの機種毎に違うのでしょうか? > 前と同じ、簡潔な記述で済む方法がありましたら紹介頂けますと幸いです。 その構造体名(及び共用体名)が不要であった変数というのは、実際に構造体 (あるいは共用体)のメンバとして定義されたものだったのでしょうか? 構造体ではなく単体の変数として定義されていた可能性はなかったのでしょうか? もし構造体メンバだったとして、その現象の違いは、マイコン(CPU)の違いに よるものではなく、コンパイラ及びその周辺(開発環境)の設定の違いによるもの だと思われます。 通常なら構造体メンバへのアクセスは、 {構造体変数名}.{メンバ名} または、 {構造体変数名}->{メンバ名} //←変数が構造体へのポインタの場合 のような記述にしないといけないと思いますが、 もしメンバ名のみの記述でコンパイルエラーがでなかったとしたのなら、 その考えられる要因の一つとして、以下のように #define 定義等でメンバ名が 「別名定義」されていたのではないでしょうか? //※別名定義の例(構造体メンバへのアクセス簡易化) #define GIE INTCONbits.GIE #define TMR2IE PIE1bits.TMR2IE #define LATA0 LATAbits.LATA0 #define LATA1 LATAbits.LATA1 #define LATC7 LATCbits.LATC7 #define LATC6 LATCbits.LATC6 上記のように別名定義しておけば、 GIE = 1; TMR2IE = 1; LATC7 = 1; LATA0 = 1; LATC6 = 1; LATA1 = 1; のように記述した箇所は、コンパイル時にコンパイラーが、 INTCONbits.GIE = 1; PIE1bits.TMR2IE = 1; LATCbits.LATC7 = 1; LATAbits.LATA0 = 1; LATCbits.LATC6 = 1; LATAbits.LATA1 = 1; のように展開しますので問題なくコンパイルされると思いますj。 これ以外にもメンバー名を簡略化する方法があるかもしれませんが、 今のところ思い付いたものはこれだけです。 以上。参考になれば幸いです。
その他の回答 (5)
- f-tomohiko
- ベストアンサー率50% (11/22)
MPLAB C16 付属の pic1684.h の一部です。 /* INTCON bits */ volatile bit GIE @ (unsigned)&INTCON*8+7; どうやらこのコンパイラではバイトの特定ビットに 名前が付けられるようです。 アドレス空間が数KBなら、わからなくもないです。 ただし、将来の互換性を考えると害も有るかと思います。 実際これを使って混乱した人がいるわけですから..........
お礼
情報提供、ありがとうございます。 とりあえず、今後のプログラム作成では事前に定義をして記述したいと思います(そのままでは記述が面倒なので)が、将来的にプログラムを業務で作成するようなシチュエーションになった際には、互換性等を考慮する必要もありそうですね。 大変参考になりました! アドバイスありがとうございました。
こんにちは。 FarEyesです。 追加情報です。 「PIC16F84A&88」の時に使用されていたコンパイラは何をお使いでしたか? 当方でPIC用のフリーのCコンパイラ「SDCC」をダウンロードして、インストール フォルダ内にあるヘッダファイルの中身を確認したところ、下記のような記述 箇所がありました。 ■ヘッダファイルの中身 "pic16f88.h"より一部抜粋したものです。 ヘッダファイルの場所: (SDCCのインストールフォルダ)\include\pic ============================ : : // ----- INTCON bits -------------------- typedef union { struct { unsigned char RBIF:1; unsigned char INTF:1; unsigned char TMR0IF:1; unsigned char RBIE:1; unsigned char INTE:1; unsigned char TMR0IE:1; unsigned char PEIE:1; unsigned char GIE:1; }; } __INTCON_bits_t; extern volatile __INTCON_bits_t __at(INTCON_ADDR) INTCON_bits; #ifndef NO_BIT_DEFINES #define RBIF INTCON_bits.RBIF #define INTF INTCON_bits.INTF #define TMR0IF INTCON_bits.TMR0IF #define RBIE INTCON_bits.RBIE #define INTE INTCON_bits.INTE #define TMR0IE INTCON_bits.TMR0IE #define PEIE INTCON_bits.PEIE #define GIE INTCON_bits.GIE #endif /* NO_BIT_DEFINES */ : : : // ----- PIE1 bits -------------------- typedef union { struct { unsigned char TMR1IE:1; unsigned char TMR2IE:1; unsigned char CCP1IE:1; unsigned char SSPIE:1; unsigned char TXIE:1; unsigned char RCIE:1; unsigned char ADIE:1; unsigned char :1; }; } __PIE1_bits_t; extern volatile __PIE1_bits_t __at(PIE1_ADDR) PIE1_bits; #ifndef NO_BIT_DEFINES #define TMR1IE PIE1_bits.TMR1IE #define TMR2IE PIE1_bits.TMR2IE #define CCP1IE PIE1_bits.CCP1IE #define SSPIE PIE1_bits.SSPIE #define TXIE PIE1_bits.TXIE #define RCIE PIE1_bits.RCIE #define ADIE PIE1_bits.ADIE #endif /* NO_BIT_DEFINES */ : : ============================ これを見ると、やはり#defineにより構造体メンバ名が別名で定義してある ものがあることが判ります。 質問者さんの以前お使いになっていたコンパイラも、このような定義がして あったのではないでしょうか? ■参考サイト(SDCC関連) フリーのCコンパイラ(SDCC)でPIC(PIC16F88)を動かす方法 http://www.welcome.mech.nagasaki-u.ac.jp/gs400e/pic_sdcc/index.htm SDCC - Small Device C Compiler http://sdcc.sourceforge.net/ 以上です。
お礼
追加情報ありがとうございます。 当方でPIC16F84A&88時に使用のコンパイラは、教材に同梱されていた「HI-TECH C PRO for the PIC 10/12/16 MCU Family」というものです。 ヘッダーファイルを見てみたところ、 /* Definitions for INTCON register */ volatile bit RBIF @ ((unsigned)&INTCON*8)+0; volatile bit INT0IF @ ((unsigned)&INTCON*8)+1; volatile bit TMR0IF @ ((unsigned)&INTCON*8)+2; volatile bit RBIE @ ((unsigned)&INTCON*8)+3; bit INT0IE @ ((unsigned)&INTCON*8)+4; volatile bit TMR0IE @ ((unsigned)&INTCON*8)+5; volatile bit PEIE @ ((unsigned)&INTCON*8)+6; volatile bit GIE @ ((unsigned)&INTCON*8)+7; となっていました。 やはり、ヘッダーファイルで事前定義がしてあったようです。 情報提供、ありがとうございました。
こんにちは。 私はPICのプログラミングの経験はありませんので、以下はWEBで調べた結果のみ での回答となります。 従って、間違っている部分があるかもしれませんので、ご了承下さい。 また、間違っていた場合はすみません。 まず、#1さん回答への補足に書かれている、ヘッダーソースの後半部分が途中で 途切れていますので、extern定義のunion(共用体)変数の全容が判りません。 ですのでWEBで調査した結果、コンパイルでエラーで表示されている識別名は、 構造体(及び共用体)のメンバ名のようだと判断しました。 結論としては、#2さんの回答と同じになりますが、 ソース上でこれらのメンバにアクセスするための記述としては、 <変更前> : GIE = 1; //グローバル割り込み設定:許可 TMR2IE = 1; //タイマ2割り込み設定:許可 : : LATC7 = 1; //モータR1:正転 LATA0 = 1; //モータL1:正転 LATC6 = 1; //モータR2:ON LATA1 = 1; //モータL2:ON : <変更後> : INTCONbits.GIE = 1; //グローバル割り込み設定:許可 PIE1bits.TMR2IE = 1; //タイマ2割り込み設定:許可 : : LATCbits.LATC7 = 1; //モータR1:正転 LATAbits.LATA0 = 1; //モータL1:正転 LATCbits.LATC6 = 1; //モータR2:ON LATAbits.LATA1 = 1; //モータL2:ON : のように構造体(及び共用体)の変数名を付けて記述する必要があると思います。 以上です。的外れな回答でしたらすみません。 参考になれば幸いです。
補足
アドバイスありがとうございます。 ご指摘の通り記述してみたところ、GIE/TMR2IE等についてもエラーが消えました! 「構造体(共用体)の変数名を付けて記述」する必要があるという事ですね。初めて知りました。 ちなみに、以前PIC16F84A&88でプログラムを記述した際には、上記対応(共用体名を付ける)は不要でしたが、マイコンの機種毎に違うのでしょうか? 前と同じ、簡潔な記述で済む方法がありましたら紹介頂けますと幸いです。 ありがとうございました。
- f-tomohiko
- ベストアンサー率50% (11/22)
回答1の補足です。 ヘッダはインクリュードされている前提で LATAbits.LTAT0 = 1; にしたらLATA0 は通りませんか。? なお、MPLIB C18は詳しくないのでLATAbitsにどうやって アドレスを与えているかは不明です。
お礼
貴重な情報、ありがとうございました。 今回頂いた情報により、初期設定関連についても少しずつ理解ができてきました。 本当にありがとうございました。
補足
連絡ありがとうございます。 アドバイス頂いた記述に変更してみたところ、LAT変数のエラーは消えました!(LAT変数については、記述のしかたが悪かったようです) あと、割り込み関連の変数(GIE,TMR2IE他)が残っています。 通常、このままでいけそう(PICでよく使う変数のはずなので)な気がするのですが、何か書き方がマズいのでしょうか? それとも、p18f2550.h以外にインクルードするファイル(ライブラリファイル等?)が必要なのでしょうか? 些細な情報でも構いませんので、アドバイスよろしくお願いします。
- f-tomohiko
- ベストアンサー率50% (11/22)
PIC18はCCS Cで使った事が有ります。 ところで p18f2550.h ファイルにGIE,LATA0の単語は出て来るんでしょうか。?
補足
ご連絡ありがとうございます。 p18f2550.hファイルの中に記載があります。 下記に抜粋します。 よろしくお願いします。 --【以下、抜粋(p18f2550.h)】-- extern volatile near unsigned char LATA; extern volatile near struct { unsigned LATA0:1; unsigned LATA1:1; unsigned LATA2:1; unsigned LATA3:1; unsigned LATA4:1; unsigned LATA5:1; unsigned LATA6:1; } LATAbits; --【途中省略】-- extern volatile near unsigned char INTCON; extern volatile near union { struct { unsigned RBIF:1; unsigned INT0IF:1; unsigned TMR0IF:1; unsigned RBIE:1; unsigned INT0IE:1; unsigned TMR0IE:1; unsigned PEIE:1; unsigned GIE:1; };
お礼
親切丁寧なアドバイス、ありがとうございました。 下名、プログラミングを始めてまだ3カ月の者で、特に初期設定関連の知識が全く無く、今回のような事態になると完全なフリーズ状態となってしまう状態にありました。 同僚にもPICに精通した者がおらず、web検索してもなかなか情報が得られない中でしたので、今回頂いた情報には本当に助けられました。 本当にありがとうございました。
補足
情報提供ありがとうございます。 PIC16F84Aのデータシートで確認したところ、例えばGIEはINTCONレジスタの中の1変数のように見て取れます。 以前(PIC16F84A&88時)、プログラム中では特に#define定義等せずにGIE,RB0,T0IE…等、構造体変数のメンバと思われる変数をプログラム中に記述しましたが、今回のようなエラーは出ませんでした。 その際に参考にした勉強用テキストにも、特にそのような処理は書かれておらず、普通に「GIE = 1;」のような記述で書かれており、その通り記述して全く問題なく動作しました。 PIC16F84A&88から今回のPIC18F2550に変更するにあたってコンパイラを変更しているため、その設定が違うのかも知れませんね。 今後は、アドバイス頂いた#define定義を使わせてもらおうと思います。 貴重な情報、ありがとうございました。