AD変換のテストプログラム user−n12−OK.c

// 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 )

}