dsPIC30F3012のサ ンプルプログラムT         2007.9.29

■動作

 dsPIC30F3012を使って、以下3つの初期設定、テスト動作を行いました。
    @12ビット A/D ad0,1,2,3,6,7の読み込み。
    AI/O ON、OFFの繰り返し→CPUの1命令速度を見ることができます。
    BUART(SIO シリアルアイオー、RS232C)

 開発環境はPICのサイトから無料でダウンロードできる統合開発環境MPLAB  V7.60MPLABI C30 Cコンパイラで製作しました。 MPLABのインストゥール、使い方、C30の仕様などはネット上に多くの例がありますので、それを参考に行なえると思います。書き込み器は電源も供給で きる PICKitを 使用しました。

dousa

■回路図

 CN1はPICKit2用のコネクタです。U4はdsPIC30F3012のU1ATX、U1ARXをRS232Cレベルに変換しているICです。発振 器は内蔵しているRC発振器の7.37MHzを使用しています。この発振器はPLLの設定で4倍、8倍、16倍にして使うこともできます(詳細後述)。周 波数精度が-40℃から125℃で最悪1.23%以内なのでRS232Cの規格を満足します。

kairozu
 ■プログラム (抜粋)

/*
    dspic30f3012 test program

    1.ad 0,1,2,3,6,7のサンプリング
    2.i/o ON,OFF繰り返し
    3.UART(シリアルアイオー)の送受信テスト

    Copyright Beyond the river Inc. 2007.9
*/

@ #include "p30F3012.h"
    #include "uart.h"   
     #include "adc12.h"

A _FWDT(WDT_OFF);
    _FOSC(CSW_FSCM_OFF & FRC);        //454.6KHz    7.37MHz    
//    _FOSC(CSW_FSCM_OFF & FRC_PLL4);    //1.803MHz    29.48MHz
//    _FOSC(CSW_FSCM_OFF & FRC_PLL8);    //3.632MHz    58.96MHz
//    _FOSC(CSW_FSCM_OFF & FRC_PLL16);//7.378MHz    117.92MHz

    char CmdMsg[] = "dsPIC30F2012 SIO通信 TEST";

B   //通信初期設定
    unsigned int UMODEValue = UART_EN & UART_IDLE_CON & UART_ALTRX_ALTTX & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD & UART_NO_PAR_8BIT & UART_1STOPBIT;
    unsigned int USTAValue = UART_INT_TX_BUF_EMPTY & UART_TX_PIN_NORMAL & UART_TX_ENABLE & UART_INT_RX_CHAR & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;

    //a/d初期設定
C unsigned int Config1 = ADC_MODULE_ON & ADC_IDLE_CONTINUE & ADC_FORMAT_INTG & ADC_CLK_AUTO & ADC_AUTO_SAMPLING_OFF & ADC_SAMP_OFF;
    unsigned int Config2 = ADC_VREF_AVDD_AVSS & ADC_SCAN_OFF & ADC_SAMPLES_PER_INT_1 & ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF;
    unsigned int Config3 = ADC_SAMPLE_TIME_8 & ADC_CONV_CLK_SYSTEM & ADC_CONV_CLK_32Tcy;
    //使用するADポートをここで宣言
     unsigned int ConfigPort = ENABLE_AN0_ANA & ENABLE_AN1_ANA & ENABLE_AN2_ANA & ENABLE_AN3_ANA & ENABLE_AN4_ANA & ENABLE_AN5_ANA & ENABLE_AN6_ANA & ENABLE_AN7_ANA;
     unsigned int ConfigScan = 0x000;
    
D unsigned int Channel0 = ADC_CH0_POS_SAMPLEA_AN0 & ADC_CH0_NEG_SAMPLEA_NVREF;
    unsigned int Channel1 = ADC_CH0_POS_SAMPLEA_AN1 & ADC_CH0_NEG_SAMPLEA_NVREF;
    unsigned int Channel2 = ADC_CH0_POS_SAMPLEA_AN2 & ADC_CH0_NEG_SAMPLEA_NVREF;
    unsigned int Channel3 = ADC_CH0_POS_SAMPLEA_AN3 & ADC_CH0_NEG_SAMPLEA_NVREF;

    unsigned int Channel6 = ADC_CH0_POS_SAMPLEA_AN6 & ADC_CH0_NEG_SAMPLEA_NVREF;
    unsigned int Channel7 = ADC_CH0_POS_SAMPLEA_AN7 & ADC_CH0_NEG_SAMPLEA_NVREF;


    void char_out1(unsigned short);
    unsigned short char_in1(void);
    void sio_test(void);
    void io_test(void);
    void ad_test(void);
    void ascout1(unsigned char dat);
    unsigned short hexascii(unsigned char dat);
    void wait(unsigned short sdata);

    void main(void)
    {
    unsigned short sdata;

E
        /* UART 初期設定 fcy=FRC/4  
                    29.48MHz    7.37MHz            BPS        BRG
            9600     46           11
            19200    23            5
            38400    11            2
            56k        NG          NG
            115k     3            NG
        */

       OpenUART1(UMODEValue,USTAValue,2);

F        /*
            a/dコンバータ 初期設定
        
        */
        
        TRISB = 0xff;    //PB0〜PB7入力
      OpenADC12(Config1,Config2,Config3,ConfigPort,ConfigScan);
        SetChanADC12(Channel0);

G     putsUART1(CmdMsg);

        sdata = char_in1();
        char_out1(sdata);

        switch(sdata)
        {
            case '0':
            case '1':
                  ad_test();break;
            case '2':
                        io_test();break;
            case '3':
                        sio_test();break;

        }



    
        while(1)
        {
        //    PORTBbits.RB0 = 1;
        
        //    PORTBbits.RB0 = 0;
        }
    }


void ad_test(void)
{
unsigned short sdata;
unsigned char cl,ch;

    while(1)
    {
H     SetChanADC12(Channel6);
        ADCON1bits.SAMP = 1;
        while(!ADCON1bits.DONE);
        sdata = ReadADC12(0);
        cl = sdata;sdata >>= 8;ch = sdata;
        char_out1('a');
        char_out1('d');
        char_out1('6');
        char_out1('=');
        ascout1(ch);
        ascout1(cl);

        char_out1(' ');
        SetChanADC12(Channel7);
        ADCON1bits.SAMP = 1;
        while(!ADCON1bits.DONE);
        sdata = ReadADC12(0);
        cl = sdata;sdata >>= 8;ch = sdata;
        char_out1('a');
        char_out1('d');
        char_out1('7');
        char_out1('=');
        ascout1(ch);
        ascout1(cl);
        wait(1000);
    }
}

■解説

@ #include "p30F3012.h"
    #include "uart.h"   
     #include "adc12.h"

    ポートなどをラベル名で使うためにヘッダファイルのインクルードが必要です。uart.hは通信、adc12はA/D用のヘッダです。例えば弊社のH8関 連のヘッダ との大きな違いは、UART、A/D等の使い方についてマイクロチップ社がきめ細かくプログラムを記述していますので、自分で書く必要が無いことで す。開発はすで にあるものを使いこなすことに時間を割くことになります。ほとんどのペリフェラルについてメーカーがプログラムをヘッダで供給しているので、これを使って プ ログラムを書けば品質を平均的に 上げることができると思います。思わぬバグの発生が防げることでしょう。デメリットがあるとすれば、せっかくC言語でプログラムを書いているのにビットま で名前が付けられているので、移植性が極め て悪いソースになることで、チップメーカーとしては当然のことかも知れません。

A _FWDT(WDT_OFF);
    _FOSC(CSW_FSCM_OFF & FRC);        //454.6KHz    7.37MHz    
//    _FOSC(CSW_FSCM_OFF & FRC_PLL4);    //1.803MHz    29.48MHz
//    _FOSC(CSW_FSCM_OFF & FRC_PLL8);    //3.632MHz    58.96MHz
//    _FOSC(CSW_FSCM_OFF & FRC_PLL16);//7.378MHz    117.92MHz

 ここの書き方で、クロック周波数を7.37MHzから117.92MHzまで変化させることができます。動作周波数はクロックの1/4です。 →dsPICは最高120MHzで1命令実行するわけではないので、注意が必要です。消費電流がクロックに応じて5mAから70mAと変 化しますので、うまい使い方としては必要とされる仕様に対して最小のクロックを設定することになります。不必要に高いと発熱が大きいですし、製品評価も下 がります。サンプルプログラムでは7.37MHz、7.37MHz/4=1.84MHz(動作クロック)で動作させています。 ソフトでクロックを16倍も変えることができるのは結構快感ですね。

B   //通信初期設定
    unsigned int UMODEValue = UART_EN & UART_IDLE_CON & UART_ALTRX_ALTTX & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD & UART_NO_PAR_8BIT & UART_1STOPBIT;
    unsigned int USTAValue = UART_INT_TX_BUF_EMPTY & UART_TX_PIN_NORMAL & UART_TX_ENABLE & UART_INT_RX_CHAR & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;

 ここで書かれている内容をOpen関数で実行し、動作モードを決めます。UARTの設定です。例えばUART_ENはUARTイネーブルで使用する、と いう意味です。それぞれの細かい意味についてはインクルードしているp30F3012.hの中に全て書かれていますので、それとハードウエアマニュアルを 併せて読めば意味が見えてくると思います。

    //a/d初期設定
C unsigned int Config1 = ADC_MODULE_ON & ADC_IDLE_CONTINUE & ADC_FORMAT_INTG & ADC_CLK_AUTO & ADC_AUTO_SAMPLING_OFF & ADC_SAMP_OFF;
    unsigned int Config2 = ADC_VREF_AVDD_AVSS & ADC_SCAN_OFF & ADC_SAMPLES_PER_INT_1 & ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF;
    unsigned int Config3 = ADC_SAMPLE_TIME_8 & ADC_CONV_CLK_SYSTEM & ADC_CONV_CLK_32Tcy;
    //使用するADポートをここで宣言
     unsigned int ConfigPort = ENABLE_AN0_ANA & ENABLE_AN1_ANA & ENABLE_AN2_ANA & ENABLE_AN3_ANA & ENABLE_AN4_ANA & ENABLE_AN5_ANA & ENABLE_AN6_ANA & ENABLE_AN7_ANA;
     unsigned int ConfigScan = 0x000;
 
 A/Dの設定です。A/Dについては基準電源の内部、外部選択、クロック、バッファの使用、不使用等々、細かく設定できます。外部基準電源に設定し、± で基準電源を用意するとA/Dの±入力が可能です。12ビットの分解能(1/4095)がありますので、そのままデータとして使えると思います。 dsPIC30F3012はわずか18ピンですが、8chの入力を持っています。
  
D unsigned int Channel0 = ADC_CH0_POS_SAMPLEA_AN0 & ADC_CH0_NEG_SAMPLEA_NVREF;
    unsigned int Channel1 = ADC_CH0_POS_SAMPLEA_AN1 & ADC_CH0_NEG_SAMPLEA_NVREF;
    unsigned int Channel2 = ADC_CH0_POS_SAMPLEA_AN2 & ADC_CH0_NEG_SAMPLEA_NVREF;
    unsigned int Channel3 = ADC_CH0_POS_SAMPLEA_AN3 & ADC_CH0_NEG_SAMPLEA_NVREF;

    unsigned int Channel6 = ADC_CH0_POS_SAMPLEA_AN6 & ADC_CH0_NEG_SAMPLEA_NVREF;
    unsigned int Channel7 = ADC_CH0_POS_SAMPLEA_AN7 & ADC_CH0_NEG_SAMPLEA_NVREF;

 A/Dはチャンネルごとに測定する範囲を設定できます。上記設定は各々のチャンネルポートとGND間を測定する設定です。


E
        /* UART 初期設定 fcy=FRC/4  
                    29.48MHz    7.37MHz            BPS        BRG
            9600    46            11
            19200    23            5
            38400    11            2
            56k        NG         NG
            115k     3            NG
        */

       OpenUART1(UMODEValue,USTAValue,2);

 ここで、UARTのオープン、各種設定を行っています。ボーレートは「2」ですが7.37MHzの場合38400bpsとなります。


F        /*
            a/dコンバータ 初期設定
        
        */
        
        TRISB = 0xff;    //PB0〜PB7入力
       OpenADC12(Config1,Config2,Config3,ConfigPort,ConfigScan);
        SetChanADC12(Channel0);

 ここでA/Dのオープン、各種設定を行っています。


G   putsUART1(CmdMsg);

        sdata = char_in1();
        char_out1(sdata);

        switch(sdata)
        {
            case '0':
            case '1':
                   ad_test();break;
            case '2':
                        io_test();break;
            case '3':
                        sio_test();break;

        }

  char CmdMsg[] = "dsPIC30F2012 SIO通信 TEST";

 をUARTで出力しています。確認は弊社フォースライタのSIOモニタを開いて行っています(フォースライタはFWR3048、、、他 なんでもOKで す)。キーボードで0,1,2,3をクリックするとパソコンからdsPIC30F3012側に1文字送信されますから、それを受信し、0または1のとき、 A/Dテスト、2のときI/Oテスト、3のときSIOテストを実行します。

void ad_test(void)
{
unsigned short sdata;
unsigned char cl,ch;

    while(1)
    {
H     SetChanADC12(Channel6);
        ADCON1bits.SAMP = 1;
        while(!ADCON1bits.DONE);
        sdata = ReadADC12(0);
        cl = sdata;sdata >>= 8;ch = sdata;
        char_out1('a');
        char_out1('d');
        char_out1('6');
        char_out1('=');
        ascout1(ch);
        ascout1(cl);

 ad_testが選択されるとチャンネルを設定し、サンプリングを開始します。終了したらデータを取り込みSIOモニタに出力しています。 SetChanADC12(Channel6);ここの赤字 を0〜7に変えて入力チャンネルを変えます。

■ダウンロード

上記内容の回路図(pdf)MPLAB用プロジェクトファイル、ソースファイル(LHA圧縮)をダウンロードすることが出来ます。

■参考書

以下の参考書が日本語で書かれていて大変参考になりました。

電 子制御・信号処理のためのDSPIC活用ガイドブック 後閑哲也 著 技術評論社  

■dsPIC30f3012 試作基板とライターPICKit2の接続(動画)

■dsPIC30f3012 サンプルプログラム動作(動画)
事前準備:ダウンロードしたファイルは解凍し、適 当なホルダに入れておきます。
画面で行っていること
@PICkit2動作開始。

Afwr3048ONE動作開始(VIEW画面を使うだけなので他のfwrでも 可)。
BMPLAB動作開始。
Cダウンロードしてきたsample2のWrokSpace  「sample2.mcw」を開く。
Dビルド オール(ソースを修正していない場合不要です)。
EBUILD SUCCEEDED(正常コンパイル)を確認し、そのファイルを削除。
FPICkit2 「Inport HEX」−>「sample2.hex」読み込み。
G「Write」で書き込み。正常書き込みで緑色が出ます。NGは赤です。
HVIEW画面クリア。
IVDD PICkit2をクリックし、試作基板に電源を入れています。正常で「dsPIC30f3012、、、」と表示されます。
J「1」をクリックしでA/Dコンバータを選択します。
KAD6,7の値が表示され続けます。



■dsPIC30f3012、 pickit2 のご購入はこちらから可能です