// Microchip USB C18 Firmware Version 1.2 /* ************************************************************************** */ /* ************************************************************************** ** ** 3チャンネルのA/D変換結果をUSB経由で出力するプログラムテスト ** ** ファイル名 user\user-n12-OK.c ** 2011/12/19 (20:10)--> 2011/12/19 (20:25) 完成 ** user\user-n11-OK.c からOpenADC()をProcessIO()からUserInit()に移す ** うまくいった。 ** user-n11.c以前ではCH0のLM35DZのデジタル値が高めに出ていたのが ** user-n12.cではきちんと出るようになった。 ** 何が違うのか解らないが、うまくいった。 ** OpenADC() は UserInit()で実行した方が良いようだ。 ** ** ** ** ** ** ** ファイル名 user\user-n11-OK.c ** 2011/12/19 (0:20)--> 2011/12/19 (0:45) ** ** user-n10-ok.cをそのままコピーして、不要な部分を削除したもの。 ** ** 2011/12/18 (23:55) --> user-n10-ok.c ** ステートマシンがうまくいかないので、固定文字列を埋める方法を考えてみる ** 結局 空白を文字配列にあらかじめ覚えさせて ** それを文末にコピーする方法とした。 ** これでうまくデジタル値の後ろに空白を2つ付けることに成功した(2011/12/18 23:55) ** ** ** 2011/12/17 --> ** 出力データの間に空白をいれる(stateマシンの記述方法) ** http://www.picfun.com/usb20/usb2006.html参照 ** --> うまくいかない空白ばかりが連続して出力される ??? ** ** ** 2011/12/16 -----> 2011/12/17 14:00 うまくいった。AD値も読める ** CASE文でANO〜AN2を使い分けてみる ** コンパイルエラーがでる --> switch文のcaseのラベルを "0" "1"などとしていた。 ** 数値で示す必要があり正しくは '0' '1'とすべきだった。(2011/12/17) ** ** デジタル変換値が正しく読めない。 ** アクイジッション時間を延ばした ADC_FOSC_4 --> ADC_FOSC_16 ** OpenADC()関数の第二引数に Vref+,Vref-の指定を追加した。 ** 今まではADCON1で指定しているつもりであった。うまくいってなかったのだろう。 ** & ADC_VREFPLUS_VDD & ADC_VREFMINUS_VSSを追加記入した。 ** これでうまくデジタル値が読めるようになった。(2011/12/17 14:00) ** ** ** * *************************************************************************** */ // ********* include ****************************************************** #include <p18cxxx.h> //#include <p18F2550.h> #include "system\typedefs.h" #include "system\usb\usb.h" #include "io_cfg.h" // io pin mapping #include "user\user.h" #include "user\temperature.h" #include "system\usb\class\cdc\cdc.h" // CDCTxService()関係 #include <adc.h> // A/D Converter Function #include <stdlib.h> #include <string.h> #include <delays.h> /* ************************************************************************** */ // //#define ADC_V?? ; // ADC Function Version in <adc.h>が不明 // 18F2550は ADC_V5のようだ。 // // Microchip\mplabc18\v3.38\h\p18f2550.hに // #define __18F2550_H // とある。 #include <p18f2550>を定義すれば // 自動的に導入されるのかな? // __18F2550_Hと__18F2550の関係が不明だが・・・ // // さらに、__18F2550が定義されると // Microchip\mplabc18\v3.38\h\pconfig.h に // 様々な18f2550用の定義が記述されている。 // /** V A R I A B L E S ********************************************************/ #pragma udata char input_buffer[64]; static char output_buffer[64]; //int result ; // A/D converter 用 /* ************************************************************************** */ /** P R I V A T E P R O T O T Y P E S ***************************************/ //void OpenADC( unsigned char config, unsigned char config2, unsigned char portconfig); //void strcpy(static char *,static char *); //void strcat(static char *,static char *); /* ************************************************************************** ** ** 2011/12/09 --> ** AD変換を使って、温度などを取り込む ** AD変換を使ってアナログデータを取り込む (AN0〜AN3) ** 作成開始 2011/12/09 --> ** PIC 18F2550 ** ** ** ** ************************************************************************** */ /** C O N F I G U R A T I O N ************************************************/ /* ************************************************************************** ** 18F2550 PINの使用状況 ** ** PIN 1 : RE3 デジタル 使用せず ** PIN 2 : RA0 アナログ入力 AN0 温度センサー LM-35DZ ** PIN 3 : RA1 アナログ入力 AN1 温度センサー LM-35DZ ** PIN 4 : RA2/Vref- アナログ入力 AN2 温度センサー LM-35DZ ** PIN 5 : RA3/Vref+ デジタル 使用せず ** PIN 6 : RA4 デジタル 使用せず ** PIN 7 : RA5 デジタル 使用せず ** PIN 8 : Vss GND ** PIN 9 : OSC1 発振子取付 ** PIN 10 : OSC2 発振子取付 ** PIN 11 : RC0 デジタル出力 LED0取付 ** PIN 12 : RC1 デジタル出力 LED1取付 ** PIN 13 : RC2 デジタル出力 LED2取付 ** PIN 14 : Vusb 3.3V出力 0.1μでGNDへ ** PIN 15 : RC4 D- USB接続に利用 ** PIN 16 : RC5 D+ USB接続に利用 ** PIN 17 : RC6 Tx RS232C用 TX 接続せず ** PIN 18 : RC7 Rx RS232C用 RX 接続せず ** PIN 19 : Vss GND ** PIN 20 : Vdd +5V ** PIN 21 : RB0 デジタル 使用せず ** PIN 22 : RB1 デジタル 使用せず ** PIN 23 : RB2 デジタル 使用せず ** PIN 24 : RB3 デジタル 使用せず ** PIN 25 : RB4 デジタル 使用せず ** PIN 26 : RB5 デジタル 使用せず ** PIN 27 : RB6 デジタル 使用せず ** PIN 28 : RB7 デジタル 使用せず ** ** ** ************************************************************************** */ #pragma code void UserInit(void){ /* ****************************************************** ** ADCON0 レジスター A/D コントロールレジスター AD変換に使う ** b7 b6 b5 b4 b3 b2 b1 b0 ** -- -- CHS3 CHS2 CHS1 CHS0 GO/DONE ADON ** ** ****************************************************** ** ** P O T ******** io_cfg.hに記述あり *************************** ** #define mInitPOT() TRISAbits.TRISA0=1;ADCON0=0x01;ADCON2=0x3C; ** ** ** b5:CHS3〜b2:CHS0 ANALOG CHANNEL SELECT BITS チャンネル選択 ** 0000 = channel 0(AN0) ** 0001 = channel 1(AN1) ** 0010 = channel 2(AN2) ** 0011 = channel 3(AN3) ** 0100 = channel 4(AN4) ** 0101 = channel 5(AN5) 18F2550にはない ** 0110 = channel 6(AN6) 18F2550にはない ** 0111 = channel 7(AN7) 18F2550にはない ** 1000 = channel 8(AN8) ** 1001 = channel 9(AN9) ** 1010 = channel 10(AN10) ** 1011 = channel 11(AN11) ** 1100 = channel 12(AN12) ** 1101 = Unimplemented ** 1110 = Unimplemented ** 1111 = Unimplemented ** ** b1:GO/DONE ** b0:ADON ** ** ** ****************************************************** */ /* ****************************************************** ** ADCON1 レジスター 基準電圧とA/D利用ピンの設定 ** b7 b6 b5 b4 b3 b2 b1 b0 ** -- -- VCFG1 VCFG0 PCFG3 PCFG2 PCFG1 PCFG0 ** ** InitializeSystem(void)にADCON1 |= 0x0F;(0b00001111) とある。 ** Default all pins to digital (参考 a |= b ビット単位のOR代入演算子) ** a |= b ( a = a|bと同じ) ** ****************************************************** */ // VCFG1〜VCFG0 基準電圧を決める ADCON1のbit5,bit4(VCFG) // VCFG1 VCFG0 −電源 +電源 // 0 0 Vss Vdd // 0 1 Vss Vref+ // 1 0 Vref- Vdd // 1 1 Vref- Vref+ // ADCON1 = 0b--00XXXX; // VssとVddを基準電圧 // // // // PCFG3〜PCFG0 // A/D利用ピンの設定 ADCON1のbit3〜bit0(PCFG) AN0から順にアナログ使用 // ADCON1 = 0b--XX1100; // AN0〜AN2をアナログで使用 // // 上記両方を併せてADCON1を設定 // ADCON1 = 0b00001100; // ここでの定義はうまくいかなかった。OpenADC()で初期設定する(2011/12/19 0:20) /* ****************************************************** ** TRIS レジスター データの入出力の方向 ** bit 1:入力 0:出力 ** TRISA TRISB TRISC TRISD TRISE ** bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 ** TRISA -- ○ ○ ○ ○ ○ ○ ○ ** TRISB ○ ○ ○ ○ ○ ○ ○ ○ ** TRISC ○ ○ -- -- -- ○ ○ ○ ** TRISD 28ピンの18f2550は無い。マニュアルP.124注3 ** TRISE 28ピンの18f2550は無い。マニュアルP.126注3 ** ** 今回はRA0(AN0)〜RA2(AN2)を入力で使用 ** 従って TRISA = 0b00000111 ** ** ** ****************************************************** */ TRISA = 0b00000111; // 1:入力 0:出力 AN2〜AN0(RA2〜RA0)を入力 TRISB = 0X01; // RB0を入力、他は出力 TRISC = 0; // すべて出力 LATA = 0; LATB = 0; LATC = 0; /* ****************************************************** ** ADCON2 レジスター manual P.267 ** 参考 (io_cfg.h) ** #define mInitPOT() TRISAbits.TRISA0=1;ADCON0=0x01;ADCON2=0x3C; ** 0x3C=00111100 ** ** アナログ変換値のそろえ方 ** ADFM ADCON2(bit7) 1:右そろえ 0:左そろえ ** ADFM = 1; 選択(12F683,16F88と同じ) ** bit6 : 未定義 ** ** アナログ入力用コンデンサー充電時間 (ADCON2 bit5〜bit3) ** ACQT2 ACQT1 ACQT0 ** bit5=1 bit4=1 bit3=1 A/D Aquisition Time Select bits ** 111=20Tad <---- io_cfg.hでこれを選択している ** 110=16Tad ** 101=12Tad ** 100= 8Tad ** 011= 6Tad ** 010= 4Tad ** 001= 2Tad ** 000= 0Tad ** ** ** AD変換周波数の選択ビット ** ADCS2 ADCS1 ADCS0 (ADCON2 bit2〜bit0) ** bit2=1 bit1=0 bit0=0 A/D Conversion Clock Select bits ** ** 111=FRC (clock devided from A/D RC oscillator) ** 110=Fosc/64 ** 101=Fosc/16 <---- 之にしないとだめかも? ** 100=Fosc/4 <---- io_cfg.hでこれを選択している ** 011=FRC (clock devided from A/D RC oscillator) ** 010=Fosc/32 ** 001=Fosc/8 ** 000=Fosc/2 ** ** 上記を合算して ADCON2=0b10111100 ** ********************************************************* */ // ADCON2=0b10111100; // ADFM 右そろえ ACQT: ADCS: // ADCON2=0b00111100; // ADFM 左そろえ ACQT: ADCS: // ここでの定義はうまくいかなかった。OpenADC()で初期設定する(2011/12/19 0:20) // // OpenADC( ADC_FOSC_16 & ADC_RIGHT_JUST & ADC_20_TAD , ADC_CH0 & ADC_CH1 & ADC_CH2 & ADC_INT_OFF & ADC_VREFPLUS_VDD & ADC_VREFMINUS_VSS, 15); // 2011/12/19(20:10) ProcessIO()からUserInit()に移した。こちらの方がうまくいった。 } // end UserInit /* ********************************************************** ** ** ProcessIO() 3ch AD出力 うまくいった。(2011/12/18 23:55) ** * *********************************************************** */ void ProcessIO(void){ // User Application USB tasks byte numBytesRead; byte i,j; char c_null[2] = "\0"; char in_data0; char out_data[8]; char blank1[3]=" "; // 空白2つ int ad0, ad1 ; // intでAD変換値がおかしい(マニュアルを読むと符号付き整数で良かった) if((usb_device_state < CONFIGURED_STATE)||(UCONbits.SUSPND==1)) return; // USBポートの準備OKか? 不可ならリターン numBytesRead = getsUSBUSART( input_buffer,64 ); // 入力バッファーを読みその文字数を入れる if( numBytesRead != 0 ) { // 文字数が0以外なら以下の実行 in_data0 = input_buffer[0]; // 入力バッファーの1文字目を入力 switch ( in_data0 ) { case '0': { SetChanADC(ADC_CH0); // AD変換するポートを指定 "0"を直接入れるとAD変換値がおかしい ADC_CH0もおかしい Delay10TCYx( 5 ); // Delay for 50 TCY 2011/12/16 1:20 この行追加 ConvertADC(); // AD変換スタート(コンデンサーチャージ) while(BusyADC()); // 読取準備完了か? ad0 = ReadADC(); // AD変換値を読む itoa(ad0,out_data); // 数値を文字列に変換 j = 0 ; // データの文字数を数える 2011/12/18 追加 for ( i=0 ; out_data[i] != '\0' ; i++ ) { j = j + 1 ; } for ( i=0 ; i<j ; i++ ){ // 2011/11/17 20:20 修正 output_buffer[i] = out_data[i] ; // output用のバッファーにコピー } output_buffer[j] = blank1[0] ; // 空白を入れる 2011/12/18 追加 output_buffer[j+1] = 0x00 ; // null if(mUSBUSARTIsTxTrfReady()) { // 出力用ポートの準備OKか putsUSBUSART(output_buffer) ; // 出力用の文字列をセット } // end if(mUSBUSARTIsTxTrfReady()) break ; } case '1': { SetChanADC(ADC_CH1); // AD変換するポートを指定 "0"を直接入れるとAD変換値がおかしい ADC_CH0もおかしい Delay10TCYx( 5 ); // Delay for 50 TCY 2011/12/16 1:20 この行追加 ConvertADC(); // AD変換スタート(コンデンサーチャージ) while(BusyADC()); // 読取準備完了か? ad0 = ReadADC(); // AD変換値を読む itoa(ad0,out_data); // 数値を文字列に変換 j = 0 ; // データの文字数を数える 2011/12/18 追加 for ( i=0 ; out_data[i] != '\0' ; i++ ) { j = j + 1 ; } for ( i=0 ; i<j ; i++ ){ // 2011/11/17 20:20 修正 output_buffer[i] = out_data[i] ; // output用のバッファーにコピー } output_buffer[j] = blank1[0] ; // 空白を入れる 2011/12/18 追加 output_buffer[j+1] = 0x00 ; // null if(mUSBUSARTIsTxTrfReady()) { // 出力用ポートの準備OKか putsUSBUSART(output_buffer) ; // 出力用の文字列をセット } // end if(mUSBUSARTIsTxTrfReady()) break ; } case '2': { SetChanADC(ADC_CH2); // AD変換するポートを指定 "0"を直接入れるとAD変換値がおかしい ADC_CH0もおかしい Delay10TCYx( 5 ); // Delay for 50 TCY 2011/12/16 1:20 この行追加 ConvertADC(); // AD変換スタート(コンデンサーチャージ) while(BusyADC()); // 読取準備完了か? ad0 = ReadADC(); // AD変換値を読む itoa(ad0,out_data); // 数値を文字列に変換 j = 0 ; // データの文字数を数える 2011/12/18 追加 for ( i=0 ; out_data[i] != '\0' ; i++ ) { j = j + 1 ; } for ( i=0 ; i<j ; i++ ){ // 2011/11/17 20:20 修正 output_buffer[i] = out_data[i] ; // output用のバッファーにコピー } // output_buffer[j] = blank1[0] ; // 空白を入れる 2011/12/18 追加 output_buffer[j+1] = 0x00 ; // null if(mUSBUSARTIsTxTrfReady()) { // 出力用ポートの準備OKか putsUSBUSART(output_buffer) ; // 出力用の文字列をセット } // end if(mUSBUSARTIsTxTrfReady()) break ; } default :{ if(mUSBUSARTIsTxTrfReady()) { // 出力用ポートの準備OKか putrsUSBUSART("Input error\r\n") ; // 出力用の文字列をセット } // end if(mUSBUSARTIsTxTrfReady()) // 出力はmain()のUSBTasks(void)の // CDCTxService()により実行される。 } } // end switch } // end if( numBytesRead != 0 ) } |