トップページ > dsPIC入門 > dsPICでAD変換(5)

PCへAD変換データを送信

UARTと組み合わせて使ってみる

AD変換が一定間隔で実行できるようになったところで、今度はそのデータをUARTモジュールを使って シリアル通信でPCへ送ることを試してみます。…とは言っても、 今回はシリアル通信の使い方のところで書いたプログラムをコピペするだけなので、 新しいことは何もしていません…。main()関数でUARTの初期設定をして、AD変換の割り込み関数内で AD変換データをUARTモジュールから出力するだけです。

ソースコード

//********************************************************************
//一定時間間隔でAD変換&UARTで送信  @dsPIC30F4012
//********************************************************************



//====================================================================
//ヘッダファイル
#include "p30f4012.h"
#include "timer.h"
#include "adc10.h"
#include "uart.h"


//====================================================================
//コンフィギュレーション
_FOSC(CSW_FSCM_OFF & XT_PLL8);     //10MHzセラロックを使っているのでクロックは80MHz。
_FWDT(WDT_OFF);
_FBORPOR(PBOR_ON & BORV_20 & PWRT_64 & MCLR_EN);
_FGS(CODE_PROT_OFF);


//====================================================================
//タイマー用のコンフィグ
unsigned int T3config = T3_ON & T3_GATE_OFF & T3_PS_1_256 & T3_SOURCE_INT;
unsigned int SampleTime = 39063; //16ビットint型の最大値「65535」を超えないように!!


//====================================================================
//AD変換用のコンフィグ

unsigned int ADconfig1 = ADC_MODULE_ON & ADC_IDLE_STOP & ADC_FORMAT_INTG & ADC_CLK_TMR 
                         & ADC_AUTO_SAMPLING_ON & ADC_SAMPLE_SIMULTANEOUS & ADC_SAMP_ON;
unsigned int ADconfig2 = ADC_VREF_AVDD_AVSS & ADC_SCAN_ON & ADC_CONVERT_CH0 & ADC_SAMPLES_PER_INT_1 
                         & ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF;
unsigned int ADconfig3 = ADC_SAMPLE_TIME_1 & ADC_CONV_CLK_SYSTEM & ADC_CONV_CLK_8Tcy;
unsigned int ADconfigPORT = ENABLE_AN0_ANA;
unsigned int ADconfigSCAN = 0;
unsigned int ADconfigCH0 = ADC_CH0_POS_SAMPLEA_AN0 & ADC_CH0_NEG_SAMPLEA_NVREF;


//====================================================================
//UART用のコンフィグ

unsigned int UARTconfig1 = UART_EN & UART_IDLE_CON & UART_ALTRX_ALTTX & UART_NO_PAR_8BIT & UART_1STOPBIT
                     & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD;

unsigned int UARTconfig2 = UART_INT_TX_BUF_EMPTY & UART_TX_PIN_NORMAL & UART_TX_ENABLE & UART_INT_RX_CHAR 
                     & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;


//====================================================================
//メイン関数

int main(void)
{

 //-------------------------------------------------------------------
 //ポート初期設定

 TRISB = 0x01;   //ポートBは0ビット目だけAD変換用入力
 TRISE = 0x00;   //ポートEは出力(緑色LED)
 TRISD = 0x00;   //ポートDも出力(赤色LED)
 PORTD = 0xff;


 //-------------------------------------------------------------------
 //AD変換モジュールの初期設定
 OpenADC10(ADconfig1,ADconfig2,ADconfig3,ADconfigPORT,ADconfigSCAN);
 SetChanADC10(ADconfigCH0); //チャンネル設定
 ConfigIntADC10(ADC_INT_ENABLE & ADC_INT_PRI_5);//AD変換機からの割り込みを許可


 //-------------------------------------------------------------------
 //タイマー3の初期設定
 OpenTimer3(T3config,SampleTime);


 //-------------------------------------------------------------------
 //UART初期設定
 //速度は115kbpsとします(80MHzクロックでは実用的に最も速い設定)
 OpenUART1(UARTconfig1,UARTconfig2,10);


 //-------------------------------------------------------------------
 //何もしないで、割り込み待ち
 while(1);


}




//====================================================================
//タイマー3からの割り込みでAD変換後、AD変換終了時に呼ばれる関数。
void __attribute__((__interrupt__,__shadow__)) _ADCInterrupt(void)
{
 
 int i; //for文のための変数
 int temp; //10進数の文字データへ変更する際に使用します。
 unsigned int ad_data; //AD変換結果を置いておく変数。
 
 //AD変換結果を文字列として格納する変数。
 //4bitだから、最大1023です。小数点を考慮して、5ケタ分の配列を用意。
 unsigned int str[5] = {};


 //割り込みフラグをクリア。
 IFS0bits.ADIF = 0;

 //PORTEの緑色LEDへ、変換結果を出力。 
 PORTE = ReadADC10(0); 

 //AD変換結果を、5[V]を最大値とした電圧値へ変換。
 ad_data = ReadADC10(0)*5/1.024;


 //「Voltage : 」と出力。
 putsUART1("Voltage : ");
 while(BusyUART1());



 //UARTでデータ送信していきます。
 for(i=0;i<5;i++)
 {

  //上から2ケタ目には、小数点を打ちます。
  if(i==3)
  {
   str[i] = '.';
  } 

  //それ以外のケタでは、普通に数値データを送信。
  else
  {
   //最下位から数字を拾っていきます。
   temp = (unsigned int)(ad_data%10);

   //数値を文字列にする作業…。
   switch(temp)
   {
    case 0:
     str[i] = '0';
     break;

    case 1:
     str[i] = '1';
     break;

    case 2:
     str[i] = '2';
     break;

    case 3:
     str[i] = '3';
     break;

    case 4:
     str[i] = '4';
     break;

    case 5:
     str[i] = '5';
     break;

    case 6:
     str[i] = '6';
     break;

    case 7:
     str[i] = '7';
     break;

    case 8:
     str[i] = '8';
     break;

    case 9:
     str[i] = '9';
     break;

    default:
     str[i] = '?';
     break;
   }

   //次の位へいきます。
   ad_data /= 10;
   
  }

 }


 //1ケタずつ送信。
 for(i=4;i>=0;i--)
 {
  WriteUART1(str[i]);
  while(BusyUART1());
 }

 //単位もつけて…
 putsUART1("[V]");
 while(BusyUART1());

 //改行を2つ分。
 putsUART1("\n\r\n\r");
 while(BusyUART1());


 //赤色LEDのON/OFFを入れ替える
 PORTD = !PORTD;

}

注意点

注意点は特にありません…。main()関数では例のごとく各モジュールの初期設定だけを行って待機する ようになっています。各モジュールの初期設定コンフイグに関しては、 タイマーのコンフィグシリアル通信のコンフィグAD変換のコンフィグ …などを参照してください。

AD変換の割り込み関数内で行っている処理は、よく用いられる「数値データ→文字列」の変換 アルゴリズムです。なんか煩雑な感じですが、割り込み関数の中では他の関数を呼ぶことができないので 処理をズラズラ記述することになります。

とりあえず、上が10bitのAD変換値から入力電圧を求めるイメージです。ただ、これだと小数値を 文字列に変換しなければならなかったり、型のキャストが必要になったり…といろいろ面倒なので、 以下のように変更します。

とりあえず、ハイパーターミナル

やっぱり、シリアル通信の最初のデバッグといえばハイパーターミナルでしょうか?(あまりハイパーターミナル にお世話になるのも悪いので、そろそろ Javaで自作ツールを作ろうと思います)

ハイパーターミナルの設定は「PCとつないで実験」のところを参照してください。




前へ   戻る