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