■ 外付けSPIインターフェース部品の読み書き                
  
SPIは部品間の通信でよくつかわれています。以下にその使用例を紹介します
     (1)12ビットA/Dコンバータ読み込み   <CCS編>
     (2) 2-1、12ビットD/Aコンバータへの書き込み(SPIモジュールから出力) <C30 dsPIC編> <C30 PIC24編>
        2-2、12ビットD/Aコンバータへの書き込み(汎用I/Oポートから出力) <C30 dsPIC編>
  (3)SDカード読み書き
     ★ 読み書き(ファイルオープン、リード、ライト)                    <C30 dsPIC 編>  <PIC32MX編>
     ★ 読み書き(FIFO)                                     <C30 dsPIC編>  <PIC32MX編>
     ★ 読み書き(EOF)                                      <C30 dsPIC編>  <PIC32MX編>
     ★ ADコンバータ値の読み書き                              <C30 dsPIC編>
     ★ 音声の録音と再生                   <C30 dsPIC編>
    ★ WAV録音付きMP3プレーヤー


 (1)12 ビット A/D コンバータ読込み                                 
    12ビットADコンバータとしては マイクロチップテクノロジー社のADコンバータ MCP3204を使いました。
   MCP3204はマイクロチップテクノロジー社から直接通販(約3ドル/個)で購入することができます。また、8チャンネル
   タイプのMCP3208秋月電商の通販(400円/個)で購入できます。
 
 <MCP3204の主要諸元>
    ・ 種類 …… 逐次比較型ADコンバータ(Succesive Approximation Anaogue-Digital Converter)
    ・ 分解能 …… 12ビット
    ・ 変換速度(サンプリングレート) …… 100Ksps ( at 電源電圧=5V) (注)
    ・ チャンネル数 …… 4チャンネル
    ・ 電源電圧範囲 …… 2.7V〜5.5V
    ・ パッケージ …… PDIP  SOIC  TSSOP

     (注) sps (sampling per second):A/D変換してとりだせるサンプリングデータ(MCP3204の場合12ビットデータ)の
        1秒間あたりの数
     
  <試作品仕様>
     ・ 電圧範囲 -5V 〜 +5Vの電圧を12ビットADコンバータで読込みこむ
     ・ PICに接続された液晶の上段には読込んでいる整数の値を 下段には測定電圧を V(ボルト)で表示する
     ・ ADコンバータの読込み及び液晶表示は200msec毎にタイマ割込みをつかっておこなう

  <MCP3204の使い方> (詳細はマイクロチップテクノロジ社のデータシートを参照してください)
   MCP3204は標準のSPIインターフェースのADコンバータです。A/D変換された値を読取る手順は以下のようになります。 
     @ PIC側よりMCP3204のCS端子をhigh→lowにする。
     A PIC側よりMCP3204のCLK端子をhigh→lowにする。これがスタートビットとなる。
        尚、この時のDin端子はhighのままにしておく。
     B MCP3204のCLK端子への信号をlow→highにする。このタイミングでMCP3204はスタートビットを認識します。
     C AD変換アンプをシングルエンドアンプで使うか差動アンプで使うかか下表にしたがってMCP3204のDin端子へ
        low/high信号を出力します。CLK端子をlow→highにします。MCP3240はDin端子情報を読込みます。
        ★MCP3204はCLKがlow→highのタイミングでDinの情報を読込みます。
     D つづく3ビットでどのチャンネルをつかうかをMCP3204のDin端子に読込ませます。
     E 3ビット目を読込ますクロックがlow→highになったあと1.5サイクルの間にデータがホールドされサンプリングが
        おこなわれます。
     F このあとのクロックlow→highのあとDout端子出力は無効なデータです。
     G 次のクロックのlow→highのあとMCP3204のDout端子にはA/D変換された12ビットデータのMSB(B11)が
        出力されてきます。これをPIC側で読み込みます。
     H このあとクロックをlow→highとしてB10を読込みます。 以下これをくりかえします。
     I LSB(B0)まで読み込んだら CSをlow→highにします。

        ★ MCP3204のCLK端子への入力クロックは最大2MHz(Clock Low Time(最小)=500nsec Clock High Time
          (最小)=500nsec) ですので プログラム設計の際、クロックのLow Time /High Timeが不足した場合は
          ウエイトをおこなう必要があります。





   
  <試作品回路図>  (→回路図のPDFファイル
    PIC18F4550をつかった場合の回路図を以下に示します。測定電圧範囲が-5v〜+5Vなので-5Vレベルシフトして
   からOPアンプで極性を反転させ、またアンプゲイン1/2にしてからMCP3204で読込むようにしています。
    MSSPは使用しないで一般のI/Oポートのモードで直接読書きしています。

 



<試作品外観> 下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています。    

          



以下のプログラム例の中にある液晶表示器制御ライブラリ 1llcd_lib.cは 後閑哲也さんが設計されたものです

   <プログラム例> 
#include    <18F4550.h>

#use delay(clock=20000000)
#FUSES  HS,PUT,NOWDT,BROWNOUT,BORV43,NOPROTECT,NOLVP
                
//////// Port define and link LCD library 
#define mode     0


#define input_x         input_D
#define output_x        output_D
#define set_tris_x      set_tris_D
#define rs PIN_D2       //chip select
#define stb PIN_D0      //strobe

#include <1lcd_lib.c>


unsigned long int myAD(){
        int i;
        unsigned int config;
        unsigned long int AdValue = 0;

        //AD開始
        output_high(PIN_C7);// Din(start bit): high(start) 
        output_low(PIN_C6);//CS:low
        output_low(PIN_B1);//CLK: low

        delay_cycles(3);//  600nsec ( = 50nsec × 4 × 3 サイクル)ウェイト

        output_high(PIN_B1);//CLK: high   MCP3204がスタートビットを読み込み

        delay_cycles(3);//  600nsec ( = 50nsec × 4 × 3 サイクル)ウェイト

        // ADコンバータの条件設定(シングルエンドか差動か、どのチャンネルを読むのか)
        config = 0b00001000; // bit3:single/diff bit   -> single = 1  シングルエンド選択
                                                 // bit2:nosignificant     -> 1
                                                 // bit1,bit0  chanel No set  00 -> ch0  チャンネル0を選択
        i = 0;
        for(i =  0; i < 4; i++){
                output_bit(PIN_C7,bit_test(config,3-i));
                output_low(PIN_B1);//CLK: low
                delay_cycles(3);
                output_high(PIN_B1);//CLK: high  MCP3204がconfig bitを読み込み
                delay_cycles(3);
        }

        // 2クロックウェイト --> MCP3204 ADコンバータの値をホールド&サンプリング
        i = 0;
        for(i = 0; i<2; i++){    
                output_low(PIN_B1);//CLK: low
                delay_cycles(4);
                output_high(PIN_B1);//CLK: high
                delay_cycles(4);
        }
        // MP3204が出力する12ビットデータを順次読込む
        i = 0;
        for(i = 0; i < 12; i++){
        output_low(PIN_B1); //CLK: low
        delay_cycles(3);
        output_high(PIN_B1);//CLK: high  MP3204がデータをDoutに出力
        delay_cycles(3);
        if(input(PIN_B0) == 1) bit_set(AdValue,11-i); //Doutが 1か0か判別
        else bit_clear(AdValue,11-i);
        }

        delay_cycles(3);
        output_high(PIN_C6);//CS:high

        return AdValue;
         
}




#int_timer0             //タイマ0割込み
interval(){
        unsigned long int adValue;
        float volt;

        set_timer0(61630); // 256*256 -3906 =  61630
                // 0.05 usec * 4 * 256 * 3906 = 200000 usec =200 msec

        adValue = myAD();//  ADコンバータが読込んだ値(12ビット整数)     MCP3204


        if(adValue >= 4095) adValue = 4095;
        if(adValue <= 0) adValue = 0;

        volt =  -((float)adValue - 2048)/2048 * 5 ;     //ADコンバータが読込んだ値を電圧値に換算

        // 液晶表示
        lcd_clear();
        printf(lcd_data,"adValue=%4lu",adValue);        // ADコンバータMCP3204が読込んだ値の表示
        lcd_cmd(0xC0); // 2行目の先頭へ
        printf(lcd_data,"V = %5.3f[V]",volt);   //電圧換算値を表示


        return 0;
}

main(){

        setup_timer_0(RTCC_INTERNAL |RTCC_DIV_256);
        set_timer0(61630);

        lcd_init();
        lcd_cmd(0b00001100);                    // カーソル:OFF    ブリンク:OFF
        lcd_clear();
        printf(lcd_data,"start!!");

        enable_interrupts(INT_TIMER0);
        enable_interrupts(GLOBAL);


        while(1)        // 割込みを待つ
        {
                output_high(PIN_C6);    // CS:high
        }


        return 0;
}


//---------------------------------------------------------------------------

//**************************************
//インクルードファイル    1lcd_lib.c
//このファイルは後閑哲也さんが設計されたものです
//**************************************


///////////////////////////////////////////////
//  液晶表示器制御ライブラリ
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去



//////// データ出力サブ関数
void lcd_out(int code, int flag)
{
        output_x((code & 0xF0) | (input_x() & 0x0F));
        if (flag == 0)
                output_high(rs);                //表示データの場合
        else
                output_low(rs);                 //コマンドデータの場合
        delay_cycles(4);                        //NOP 1         
        output_high(stb);                       //strobe out
        delay_cycles(8);                        //NOP 2
        output_low(stb);                        //reset strobe
}
//////// 1文字表示関数
void lcd_data(int asci)
{
        lcd_out(asci, 0);                       //上位4ビット出力
        lcd_out(asci<<4, 0);            //下位4ビット出力
        delay_us(50);                           //50μsec待ち
}
/////// コマンド出力関数
void lcd_cmd(int cmd)
{
        lcd_out(cmd, 1);                        //上位4ビット出力
        lcd_out(cmd<<4, 1);                     //下位4ビット出力
        delay_ms(2);                            //2msec待ち
}
/////// 全消去関数
void lcd_clear()
{
        lcd_cmd(0x01);                          //初期化コマンド出力
        delay_ms(15);                           //15msec待ち
}
/////// 初期化関数
void lcd_init()
{
        set_tris_x(mode);                       //モードセット
        delay_ms(15);
        lcd_out(0x30, 1);                       //8bit mode set
        delay_ms(5);
        lcd_out(0x30, 1);                       //8bit mode set
        delay_ms(1);
        lcd_out(0x30, 1);                       //8bit mode set
        delay_ms(1);
        lcd_out(0x20, 1);                       //4bit mode set
        delay_ms(1);
        lcd_cmd(0x2E);                          //DL=0 4bit mode
        lcd_cmd(0x08);                          //display off C=D=B=0
        lcd_cmd(0x0D);                          //display on C=D=1 B=0
        lcd_cmd(0x06);                          //entry I/D=1 S=0
        lcd_cmd(0x02);                          //cursor home
}


   <動作結果>
測定電圧に-2.36Vが入力された時の液晶表示を下記に示します。
 



(2) 12ビットD/Aコンバータへの書き込み    <dsPIC C30編>

    (2−1) SPI モジュールを使用した場合

    マイクロチップテクノロジーのD/AコンバータMCP4822をSPI通信で制御したD/A変換の例を紹介します。

  <試作品の仕様>
  ・ PICで1度毎の正弦波テーブルを生成し、このデータを200KHzでサンプリングしてSPI通信でD/Aコンバータ
    MCP4822に伝送する。
  ・ MCP4822(電源電圧+5V)からは、555Hz(注)、Vp-p 4.096V、分解能12ビットの正弦波電圧を出力する。
        (注)555Hz = 200KHz ÷ 360
      

 <試作品の回路図>  (→ 回路図のPDFファイル
   


 <試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています


   <プログラム例> 

//********************************************************************************************************
// 外付けDAコンバータMCP4822
//                 SPI通信による正弦波出力                   
//      サンプリング周波数:200KHz         出力正弦波 12bit 555Hz     dsPIC30F4013
//********************************************************************************************************

// MPLABのLink File 
//    Linler Script : p30f4013.gld 
//    Library File  : libp30F4013-coff.a

#include <p30f4013.h>
#include <timer.h>
#include "math.h"
#include "spi.h"

#define Clock   80000000       // 単位はHzで指定

_FOSC(CSW_FSCM_OFF &    // クロック切り替えなし、フェールセイフクロックモニタなし
                XT_PLL8         //外部発振子周波数 × ポストスケーラ:1 × PLL:8倍  → 10MHz × 1 ×  8 = 80MHz
                );
_FWDT(WDT_OFF);                 //ウォッチドックタイマ:OFF        

_FBORPOR(PBOR_ON &              //ブラウンアウトリセット機能:ON
                BORV_42 &               //ブラウンアウト電圧:4.2V
                PWRT_64 &               //パワーオンリセットタイマ64msec
                MCLR_EN         //MCLR機能:ON
                );
_FGS(CODE_PROT_OFF);    //コードプロテクト:OFF

unsigned int Fre_Out    = 1000;                 // 出力周波数 1KHz
unsigned int Fre_Sampling       = 200000;       //サンプリング周波数200KHz
unsigned int sinValue[360];     //sinテーブル値 RAM容量が少ないので大きな値(例1000)をとると不可解な現象がでる

unsigned int angleValue = 0;            //
float PAI = 3.1416;
int Led = 0; 

//// SPIの初期設定パラメータ クロック20MHz
unsigned int SPICONValue = FRAME_ENABLE_OFF & FRAME_SYNC_INPUT &
                        ENABLE_SDO_PIN & SPI_MODE16_ON & SPI_SMP_ON & SPI_CKE_OFF
                        &  CLK_POL_ACTIVE_LOW & 
                        MASTER_ENABLE_ON & SEC_PRESCAL_1_1 & PRI_PRESCAL_1_1;

unsigned int SPISTATValue = SPI_ENABLE & SPI_IDLE_CON & 
                        SPI_RX_OVFLOW_CLR;

 


void _ISR _T1Interrupt(void)    //5μsec毎の割込み発生
{
        LATDbits.LATD8 = 0;                     //CS = 0;
        IFS0bits.T1IF = 0;                      //IFS0レジスタの T1IF(タイマ1の割込み検出)フラグリセット

        WriteSPI1(sinValue[angleValue] | 0b0001000000000000);   //VoutAにゲイン2で出力
                                                                //MCP4822への書き込みコマンド 
                                                                //bit15(書き込みレジスタ選択)   1:VoutB   0:VoutA  
                                                                //bit14(予備)
                                                                //bit13(出力ゲイン選択)  1:1倍   0:2倍 
                                                                //bit12(出力オフ制御)  1:出力ON  0:出力OFF 
                                                                //bit11〜bit0    データ  MSBから順次送信される
        angleValue++;
        if(angleValue >= 360)angleValue = 0;


//1μsec delay ( Nop()0.05μsec ×20個 = 1μsec )   // 0.2μsec以下NG
        Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();
        Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();

        LATDbits.LATD8 = 1;                     //CS = 1 → CSの立ち上がりエッジでMCP4822の出力レジスタに送信データがラッチされる
}


void SinTable()         //Sin のテーブル作成
{
        unsigned int i;

        for(i = 0; i < 360; i++)
        {
                sinValue[i] = (unsigned int)(4095*(1 + sinf(2*PAI*i/360))/2);   //sinf():単精度  vs  sin():倍精度
        }
}

int main(void)
{
        TRISD = 0;                                              //ポートDを出力モードに設定 
        TRISF = 0;
                
        //タイマ1設定
        OpenTimer1(T1_ON  &                             //タイマ1ON
                                T1_GATE_OFF     &               //ゲート制御off
                                T1_PS_1_1 &                     //プリスケーラ 1/1
                                T1_SYNC_EXT_OFF &       //クロック同期制御OFF
                                T1_SOURCE_INT   ,       //クロック源:内部クロック
                                (unsigned int)(80000000/4/ 200000/1 - 1)        //  サンプリング周波数200KHz
                                );
        //SPI通信設定
        OpenSPI1(                                       // SPI1CONレジスタとSPI1STATレジスタの設定
                        FRAME_ENABLE_OFF &      //フレーム制御なし<Frame SPI support Enable/Disable:FRMEN>
                        FRAME_SYNC_INPUT &      //フレーム制御時の入出力方向<Frame Sync Pulse direction control:SPIFSD>
                        ENABLE_SDO_PIN &        //SDOピンを汎用ピンとしてではなくSPI制御用として使用 <SDO Pin Control bit:DISSDO>
                        SPI_MODE16_ON &         //送受信単位:16ビット (8ビット→ SPI_MODE16_OFF)<Word/Byte Communication mode:MODE16> 
                        SPI_SMP_ON &            //データ入力サンプルフェーズ:データ出力時間の終了時に入力データをサンプルする<SPI Data Input Sample phase:SMP>
                        SPI_CKE_OFF     &               //クロックエッジ選択:IDLE 状態からアクテイブクロック状態に遷移するエッジでシリアル出力データが変化CKE=0<SPI Clock Edge Select:CKE>
//                      SLAVE_SELECT_ENABLE_OFF &//SS ピン有効化:SSピン使用せず<SPI Slave Select enable:SSEN>                       
                        CLK_POL_ACTIVE_LOW &//クロック極性選択ビット:アクティブ状態Low(CKP=1)<SPI Clock polarity select:CKP> 
                                                                //SDカードはクロックの立ち上がりでデータを取り込む → CKE=0 CKP=1
                        MASTER_ENABLE_ON &      //マスターモード有効化:マスターモードに設定<SPI Mode Select bit:MSTEN>
                        SEC_PRESCAL_1_1 &       //2次プリスケール選択: 1:1<Secondary Prescale select:SPRE2-SPRE0>
                        PRI_PRESCAL_1_1,        //1次プリスケール選択: 1:1<Primary Prescale select : PRE1-PRE0>
                                                                //SPIクロック周波数=Fosc × 1/4  ÷  (1次プリスケーラ×2次プリスケーラ)
                                                                // = 80MHz × 1/4 ÷ ( 1 × 1) = 20MHz 
                        SPI_ENABLE &            //SPI有効無効設定: 有効<SPI Enable/Disable:SPIEN>
                        SPI_IDLE_CON &          //アイドル時の動作設定: 動作<SPI Idle mode Operation:SPISIDL>
                        SPI_RX_OVFLOW_CLR);     //オーバーフロー発生時フラグクリア:クリア<Clear Receive Overflow Flag bit:SPIROV>


        SinTable();                                     //Sinのテーブル作成

        ConfigIntTimer1( T1_INT_ON & T1_INT_PRIOR_5 );  //タイマ1割込みON  割込みレベル5 
        ConfigIntSPI1(SPI_INT_DIS & SPI_INT_PRI_6);             //SPI割込みOFF
        EnableIntT1;                                                                    //割込み許可

        while(1)
        {
        }
        CloseTimer1();
        CloseSPI1();

        return 0;
}

<動作結果>
  D/Aコンバータ MCP4822のVoutA(8番ピン)端子の出力電圧の波形を以下に示します。
     出力電圧諸元
       ・周波数 : 555Hz
       ・分解能 : 12ビット
       ・振幅(Vp-p) : 4.096V
        ・サンプリング周波数 : 200KHz      

(測定器:デジタルオシロ 岩通 DS-5102



(2A) 12ビットD/Aコンバータへの書き込み    <PIC24 C30編>

     SPI モジュールとして、 マイクロチップテクノロジーのD/AコンバータMCP4822をSPI通信で制御したD/A変換の例を紹介します。

  <試作品の仕様>
  ・ PICで1度毎の正弦波テーブルを生成し、このデータを100KHzでサンプリングしてSPI通信でD/Aコンバータ
    MCP4822に伝送する。
  ・ MCP4822(電源電圧+3.3V)からは、277.5Hz(注)、Vp-p 2.7V、分解能12ビットの正弦波電圧を出力する。
        (注)277.5Hz = 100KHz ÷ 360

<試作品の回路図>  (→ 回路図のPDFファイル


<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています



          

   <プログラム例>

///************************************************************/
// SPI通信による正弦波出力                   
//      サンプリング周波数:100KHz  出力正弦波 12bit 277.5Hz     PC24FJ64GA002
//************************************************************/
#include        "p24FJ64GA002.h"
#include <timer.h>
#include "math.h"
#include "spi.h"

#define Clock   32000000        // 単位はHzで指定

/// コンフィギュレーション ビットの設定
_CONFIG1( JTAGEN_OFF &  //JTAGポート: OFF
                         GCP_OFF &      //コードプロテクト: OFF
                        GWRP_OFF &      //書き込みプロテクト: OFF
                        BKBUG_OFF &     //バックグランドデバック: OFF
                        COE_OFF &       //クリップオン エミュレーション: OFF 
                        ICS_PGx1&       //ICDピンの選択: EMUC/EMUDをPGC1/PGD1と共用
                        FWDTEN_OFF )//ウォッチドックタイマ: OFF 


_CONFIG2( IESO_OFF &    // 2速度スタートアップ機能:OFF
                FNOSC_FRCPLL &  //内臓高速RC発振(8MHZ)回路 + 4倍PLL → 32MHz(= 8MHz × 4)
                FCKSM_CSDCMD &  //クロック切替え制御:OFF クロックモニタ:OFF
                OSCIOFNC_OFF &  //OSCO/RC15 function: OSCO or Fosc/2
                IOL1WAY_OFF &   //RP Register Protection: Unlimited Writes To RP Registers
                I2C1SEL_PRI &   //I2C1 pins Select: Use Primary I2C1 pins
                POSCMOD_NONE)   //発振回路モード Oscillator Selection:  Primary disabled

unsigned int sinValue[360];     //sinテーブル値 RAM容量が少ないので大きな値(例1000)をとると不可解な現象がでる
unsigned int angleValue = 0;            //
float PAI = 3.1416;



void _ISR _T1Interrupt(void)    //10μsec毎の割込み発生
{
        LATBbits.LATB7 = 0;                     //CS = 0;       チップセレクト
        IFS0bits.T1IF = 0;                      //IFS0レジスタの T1IF(タイマ1の割込み検出)フラグリセット


        WriteSPI1(sinValue[angleValue] | 0b0001000000000000);   //VoutAにゲイン2で出力
                                                                //MCP4822への書き込みコマンド 
                                                                //bit15(書き込みレジスタ選択)   1:VoutB   0:VoutA  
                                                                //bit14(予備)
                                                                //bit13(出力ゲイン選択)  1:1倍   0:2倍 
                                                                //bit12(出力オフ制御)  1:出力ON  0:出力OFF 
                                                                //bit11〜bit0    データ  MSBから順次送信される
        angleValue++;
        if(angleValue >= 360)angleValue = 0;

                //1μsec delay ( Nop()0.05μsec ×20個 = 1μsec )   // 0.2μsec以下NG
        Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();
        Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();

        LATBbits.LATB7 = 1;                     //CS = 1 → CSの立ち上がりエッジでMCP4822の出力レジスタに送信データがラッチされる


}


void SinTable()         //Sin のテーブル作成
{
        unsigned int i;

        for(i = 0; i < 360; i++)
        {
                        sinValue[i] = (unsigned int)((1 + sinf(2*PAI*i/360))/2*4095*3.3/5);   //sinf():単精度  vs  sin():倍精度
                        //Vout = 2.048×2×Dn/4095  Vout(max) = 4.096[V] ( > 3.3V(電源電圧))   4.096×3.3/5 = 2.7V (< (3.3V時オペアンプ飽和電圧))        
        }
}


/// メイン関数
int     main(void)
{
        TRISB = 0;      //Bポートを出力モードに設定
        CLKDIV = 0;     //内蔵FRC8MHz: 分周なし直結  ★このレジスタを明示的にリセットしておかないとFRCが分周されてくることがある(?)


        RPOR2bits.RP5R = 8;     //RB5(RPOR2レジスタのRP5)に機能8(SCK1OUT)を割り付ける
        RPOR3bits.RP6R = 7; //RB6(RPOR3レジスタのRP6)に機能7(SDO1)を割り付ける
  

        // タイマ1: 周期 10 μsec   サンプリング周波数:100KHz
        OpenTimer1
        (
                T1_ON   &       //タイマ1ON
                T1_GATE_OFF &   //ゲート制御off
                T1_PS_1_1       &       //プリスケーラ 1/1
                T1_SYNC_EXT_OFF &       //クロック同期制御OFF
                T1_SOURCE_INT,          //クロック源:内部クロック
                159                     //10*(32MHz/2MHz)=160   PR1設定値 = 159 (=160-1)
        );
                 
        //SPI通信設定               spi.h参照(\Program Files\Microchip\MPLAB C30\support\peripheral_24F)
        OpenSPI1
        ( 
                /* SPI1CON1 レジスタの設定 */
                ENABLE_SCK_PIN  &       //内臓SPIクロック有効 0xefff /*Internal SPI clock is enabled */
                ENABLE_SDO_PIN  &       //内臓モジュール(SDOピン)使用  0xf7ff /* SDO pin is  used by module      */
                SPI_MODE16_ON   &       //通信単位: 16ビット  0x0400 /* Communication is word wide */
                SPI_SMP_ON              &       //入力データを後段でサンプリングする  0xffff /* Input data sampled at end of data output time */
                SPI_CKE_OFF             &       //出力データ変化の発生: アイドル→アクティブ変化時  0xfeff /* Transmit happens on transition from idle clock state to active clock state */
                SLAVE_ENABLE_OFF        &       //SS1ピン使用せず 0xff7f /* Slave Select not used by module   */
                CLK_POL_ACTIVE_LOW      &       //クロックの極性選択: アイドル時Low、アクティブ時Low  0xffff /* Idle state for clock is high, active is low */
                MASTER_ENABLE_ON        &       //マスターモード       0xffff /* Master Mode              */
                SEC_PRESCAL_1_1         &       //2次プリスケーラ: 1:1  0xffff /* Secondary Prescale 1:1   */
                PRI_PRESCAL_1_1         ,       //1次プリスケーア: 1:1  0xffff /* Primary Prescale 1:1     */

                /*SPI2CON2 レジスタの設定 */
                FRAME_ENABLE_OFF        &       //フレームSPIサポート: OFF  0x7fff /* Frame SPI support Disable       */
                FRAME_SYNC_INPUT        &       //フレーム同期パルスを入力とする  0xffff /* Frame sync pulse Input (slave)  */
                FRAME_POL_ACTIVE_HIGH   &       //フレーム同期パルスをアクティブHighにする  0xffff /* Frame sync pulse is active-high*/
                FRAME_SYNC_EDGE_COINCIDE        &       // フレーム同期パルスを最初のビットと同期する0xffff /* Frame sync pulse coincides with first bit clock */
                FIFO_BUFFER_ENABLE      ,       //FIFOバッファー有効   0xffff /* FIFO buffer enabled */

                /* SPI1STAT レジスタの設定 */
                SPI_ENABLE      &       //SPIモジュール有効  0xffff /* Enable module */
                SPI_IDLE_CON    &       //デバイスがアイドル時もモジュールは動作  0xdfff /* Continue module operation in idle mode */
                SPI_RX_OVFLOW_CLR       //受信オーバーフローフラグビットクリア      0xffbf /* Clear receive overflow bit.*/
        );

        SinTable();                                     //Sinのテーブル作成

        ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_ON);    //割込みレベル5、 タイマ1割込みON
        ConfigIntSPI1(SPI_INT_DIS & SPI_INT_PRI_6);             //割り込みレベル6、 SPI割込みOFF

        EnableIntT1;    //タイマ1割込み許可

        while(1)
        {
        }

        CloseTimer1();
        CloseSPI1();

        return 0;
}


 

<動作結果>
  D/Aコンバータ MCP4822のVoutA(8番ピン)端子の出力電圧の波形を以下に示します。
     出力電圧諸元
       ・周波数 : 277.5Hz (周期: 3.6msec = 10μsec ×360 )
       ・分解能 : 12ビット
       ・振幅(Vp-p) : 2.7V
        ・サンプリング周波数 : 100KHz      

(測定器:デジタルオシロ 岩通 DS-5102


 12ビットD/Aコンバータへの書き込み    <dsPIC C30編>

(2−2) 汎用I/Oポートを使用した場合

   PICのSPIモジュールをSPI通信以外の別の目的で使用している場合などには、汎用ポートからSPI通信をする必要が
  あります。以下にその例を紹介します。PIC18F452の例にMCP4822のクロックレベルの説明がありますので参照願い
  ます。

  <試作品の仕様>
  ・ 1msec毎に、1度毎の正弦関数値を計算しSPI通信でD/AコンバータMCP4822に伝送する。
  ・ MCP4822(電源電圧+5V)からは、0〜 4.096V、分解能12ビットの正弦波電圧を出力する。
     出力される正弦波は周期360msec(周波数=2.78Hz)である。 
      

 <試作品の回路図>  (→ 回路図のPDFファイル




 <試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

   <プログラム例> 

//*******************************************************************
// 外付けDAコンバータMCP4822 (汎用ポート出力)
//                 正弦波出力                   
//      サンプリング周波数:1KHz          dsPIC30F4013
//*******************************************************************

// MPLABのLink File 
//    Linler Script : p30f4013.gld 
//    Library File  : libp30F4013-coff.a

#include <p30f4013.h>
#include <timer.h>
#include "math.h"


#define Clock   80000000       // 単位はHzで指定

_FOSC(CSW_FSCM_OFF &    // クロック切り替えなし、フェールセイフクロックモニタなし
                XT_PLL8         //外部発振子周波数 × ポストスケーラ:1 × PLL:8倍  → 10MHz × 1 ×  8 = 80MHz
                );
_FWDT(WDT_OFF);                 //ウォッチドックタイマ:OFF        

_FBORPOR(PBOR_ON &              //ブラウンアウトリセット機能:ON
                BORV_42 &               //ブラウンアウト電圧:4.2V
                PWRT_64 &               //パワーオンリセットタイマ64msec
                MCLR_EN         //MCLR機能:ON
                );
_FGS(CODE_PROT_OFF);    //コードプロテクト:OFF

unsigned int Angle = 0;         //
float PAI = 3.1416;
int Chanel = 0; //出力チャンネル:A



void DAout(unsigned int Out)
{
        int     i =0;

        LATDbits.LATD9 = 0;     // clock low  // RD9 : Clock(SCK)
        LATDbits.LATD8 = 0;     // cs low (select) // RD8 : Chip Select(CS)
        LATDbits.LATD3 = Chanel; // VoutAに出力 0:Chanel A  1:Chanel B 
                                                         // RD3 : Data(SDI)
        LATDbits.LATD9 = 1;     // clock high
        LATDbits.LATD9 = 0;     // clock low

        LATDbits.LATD3 = 1;     //dumy
        LATDbits.LATD9 = 1;     // clock high
        LATDbits.LATD9 = 0;     // clock low

        LATDbits.LATD3 = 0;     //ゲイン設定ビット 1: G = 1      0: G = 2
                                        // G = 2; V = Data/4096 * 2.048*2 [V]
        LATDbits.LATD9 = 1;     // clock high
        LATDbits.LATD9 = 0;     // clock low

        LATDbits.LATD3 = 1;     //シャットダウン設定ビット 1: 出力イネイブル    0: シャットダウン
                        // output enable
        LATDbits.LATD9 = 1;     // clock high
        LATDbits.LATD9 = 0;     // clock low

        for(i=0; i<12; i++)             // 送信データをMSBから順次1ビットづつ出力する
        {
                if((Out & 0b0000100000000000) == 0)LATDbits.LATD3 = 0;
                else LATDbits.LATD3 = 1;
                Out = (Out << 1);
                LATDbits.LATD9 = 1;     // clock high
                LATDbits.LATD9 = 0;     // clock low
        }

        LATDbits.LATD8 = 1;     // cs high  (MCP4822 Disable)


} 

void _ISR _T1Interrupt(void)    //1msec毎の割込み発生
{
        unsigned int Out;
        IFS0bits.T1IF = 0;                      //IFS0レジスタの T1IF(タイマ1の割込み検出)フラグリセット
        Out = (unsigned int)(4095*(1 + sinf(2*PAI*Angle/360))/2);
                                                                                                //sinf():単精度  vs  sin():倍精度
        DAout(Out);

        Angle++;
        if(Angle >= 360)Angle = 0;

}



int main(void)
{
        TRISD = 0;                                              //ポートDを出力モードに設定 
        TRISF = 0;
                
        //タイマ1設定
        OpenTimer1(T1_ON  &                             //タイマ1ON
                                T1_GATE_OFF     &               //ゲート制御off
                                T1_PS_1_1 &                     //プリスケーラ 1/1
                                T1_SYNC_EXT_OFF &       //クロック同期制御OFF
                                T1_SOURCE_INT   ,       //クロック源:内部クロック
                                (unsigned int)(80000000/4/ 1000/1 - 1)  //  サンプリング周波数1KHz
                                );

        LATDbits.LATD8 = 0;                     //CS = 0;

        ConfigIntTimer1( T1_INT_ON & T1_INT_PRIOR_5 );  //タイマ1割込みON  割込みレベル5 
        EnableIntT1;                                                                    //割込み許可

        while(1)
        {
        }
        CloseTimer1();


        return 0;
}


<動作結果>
  D/Aコンバータ MCP4822のVoutA(8番ピン)端子の出力電圧の波形を以下に示します。
     出力電圧諸元
       ・周波数 : 2.78Hz( = 1000msec / 360msec)
       ・分解能 : 12ビット
       ・振幅(Vp-p) : 4.096V
        ・サンプリング周波数 : 1KHz   

(測定器:デジタルオシロ 岩通 DS-5102


 12ビットD/Aコンバータへの書き込み    <PIC32MX460F512L  C32編>

     SPI モジュールとして、 マイクロチップテクノロジーのD/AコンバータMCP4822をSPI通信で制御したD/A変換の例を紹介します。

  <試作品の仕様>
  ・ PICで1度毎の正弦波テーブルを生成し、このデータを500KHzでサンプリングしてSPI通信でD/Aコンバータ
    MCP4822に伝送する。
  ・ MCP4822(電源電圧+3.3V)からは、1.39KHz(注)、Vp-p 2.7V、分解能12ビットの正弦波電圧を出力する。
        (注)1.39KHz = 500KHz ÷ 360

<試作品の回路図>  (→ 回路図のPDFファイル



<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています
          ・ QFPのPIC32MX460F512Lは、マイクロチップから開発用ターゲットボードExplore 16のCPUボードとして、販売されている
            PIM(Plug in Moduke)に実装されているものを使っています。

          ・使用しているユニバーサルキバンは自作のユニバーサルキバンです。



   <プログラム例>

///************************************************************/
// SPI通信による正弦波出力                   
//      サンプリング周波数:500KHz    出力正弦波 12bit 1.39 KHz 
//                                    PC32MX460F512L + MCP4822
//************************************************************/

#include <plib.h>               // PIC32 peripheral library 
                                                        //for SYSTEMConfigPerformance()

//#include "math.h"     //math.hは plib.hの含まれている



// コンフィギュレーション設定
// CPU=80MHz Peri=80MHz,HS+PLL,Divider=1/2,PLL=x20,WDT=Off
#pragma config FNOSC=PRIPLL, POSCMOD=HS, FPLLIDIV=DIV_2
#pragma config FPLLMUL=MUL_20, FPBDIV=DIV_1, FPLLODIV=DIV_1
#pragma config FWDTEN=OFF, ICESEL=ICS_PGx2

int Clock = 80000000;   //80MHz

short int sinValue[360];     //sinテーブル値 RAM容量が少ないので大きな値(例1000)をとると不可解な現象がでる
short int angleValue = 0;            //
float PAI = 3.1416;

void __ISR(4,ipl2)T1Hander(void)        //タイマ1割込 2μsec毎
{
        short int temp;
        mT1ClearIntFlag(); //タイマ1 フラグクリア

        LATDbits.LATD11 = 0;    //CS = 0

     WriteSPI1(sinValue[angleValue] | 0b0001000000000000);   //VoutAにゲイン2で出力


                                                                //MCP4822への書き込みコマンド 
                                                                //bit15(書き込みレジスタ選択)   1:VoutB   0:VoutA  
                                                                //bit14(予備)
                                                                //bit13(出力ゲイン選択)  1:1倍   0:2倍 
                                                                //bit12(出力オフ制御)  1:出力ON  0:出力OFF 
                                                                //bit11〜bit0    データ  MSBから順次送信される
     angleValue++;
        if(angleValue >= 360)angleValue = 0;


                //1μsec delay ( Nop()0.05μsec ×20個 = 1μsec )   // 0.2μsec以下NG
        Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();
        Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();

                Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();
        Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();

                Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();
        Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();


                LATDbits.LATD11 = 1;    //CS = 1 → CSの立ち上がりエッジでMCP4822の出力レジスタに送信データがラッチされる
}


void SinTable()         //Sin のテーブル作成
{
        short int i;
        int value;

        for(i = 0; i < 360; i++)
        {
                value = (1 + sinf(2*PAI*i/360))/2*4095*3.3/5;   //sinf():単精度  vs  sin():倍精度
                if( value < 0) value = 0;
                sinValue[i] = (short int)value;
                        //Vout = 2.048×2×Dn/4095  Vout(max) = 4.096[V] ( > 3.3V(電源電圧))   4.096×3.3/5 = 2.7V (< (3.3V時オペアンプ飽和電圧))        
        }
}



int main(void)
{
        SYSTEMConfigPerformance(80000000);      // システム最適化
        mJTAGPortEnable(DEBUG_JTAGPORT_OFF);
        TRISD = 0x00000000;     //SCK1/RD10、SDO1/RD0 (CS)RD11 の各ポートを出力モードに設定


        OpenTimer1
        (
                T1_ON | //      タイマ1 イネーブル  //T1_OFF → タイマ1 ディセーブル
                T1_SOURCE_INT | //クロックソース:インターナル //T1_SOURCE_EXT → 外部発振器
                T1_PS_1_1,      //プリスケール 1/256   //1/1、1/2、1/4、1/8、1/16、1/32、1/64、1/256

                160             //PRx値:800 →  T0[μsec] = 1000000/80000000*1*200 = 2.0 μsec
                                        //PICMX32は1クロックで1命令
                                        //周期 T0[sec] = 1/Fosc × プリスケーラの逆数 × PRx値
        );


        SpiChnOpen
        (
                1,              //有効化チャンネル: チャンネル1
                SPICON_MSTEN |  //マスターモード有効化 //Master mode Enable
//              SPICON_CKP |    //クロック極性制御有     //Clock Polarity control
//              SPICON_SSEN |   //SSピン制御:有 //Slave Select pin control
                SPICON_CKE |    //★★ クロックエッジ制御: イネーブル// クロックがActive→idleに変化した時データ変化 //Clock Edge control
                SPICON_SMP |    //データ抽出タイミング: データの後縁 //Sample phase control
                SPICON_MODE16 | //データ幅: 16ビット //Character width control


//              SPICON_DISSDO | //SDOピン制御: 無 (SDOポートをSPIモジュールとして使用しない) //SDO pin control
//              SPICON_SIDL |   //アイドル時CPU動作: 停止 //idle functinality control
//              SPICON_FRZ |    //デバッグ例外モード動作: 停止//debug functionality control
                SPICON_ON,              //SPI制御: 有効 //Module ON control
//              SPICON_SPIFE |  //フレーム同期パルスエッジ: 第一パルスと一致 //Frame Sync edge control
//              SPICON_FRMPOL | //フレーム制御: Active High //Frame Sync Polality control
//              SPICON_FRMSYNC |        //フレーム同期パルス: 入力 //Frame Sync Direction control
//              SPICON_FRMEN |  //フレームモード: 有効 //Frame Mode enable

                4       //fpbDiv = 4 →  SPIクロック周波数:20MHz (=80MHz(システムクロック周波数)÷1(Postscaler div:FPBDIV=DIV_1)÷4)
                        ////fpbDiv: Fpbclk(ペリフェラルバスクロック周波数)の分周比で2〜1024の値
                        //fpbDiv = 2 × (SPIxBRG<8:0> + 1)
                        //SPIクロック周波数 = Fpbclk / fpbDiv
                        //              = Fpbclk / ( 2 ×(SPIxBRG<8:0> + 1))
        );

        
        LATDbits.LATD11 = 1;    //CS = 1
       


        SinTable();                                     //Sinのテーブル作成


        ConfigIntTimer1(T1_INT_ON | T1_INT_PRIOR_2);    //タイマ1割込ON、割り込みレベル2
        INTEnableSystemMultiVectoredInt();      //割り込みをマルチベクタモードで許可



        while(1)        //割り込みを待つ
        {
        }

}



<動作結果>
  D/Aコンバータ MCP4822のVoutA(8番ピン)端子の出力電圧の波形を以下に示します。
     出力電圧諸元
       ・周波数 : 1.39KHz( = 1000msec / 360msec)
       ・分解能 : 12ビット
       ・振幅(Vp-p) : 2.7V
        ・サンプリング周波数 : 500KHz 


(測定器:デジタルオシロ 岩通 DS-5102

















12ビットD/Aコンバータへの書き込み    <PIC32MZ2048ECH100  Harmony + XC32編>

     SPI モジュールとして、 マイクロチップテクノロジーのD/AコンバータMCP4822をSPI通信で制御したD/A変換の例を紹介します。

  <試作品の仕様>
  ・ PICで1度毎の正弦波テーブルを生成し、このデータを500KHzでサンプリングしてSPI通信でD/Aコンバータ
    MCP4822に伝送する。
  ・ MCP4822(電源電圧+3.3V)からは、1.39KHz(注)、Vp-p 2.7V、分解能12ビットの正弦波電圧を出力する。
        (注)1.39KHz = 500KHz ÷ 360
  ・ 開発環境 ……  Harmony: ver. 1.00   XC32: ver.1.33    MPLABX: ver.2.25    PIC32MZ2048ECH100: revision 5

<試作品の回路図>  (→ 回路図のPDFファイル



   <試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

  


    

          

   <プログラム例>
//以下、main.c
//-------------------------------------------------------------------------------------------------------------------
/*******************************************************************************
  MPLAB Harmony Project Main Source File

  Company:
    Microchip Technology Inc.
  
  File Name:
    main.c

  Summary:
    This file contains the "main" function for an MPLAB Harmony project.

  Description:
    This file contains the "main" function for an MPLAB Harmony project.  The
    "main" function calls the "SYS_Initialize" function to initialize the state 
    machines of all MPLAB Harmony modules in the system and it calls the 
    "SYS_Tasks" function from within a system-wide "super" loop to maintain 
    their correct operation. These two functions are implemented in 
    configuration-specific files (usually "system_init.c" and "system_tasks.c")
    in a configuration-specific folder under the "src/system_config" folder 
    within this project's top-level folder.  An MPLAB Harmony project may have
    more than one configuration, each contained within it's own folder under
    the "system_config" folder.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

//Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include <stddef.h>                     // Defines NULL
#include <stdbool.h>                    // Defines true
#include <stdlib.h>                     // Defines EXIT_FAILURE
#include "system/common/sys_module.h"   // SYS function prototypes


// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************

int main ( void )
{
    /* Initialize all MPLAB Harmony modules, including application(s). */
    SYS_Initialize ( NULL );

    while ( true )
    {
        /* Maintain state machines of all polled MPLAB Harmony modules. */
        SYS_Tasks ( );

    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}


/*******************************************************************************
 End of File
*/






//以下、sysytem_config.h
//-------------------------------------------------------------------------------------------------------------------
/*******************************************************************************
  MPLAB Harmony System Configuration Header

  File Name:
    system_config.h

  Summary:
    Build-time configuration header for the system defined by this MPLAB Harmony
    project.

  Description:
    An MPLAB Project may have multiple configurations.  This file defines the
    build-time options for a single configuration.

  Remarks:
    This configuration header must not define any prototypes or data
    definitions (or include any files that do).  It only provides macro
    definitions for build-time configuration options that are not instantiated
    until used by another MPLAB Harmony module or application.
    
    Created with MPLAB Harmony Version 1.00
*******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
*******************************************************************************/
// DOM-IGNORE-END

#ifndef _SYSTEM_CONFIG_H
#define _SYSTEM_CONFIG_H


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************
/*  This section Includes other configuration headers necessary to completely
    define this configuration.
*/


// *****************************************************************************
// *****************************************************************************
// Section: System Service Configuration
// *****************************************************************************
// *****************************************************************************


// *****************************************************************************
/* Clock System Service Configuration Options
*/

#define SYS_CLK_SOURCE                      SYS_CLK_SOURCE_PRIMARY_SYSPLL
#define SYS_CLK_FREQ                        200000000ul
#define SYS_CLK_CONFIG_PRIMARY_XTAL         24000000ul
#define SYS_CLK_CONFIG_SECONDARY_XTAL       32768ul
#define SYS_CLK_CONFIG_SYSPLL_INP_DIVISOR   8
#define SYS_CLK_CONFIG_FREQ_ERROR_LIMIT     10
#define SYS_CLK_CONFIGBIT_USBPLL_ENABLE     true
#define SYS_CLK_CONFIG_USB_CLOCK            24000000ul
#define SYS_CLK_WAIT_FOR_SWITCH             true
#define SYS_CLK_KEEP_SECONDARY_OSC_ENABLED  true
#define SYS_CLK_ON_WAIT                     OSC_ON_WAIT_IDLE

 
/*** Common System Service Configuration ***/

#define SYS_BUFFER  false
#define SYS_QUEUE   false


// *****************************************************************************
/* Device Control System Service Configuration Options
*/

#define SYS_DEVCON_SYSTEM_CLOCK         200000000



/*** Interrupt System Service Configuration ***/

#define SYS_INT                     true


// *****************************************************************************
// *****************************************************************************
// Section: Driver Configuration
// *****************************************************************************
// *****************************************************************************


/*** Timer Driver Configuration ***/

#define DRV_TMR_INTERRUPT_SOURCE_IDX0       INT_SOURCE_TIMER_1
 
 
/*** SPI Driver Configuration ***/
/*** Driver Compilation and static configuration options. ***/
/*** Select SPI compilation units.***/
#define DRV_SPI_ISR                             0
#define DRV_SPI_POLLED                          1
#define DRV_SPI_MASTER                          1
#define DRV_SPI_SLAVE                           0
#define DRV_SPI_RM                              0
#define DRV_SPI_EBM                             1
#define DRV_SPI_8BIT                            0
#define DRV_SPI_16BIT                           1
#define DRV_SPI_32BIT                           0
#define DRV_SPI_DMA                             0

/*** SPI Driver Static Allocation Options ***/
#define DRV_SPI_INSTANCES_NUMBER                1
#define DRV_SPI_CLIENTS_NUMBER                  1
#define DRV_SPI_ELEMENTS_PER_QUEUE              10

/*** SPI Driver Index 0 configuration ***/
#define DRV_SPI_SPI_ID_IDX0                     SPI_ID_4                    //SPIチャンネル4を設定
#define DRV_SPI_TASK_MODE_IDX0                  DRV_SPI_TASK_MODE_POLLED
#define DRV_SPI_SPI_MODE_IDX0                   DRV_SPI_MODE_MASTER         //マスターモード
#define DRV_SPI_ALLOW_IDLE_RUN_IDX0             false
#define DRV_SPI_SPI_PROTOCOL_TYPE_IDX0          DRV_SPI_PROTOCOL_TYPE_STANDARD  //標準モード
#define DRV_SPI_COMM_WIDTH_IDX0                 SPI_COMMUNICATION_WIDTH_16BITS  //データ幅: 16ビット
#define DRV_SPI_SPI_CLOCK_IDX0                  CLK_BUS_PERIPHERAL_2            //クロックそーし PBCLK2
#define DRV_SPI_BAUD_RATE_IDX0                  1000000                         //ボーレート: 1MHz
#define DRV_SPI_BUFFER_TYPE_IDX0                DRV_SPI_BUFFER_TYPE_ENHANCED    //バッファー:エンハンスト
#define DRV_SPI_CLOCK_MODE_IDX0                 DRV_SPI_CLOCK_MODE_IDLE_LOW_EDGE_FALL   //アイドル時:Low    //検出エッジ: 立下り
#define DRV_SPI_INPUT_PHASE_IDX0                SPI_INPUT_SAMPLING_PHASE_IN_MIDDLE      //検出位相: 中央部
#define DRV_SPI_TX_INT_SOURCE_IDX0              INT_SOURCE_SPI_4_TRANSMIT
#define DRV_SPI_RX_INT_SOURCE_IDX0              INT_SOURCE_SPI_4_RECEIVE
#define DRV_SPI_ERROR_INT_SOURCE_IDX0           INT_SOURCE_SPI_4_ERROR
#define DRV_SPI_QUEUE_SIZE_IDX0                 10
#define DRV_SPI_RESERVED_JOB_IDX0               1


// *****************************************************************************
// *****************************************************************************
// Section: Middleware & Other Library Configuration
// *****************************************************************************
// *****************************************************************************






#endif // _SYSTEM_CONFIG_H
/*******************************************************************************
 End of File
*/








//以下、appp.c
//---------------------------------------------------------------------------------------------------
/*******************************************************************************
  MPLAB Harmony Application Source File

  Company:
    Microchip Technology Inc.

  File Name:
    app.c

  Summary:
    This file contains the source code for the MPLAB Harmony application.

  Description:
    This file contains the source code for the MPLAB Harmony application.  It
    implements the logic of the application's state machine and it may call
    API routines of other MPLAB Harmony modules in the system, such as drivers,
    system services, and middleware.  However, it does not call any of the
    system interfaces (such as the "Initialize" and "Tasks" functions) of any of
    the modules in the system or make any assumptions about when those functions
    are called.  That is the responsibility of the configuration-specific system
    files.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "app.h"


#include "math.h"



short int sinValue[360];     //sinテーブル値

int delay_Clock = 200000000;   //200MHz

void delay_us(volatile unsigned int usec)        //1μsec遅延
{
        volatile  int count;

        count = (int)(delay_Clock/20000000)*usec;


        do      //実測 at 200MH (Clock=200000000)
        {       //delay_us(1000):1000.4μsec  delay_us(100):100.6μsec  delay_us(10):10.5μsec  delay_us(1):1.5μsec
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

                count--;
        }while(count != 0);


}

void delay_ms(volatile unsigned int msec)        //1msec遅延
{
        volatile unsigned int i;         //実測:at200MH (Clock=200000000)//delay_ms(1): 1.0006msec   delay_ms(100):100.04msec

        for(i=0; i<msec; i++)
        delay_us(1000);
}



 void SinTable()         //Sin のテーブル作成
{
        short int i;
        float PAI = 3.1416;
        int value;

        for(i = 0; i < 360; i++)
        {
                value = (1 + sinf(2*PAI*i/360))/2*4095*3.3/5;   //sinf():単精度  vs  sin():倍精度
                if( value < 0) value = 0;
                sinValue[i] = (short int)value;
                        //Vout = 2.048×2×Dn/4095  Vout(max) = 4.096[V] ( > 3.3V(電源電圧))   4.096×3.3/5 = 2.7V (< (3.3V時オペアンプ飽和電圧))
        }
}




// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* Application Data

  Summary:
    Holds application data

  Description:
    This structure holds the application's data.

  Remarks:
    This structure should be initialized by the APP_Initialize function.

    Application strings and buffers are be defined outside this structure.
*/

APP_DATA appData;


// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************

/* TODO:  Add any necessary callback funtions.
*/


// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************

/* TODO:  Add any necessary local functions.
*/


// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void APP_Initialize ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    appData.state = APP_STATE_INIT;

    /* TODO: Initialize your application's state machine and other
     * parameters.
     */
        PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_D, 10 );
        //TRISDbits.TRISD10 = 0;   //RD10: out --> SCK4端子出力ポートに設定

        PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_D, 11 );
        //TRISDbits.TRISD11 = 0;   //RD11: out --> SDO4端子出力ポートに設定

        PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_A, 14 );
        //TRISAbits.TRISA14 = 0;   //RA14: out --> CS制御(MP4822)



        PLIB_SPI_Enable(SPI_ID_4);
        //SPI4CONbits.ON = 1;         //SPI4 イネーブル


        SinTable();     //Sin波形テーブル作成   //1deg毎


}


/******************************************************************************
  Function:
    void APP_Tasks ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Tasks ( void )
{
    /* Check the application's current state. */
    switch ( appData.state )
    {
        /* Application's initial state. */
        case APP_STATE_INIT:
        {
            break;
        }

        /* TODO: implement your application state machine.*/

        /* The default state should never be executed. */
        default:
        {
            /* TODO: Handle error in application's state machine. */
            break;
        }
    }
}


/*******************************************************************************
 End of File
 */







//以下、system_init.c
//--------------------------------------------------------------------------------------------------------------

/*******************************************************************************
  System Initialization File

  File Name:
    system_init.c

  Summary:
    This file contains source code necessary to initialize the system.

  Description:
    This file contains source code necessary to initialize the system.  It
    implements the "SYS_Initialize" function, configuration bits, and allocates
    any necessary global system resources, such as the systemObjects structure
    that contains the object handles to all the MPLAB Harmony module objects in
    the system.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "system_config.h"
#include "app.h"
#include "system_definitions.h"



// ****************************************************************************
// ****************************************************************************
// Section: Configuration Bits
// ****************************************************************************
// ****************************************************************************

//-----------------------------------------------------------------------
//DEVCFG0レジスタ
#pragma config EJTAGBEN = NORMAL
#pragma config DBGPER = ALLOW_PG2
#pragma config FSLEEP = OFF
#pragma config FECCCON = OFF_UNLOCKED
#pragma config BOOTISA = MIPS32
#pragma config TRCEN = OFF
#pragma config ICESEL = ICS_PGx2
#pragma config JTAGEN = OFF //JTAG ポート Disable
#pragma config DEBUG = OFF



//----------------------------------------------------------------------
//DEVCFG1レジスタ
#pragma config FNOSC = SPLL //PLL回路(システムPLL)選択   //システム発振回路 //内蔵FRC(8MHz)選択の場合:FNOSC = FRCDIV   //Oscillator Selection Bits (Fast RC Osc w/Div-by-N (FRCDIV))
#pragma config FDMTEN = OFF //デッドマンタイマ OFF (Deadman Timer is disabled)
//#pragma config DMTINTV = WIN_127_128 // DMT Count Window Interval (Window/Interval value is 127/128 counter value)

#pragma config FSOSCEN = OFF // 副発振器OFF   //Secondary Oscillator Enable (Disable SOSC)
#pragma config IESO = OFF //ウェイクアップ時の2段速度スタートアップ // Internal/External Switch Over (Disabled)

#pragma config POSCMOD = HS //HS: ハイスピードレゾネータモード // HS(High Speed Resonator Operation) Oscillator mode selected
                            //EC: 外部発振器    //EC(External Clock Input Operation) mode selected // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF //OSCCOピン出力無効
#pragma config FCKSM = CSECME   //クロック発振:切替及びモニタ有効  //主発振器失陥でFRC(内蔵高速発振器)に切替   //FSCM(Fail Safe Clock Monitor)制御

#pragma config FWDTEN = OFF // ウォッチドックタイマ OFF    //Watchdog Timer Disable
//#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576)
//#pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming)
//#pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode)
//#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%)



//--------------------------------------------------------------------------------------------------------------------
// DEVCFG2レジスタ
//システムクロック:200MHz
//ペリフェラル周波数://default: 100MHz    //PBxDIVで8系統毎に設定変更可
//PBxDIV: PERIPHERAL BUS CLOCK DIVISOR CONTROL レジスタのPBDIV<6:0>: Peripheral Bus Clock Divisor Control ビットで設定

#pragma config FPLLRNG = RANGE_13_26_MHZ        //PLL Input周波数入力範囲設定// System PLL Input Range (13-26 MHz Input)  //24MHz故
#pragma config FPLLIDIV = DIV_3 //PLL入力側での分周: 1/3  // PLL Input周波数 = 24MHz ÷ 3 = 8MHz     // System PLL Input Divider (1x Divider)

//#pragma config FPLLICLK = PLL_POSC //主発振回路選択 //内蔵FRC(8MHz)の場合はFPLLICLK = PLL_FRC//  System PLL Input Clock Selection (POSC is input to the System PLL)
#pragma config FPLLICLK = PLL_FRC   //内蔵高速発振器選択    //★★★ バグ有 主発振回路選択の時、FPLLICLK = PLL_POSCではなくFPLLICLK = PLL_FRCを選択する。(at ver.1.33 XC32)

#pragma config FPLLMULT = MUL_50 //PLL倍率:50倍 //8MHz x 50 = 400MHz  //System PLL Multiplier (PLL Multiply by 50)
#pragma config FPLLODIV = DIV_2 //PLL出力側での分周: 1/2  //システムクロック = 400MHz ÷ 2 = 200MHz


#pragma config UPLLFSEL = FREQ_24MHZ //USBのPLL入力を 24MHz→12MHzに変換 // USB PLL Input Frequency Selection (USB PLL input is 12 MHz)
#pragma config UPLLEN = ON //USBのPLL変換:イネーブル // USB PLL Enable (USB PLL is enabled)




//--------------------------------------------------------------------------------------------------------------------------
//DEVCFG3レジスタ
#pragma config USERID =     0xffff
#pragma config FMIIEN =     ON
#pragma config FETHIO =     ON
#pragma config PGL1WAY =    ON
#pragma config PMDL1WAY =   ON
#pragma config IOL1WAY =    ON
#pragma config FUSBIDIO =   ON


/*** BF1SEQ0 ***/

#pragma config TSEQ =       0xffff
#pragma config CSEQ =       0xffff


// *****************************************************************************
// *****************************************************************************
// Section: Library/Stack Initialization Data
// *****************************************************************************
// *****************************************************************************/



// *****************************************************************************
// *****************************************************************************
// Section: Driver Initialization Data
// *****************************************************************************
// *****************************************************************************



 /*** SPI Driver Initialization Data ***/
 /*** Index 0  ***/
 DRV_SPI_INIT drvSpi0InitData =     //SPI4オブジェクト初期化
 {
    .spiId = DRV_SPI_SPI_ID_IDX0,
    .taskMode = DRV_SPI_TASK_MODE_IDX0,
    .spiMode = DRV_SPI_SPI_MODE_IDX0,
    .allowIdleRun = DRV_SPI_ALLOW_IDLE_RUN_IDX0,
    .spiProtocolType = DRV_SPI_SPI_PROTOCOL_TYPE_IDX0,
    .commWidth = DRV_SPI_COMM_WIDTH_IDX0,
    .spiClk = DRV_SPI_SPI_CLOCK_IDX0,
    .baudRate = DRV_SPI_BAUD_RATE_IDX0,
    .bufferType = DRV_SPI_BUFFER_TYPE_IDX0,
    .clockMode = DRV_SPI_CLOCK_MODE_IDX0,
    .inputSamplePhase = DRV_SPI_INPUT_PHASE_IDX0,
    .queueSize = DRV_SPI_QUEUE_SIZE_IDX0,
    .jobQueueReserveSize = DRV_SPI_RESERVED_JOB_IDX0,
 };










// *****************************************************************************
// *****************************************************************************
// Section: System Data
// *****************************************************************************
// *****************************************************************************

/* Structure to hold the object handles for the modules in the system. */
SYSTEM_OBJECTS sysObj;

// *****************************************************************************
// *****************************************************************************
// Section: Module Initialization Data
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* System Clock Initialization Data
*/

const SYS_CLK_INIT sysClkInit =
{
    .moduleInit = {0},
    .systemClockSource = SYS_CLK_SOURCE,
    .systemClockFrequencyHz = SYS_CLK_FREQ,
    .waitTillComplete = true,
    .secondaryOscKeepEnabled = true,
    .onWaitInstruction = SYS_CLK_ON_WAIT,
};


/*** System Device Control Initialization Data ***/

const SYS_DEVCON_INIT sysDevconInit =
{
    .moduleInit = {0},
};


// *****************************************************************************
// *****************************************************************************
// Section: Static Initialization Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void DRV_TMR0_Initialize(void)

  Summary:
    Initializes Timer Driver Instance 0

  Remarks:
 */
void DRV_TMR0_Initialize(void)  //タイマ1初期設定
{
            /* Setup TMR0 Instance */
    PLIB_TMR_Stop(TMR_ID_1); /* Disable Timer */
    PLIB_TMR_ClockSourceSelect(TMR_ID_1, TMR_CLOCK_SOURCE_PERIPHERAL_CLOCK); /* Select clock source */

    PLIB_TMR_PrescaleSelect(TMR_ID_1, TMR_PRESCALE_VALUE_8); /* Select prescalar value */
 //   PLIB_TMR_PrescaleSelect(TMR_ID_1, TMR_PRESCALE_VALUE_256); /* Select prescalar value */
    PLIB_TMR_Mode16BitEnable(TMR_ID_1); /* Enable 16 bit mode */
    PLIB_TMR_Counter16BitClear(TMR_ID_1); /* Clear counter */

    /* Setup Interrupt */
    PLIB_INT_SourceEnable(INT_ID_0, INT_SOURCE_TIMER_1);
    PLIB_INT_VectorPrioritySet(INT_ID_0, INT_VECTOR_T1, INT_PRIORITY_LEVEL1);
    PLIB_INT_VectorSubPrioritySet(INT_ID_0, INT_VECTOR_T1, INT_SUBPRIORITY_LEVEL2);


    PLIB_TMR_Period16BitSet(TMR_ID_1,39063);    //5 nsec x2  x 39063 x 8 = 100.0128msec = 100msec
    PLIB_TMR_Start(TMR_ID_1);    //タイマスタート
}

// *****************************************************************************
// *****************************************************************************
// Section: System Initialization
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void SYS_Initialize ( SYS_INIT_DATA *data )

  Summary:
    Initializes the board, services, drivers, application and other modules.

  Remarks:
    See prototype in system/common/sys_module.h.
 */

void SYS_Initialize ( void* data )
{
    /* Core Processor Initialization */
    SYS_CLK_Initialize(&sysClkInit);
    sysObj.sysDevcon = SYS_DEVCON_Initialize(SYS_DEVCON_INDEX_0, (SYS_MODULE_INIT*)&sysDevconInit);
    SYS_DEVCON_PerformanceConfig(SYS_DEVCON_SYSTEM_CLOCK);

    /* System Services Initialization */
    SYS_INT_Initialize();

    /* Initialize Drivers */
    /* Timer Instanace 0 Call */
    DRV_TMR0_Initialize();


    /*** SPI Driver Index 0 initialization***/
    //SPI4用 リマップ

    RPD11Rbits.RPD11R = 0b1000;    //RD11ピンに SDO4の出力を割り付け

    sysObj.spiObjectIdx0 = DRV_SPI_Initialize(0, (const SYS_MODULE_INIT  * const)&drvSpi0InitData);



    /* Initialize System Services */

    /* Initialize Middleware */

    /* Enable Global Interrupts */
    SYS_INT_Enable();

    /* Initialize the Application */
    APP_Initialize();
}

/*******************************************************************************
 End of File
*/





//以下、system_interrupt.c
//--------------------------------------------------------------------------------------------------------------
/*******************************************************************************
 System Interrupts File

  File Name:
    system_int.c

  Summary:
    Raw ISR definitions.

  Description:
    This file contains a definitions of the raw ISRs required to support the
    interrupt sub-system.

  Summary:
    This file contains source code for the interrupt vector functions in the
    system.

  Description:
    This file contains source code for the interrupt vector functions in the
    system.  It implements the system and part specific vector "stub" functions
    from which the individual "Tasks" functions are called for any modules
    executing interrupt-driven in the MPLAB Harmony system.

  Remarks:
    This file requires access to the systemObjects global data structure that
    contains the object handles to all MPLAB Harmony module objects executing
    interrupt-driven in the system.  These handles are passed into the individual
    module "Tasks" functions to identify the instance of the module to maintain.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2011-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include <xc.h>
#include <sys/attribs.h>
#include "app.h"
#include "system_definitions.h"


# ifndef _MY_INCLUDE_PERIPHERAL
#define   _MY_INCLUDE_PERIPHERAL
#include <peripheral/peripheral.h>
#include <peripheral/ports/plib_ports.h>
#endif

int IntervalCount = 0;
short int angleValue = 0;
extern short int sinValue[360];     //sinテーブル値


// *****************************************************************************
// *****************************************************************************
// Section: System Interrupt Vector Functions
// *****************************************************************************
// *****************************************************************************
void __ISR(_TIMER_1_VECTOR, ipl2) _IntHandlerDrvTmrInstance0(void)
{

    PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_TIMER_1);
//    IFS0bits.T1IF= 0;    //タイマ1割り込みフラグクリア

    LATAbits.LATA14 = 0;     //MCP4822 CS = 0



    PLIB_TMR_Period16BitSet(TMR_ID_1,25000);    //5 nsec x2  x 25000 x 8 = 10000nsec = 1000μsec = 2msec

 PLIB_SPI_BufferWrite16bit ( SPI_ID_4, (short int)(sinValue[angleValue] | 0b0001000000000000));
//    SPI4BUF = (short int)(sinValue[angleValue] | 0b0001000000000000);                //送信データ送信
                                                                //MP4822 制御コマンド
                                                                //VoutAにゲイン2で出力
                                                                //MCP4822への書き込みコマンド
                                                                //bit15(書き込みレジスタ選択)   1:VoutB   0:VoutA
                                                                //bit14(予備)
                                                                //bit13(出力ゲイン選択)  1:1倍   0:2倍 
                                                                //bit12(出力オフ制御)  1:出力ON  0:出力OFF 
                                                                //bit11?bit0    データ  MSBから順次送信される
 while(PLIB_SPI_IsBusy(SPI_ID_4));  //書込み完了をまつ
 //   while(SPI4STATbits.SPITBF);    //: SPI Transmit Buffer Full Status bit //SPI2SRレジスタへの書込み完了
    angleValue++;
    if(angleValue >= 360)angleValue = 0;



    delay_us(200);


    LATAbits.LATA14 = 1;     //MCP4822 CS = 1;
   
}



/*******************************************************************************
 End of File
*/



 

<動作結果>

D/Aコンバータ MCP4822のVoutA(8番ピン)端子の出力電圧の波形を以下に示します。
     出力電圧諸元
       ・周波数 : 1.39KHz( = 1000msec / 360msec)
       ・分解能 : 12ビット
       ・振幅(Vp-p) : 2.7V
        ・サンプリング周波数 : 500KHz 



(測定器:デジタルオシロ 岩通 DS-5102


★ フラッシュメモリ 読み書き 
    <PIC32MZ2048ECH100  Harmony + XC32編>
  
SPIインターフェース フラッシュメモリへの読み書きの例を紹介します。

<試作品の仕様>
  ・ SPIインターフェースをもつフラッシュメモリへの読み書きをおこなう
  ・ フラッシュメモリは マイクロチップのSST25VF016(メモリ容量: 16Mビット)とする
  ・ マイコンが立ち上がったら フラッシュメモリに 以下の文字列を順次書込む
    @ Hellow World
    A PIC32MZ Run
    B SPI Flash

  ・ その後、書き込んだ文字列を順次読みだして キャラクタ液晶に表示する。
    表示は以下の要領で行う
    @ 上段: 1st
       下段:  Str=Hellow World
    A 上段:  2nd
      下段:  Str=PIC32MZ Run
    B 上段: 3rd
      下段:  Str=SPI Flash

  ・ 開発環境 ……  Harmony: ver. 1.00   XC32: ver.1.33    MPLABX: ver.2.25    PIC32MZ2048ECH100: revision 5


<試作品の回路図> (→ 回路図のPDFファイル



<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています



    

          

   <プログラム例>

//以下、main.c
//---------------------------------------------------------------------------------------------------
/*******************************************************************************
  MPLAB Harmony Project Main Source File

  Company:
    Microchip Technology Inc.
  
  File Name:
    main.c

  Summary:
    This file contains the "main" function for an MPLAB Harmony project.

  Description:
    This file contains the "main" function for an MPLAB Harmony project.  The
    "main" function calls the "SYS_Initialize" function to initialize the state 
    machines of all MPLAB Harmony modules in the system and it calls the 
    "SYS_Tasks" function from within a system-wide "super" loop to maintain 
    their correct operation. These two functions are implemented in 
    configuration-specific files (usually "system_init.c" and "system_tasks.c")
    in a configuration-specific folder under the "src/system_config" folder 
    within this project's top-level folder.  An MPLAB Harmony project may have
    more than one configuration, each contained within it's own folder under
    the "system_config" folder.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

//Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include <stddef.h>                     // Defines NULL
#include <stdbool.h>                    // Defines true
#include <stdlib.h>                     // Defines EXIT_FAILURE
#include "system/common/sys_module.h"   // SYS function prototypes


// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************

int main ( void )
{
    /* Initialize all MPLAB Harmony modules, including application(s). */
    SYS_Initialize ( NULL );

    while ( true )
    {
        /* Maintain state machines of all polled MPLAB Harmony modules. */
        SYS_Tasks ( );

    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}


/*******************************************************************************
 End of File
*/





//以下、system_config.h
//--------------------------------------------------------------------------------------------------
/*******************************************************************************
  MPLAB Harmony System Configuration Header

  File Name:
    system_config.h

  Summary:
    Build-time configuration header for the system defined by this MPLAB Harmony
    project.

  Description:
    An MPLAB Project may have multiple configurations.  This file defines the
    build-time options for a single configuration.

  Remarks:
    This configuration header must not define any prototypes or data
    definitions (or include any files that do).  It only provides macro
    definitions for build-time configuration options that are not instantiated
    until used by another MPLAB Harmony module or application.

    Created with MPLAB Harmony Version 1.00
*******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
*******************************************************************************/
// DOM-IGNORE-END

#ifndef _SYSTEM_CONFIG_H
#define _SYSTEM_CONFIG_H


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************
/*  This section Includes other configuration headers necessary to completely
    define this configuration.
*/


// *****************************************************************************
// *****************************************************************************
// Section: System Service Configuration
// *****************************************************************************
// *****************************************************************************


// *****************************************************************************
/* Clock System Service Configuration Options
*/

#define SYS_CLK_SOURCE                      SYS_CLK_SOURCE_PRIMARY_SYSPLL
#define SYS_CLK_FREQ                        200000000ul
#define SYS_CLK_CONFIG_PRIMARY_XTAL         24000000ul
#define SYS_CLK_CONFIG_SECONDARY_XTAL       32768ul
#define SYS_CLK_CONFIG_SYSPLL_INP_DIVISOR   8
#define SYS_CLK_CONFIG_FREQ_ERROR_LIMIT     10
#define SYS_CLK_CONFIGBIT_USBPLL_ENABLE     true
#define SYS_CLK_CONFIG_USB_CLOCK            24000000ul
#define SYS_CLK_WAIT_FOR_SWITCH             true
#define SYS_CLK_KEEP_SECONDARY_OSC_ENABLED  true
#define SYS_CLK_ON_WAIT                     OSC_ON_WAIT_IDLE


/*** Common System Service Configuration ***/

#define SYS_BUFFER  false
#define SYS_QUEUE   false


// *****************************************************************************
/* Device Control System Service Configuration Options
*/

#define SYS_DEVCON_SYSTEM_CLOCK         200000000



/*** Interrupt System Service Configuration ***/

#define SYS_INT                     true


// *****************************************************************************
// *****************************************************************************
// Section: Driver Configuration
// *****************************************************************************
// *****************************************************************************


/*** Timer Driver Configuration ***/

#define DRV_TMR_INSTANCES_NUMBER           1
#define DRV_TMR_CLIENTS_NUMBER             1
#define DRV_TMR_INTERRUPT_MODE             true

#define DRV_TMR_PERIPHERAL_ID_IDX0          TMR_ID_1
#define DRV_TMR_INTERRUPT_SOURCE_IDX0       INT_SOURCE_TIMER_1
#define DRV_TMR_INTERRUPT_VECTOR_IDX0       INT_VECTOR_T1
#define DRV_TMR_ISR_VECTOR_IDX0             _TIMER_1_VECTOR
#define DRV_TMR_INTERRUPT_PRIORITY_IDX0     INT_PRIORITY_LEVEL1
#define DRV_TMR_INTERRUPT_SUB_PRIORITY_IDX0 INT_SUBPRIORITY_LEVEL0
#define DRV_TMR_CLOCK_SOURCE_IDX0           DRV_TMR_CLKSOURCE_INTERNAL
#define DRV_TMR_PRESCALE_IDX0               TMR_PRESCALE_VALUE_256
#define DRV_TMR_OPERATION_MODE_IDX0         DRV_TMR_OPERATION_MODE_16_BIT
#define DRV_TMR_ASYNC_WRITE_ENABLE_IDX0     false
#define DRV_TMR_POWER_STATE_IDX0            SYS_MODULE_POWER_RUN_FULL










/*** SPI Driver Configuration ***/
/*** Driver Compilation and static configuration options. ***/
/*** Select SPI compilation units.***/
#define DRV_SPI_ISR                             0
#define DRV_SPI_POLLED                          1
#define DRV_SPI_MASTER                          1
#define DRV_SPI_SLAVE                           0
#define DRV_SPI_RM                              0
#define DRV_SPI_EBM                             1
#define DRV_SPI_8BIT                            1
#define DRV_SPI_16BIT                           0
#define DRV_SPI_32BIT                           0
#define DRV_SPI_DMA                             0

/*** SPI Driver Static Allocation Options ***/
#define DRV_SPI_INSTANCES_NUMBER                1
#define DRV_SPI_CLIENTS_NUMBER                  1
#define DRV_SPI_ELEMENTS_PER_QUEUE              10

/*** SPI Driver Index 0 configuration ***/
#define DRV_SPI_SPI_ID_IDX0                     SPI_ID_1
#define DRV_SPI_TASK_MODE_IDX0                  DRV_SPI_TASK_MODE_POLLED
#define DRV_SPI_SPI_MODE_IDX0                   DRV_SPI_MODE_MASTER             //マスターモード
#define DRV_SPI_ALLOW_IDLE_RUN_IDX0             false
#define DRV_SPI_SPI_PROTOCOL_TYPE_IDX0          DRV_SPI_PROTOCOL_TYPE_STANDARD  //SPIプリトコル 標準
#define DRV_SPI_COMM_WIDTH_IDX0                 SPI_COMMUNICATION_WIDTH_8BITS   //データ幅 8ビット
#define DRV_SPI_SPI_CLOCK_IDX0                  CLK_BUS_PERIPHERAL_2            //クロック源 PBCLK2
#define DRV_SPI_BAUD_RATE_IDX0                  1000000                         //SPIクロック   1MHz
#define DRV_SPI_BUFFER_TYPE_IDX0                DRV_SPI_BUFFER_TYPE_ENHANCED
#define DRV_SPI_CLOCK_MODE_IDX0                 DRV_SPI_CLOCK_MODE_IDLE_LOW_EDGE_FALL   //SPI4CONbits.CKP = 0;  //クロックの極性: アイドル時 = Low、 アクティブ = High
                                                                                        //SPI4CONbits.CKE = 1;  //クロックがActive→idleに変化した時データ変化
#define DRV_SPI_INPUT_PHASE_IDX0                SPI_INPUT_SAMPLING_PHASE_IN_MIDDLE
#define DRV_SPI_TX_INT_SOURCE_IDX0              INT_SOURCE_SPI_1_TRANSMIT
#define DRV_SPI_RX_INT_SOURCE_IDX0              INT_SOURCE_SPI_1_RECEIVE
#define DRV_SPI_ERROR_INT_SOURCE_IDX0           INT_SOURCE_SPI_1_ERROR
#define DRV_SPI_QUEUE_SIZE_IDX0                 10
#define DRV_SPI_RESERVED_JOB_IDX0               1


// *****************************************************************************
// *****************************************************************************
// Section: Middleware & Other Library Configuration
// *****************************************************************************
// *****************************************************************************






#endif // _SYSTEM_CONFIG_H
/*******************************************************************************
 End of File
*/





//以下、app.c
//----------------------------------------------------------------------------------------------------------
/*******************************************************************************
  MPLAB Harmony Application Source File

  Company:
    Microchip Technology Inc.

  File Name:
    app.c

  Summary:
    This file contains the source code for the MPLAB Harmony application.

  Description:
    This file contains the source code for the MPLAB Harmony application.  It
    implements the logic of the application's state machine and it may call
    API routines of other MPLAB Harmony modules in the system, such as drivers,
    system services, and middleware.  However, it does not call any of the
    system interfaces (such as the "Initialize" and "Tasks" functions) of any of
    the modules in the system or make any assumptions about when those functions
    are called.  That is the responsibility of the configuration-specific system
    files.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "app.h"


# ifndef _MY_INCLUDE_PERIPHERAL
#define   _MY_INCLUDE_PERIPHERAL
#include <peripheral/peripheral.h>
#include <peripheral/ports/plib_ports.h>
#endif

#include "1lcd_lib_C32.h"

int delay_Clock = 200000000;   //200MHz
char Buf[17];   //1液晶表示バッファー
char Buf2[25];

unsigned int adrStr = 0x00005678;  //読み書きするSPIフラッシュの先頭アドレス
char* str;
char str_Hellow[] = "Hellow World";
char str_PIC32MZ[] = "PIC32MZ Run";
char str_SpiFlash[] = "SPI Flash";



void delay_us(volatile unsigned int usec)        //1μsec遅延
{
        volatile  int count;

        count = (int)(delay_Clock/20000000)*usec;

        do      //実測 at 200MH (Clock=200000000)
        {       //delay_us(1000):1000.4μsec  delay_us(100):100.6μsec  delay_us(10):10.5μsec  delay_us(1):1.5μsec
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

                count--;
        }while(count != 0);


}

void delay_ms(volatile unsigned int msec)        //1msec遅延
{
        volatile unsigned int i;         //実測:at200MH (Clock=200000000)//delay_ms(1): 1.0006msec   delay_ms(100):100.04msec

        for(i=0; i<msec; i++)
        delay_us(1000);
}






// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* Application Data

  Summary:
    Holds application data

  Description:
    This structure holds the application's data.

  Remarks:
    This structure should be initialized by the APP_Initialize function.

    Application strings and buffers are be defined outside this structure.
*/

APP_DATA appData;


// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************

/* TODO:  Add any necessary callback funtions.
*/


// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************

/* TODO:  Add any necessary local functions.
*/


// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void APP_Initialize ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Initialize ( void )
{

    /* Place the App state machine in its initial state. */
    appData.state = APP_STATE_INIT;

    /* TODO: Initialize your application's state machine and other
     * parameters.
     */
        ysSPIInitialize();

     //SPI2ポート & CSポート設定

        PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_G, 6 );  //RG6: out --> SCK2端子出力ポートに設定
        PLIB_PORTS_PinDirectionInputSet( PORTS_ID_0, PORT_CHANNEL_G, 7 );   //RG7: out --> SDI2端子入力ポートに設定
        PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_G, 8 );  //RG8: out --> SDO2端子出力ポートに設定
        PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_A, 0 );  //RA0: out --> CS端子(MCP4822)

         //アナログ・デジタルモード設定
        PLIB_PORTS_PinModeSelect(PORTS_ID_0, PORTS_ANALOG_PIN_14, PORTS_PIN_MODE_DIGITAL);   //RG6/AN14ポートをデジタルモードに設定 //SCK2
        PLIB_PORTS_PinModeSelect(PORTS_ID_0, PORTS_ANALOG_PIN_13, PORTS_PIN_MODE_DIGITAL);   //RG7/AN13ポートをデジタルモードに設定 //SDI2
        PLIB_PORTS_PinModeSelect(PORTS_ID_0, PORTS_ANALOG_PIN_12, PORTS_PIN_MODE_DIGITAL);   //RG8/AN12ポートをデジタルモードに設定 //SDO2
        PLIB_PORTS_PinModeSelect(PORTS_ID_0, PORTS_ANALOG_PIN_24, PORTS_PIN_MODE_DIGITAL);   //RA0/AN24ポートをデジタルモードに設定 //CS

/*

        TRISGbits.TRISG6 = 0;   //RG6: out --> SCK2端子出力ポートに設定
        TRISGbits.TRISG7 = 1;   //RG7: out --> SDI2端子入力ポートに設定
        TRISGbits.TRISG8 = 0;   //RG8: out --> SDO2端子出力ポートに設定
        TRISAbits.TRISA0 = 0;   //RA0: out --> CS端子(MCP4822)

        ANSELGbits.ANSG6 = 0;  //RG6 デジタルモード
        ANSELGbits.ANSG7 = 0;  //RG7 デジタルモード
        ANSELGbits.ANSG8 = 0;  //RG8 デジタルモード
        ANSELAbits.ANSA0 = 0;  //RA0 デジタルモード
*/




    //液晶ポート入出力設定-----------------------------
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_B, 15 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_B, 14 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_B, 13 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_B, 12 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_A, 10 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_A, 9 );
/*
    TRISBbits.TRISB15 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB14 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB13 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB12 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA10 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA9 = 0;       //キャラクタ液晶ポート設定
*/


    lcd_init();                         // LCD初期化
    lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

    lcd_cmd(0x80);          //1目の先頭へ
    sprintf(Buf,"SPI R/W String     ");//
    lcd_str(Buf);                   //液晶表示

    lcd_cmd(0xC0);          //2行目の先頭へ
    sprintf(Buf,"    Start !! ");       //
    lcd_str(Buf);           // 開始メッセージ1行目表示

    delay_ms(2000);


    ysSPIInitialize();//SPIモジュール初期化
    ysSST25ResetWriteProtection();  //SPIフラッシュメモリ ライトプロテクト解除

//1回目---------------------------------------------------------------------------
    ysSST25SectorErase(adrStr);  //セクタ消去
    //ysSST25ChipErase(); //チップ消去

    ysSST25WriteArray(adrStr, str_Hellow, sizeof(str_Hellow));   ////文字列書き込み

    delay_ms(100);

    lcd_cmd(0x80);          //1目の先頭へ
    sprintf(Buf,"1st                "); //
    lcd_str(Buf);                   //液晶表示

    lcd_cmd(0xC0);          //2行目の先頭へ

    str = &Buf[0];  // ポインタにアドレスを代入
    ysSST25ReadArray(adrStr, str, 17) ; //文字列読出し

    sprintf(Buf,"%s",str);
    sprintf(Buf2,"Str=%s        ",Buf);
    lcd_str(Buf2);

    delay_ms(3000);


//2回目-----------------------------------------------------------------------------

      ysSST25SectorErase(adrStr);  //セクタ消去
    //ysSST25ChipErase(); //チップ消去

    ysSST25WriteArray(adrStr, str_PIC32MZ, sizeof(str_PIC32MZ));   ////文字列書き込み

    delay_ms(100);

    lcd_cmd(0x80);          //1目の先頭へ
    sprintf(Buf,"2nd                "); //
    lcd_str(Buf);                   //液晶表示

    lcd_cmd(0xC0);          //2行目の先頭へ

    str = &Buf[0];  // ポインタにアドレスを代入
    ysSST25ReadArray(adrStr, str, 17) ; //文字列読出し

    sprintf(Buf,"%s",str);
    sprintf(Buf2,"Str=%s        ",Buf);
    lcd_str(Buf2);

    delay_ms(3000);

    //3回目------------------------------------------------------------------------
        ysSST25SectorErase(adrStr);  //セクタ消去
    //ysSST25ChipErase(); //チップ消去

    ysSST25WriteArray(adrStr, str_SpiFlash, sizeof(str_SpiFlash));   ////文字列書き込み

    delay_ms(100);

    lcd_cmd(0x80);          //1目の先頭へ
    sprintf(Buf,"3rd                "); //
    lcd_str(Buf);                   //液晶表示

    lcd_cmd(0xC0);          //2行目の先頭へ

    str = &Buf[0];  // ポインタにアドレスを代入
    ysSST25ReadArray(adrStr, str, 17) ; //文字列読出し

    sprintf(Buf,"%s",str);
    sprintf(Buf2,"Str=%s        ",Buf);
    lcd_str(Buf2);

    delay_ms(2000);




}


/******************************************************************************
  Function:
    void APP_Tasks ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Tasks ( void )
{
    /* Check the application's current state. */
    switch ( appData.state )
    {
        /* Application's initial state. */
        case APP_STATE_INIT:
        {
            break;
        }

        /* TODO: implement your application state machine.*/

        /* The default state should never be executed. */
        default:
        {
            /* TODO: Handle error in application's state machine. */
            break;
        }
    }
}


/*******************************************************************************
 End of File
 */




//以下、system_init.c
//----------------------------------------------------------------------------------------------
/*******************************************************************************
  System Initialization File

  File Name:
    system_init.c

  Summary:
    This file contains source code necessary to initialize the system.

  Description:
    This file contains source code necessary to initialize the system.  It
    implements the "SYS_Initialize" function, configuration bits, and allocates
    any necessary global system resources, such as the systemObjects structure
    that contains the object handles to all the MPLAB Harmony module objects in
    the system.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "system_config.h"
#include "app.h"
#include "system_definitions.h"


# ifndef _MY_INCLUDE_PERIPHERAL
#define   _MY_INCLUDE_PERIPHERAL
#include <peripheral/peripheral.h>
#include <peripheral/ports/plib_ports.h>
#endif


// ****************************************************************************
// ****************************************************************************
// Section: Configuration Bits
// ****************************************************************************
// ****************************************************************************


//コンフィグ
//-----------------------------------------------------------------------
//DEVCFG0レジスタ
#pragma config EJTAGBEN = NORMAL
#pragma config DBGPER = ALLOW_PG2
#pragma config FSLEEP = OFF
#pragma config FECCCON = OFF_UNLOCKED
#pragma config BOOTISA = MIPS32
#pragma config TRCEN = OFF
#pragma config ICESEL = ICS_PGx2
#pragma config JTAGEN = OFF //JTAG ポート Disable
#pragma config DEBUG = OFF



//----------------------------------------------------------------------
//DEVCFG1レジスタ
#pragma config FNOSC = SPLL //PLL回路(システムPLL)選択   //システム発振回路 //内蔵FRC(8MHz)選択の場合:FNOSC = FRCDIV   //Oscillator Selection Bits (Fast RC Osc w/Div-by-N (FRCDIV))
#pragma config FDMTEN = OFF //デッドマンタイマ OFF (Deadman Timer is disabled)
//#pragma config DMTINTV = WIN_127_128 // DMT Count Window Interval (Window/Interval value is 127/128 counter value)

#pragma config FSOSCEN = OFF // 副発振器OFF   //Secondary Oscillator Enable (Disable SOSC)
#pragma config IESO = OFF //ウェイクアップ時の2段速度スタートアップ // Internal/External Switch Over (Disabled)

#pragma config POSCMOD = HS //HS: ハイスピードレゾネータモード // HS(High Speed Resonator Operation) Oscillator mode selected
                            //EC: 外部発振器    //EC(External Clock Input Operation) mode selected // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF //OSCCOピン出力無効
#pragma config FCKSM = CSECME   //クロック発振:切替及びモニタ有効  //主発振器失陥でFRC(内蔵高速発振器)に切替   //FSCM(Fail Safe Clock Monitor)制御

#pragma config FWDTEN = OFF // ウォッチドックタイマ OFF    //Watchdog Timer Disable
//#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576)
//#pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming)
//#pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode)
//#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%)



//--------------------------------------------------------------------------------------------------------------------
// DEVCFG2レジスタ
//システムクロック:200MHz
//ペリフェラル周波数://default: 100MHz    //PBxDIVで8系統毎に設定変更可
//PBxDIV: PERIPHERAL BUS CLOCK DIVISOR CONTROL レジスタのPBDIV<6:0>: Peripheral Bus Clock Divisor Control ビットで設定

#pragma config FPLLRNG = RANGE_13_26_MHZ        //PLL Input周波数入力範囲設定// System PLL Input Range (13-26 MHz Input)  //24MHz故
#pragma config FPLLIDIV = DIV_3 //PLL入力側での分周: 1/3  // PLL Input周波数 = 24MHz ÷ 3 = 8MHz     // System PLL Input Divider (1x Divider)

//#pragma config FPLLICLK = PLL_POSC //主発振回路選択 //内蔵FRC(8MHz)の場合はFPLLICLK = PLL_FRC//  System PLL Input Clock Selection (POSC is input to the System PLL)
#pragma config FPLLICLK = PLL_FRC   //内蔵高速発振器選択    //★★★ バグ有 主発振回路選択の時、FPLLICLK = PLL_POSCではなくFPLLICLK = PLL_FRCを選択する。(at ver.1.33 XC32)

#pragma config FPLLMULT = MUL_50 //PLL倍率:50倍 //8MHz x 50 = 400MHz  //System PLL Multiplier (PLL Multiply by 50)
#pragma config FPLLODIV = DIV_2 //PLL出力側での分周: 1/2  //システムクロック = 400MHz ÷ 2 = 200MHz


#pragma config UPLLFSEL = FREQ_24MHZ //USBのPLL入力を 24MHz→12MHzに変換 // USB PLL Input Frequency Selection (USB PLL input is 12 MHz)
#pragma config UPLLEN = ON //USBのPLL変換:イネーブル // USB PLL Enable (USB PLL is enabled)




//--------------------------------------------------------------------------------------------------------------------------
//DEVCFG3レジスタ
#pragma config USERID =     0xffff
#pragma config FMIIEN =     ON
#pragma config FETHIO =     ON
#pragma config PGL1WAY =    ON
#pragma config PMDL1WAY =   ON
#pragma config IOL1WAY =    ON
#pragma config FUSBIDIO =   ON


/*** BF1SEQ0 ***/

#pragma config TSEQ =       0xffff
#pragma config CSEQ =       0xffff


// *****************************************************************************
// *****************************************************************************
// Section: Library/Stack Initialization Data
// *****************************************************************************
// *****************************************************************************/



// *****************************************************************************
// *****************************************************************************
// Section: Driver Initialization Data
// *****************************************************************************
// *****************************************************************************


/*** TMR Driver Initialization Data ***/

const DRV_TMR_INIT drvTmr0InitData =
{
    .moduleInit.sys.powerState = DRV_TMR_POWER_STATE_IDX0,
    .tmrId = DRV_TMR_PERIPHERAL_ID_IDX0,
    .clockSource = DRV_TMR_CLOCK_SOURCE_IDX0,
    .prescale = DRV_TMR_PRESCALE_IDX0,
    .mode = DRV_TMR_OPERATION_MODE_IDX0,
    .interruptSource = DRV_TMR_INTERRUPT_SOURCE_IDX0,
    .asyncWriteEnable = false,
};

 /*** SPI Driver Initialization Data ***/
 /*** Index 0  ***/
 DRV_SPI_INIT drvSpi0InitData =     //SPI通信諸元 初期化
 {
    .spiId = DRV_SPI_SPI_ID_IDX0,
    .taskMode = DRV_SPI_TASK_MODE_IDX0,
    .spiMode = DRV_SPI_SPI_MODE_IDX0,
    .allowIdleRun = DRV_SPI_ALLOW_IDLE_RUN_IDX0,
    .spiProtocolType = DRV_SPI_SPI_PROTOCOL_TYPE_IDX0,
    .commWidth = DRV_SPI_COMM_WIDTH_IDX0,
    .spiClk = DRV_SPI_SPI_CLOCK_IDX0,
    .baudRate = DRV_SPI_BAUD_RATE_IDX0,
    .bufferType = DRV_SPI_BUFFER_TYPE_IDX0,
    .clockMode = DRV_SPI_CLOCK_MODE_IDX0,
    .inputSamplePhase = DRV_SPI_INPUT_PHASE_IDX0,
    .queueSize = DRV_SPI_QUEUE_SIZE_IDX0,
    .jobQueueReserveSize = DRV_SPI_RESERVED_JOB_IDX0,
 };










// *****************************************************************************
// *****************************************************************************
// Section: System Data
// *****************************************************************************
// *****************************************************************************

/* Structure to hold the object handles for the modules in the system. */
SYSTEM_OBJECTS sysObj;

// *****************************************************************************
// *****************************************************************************
// Section: Module Initialization Data
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* System Clock Initialization Data
*/

const SYS_CLK_INIT sysClkInit =
{
    .moduleInit = {0},
    .systemClockSource = SYS_CLK_SOURCE,
    .systemClockFrequencyHz = SYS_CLK_FREQ,
    .waitTillComplete = true,
    .secondaryOscKeepEnabled = true,
    .onWaitInstruction = SYS_CLK_ON_WAIT,
};


/*** System Device Control Initialization Data ***/

const SYS_DEVCON_INIT sysDevconInit =
{
    .moduleInit = {0},
};


// *****************************************************************************
// *****************************************************************************
// Section: Static Initialization Functions
// *****************************************************************************
// *****************************************************************************


// *****************************************************************************
// *****************************************************************************
// Section: System Initialization
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void SYS_Initialize ( SYS_INIT_DATA *data )

  Summary:
    Initializes the board, services, drivers, application and other modules.

  Remarks:
    See prototype in system/common/sys_module.h.
 */

void SYS_Initialize ( void* data )
{
    /* Core Processor Initialization */
    SYS_CLK_Initialize(&sysClkInit);
    sysObj.sysDevcon = SYS_DEVCON_Initialize(SYS_DEVCON_INDEX_0, (SYS_MODULE_INIT*)&sysDevconInit);
    SYS_DEVCON_PerformanceConfig(SYS_DEVCON_SYSTEM_CLOCK);

    /* System Services Initialization */
    SYS_INT_Initialize();

    /* Initialize Drivers */
    sysObj.drvTmr0 = DRV_TMR_Initialize(DRV_TMR_INDEX_0, (SYS_MODULE_INIT *)&drvTmr0InitData);

    SYS_INT_VectorPrioritySet(INT_VECTOR_T1, INT_PRIORITY_LEVEL1);
    SYS_INT_VectorSubprioritySet(INT_VECTOR_T1, INT_SUBPRIORITY_LEVEL0);


    /*** SPI Driver Index 0 initialization***/

    

    //SPI2用 ピン割り付け(リマップ)
    RPG8Rbits.RPG8R = 0b0110;       //RG8ピンに SDO2の出力を割り付け
    SDI2Rbits.SDI2R = 0b0001;       //RPG7ピンに SDI2(入力)を割り付け




    sysObj.spiObjectIdx0 = DRV_SPI_Initialize(0, (const SYS_MODULE_INIT  * const)&drvSpi0InitData);

    /* Initialize System Services */

    /* Initialize Middleware */

    /* Enable Global Interrupts */
    SYS_INT_Enable();

    /* Initialize the Application */
    APP_Initialize();
}

/*******************************************************************************
 End of File
*/





//以下、spiMem_25LC_lib.h
//------------------------------------------------------------------------------------------------------------
//spiMem_25LC_lib.h

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// SPIフラッシュメモリ 読み書きライブラリ
// 関数
// void ysSPIInitialize(void)   …… 初期化
//
// unsigned char ysSST25ReadByte(unsigned int address)  …… 1バイト読み込み 
//                                  引数:読み込むメモリのアドレス、戻り値:読み込み値
// void ysSST25WriteByte(unsigned char data, unsigned int address) ……1バイト書込み
//                                  第1引数:書込み値、第2引数:書き込むメモリのアドレス
// void ysSST25ReadArray(unsigned int address, unsigned char *pData, unsigned short int nCount)……文字列読み込み
//                                  第1引数:読み込む先頭アドレス、第2引数:読み込んだ文字列のポインタ、第3引数:読込む文字列の長さ
// void ysSST25WriteArray(unsigned int address, unsigned char *pData, unsigned short nCount) ……文字列書込み
//                                  第1引数:書き込む先頭アドレス、第2引数:書き込む文字列のポインタ、書き込む文字列の長さ
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////

//適用SPIメモリ
//マイクロチップ、テキサス他
//25LXXX    例:25L640(64Kビット)
//25LCXXX   例:25LC128(128Kビット)
//25AAXXX   例:25AA512(512Kビット)
//SST25VFXXX    例:SST25VF16B(16Mビット)


//LC25 コマンド
#define ysSST25_CMD_READ  (unsigned)0x03  //Read instruction, 03H,
#define ysSST25_CMD_WRITE (unsigned)0x02  //Page-Program instruction, 02H //To program up to 256 Bytes
#define ysSST25_CMD_WREN  (unsigned)0x06  //Write-Enable (WREN) instruction, 06H,
#define ysSST25_CMD_RDSR  (unsigned)0x05  //Read-Status-Register (RDSR) instruction,05H,
#define ysSST25_CMD_EWSR  (unsigned)0x50  //64 KByte Block-Erase
#define ysSST25_CMD_SER   (unsigned)0x20  //4 KByte Sector-Erase
#define ysSST25_CMD_ERASE (unsigned)0x60  //Chip-Erase
#define ysSST25_CMD_WRSR  (unsigned)0x01  // Write Status Register



//SPIモジュールチャンネル設定
#define SPIXCON SPI2CON         //SPI2コントロールレジスタ設定
#define SPIXSTAT SPI2STAT       //SPI2ステータスレジスタ設定
#define SPIXCONbits SPI2CONbits
#define SPIXSTATbits SPI2STATbits
#define SPIXBUF SPI2BUF         //SPI2バッファレジスタ設定
#define SPIXBRG SPI2BRG         //SPI2ボーレートレジスタ設定


//CS ポート設定
#define ysSST25CSLow()    LATAbits.LATA0 = 0
#define ysSST25CSHigh()   LATAbits.LATA0 = 1






//プロトタイプ宣言
void ysSPIInitialize(void);
void ysSPIPut(unsigned char data);
unsigned char ysSPIGet (void);
unsigned char ysSST25IsWriteBusy(void);
void ysSST25WriteEnable(void);
void ysSST25SectorErase(unsigned int address);
void ysSST25ChipErase(void);
void ysSST25ResetWriteProtection(void);
unsigned char ysSST25ReadByte(unsigned int address);
void ysSST25WriteByte(unsigned char data, unsigned int address);
void ysSST25ReadArray(unsigned int address, unsigned char *pData, unsigned short int nCount);
void ysSST25WriteArray(unsigned int address, unsigned char *pData, unsigned short nCount);







//参考
//SPIフラッシュメモリ 諸元
//16 Mbit SPI Serial Flash    SST25VF016B
//Features
//Single Voltage Read and Write Operations   2.7-3.6V
//Serial Interface Architecture   SPI Compatible: Mode 0 and Mode 3
//High Speed Clock Frequency?   Up to 80 MHz
//Superior Reliability   Endurance: 100,000 Cycles (typical)
//                         Greater than 100 years Data Retention
//Low Power Consumption:   Active Read Current: 10 mA (typical)
//                           Standby Current: 5 μA (typical)
//Flexible Erase Capability   Uniform 4 KByte sectors
//                              Uniform 32 KByte overlay blocks
//                              Uniform 64 KByte overlay blocks
//Fast Erase and Byte-Program:   Chip-Erase Time: 35 ms (typical)
//                                Sector-/Block-Erase Time: 18 ms (typical)
//                                Byte-Program Time: 7 μs (typical)







//以下、spiMem_25LC_lib.c
//---------------------------------------------------------------------------------------------------

//spiMem_25LC_lib.c


#include "spiMem_25LC_lib.h"


# ifndef _MY_INCLUDE_PERIPHERAL
#define   _MY_INCLUDE_PERIPHERAL
#include <peripheral/peripheral.h>
#include <peripheral/ports/plib_ports.h>
#endif



void ysSPIInitialize(void)
{

   //チャンネル諸元設定
    SPIXCON = 0;    //SPIX 無効
    SPIXSTAT = 0;

    SPIXCONbits.FRMEN = 0;      //フレーム化 ディセーブル
    SPIXCONbits.MSTEN = 1;      //マスターモード イネーブル

    SPIXCONbits.CKP = 0;        //クロックの極性: アイドル時 = Low、 アクティブ = High
    SPIXCONbits.CKE = 1;        //クロックエッジ制御: イネーブル// クロックがActive→idleに変化した時データ変化 //Clock Edge control
                                //MCP4822: クロックの立上りエッジでデータ読み込み
    SPIXCONbits.SMP = 1;        //データ抽出タイミング: データの後縁 //Sample phase control
    SPIXCONbits.MODE32 = 0;     //データ幅: 8ビット
    SPIXCONbits.MODE16 = 0;

    SPIXBRG = 49;               //SPIクロック周波数[Hz} = Fpbclk2(ペリフェラルバスクロック)/ 2 x (SPI2BRG + 1)
                                //  = 100MHz /2 /(49 +1) = 1 MHz
    SPIXCONbits.ON = 1;         //SPI2 有効

}

void ysSPIPut(unsigned char data)
{
    while(!SPIXSTATbits.SPITBE);    //送信バッファーが空になるまで待つ
    SPIXBUF = data;     //送受信バッファにデータを書き込む
    while(!SPIXSTATbits.SPIRBF);    //RX FIFOが空になるまでするまで待つ

    return;
}


unsigned char ysSPIGet (void)
{
    unsigned char spiData = 0;

    spiData = SPIXBUF;  //送受信バッファのデータを読込む
    return spiData;
}


unsigned char ysSST25IsWriteBusy(void)
{
    unsigned char    temp;

    ysSPIInitialize();  //SPIモジュール初期化
    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_RDSR);
    ysSPIGet();

    ysSPIPut(0);  //ダミーを送信
    temp = ysSPIGet();

    ysSST25CSHigh();
    return (temp & 0x01);

}



void ysSST25WriteEnable(void)
{

    ysSPIInitialize();  //SPIモジュール初期化
    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_WREN);
    ysSPIGet();
    ysSST25CSHigh();

}

void ysSST25SectorErase(unsigned int address)     //セクタ消去  //消去セクタ--> FFH    //消去するセクタは 最初に送信されるMSBにより決まる
{
    ysSST25WriteEnable();

    ysSPIInitialize();  //SPIモジュール初期化
    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_SER);
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x00FF0000) >> 16));   //書込みアドレスの第2バイト(MSB)送信 //SPIPut(((DWORD_VAL) address).v[2]);
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x0000FF00) >> 8 ));     //書込みアドレスの第1バイト送信 //SPIPut(((DWORD_VAL) address).v[1])
    ysSPIGet();

    ysSPIPut((unsigned char)(address & 0x000000FF));             //書込みアドレスの第0バイト(LSB)送信 //SPIPut(((DWORD_VAL) address).v[0]);
    ysSPIGet();

    ysSST25CSHigh();

    // Wait for write end
    while(ysSST25IsWriteBusy());
}





void ysSST25ChipErase(void)   //全チップ消去    //全データ --> FFH
{
    ysSST25WriteEnable();  //追加

    ysSST25CSLow();

    ysSPIInitialize();//SPIモジュール初期化

    ysSPIPut(ysSST25_CMD_ERASE);
    ysSPIGet();

    ysSST25CSHigh();

    while(ysSST25IsWriteBusy());

}


void ysSST25ResetWriteProtection(void)  //ライトプロテクトリセット
{
     ysSPIInitialize();     //SPIモジュール初期化

    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_EWSR); //書込みイネーブル  // send write enable command
                                //The Enable-Write-Status-Register (EWSR) instruction arms the Write-Status-Register (WRSR)instruction and opens the status register for alteration.
    ysSPIGet();

    ysSST25CSHigh();
    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_WRSR); //ステータスレジスタ(WRSR)書換えコマンド送信
                                //The Write-Status-Register instruction writes new values to the BP3, BP2, BP1, BP0, and BPL bits of the status register.
    ysSPIGet();

    ysSPIPut(0);    //ステータスレジスタ クリア --> BP3, BP2, BP1, BP0 = 0 --> ライトプロテクト解除
    ysSPIGet();

    ysSST25CSHigh();

    while(ysSST25IsWriteBusy());    // Wait for write end
}




unsigned char ysSST25ReadByte(unsigned int address) //1バイト読み込み
{
    unsigned char    temp;


    ysSPIInitialize();      //SPIモジュール初期化
    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_READ);
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x00FF0000) >> 16));   //書込みアドレスの第2バイト(MSB)送信 //SPIPut(((DWORD_VAL) address).v[2]);
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x0000FF00) >> 8 ));     //書込みアドレスの第1バイト送信 //SPIPut(((DWORD_VAL) address).v[1])
    ysSPIGet();

    ysSPIPut((unsigned char)(address & 0x000000FF));             //書込みアドレスの第0バイト(LSB)送信 //SPIPut(((DWORD_VAL) address).v[0]);
    ysSPIGet();

    ysSPIPut(0);  //ダミーを送信
    temp = ysSPIGet();

    ysSST25CSHigh();

    return (temp);

}







void ysSST25WriteByte(unsigned char data, unsigned int address)     //1バイト書込み
{
    ysSST25WriteEnable();

    ysSPIInitialize();    //SPIモジュール初期化
    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_WRITE);
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x00FF0000) >> 16));   //書込みアドレスの第2バイト(MSB)送信 //SPIPut(((DWORD_VAL) address).v[2]);
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x0000FF00) >> 8 ));     //書込みアドレスの第1バイト送信 //SPIPut(((DWORD_VAL) address).v[1])
    ysSPIGet();

    ysSPIPut((unsigned char)(address & 0x000000FF));             //書込みアドレスの第0バイト(LSB)送信 //SPIPut(((DWORD_VAL) address).v[0]);
    ysSPIGet();

    ysSPIPut(data);   //データ(unsigned char)を送信
    ysSPIGet();

    ysSST25CSHigh();

    // Wait for write end
    while(ysSST25IsWriteBusy());


}





void ysSST25WriteArray(unsigned int address, unsigned char *pData, unsigned short nCount)  //文字列書込み
{
    unsigned int   addr;
    unsigned char    *pD;
    unsigned short    counter;


    addr = address;
    pD = pData;

    // WRITE
    for(counter = 0; counter < nCount; counter++)
    {
        ysSST25WriteByte(*pD++, addr++);
    }

}


void ysSST25ReadArray(unsigned int address, unsigned char *pData, unsigned short int nCount)    //文字列読み込み
{
    ysSPIInitialize();//SPIモジュール初期化

    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_READ);
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x00FF0000) >> 16));   //書込みアドレスの第2バイト(MSB)送信 //SPIPut(((DWORD_VAL) address).v[2]);
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x0000FF00) >> 8 ));     //書込みアドレスの第1バイト送信 //SPIPut(((DWORD_VAL) address).v[1])
    ysSPIGet();

    ysSPIPut((unsigned char)(address & 0x000000FF));             //書込みアドレスの第0バイト(LSB)送信 //SPIPut(((DWORD_VAL) address).v[0]);
    ysSPIGet();

    while(nCount--)
    {
        ysSPIPut(0);
        *pData++ = ysSPIGet();
    }

    ysSST25CSHigh();
}





//以下、1lcd_lib_C32.h
//------------------------------------------------------------------------------------------------

//*************************************************************************
//インクルードファイル    1lcd_lib_C32.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//*************************************************************************
#include <p32xxxx.h>
#define lcd_Clock   200000000        // 単位はHzで指定


// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB13 //のDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_rs          LATAbits.LATA9  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定
#define lcd_stb         LATAbits.LATA10 //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定



void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);





//以下、1lcd_lib_C32.c
//-------------------------------------------------------------------------------------------------------
//**************************************************************************
//インクルードファイル    1lcd_lib_C32.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C32コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C32.h"

void lcd_delay_us(unsigned int usec)    //1μsec遅延関数
{
        int count;

        count = (int)(lcd_Clock/20000000)*usec;

        do      //実測: at 200MH (Clock=200000000)
        {       //delay_us(1000)→1000.4μsec、 delay_us(100)→100.6μsec、delay_us(10)→10.5μsec、delay_us(1)→1.5μsec
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

                count--;
        }while(count != 0);
        

}

void lcd_delay_ms(unsigned int msec)    //1msec遅延関数
{
        unsigned int i;
        
        for(i=0; i<msec; i++)
        lcd_delay_us(1000);
}


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        lcd_delay_us(3);                //1μsecウェイト
//      lcd_delay_us(1);                //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
        lcd_delay_us(3);                //1μsecウェイト
//      lcd_delay_us(1);                // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        lcd_delay_us(50);               //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        lcd_delay_ms(2);        //      2msec待ち
        else
        lcd_delay_us(50);       //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_delay_ms(20);               //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(5);                //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}






 

 <動作結果>


  表示内容 液晶表示  備考 
 @  最初の読み書き後の表示   
A 2番目の読み書き後の表示   
B 3番目の読み書き後の表示   





★ SDカード読み書き(EOF)                   <dsPIC   C30編>
 書き込んだデータをすぺて読み出す例を以下に紹介します。FSfread( )の戻り値は読み込んだブロック数です。以下の例
では読み込もうとした時0が戻ってきたら(エラーの場合もありますが)ファイルエンド(End OF File)と判断しています。

<試作品の仕様>
 ・500msecごとにSDカードに整数を書き込む
 ・500msec毎の読み出しをおこない、SDカードのデータをすべて読み出す
 ・読み出したデータを読み出した順番に液晶1行目の左から順番に表示する。5つめから8つめまでのデータは2行目の
  左から順番にならべる。

<試作品の回路図> (→ 回路図のPDFファイル



<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

   <プログラム例>   

///**************************************************************************************************/
//       SDカード書き込み 及び 読み出し                File Name: SD R_W Basic3 4013.c
//              EOF
//                                       dsPIC30F4013
//****************************************************************************************************/
// MPLAB プロジェクトへの追加ファイル
// Source Filesフォルダ   FSIO.c
//                    SD-SPI.c
//                    1lcd_lib_C30.c
//                    SD R_W Basic3 4013.c
// Header Filesフォルダ   FScohfig.h
//                    FSDefs.h
//                    FSIO.h
//                    GenericTypeDefs.h
//                    SD-SPI.h
//                    1lcd_lib_C30.h
// Linker Scriptフォルダ  p30f2012.gld
// Library Filesフォルダ  lib30F2012-coff.a


#include        "p30f4013.h"
#include        "1lcd_lib_C30.h"
#include        <stdio.h>
#include        <timer.h>

#include        "FSIO.h"


_FOSC(CSW_FSCM_OFF & XT_PLL8);                  // 10MHzx8=80MHz

_FWDT(WDT_OFF);
_FBORPOR(PBOR_ON & BORV_20              //2V:BORV_20  2.7V:BORV_27  4.2V:BORV_42  4.5V:BORV_45
                & PWRT_64 & MCLR_EN);
_FGS(CODE_PROT_OFF); 


char Buf[17];                           //文字列のバッファー用レジスタ
unsigned int Buf_Input[1];              //AD読込みのホールド値&SDカード書き込み値
unsigned int Buf_Output[1];     //SDカード読込み値
unsigned int SD[20];

char blk = ' ';                         //ブランク
int N_Write;                            //書き込み回数戻り値
unsigned int N_Read;            //読み出し回数戻り値
FSFILE* pfile;                          //SDカードのファイルポインタ
unsigned int ix = 0,iy = 0;
int Mode_SD = 0;        //


///プロトタイプ関数
void delay_ms(unsigned int);


//-------------------------------------------------------

void delay_ms(unsigned int N)                   //ウェイト関数
{
        __delay32(Clock/4000*N);
}

void _ISR _T1Interrupt(void)    //500msec毎の割込み発生
{
        IFS0bits.T1IF = 0;                      //IFS0レジスタの T1IF(タイマ1の割込み検出)フラグリセット

        if(Mode_SD == 0)        //SDカードへ書き込みの場合
        {
                Buf_Input[0] = 100 * (ix +1);   //書き込みデータをセット
                N_Write = FSfwrite((const void*)Buf_Input,sizeof(unsigned int),1,pfile);//ファイルにデータ書き込み
                if(N_Write == 1)        //正常な場合:書き込み回数が返ってくる
                {
                        lcd_clear();    
                        sprintf(Buf,"Write No%d OK !!",ix);     //液晶に"Write OK !" を表示
                        lcd_str(Buf);
                        delay_ms(100);
                }
                else    //異常な場合
                {
                        lcd_clear();    
                        sprintf(Buf,"Write No%d NG !!",ix);     //液晶に"Write NG !" を表示
                        lcd_str(Buf);
                        return 0;
                }
        
                ix++;
        }
        else    //SDカードから読み込みの場合
        {
        
                N_Read = FSfread(Buf_Output,sizeof(unsigned int),1,pfile);//ファイルからデータ読込み
                        if(N_Read != 0)
                        {
                                SD[iy] = Buf_Output[0];
                                iy++;
                        }
        }
}

        

/// メイン関数
int     main(void)
{
        int i;
        //// ポート入出力モード設定
        TRISB = 0b0000000000000000;     // in : 
        TRISC = 0b0100000000000000;     // in : RC14(Hold SW)
        TRISD = 0b0000000000000011;     // in : RD0(CD) RD1(WE) 
        TRISF = 0b0000000000000100;     // in : RF2(SDI)


/// タイマ1周期 10msec
///     bit15:タイマOn制御ビット bit14:未実装 ビット13
        OpenTimer1(T1_ON  &                             //タイマ1ON
                                T1_GATE_OFF     &               //ゲート制御off
                                T1_PS_1_256 &           //プリスケーラ 1/256
                                T1_SYNC_EXT_OFF &       //クロック同期制御OFF
                                T1_SOURCE_INT   ,       //クロック源:内部クロック
                                80000000/4/2/256 - 1    //2Hz → 500msec毎の割込み  
                                );


        lcd_init();                                                     // LCD初期化
        lcd_cmd(0b00001100);                            // カーソル:OFF  ブリンク:OFF

        lcd_clear();                                            // 全消去
        sprintf(Buf,"SD R/W  INT !!%c",blk);//arguementがないと遅い  C30のバグ?
        lcd_str(Buf);                                           //液晶表示
        delay_ms(1000); 

        for(i = 0; i < 20; i++)SD[i] = 0;       //SD[i]の値:0リセット

        PORTFbits.RF5 = 0;                      //CS=0 SDカードのチップセレクトenable 
        LATDbits.LATD2 = 1;

        while(!FSInit());                       //SDカードイニシャライズ SDカードの実装とフォーマット済をチェック

        pfile = FSfopen("DATA.DAT","w");        //ファイル書き込みモードでオープン 但しファイルがなければ新規ファイル作成

        Mode_SD = 0;
        ix = 0;
        ConfigIntTimer1(T1_INT_PRIOR_7 & T1_INT_ON);    //割込みレベル5 タイマ1割込みON
        EnableIntT1;                                                                    //割込み許可

        do
        {
        }while(ix < 6);                 // 6個の符号なし整数(2バイト)データをSDカードに書き込むまで繰り返す

        DisableIntT1;
        FSfclose(pfile);        //      ファイルを閉じる

        pfile = FSfopen("DATA.DAT","r");        //ファイル読込みモードでオープン 

        Mode_SD = 1;
        iy = 0;
        N_Read = 1;             //0だとwhile(N_Read !=0)が割込みが入る前に真となりループを抜けてしまう
        EnableIntT1;    //タイマ1割込み許可
        do
        {
        }while(N_Read !=0);                             //N_ReaDに0が戻ってくる(EOF)まで待つ
        

        FSfclose(pfile);        //      ファイルを閉じる
        DisableIntT1;
        PORTFbits.RF5 = 1;      // CS = 1 

        lcd_clear();
        sprintf(Buf,"%u %u %u %u ",SD[0],SD[1],SD[2],SD[3]);//SDカードから読み込んだデータを液晶に表示
        lcd_str(Buf);
        lcd_cmd(0xC0);//2行目の先頭へ
        sprintf(Buf,"%u %u %u %u ",SD[4],SD[5],SD[6],SD[7]);//SDカードから読み込んだデータを液晶に表示
        lcd_str(Buf);

        while(1);

        return 0;
}
//**************************************************************************
//インクルードファイル    1lcd_lib_C30.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C30コンパイラー
//  内蔵関数は以下
//  lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//  lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C30.h"
unsigned int _1usec;    // 1μsec待つに必要なウェイト回数
unsigned int _50usec;   //50μsec待つに必要なウェイト回数
unsigned long N_msec;   // 1msec待つに必要なウェイト回数



//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;             // 表示データの場合
        else
                lcd_rs = 0;             // コマンドデータの場合

        __delay32(_1usec);              //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        __delay32(_1usec);              // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);            // 下位4ビット出力
        __delay32(_50usec);             //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)           // clear Homeの場合
        __delay32(2*N_msec);            //      2msec待ち
        else
        __delay32(_50usec);             //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
//      __delay32(15*N_msec);           //15msecウェイト
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                     //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                  //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        _1usec =(unsigned int)( Clock / 4000000);       // 1μsecに要するウェイト回数
                                                        //__delay32(N) : Nが11以下の場合でも11回ウェイト
        _50usec = (unsigned int)(Clock / 4000000 * 50); //50μescに要するウェイト回数

        N_msec = (unsigned long int)(Clock / 4000);     // 1msecに要するウェイト回数
                                                        // = Clock / 4000000*1000
        __delay32(20*N_msec);           //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(5*N_msec);            //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}



*************************************************************************************************   
*************************************************************************************************   
***                                              ***
***      その他のインクルードファイルは                                                       ***
***          「C言語ではじめるPIC24F活用ガイドブック」(後閑哲也 著 技術評論社)             ***
***                                        の付属CDに収納されています。     ***
*************************************************************************************************   
*************************************************************************************************   


//************************************************************************************************
//************************************************************************************************
//以下は インクルードファイル SD-SPI.hの中で変更部位のみを抜粋したものです。 ピンアサイン関係の
 変更です。
// 
    …
    …
/********************************************************************/
/*                Pin and register definitions                      */
/********************************************************************/

#define SD_CS                           PORTFbits.RF5
#define SD_CS_TRIS                      TRISFbits.TRISF5
#define SD_CD                           PORTDbits.RD0
#define SD_CD_TRIS                      TRISDbits.TRISD0
#define SD_WE                           PORTDbits.RD1
#define SD_WE_TRIS                      TRISDbits.TRISD1

// Registers for the SPI module you want to use
#define SPICON1                         SPI1CON
#define SPISTAT                         SPI1STAT
#define SPIBUF                          SPI1BUF
#define SPISTAT_RBF                     SPI1STATbits.SPIRBF
#define SPICON1bits                     SPI1CONbits
#define SPISTATbits                     SPI1STATbits
// Tris pins for SCK/SDI/SDO lines
#define SPICLOCK        TRISFbits.TRISF6        
#define SPIIN   TRISFbits.TRISF2        
#define SPIOUT  TRISFbits.TRISF3

 …
 …


//************************************************************************************************
//************************************************************************************************
// 以下は インクルードファイル SD-SPI.cの中で修正した部分のみを抜粋したものです。
// SDカードのソケットにより書き込みプロテクトの論理が異なるものがあるようです。
//                           (後閑さんにおしえていただきました)
// わたしが使用したSDカードソケットはサンハヤト鰍フCK29です。CK29のライトプロテクトWEの論理は // ”ライトプロテクトが書き込み可能な位置にあるSDカードを奥まで挿入すると ON ”です。すなわち // 以下の場合 SDカードのWEはOFFです。 //    ・SDカードが挿入されていない場合 //    ・ライトプロテクトが書き込み不可の位置にあるSDカードが奥まで挿入されている場合
//
// 以下は修正前のソースコードです。SDカードの検出チェックの部分です。修正したものは SD_WEの // 前の”!”が削除されています。 //  // BYTE // WriteProtectState(void)
// {
//   return(!SD_WE); // 修正後は”!”が削除されています。
// }
// // // // 以下は修正後のソースコードです。 BYTE WriteProtectState(void)
{
   return(SD_WE); // ”!”が削除されています。
}



//*********************************************************************************************************
//*************************************************************************************************:********

 // 以下はFSconfig.hファイルの中で変更した部分のみを記載しています。システムクロックを20MHzから80MHzに変更
 //したことに伴う変更です

// Define the system clock speed
//#define SYSTEM_CLOCK (DWORD)20000000
#define SYSTEM_CLOCK (DWORD)80000000





<動作結果>
  6個のデータを書き込んだあと、FSfread( ) で6個のデータすべてを読み出した結果を下記に示します。




★ SDカード読み書き(EOF)                   <PIC32MX編>
 
<試作品の仕様>
 ・500msecごとにSDカードに整数を書き込む
 ・500msec毎の読み出しをおこない、SDカードのデータをすべて読み出す
 ・読み出したデータを読み出した順番に液晶1行目の左から順番に表示する。5つめから8つめまでのデータは2行目の
  左から順番にならべる。

<試作品の回路図> (→ 回路図のPDFファイル

<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

          

<プログラム例>



 



//    SDカード読書き EOF
//                 PIC32MX460F512L 

#include <proc/p32mx460f512l.h>         //PIC32MX460F512L
#include <plib.h>               // PIC32 peripheral library 
                                                        //for SYSTEMConfigPerformance()


#include        "1lcd_lib_C32.h"

#include        "FSIO.h"

// コンフィギュレーション設定
// CPU=80MHz Peri=80MHz,HS+PLL,Divider=1/2,PLL=x20,WDT=Off
#pragma config FNOSC=PRIPLL, POSCMOD=HS, FPLLIDIV=DIV_2
#pragma config FPLLMUL=MUL_20, FPBDIV=DIV_1, FPLLODIV=DIV_1
#pragma config FWDTEN=OFF, ICESEL=ICS_PGx2


char Buf[17];   //文字列のバッファー用レジスタ
unsigned int Buf_Input[1];              //AD読込みのホールド値&SDカード書き込み値
unsigned int Buf_Output[1];     //SDカード読込み値
unsigned int SD[20];

int N_Write;                            //書き込み回数戻り値

FSFILE* pfile;                          //SDカードのファイルポインタ
unsigned int N_Read;            //読み出し回数戻り値
unsigned int ix = 0,iy = 0;
int Mode_SD = 0;        //




void delay_us(unsigned int usec)        //1μsec遅延関数
{
        int count;
        count = (int)(Clock/20000000)*usec;
        do      //実測: at Clock=80000000
        {       //delay_us(1000)→1003μsec、 delay_us(100)→102μsec、delay_us(10)→11μsec、delay_us(1)→1.6μsec
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                count--;        
        }while(count != 0);
}

void delay_ms(unsigned int msec)        //1msec遅延関数
{
        unsigned int i;
        
        for(i=0; i<msec; i++)
        delay_us(1000);
}


void __ISR(20,ipl2)T45Hander(void)      //タイマ4+5 32bitタイマ割り込み 500msec毎
{
        mT5ClearIntFlag();  //フラグクリア

        if(Mode_SD == 0)        //SDカードへ書き込みの場合
        {
                Buf_Input[0] = 100 * (ix +1);   //書き込みデータをセット
                N_Write = FSfwrite((const void*)Buf_Input,sizeof(unsigned int),1,pfile);//ファイルにデータ書き込み
                if(N_Write == 1)        //正常な場合:書き込み回数が返ってくる
                {
                        lcd_clear();    
                        sprintf(Buf,"Write No%d OK !!",ix);     //液晶に"Write OK !" を表示
                        lcd_str(Buf);
                        delay_ms(100);
                }
                else    //異常な場合
                {
                        lcd_clear();    
                        sprintf(Buf,"Write No%d NG !!",ix);     //液晶に"Write NG !" を表示
                        lcd_str(Buf);
                        return 0;
                }
        
                ix++;
        }
        else    //SDカードから読み込みの場合
        {
        
                N_Read = FSfread(Buf_Output,sizeof(unsigned int),1,pfile);//ファイルからデータ読込み
                        if(N_Read != 0)
                        {
                                SD[iy] = Buf_Output[0];
                                iy++;
                        }
        }
}






int main(void)
{
        int i;
        SYSTEMConfigPerformance(80000000);      // システム最適化

        TRISC = 0;              //Cポートを出力モードに設定
        TRISE = 0;              //Eポートを出力モードに設定
        DDPCONbits.JTAGEN = 0;//  

        lcd_init();                                                     // LCD初期化
        lcd_cmd(0b00001100);                            // カーソル:OFF  ブリンク:OFF

        lcd_clear();                                            // 全消去
        sprintf(Buf,"SD EOF !!");//
        lcd_str(Buf);                                           //液晶表示
        delay_ms(1000); 


        OpenTimer45(T45_ON |    //      タイマ1 イネーブル  //T1_OFF → タイマ1 ディセーブル
                                        T45_SOURCE_INT |        //クロックソース:インターナル //T1_SOURCE_EXT → 外部発振器
                                        T45_PS_1_256,   //プリスケール 1/256   //1/1、1/2、1/4、1/8、1/16、1/32、1/64、1/256
                                        156246                  //PRx値:  T0[msec] = 1000/80000000*256*156246 = 499.987 msec
                                                                        //PICMX32は1クロックで1命令
                                                                        //周期 T0[sec] = 1/Fosc × プリスケーラの逆数 × PRx値
                                );


        for(i = 0; i < 20; i++)SD[i] = 0;       //SD[i]の値:0リセット

        LATCbits.LATC3 = 0;             //CS=0 SDカードのチップセレクトenable 
        while(!FSInit());               //SDカードイニシャライズ SDカードの実装とフォーマット済をチェック

        pfile = FSfopen("DATA.DAT","w");        //ファイル書き込みモードでオープン 但しファイルがなければ新規ファイル作成
        Mode_SD = 0;
        ix = 0;

        ConfigIntTimer45(T45_INT_ON | T45_INT_PRIOR_2); //タイマ1割込ON、割り込みレベル2
        INTEnableSystemMultiVectoredInt();      //割り込みをマルチベクタモードで許可
        
        do
        {
        }while(ix < 6);                 // 6個の符号なし整数(2バイト)データをSDカードに書き込むまで繰り返す

        DisableIntT45;                  //タイマ45割込み禁止

        FSfclose(pfile);        //      ファイルを閉じる


        pfile = FSfopen("DATA.DAT","r");        //ファイル読込みモードでオープン 

        Mode_SD = 1;
        iy = 0;
        N_Read = 1;             //0だとwhile(N_Read !=0)が割込みが入る前に真となりループを抜けてしまう
        EnableIntT45;    //タイマ45割込み許可
        do
        {
        }while(N_Read !=0);                             //N_ReaDに0が戻ってくる(EOF)まで待つ
        
        FSfclose(pfile);        //      ファイルを閉じる
        DisableIntT45;

        LATCbits.LATC3 = 1;             //CS=1 SDカードのチップセレクトdisable 
        
        lcd_clear();
        sprintf(Buf,"%u %u %u %u ",SD[0],SD[1],SD[2],SD[3]);//SDカードから読み込んだデータを液晶に表示
        lcd_str(Buf);
        lcd_cmd(0xC0);//2行目の先頭へ
        sprintf(Buf,"%u %u %u %u ",SD[4],SD[5],SD[6],SD[7]);//SDカードから読み込んだデータを液晶に表示
        lcd_str(Buf);

        while(1);
        return 0;
}


//*************************************************************************
//インクルードファイル    1lcd_lib_C32.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//*************************************************************************

#include <proc/p32mx460f512l.h>         //PIC32MX460F512L

#define Clock   80000000        // 単位はHzで指定


// LCDポート設定
#define lcd_port_DB7    LATEbits.LATE7  //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATEbits.LATE6  //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATEbits.LATE5  //LCDのDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATEbits.LATE4  //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_stb                 LATEbits.LATE3  //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定  
#define lcd_rs                  LATEbits.LATE2  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定


void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);



//**************************************************************************
//インクルードファイル    1lcd_lib_C32.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C32コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C32.h"

void lcd_delay_us(unsigned int usec)    //1μsec遅延関数
{
        int count;

        count = (int)(Clock/20000000)*usec;
        do
        {
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                count--;        
        }while(count != 0);
}

void lcd_delay_ms(unsigned int msec)    //1msec遅延関数
{
        unsigned int i;
        
        for(i=0; i<msec; i++)
        lcd_delay_us(1000);
}


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        lcd_delay_us(1);                //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        lcd_delay_us(1);                // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        lcd_delay_us(50);               //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        lcd_delay_ms(2);        //      2msec待ち
        else
        lcd_delay_us(50);       //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_delay_ms(20);               //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(5);                //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}



//HardwareProfile.h にピンアサイン変更の修正をおこないます。
/******************************************************************************
 *
 *                Microchip Memory Disk Drive File System
 *
 ******************************************************************************
 * FileName:        HardwareProfile.h
 * Dependencies:    None
 * Processor:       PIC18/PIC24/dsPIC30/dsPIC33/PIC32
 * Compiler:        C18/C30/C32
 * Company:         Microchip Technology, Inc.
 *
 * Software License Agreement
 *
 * The software supplied herewith by Microchip Technology Incorporated
 * (the 鼎ompany・ for its PICmicroョ Microcontroller is intended and
 * supplied to you, the Company痴 customer, for use solely and
 * exclusively on Microchip PICmicro Microcontroller products. The
 * software is owned by the Company and/or its supplier, and is
 * protected under applicable copyright laws. All rights are reserved.
 * Any use in violation of the foregoing restrictions may subject the
 * user to criminal sanctions under applicable laws, as well as to
 * civil liability for the breach of the terms and conditions of this
 * license.
 *
 * THIS SOFTWARE IS PROVIDED IN AN 鄭S IS・CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
*****************************************************************************/


#ifndef _HARDWAREPROFILE_H_
#define _HARDWAREPROFILE_H_

// Define your clock speed here

// Sample clock speed for PIC18
#if defined (__18CXX)

    #define GetSystemClock()        40000000                        // System clock frequency (Hz)
    #define GetPeripheralClock()    GetSystemClock()                // Peripheral clock freq.
    #define GetInstructionClock()   (GetSystemClock() / 4)          // Instruction clock freq.

// Sample clock speed for a 16-bit processor
#elif defined (__C30__)

    #define GetSystemClock()        32000000
    #define GetPeripheralClock()    GetSystemClock()
    #define GetInstructionClock()   (GetSystemClock() / 2)

    // Clock values
    #define MILLISECONDS_PER_TICK       10                      // Definition for use with a tick timer
    #define TIMER_PRESCALER             TIMER_PRESCALER_8       // Definition for use with a tick timer
    #define TIMER_PERIOD                20000                   // Definition for use with a tick timer

// Sample clock speed for a 32-bit processor
#elif defined (__PIC32MX__)

    // Indicates that the PIC32 clock is running at 48 MHz
    //#define RUN_AT_48MHZ
    // Indicates that the PIC32 clock is running at 24 MHz
    //#define RUN_AT_24MHZ
    // Indicates that the PIC32 clock is running at 80 MHz
    #define RUN_AT_80MHZ

    // Various clock values

    #if defined(RUN_AT_48MHZ)
        #define GetSystemClock()            48000000UL              // System clock frequency (Hz)
        #define GetPeripheralClock()        48000000UL              // Peripheral clock frequency
        #define GetInstructionClock()       (GetSystemClock())      // Instruction clock frequency
    #elif defined(RUN_AT_24MHZ)
        #define GetSystemClock()            24000000UL
        #define GetPeripheralClock()        24000000UL
        #define GetInstructionClock()       (GetSystemClock())
    #elif defined(RUN_AT_80MHZ)    
        #define GetSystemClock()            (80000000ul)
        #define GetPeripheralClock()        (GetSystemClock()/2) 
        #define GetInstructionClock()       (GetSystemClock())
    #else
        #error Choose a speed
    #endif

    // Clock values

    #define MILLISECONDS_PER_TICK       10                  // Definition for use with a tick timer
    #define TIMER_PRESCALER             TIMER_PRESCALER_8   // Definition for use with a tick timer
    #define TIMER_PERIOD                37500               // Definition for use with a tick timer
#endif
    




// Select your interface type
// This library currently only supports a single physical interface layer at a time


// Description: Macro used to enable the SD-SPI physical layer (SD-SPI.c and .h)
#define USE_SD_INTERFACE_WITH_SPI

// Description: Macro used to enable the CF-PMP physical layer (CF-PMP.c and .h)
//#define USE_CF_INTERFACE_WITH_PMP

// Description: Macro used to enable the CF-Manual physical layer (CF-Bit transaction.c and .h)                                                                
//#define USE_MANUAL_CF_INTERFACE

// Description: Macro used to enable the USB Host physical layer (USB host MSD library)
//#define USE_USB_INTERFACE


/*********************************************************************/
/******************* Pin and Register Definitions ********************/
/*********************************************************************/

/* SD Card definitions: Change these to fit your application when using
   an SD-card-based physical layer                                   */

#ifdef USE_SD_INTERFACE_WITH_SPI
    #ifdef __18CXX
    
        // Sample definition for PIC18 (modify to fit your own project)

        // Description: SD-SPI Chip Select Output bit
        #define SD_CS               LATBbits.LATB3
        // Description: SD-SPI Chip Select TRIS bit
        #define SD_CS_TRIS          TRISBbits.TRISB3
        
        // Description: SD-SPI Card Detect Input bit
        #define SD_CD               PORTBbits.RB4
        // Description: SD-SPI Card Detect TRIS bit
        #define SD_CD_TRIS          TRISBbits.TRISB4
        
        // Description: SD-SPI Write Protect Check Input bit
        #define SD_WE               PORTAbits.RA4
        // Description: SD-SPI Write Protect Check TRIS bit
        #define SD_WE_TRIS          TRISAbits.TRISA4
        
        // Registers for the SPI module you want to use

        // Description: The main SPI control register
        #define SPICON1             SSP1CON1
        // Description: The SPI status register
        #define SPISTAT             SSP1STAT
        // Description: The SPI buffer
        #define SPIBUF              SSP1BUF
        // Description: The receive buffer full bit in the SPI status register
        #define SPISTAT_RBF         SSP1STATbits.BF
        // Description: The bitwise define for the SPI control register (i.e. _____bits)
        #define SPICON1bits         SSP1CON1bits
        // Description: The bitwise define for the SPI status register (i.e. _____bits)
        #define SPISTATbits         SSP1STATbits

        // Description: The interrupt flag for the SPI module
        #define SPI_INTERRUPT_FLAG  PIR1bits.SSPIF   
        // Description: The enable bit for the SPI module
        #define SPIENABLE           SPICON1bits.SSPEN

/*
        // Defines for the FS-USB demo board

        // Tris pins for SCK/SDI/SDO lines
        #define SPICLOCK            TRISBbits.TRISB1
        #define SPIIN               TRISBbits.TRISB0
        #define SPIOUT              TRISCbits.TRISC7

        // Latch pins for SCK/SDI/SDO lines
        #define SPICLOCKLAT         LATBbits.LATB1
        #define SPIINLAT            LATBbits.LATB0
        #define SPIOUTLAT           LATCbits.LATC7

        // Port pins for SCK/SDI/SDO lines
        #define SPICLOCKPORT        PORTBbits.RB1
        #define SPIINPORT           PORTBbits.RB0
        #define SPIOUTPORT          PORTCbits.RC7
*/

        // Defines for the HPC Explorer board

        // Description: The TRIS bit for the SCK pin
        #define SPICLOCK            TRISCbits.TRISC3
        // Description: The TRIS bit for the SDI pin
        #define SPIIN               TRISCbits.TRISC4
        // Description: The TRIS bit for the SDO pin
        #define SPIOUT              TRISCbits.TRISC5

        // Description: The output latch for the SCK pin
        #define SPICLOCKLAT         LATCbits.LATC3
        // Description: The output latch for the SDI pin
        #define SPIINLAT            LATCbits.LATC4
        // Description: The output latch for the SDO pin
        #define SPIOUTLAT           LATCbits.LATC5

        // Description: The port for the SCK pin
        #define SPICLOCKPORT        PORTCbits.RC3
        // Description: The port for the SDI pin
        #define SPIINPORT           PORTCbits.RC4
        // Description: The port for the SDO pin
        #define SPIOUTPORT          PORTCbits.RC5


        // Will generate an error if the clock speed is too low to interface to the card
        #if (GetSystemClock() < 400000)
            #error System clock speed must exceed 400 kHz
        #endif

    #elif defined __PIC24F__

        // Description: SD-SPI Chip Select Output bit
        #define SD_CS                           LATBbits.LATB1
        // Description: SD-SPI Chip Select TRIS bit
        #define SD_CS_TRIS                      TRISBbits.TRISB1
        
        // Description: SD-SPI Card Detect Input bit
        #define SD_CD               PORTFbits.RF0
        // Description: SD-SPI Card Detect TRIS bit
        #define SD_CD_TRIS          TRISFbits.TRISF0
        
        // Description: SD-SPI Write Protect Check Input bit
        #define SD_WE               PORTFbits.RF1
        // Description: SD-SPI Write Protect Check TRIS bit
        #define SD_WE_TRIS          TRISFbits.TRISF1
        
        // Registers for the SPI module you want to use

        // Description: The main SPI control register
        #define SPICON1             SPI1CON1
        // Description: The SPI status register
        #define SPISTAT             SPI1STAT
        // Description: The SPI Buffer
        #define SPIBUF              SPI1BUF
        // Description: The receive buffer full bit in the SPI status register
        #define SPISTAT_RBF         SPI1STATbits.SPIRBF
        // Description: The bitwise define for the SPI control register (i.e. _____bits)
        #define SPICON1bits         SPI1CON1bits
        // Description: The bitwise define for the SPI status register (i.e. _____bits)
        #define SPISTATbits         SPI1STATbits
        // Description: The enable bit for the SPI module
        #define SPIENABLE           SPISTATbits.SPIEN

        // Tris pins for SCK/SDI/SDO lines

        // Description: The TRIS bit for the SCK pin
        #define SPICLOCK            TRISFbits.TRISF6
        // Description: The TRIS bit for the SDI pin
        #define SPIIN               TRISFbits.TRISF7
        // Description: The TRIS bit for the SDO pin
        #define SPIOUT              TRISFbits.TRISF8

        // Will generate an error if the clock speed is too low to interface to the card
        #if (GetSystemClock() < 100000)
            #error Clock speed must exceed 100 kHz
        #endif    

    #elif defined (__PIC32MX__)
        // Registers for the SPI module you want to use
   //     #define MDD_USE_SPI_1
       #define MDD_USE_SPI_2    //変更箇所

                //SPI Configuration
                #define SPI_START_CFG_1     (PRI_PRESCAL_64_1 | SEC_PRESCAL_8_1 | MASTER_ENABLE_ON | SPI_CKE_ON | SPI_SMP_ON)
        #define SPI_START_CFG_2     (SPI_ENABLE)

        // Define the SPI frequency
        #define SPI_FREQUENCY                   (20000000)
    
        #if defined MDD_USE_SPI_1
            // Description: SD-SPI Chip Select Output bit
                #define SD_CS               LATBbits.LATB1
                // Description: SD-SPI Chip Select TRIS bit
            #define SD_CS_TRIS          TRISBbits.TRISB1
            
            // Description: SD-SPI Card Detect Input bit
            #define SD_CD               PORTFbits.RF0
            // Description: SD-SPI Card Detect TRIS bit
            #define SD_CD_TRIS          TRISFbits.TRISF0

            // Description: SD-SPI Write Protect Check Input bit
            #define SD_WE               PORTFbits.RF1
            // Description: SD-SPI Write Protect Check TRIS bit
            #define SD_WE_TRIS          TRISFbits.TRISF1
                   
            // Description: The main SPI control register
            #define SPICON1             SPI1CON
            // Description: The SPI status register
            #define SPISTAT             SPI1STAT
            // Description: The SPI Buffer
            #define SPIBUF              SPI1BUF
            // Description: The receive buffer full bit in the SPI status register
            #define SPISTAT_RBF         SPI1STATbits.SPIRBF
            // Description: The bitwise define for the SPI control register (i.e. _____bits)
            #define SPICON1bits         SPI1CONbits
            // Description: The bitwise define for the SPI status register (i.e. _____bits)
            #define SPISTATbits         SPI1STATbits
            // Description: The enable bit for the SPI module
            #define SPIENABLE           SPICON1bits.ON
            // Description: The definition for the SPI baud rate generator register (PIC32)
            #define SPIBRG                          SPI1BRG

            // Tris pins for SCK/SDI/SDO lines

            // Description: The TRIS bit for the SCK pin
            #define SPICLOCK            TRISFbits.TRISF6
            // Description: The TRIS bit for the SDI pin
            #define SPIIN               TRISFbits.TRISF7
            // Description: The TRIS bit for the SDO pin
            #define SPIOUT              TRISFbits.TRISF8
            //SPI library functions
            #define putcSPI             putcSPI1
            #define getcSPI             getcSPI1
            #define OpenSPI(config1, config2)   OpenSPI1(config1, config2)
            
        #elif defined MDD_USE_SPI_2
            // Description: SD-SPI Chip Select Output bit
                        #define SD_CS               LATCbits.LATC3              //変更箇所
           // #define SD_CS               LATBbits.LATB9
            // Description: SD-SPI Chip Select TRIS bit
            #define SD_CS_TRIS          TRISCbits.TRISC3        //変更箇所
           //  #define SD_CS_TRIS          TRISBbits.TRISB9
 
                        // Description: SD-SPI Card Detect Input bit
                        #define SD_CD               PORTDbits.RD8               //変更箇所
                    // #define SD_CD            PORTGbits.RG0
            // Description: SD-SPI Card Detect TRIS bit
            #define SD_CD_TRIS          TRISDbits.TRISD8        //変更箇所  
                        //#define SD_CD_TRIS          TRISGbits.TRISG0

                        // Description: SD-SPI Write Protect Check Input bit
            #define SD_WE               PORTDbits.RD9           //変更箇所
                        //      #define SD_WE               PORTGbits.RG1
                // Description: SD-SPI Write Protect Check TRIS bit
            #define SD_WE_TRIS          TRISDbits.TRISD9        //変更箇所
                        //   #define SD_WE_TRIS          TRISGbits.TRISG1
           




 // Description: The main SPI control register
            #define SPICON1             SPI2CON
            // Description: The SPI status register
            #define SPISTAT             SPI2STAT
            // Description: The SPI Buffer
            #define SPIBUF              SPI2BUF
            // Description: The receive buffer full bit in the SPI status register
            #define SPISTAT_RBF         SPI2STATbits.SPIRBF
            // Description: The bitwise define for the SPI control register (i.e. _____bits)
            #define SPICON1bits         SPI2CONbits
            // Description: The bitwise define for the SPI status register (i.e. _____bits)
            #define SPISTATbits         SPI2STATbits
            // Description: The enable bit for the SPI module
            #define SPIENABLE           SPI2CONbits.ON
            // Description: The definition for the SPI baud rate generator register (PIC32)
            #define SPIBRG                          SPI2BRG

            // Tris pins for SCK/SDI/SDO lines

            // Description: The TRIS bit for the SCK pin
            #define SPICLOCK            TRISGbits.TRISG6
            // Description: The TRIS bit for the SDI pin
            #define SPIIN               TRISGbits.TRISG7
            // Description: The TRIS bit for the SDO pin
            #define SPIOUT              TRISGbits.TRISG8
            //SPI library functions
            #define putcSPI             putcSPI2
            #define getcSPI             getcSPI2
            #define OpenSPI(config1, config2)   OpenSPI2(config1, config2)
        #endif       
        // Will generate an error if the clock speed is too low to interface to the card
        #if (GetSystemClock() < 100000)
            #error Clock speed must exceed 100 kHz
        #endif    
    
    #endif

#endif


#ifdef USE_CF_INTERFACE_WITH_PMP

    /* CompactFlash-PMP card definitions: change these to fit your application when
    using the PMP module to interface with CF cards                                */
    
    #ifdef __18CXX
        #error The PIC18 architecture does not currently support PMP interface to CF cards
    #elif defined __dsPIC30F__
    
        // Sample dsPIC30 defines
        
        // Description: The output latch for the CF Reset signal
        #define CF_PMP_RST                  _RD0
        // Description: The TRIS bit for the CF Reset signal
        #define CF_PMP_RESETDIR     _TRISD0
        // Description: The input port for the CF Ready signal
        #define CF_PMP_RDY                  _RD12
        // Description: The TRIS bit for the CF Ready signal
        #define CF_PMP_READYDIR     _TRISD12
        // Description: The input port for the CF card detect signal
        #define CF_PMP_CD1                  _RC4
        // Description: The TRIS bit for the CF card detect signal
        #define CF_PMP_CD1DIR       _TRISC4
    
    #elif defined __dsPIC33F__
    
        // Sample dsPIC33 defines

        // Description: The output latch for the CF Reset signal
        #define CF_PMP_RST                  _RD0
        // Description: The TRIS bit for the CF Reset signal
        #define CF_PMP_RESETDIR     _TRISD0
        // Description: The input port for the CF Ready signal
        #define CF_PMP_RDY                  _RD12
        // Description: The TRIS bit for the CF Ready signal
        #define CF_PMP_READYDIR     _TRISD12
        // Description: The input port for the CF card detect signal
        #define CF_PMP_CD1                  _RC4
        // Description: The TRIS bit for the CF card detect signal
        #define CF_PMP_CD1DIR       _TRISC4
    
    #elif defined __PIC24F__
    
        // Default case for PIC24F

        // Description: The output latch for the CF Reset signal
        #define CF_PMP_RST                  LATDbits.LATD0
        // Description: The TRIS bit for the CF Reset signal
        #define CF_PMP_RESETDIR     TRISDbits.TRISD0
        // Description: The input port for the CF Ready signal
        #define CF_PMP_RDY                  PORTDbits.RD12
        // Description: The TRIS bit for the CF Ready signal
        #define CF_PMP_READYDIR     TRISDbits.TRISD12
        // Description: The input port for the CF card detect signal
        #define CF_PMP_CD1                  PORTCbits.RC4
        // Description: The TRIS bit for the CF card detect signal
        #define CF_PMP_CD1DIR       TRISCbits.TRISC4
    
    #endif
    
    // Description: Defines the PMP data bus direction register
    #define MDD_CFPMP_DATADIR       TRISE
#endif


#ifdef USE_MANUAL_CF_INTERFACE
    // Use these definitions with CF-Bit transaction.c and .h
    // This will manually perform parallel port transactions

    #ifdef __18CXX
    
        // Address lines

        // Description: The CF address bus output latch register (for PIC18)
        #define ADDBL                   LATA
        // Description: The CF address bus TRIS register (for PIC18)
        #define ADDDIR                  TRISA
        
        // Data bus

        // Description: The Manual CF data bus port register
        #define MDD_CFBT_DATABIN        PORTD
        // Description: The Manual CF data bus output latch register
        #define MDD_CFBT_DATABOUT       LATD
        // Description: The Manual CF data bus TRIS register
        #define MDD_CFBT_DATADIR        TRISD

        // control bus lines

        // Description: The CF card chip select output latch bit
        #define CF_CE                   LATEbits.LATE1
        // Description: The CF card chip select TRIS bit
        #define CF_CEDIR                TRISEbits.TRISE1
        // Description: The CF card output enable strobe latch bit
        #define CF_OE                   LATAbits.LATA5
        // Description: The CF card output enable strobe TRIS bit
        #define CF_OEDIR                TRISAbits.TRISA5
        // Description: The CF card write enable strobe latch bit
        #define CF_WE                   LATAbits.LATA4
        // Description: The CF card write enable strobe TRIS bit
        #define CF_WEDIR                TRISAbits.TRISA4
        // Description: The CF card reset signal latch bit
        #define CF_BT_RST               LATEbits.LATE0
        // Description: The CF card reset signal TRIS bit
        #define CF_BT_RESETDIR          TRISEbits.TRISE0
        // Description: The CF card ready signal port bit
        #define CF_BT_RDY               PORTEbits.RE2
        // Description: The CF card ready signal TRIS bit
        #define CF_BT_READYDIR          TRISEbits.TRISE2
        // Description: The CF card detect signal port bit
        #define CF_BT_CD1               PORTCbits.RC2
        // Description: The CF card detect signal TRIS bit
        #define CF_BT_CD1DIR            TRISCbits.TRISC2
    
    #elif defined __dsPIC30F__
    
        // Address lines

         // Description: The CF address bus bit 0 output latch definition (for PIC24/30/33/32)
        #define ADDR0                   _LATB15
        // Description: The CF address bus bit 1 output latch definition (for PIC24/30/33/32)
        #define ADDR1                   _LATB14
        // Description: The CF address bus bit 2 output latch definition (for PIC24/30/33/32)
        #define ADDR2                   _LATG9
        // Description: The CF address bus bit 3 output latch definition (for PIC24/30/33/32)
        #define ADDR3                   _LATG8
        // Description: The CF address bus bit 0 TRIS definition (for PIC24/30/33/32)
        #define ADRTRIS0                _TRISB15
        // Description: The CF address bus bit 1 TRIS definition (for PIC24/30/33/32)
        #define ADRTRIS1                _TRISB14
        // Description: The CF address bus bit 2 TRIS definition (for PIC24/30/33/32)
        #define ADRTRIS2                _TRISG9
        // Description: The CF address bus bit 3 TRIS definition (for PIC24/30/33/32)
        #define ADRTRIS3                _TRISG8
        
        // Data bus

        // Description: The Manual CF data bus port register
        #define MDD_CFBT_DATABIN        PORTE
        // Description: The Manual CF data bus output latch register
        #define MDD_CFBT_DATABOUT       PORTE
        // Description: The Manual CF data bus TRIS register
        #define MDD_CFBT_DATADIR        TRISE
        
        // control bus lines

        // Description: The CF card chip select output latch bit
        #define CF_CE                   _RD11
        // Description: The CF card chip select TRIS bit
        #define CF_CEDIR                _TRISD11
        // Description: The CF card output enable strobe latch bit
        #define CF_OE                   _RD5
        // Description: The CF card output enable strobe TRIS bit
        #define CF_OEDIR                _TRISD5 
        // Description: The CF card write enable strobe latch bit
        #define CF_WE                   _RD4
        // Description: The CF card write enable strobe TRIS bit
        #define CF_WEDIR                _TRISD4
        // Description: The CF card reset signal latch bit
        #define CF_BT_RST               _RD0
        // Description: The CF card reset signal TRIS bit
        #define CF_BT_RESETDIR          _TRISD0
        // Description: The CF card ready signal port bit
        #define CF_BT_RDY               _RD12
        // Description: The CF card ready signal TRIS bit
        #define CF_BT_READYDIR          _TRISD12
        // Description: The CF card detect signal port bit
        #define CF_BT_CD1               _RC4
        // Description: The CF card detect signal TRIS bit
        #define CF_BT_CD1DIR            _TRISC4

    #elif defined __dsPIC33F__

        // Address lines

        // Description: The CF address bus bit 0 output latch definition (for PIC24/30/33/32)
        #define ADDR0                   _LATB15
        // Description: The CF address bus bit 1 output latch definition (for PIC24/30/33/32)
        #define ADDR1                   _LATB14
        // Description: The CF address bus bit 2 output latch definition (for PIC24/30/33/32)
        #define ADDR2                   _LATG9
        // Description: The CF address bus bit 3 output latch definition (for PIC24/30/33/32)
        #define ADDR3                   _LATG8
        // Description: The CF address bus bit 0 TRIS definition (for PIC24/30/33/32)
        #define ADRTRIS0                _TRISB15
        // Description: The CF address bus bit 1 TRIS definition (for PIC24/30/33/32)
        #define ADRTRIS1                _TRISB14
        // Description: The CF address bus bit 2 TRIS definition (for PIC24/30/33/32)
        #define ADRTRIS2                _TRISG9
        // Description: The CF address bus bit 3 TRIS definition (for PIC24/30/33/32)
        #define ADRTRIS3                _TRISG8
        
        // Data bus

        // Description: The Manual CF data bus port register
        #define MDD_CFBT_DATABIN        PORTE
        // Description: The Manual CF data bus output latch register
        #define MDD_CFBT_DATABOUT       PORTE
        // Description: The Manual CF data bus TRIS register
        #define MDD_CFBT_DATADIR        TRISE
        
        // control bus lines

        // Description: The CF card chip select output latch bit
        #define CF_CE                   _RD11
        // Description: The CF card chip select TRIS bit
        #define CF_CEDIR                _TRISD11
        // Description: The CF card output enable strobe latch bit
        #define CF_OE                   _RD5
        // Description: The CF card output enable strobe TRIS bit
        #define CF_OEDIR                _TRISD5 
        // Description: The CF card write enable strobe latch bit
        #define CF_WE                   _RD4
        // Description: The CF card write enable strobe TRIS bit
        #define CF_WEDIR                _TRISD4
        // Description: The CF card reset signal latch bit
        #define CF_BT_RST               _RD0
        // Description: The CF card reset signal TRIS bit
        #define CF_BT_RESETDIR          _TRISD0
        // Description: The CF card ready signal port bit
        #define CF_BT_RDY               _RD12
        // Description: The CF card ready signal TRIS bit
        #define CF_BT_READYDIR          _TRISD12
        // Description: The CF card detect signal port bit
        #define CF_BT_CD1               _RC4
        // Description: The CF card detect signal TRIS bit
        #define CF_BT_CD1DIR            _TRISC4
    
    #elif defined __PIC24F__
    
        // Address lines

        // Description: The CF address bus bit 0 output latch definition (for PIC24/30/33/32)
        #define ADDR0                   LATBbits.LATB15
        // Description: The CF address bus bit 1 output latch definition (for PIC24/30/33/32)
        #define ADDR1                   LATBbits.LATB14
        // Description: The CF address bus bit 2 output latch definition (for PIC24/30/33/32)
        #define ADDR2                   LATGbits.LATG9
        // Description: The CF address bus bit 3 output latch definition (for PIC24/30/33/32)
        #define ADDR3                   LATGbits.LATG8
        // Description: The CF address bus bit 0 TRIS definition (for PIC24/30/33/32)
        #define ADRTRIS0                TRISBbits.TRISB15
        // Description: The CF address bus bit 1 TRIS definition (for PIC24/30/33/32)
        #define ADRTRIS1                TRISBbits.TRISB14
        // Description: The CF address bus bit 2 TRIS definition (for PIC24/30/33/32)
        #define ADRTRIS2                TRISGbits.TRISG9
        // Description: The CF address bus bit 3 TRIS definition (for PIC24/30/33/32)
        #define ADRTRIS3                TRISGbits.TRISG8
        
        // Data bus

        // Description: The Manual CF data bus port register
        #define MDD_CFBT_DATABIN        PORTE
        // Description: The Manual CF data bus output latch register
        #define MDD_CFBT_DATABOUT       PORTE
        // Description: The Manual CF data bus TRIS register
        #define MDD_CFBT_DATADIR        TRISE
        
        // control bus lines

        // Description: The CF card chip select output latch bit
        #define CF_CE                   PORTDbits.RD11
        // Description: The CF card chip select TRIS bit
        #define CF_CEDIR                TRISDbits.TRISD11
        // Description: The CF card output enable strobe latch bit
        #define CF_OE                   PORTDbits.RD5
        // Description: The CF card output enable strobe TRIS bit
        #define CF_OEDIR                TRISDbits.TRISD5        
        // Description: The CF card write enable strobe latch bit
        #define CF_WE                   PORTDbits.RD4
        // Description: The CF card write enable strobe TRIS bit
        #define CF_WEDIR                TRISDbits.TRISD4
        // Description: The CF card reset signal latch bit
        #define CF_BT_RST               PORTDbits.RD0
        // Description: The CF card reset signal TRIS bit
        #define CF_BT_RESETDIR          TRISDbits.TRISD0
        // Description: The CF card ready signal port bit
        #define CF_BT_RDY               PORTDbits.RD12
        // Description: The CF card ready signal TRIS bit
        #define CF_BT_READYDIR          TRISDbits.TRISD12
        // Description: The CF card detect signal port bit
        #define CF_BT_CD1               PORTCbits.RC4
        // Description: The CF card detect signal TRIS bit
        #define CF_BT_CD1DIR            TRISCbits.TRISC4
    #endif
#endif

#include <uart2.h>



#endif



//SD-SPI.c ファイルの修正箇所

//SDカードのソケットのライトプロテクトの動作が逆のものがあります。2010年12月のマイクロチップのライブラリは
//ライトプロテクトのモードで、PICからみて下記のソケットを想定してできています。
//  ・ライトプロテクトされている場合 …… 1(+3.3V)
//  ・ライトプロテクトされていない場合…… 0(0V)
//サンハヤト鰍フCK29の場合上記論理とは逆なので下記のようにソースコードを一部変更する必要があります。
//下記は修正後のコードです。



  ***************************************************************************************/

BYTE MDD_SDSPI_WriteProtectState(void)
{
    return(!SD_WE);     //修正前のコード  return(SD_WE);
                                        //!が追加になっています。
}


/****************************************************************************



 


<動作結果>
  










★ SDカード読み書き                   <PIC32MX795F512L   チャンネル4>

 PIC32MX795F512Lのチャンネル4(SPI4)によりSDカードを読書きする場合は、putcSPI4( ) , getcSPI4( ) , OpenSPI4( )  が SDカードのライブラリとして用意されていないので  SpiPutC(SPI_CHANNEL4, ), SpiGetC(SPI_CHANNEL4, ) SpiChnOpen(SPI_CHANNEL4, ).  などをつかい  ライブラリファイルSD-SPI.c. も変更する必要があるようです。 以下にその例を紹介します。

<試作品の仕様>
 1. PIC32MX795512Lのチャンネル4(SPI4)を用いSDカードの読み書きをおこなう
 2. SDカードに12345を書込み、これを読出し液晶に表示する


<試作品回路図>(→ 回路図のpdfファイル







<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています





 

          

   <プログラム例>



#include <p32xxxx.h>
#include <plib.h>               // PIC32 peripheral library

#include        "1lcd_lib_C32.h"
#include        "FSIO.h"


// configuration CPU=80MHz Peri=80MHz,HS+PLL,Divider=1/2,PLL=x20,WDT=Off
#pragma config FNOSC=PRIPLL, POSCMOD=HS, FPLLIDIV=DIV_2
#pragma config FPLLMUL=MUL_20, FPBDIV=DIV_1, FPLLODIV=DIV_1
#pragma config FWDTEN=OFF, ICESEL=ICS_PGx2


char Buf[17];   //文字列のバッファー用レジスタ
unsigned int Buf_Input[3];              //SDカード書き込み値
unsigned int Buf_SD[3];                 //SDカード読込み値

int N_Write;                            //書き込み回数戻り値

FSFILE* pfile;                          //SDカードのファイルポインタ

void delay_us(unsigned int usec)        //1μsec遅延関数
{
        int count;
        count = (int)(Clock/20000000)*usec;
        do      //実測: at Clock=80000000
        {       //delay_us(1000)→1003μsec、 delay_us(100)→102μsec、delay_us(10)→11μsec、delay_us(1)→1.6μsec
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                count--;
        }while(count != 0);
}

void delay_ms(unsigned int msec)        //1msec遅延関数
{
        unsigned int i;

        for(i=0; i<msec; i++)
        delay_us(1000);
}




int main(void)
{
        SYSTEMConfigPerformance(80000000);      // システム最適化
   //   INTEnableSystemMultiVectoredInt();  //マルチベクタ方式割り込み許可
        mJTAGPortEnable(DEBUG_JTAGPORT_OFF);    //JTAG無効化//DDPCONbits.JTAGEN = 0;  //I/OポートとしてRA0、RA1、RA4、RA5をつかう場合必須
    AD1PCFG =0xFFFF;    //Bポート:アナログ → デジタル//状態変化ピンとして使う場合必須

    TRISBbits.TRISB15 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB14 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB13 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB12 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA10 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA9 = 0;       //キャラクタ液晶ポート設定



        lcd_init();                             // LCD初期化
        lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

        lcd_clear();            // 全消去
        sprintf(Buf,"SD W/R Start2 !!");//C30とは異なり、arguement 不要
        lcd_str(Buf);                   //液晶表示

        delay_ms(1000);




        //// SDカードの実装とフォーマット済をチェック
        SD_CS = 0;          //    LATCbits.LATC3 = 0;           //CS=0 SDカードのチップセレクトenable
        while(!FSInit());                      //SDカードの実装とフォーマット済をチェック
        SD_CS = 1;          //    LATCbits.LATC3 = 1;           //CS=1 SDカードのチップセレクトdisable
        

        lcd_clear();            // 全消去
        sprintf(Buf,"Initialize OK !!");//C30とは異なり、arguement 不要
        lcd_str(Buf);                   //液晶表示
        delay_ms(1000);



      //// ファイルを書き込みモードでオープン
        SD_CS = 0;          //    LATCbits.LATC3 = 0;           //CS=0 SDカードのチップセレクトenable
        pfile = FSfopen("DATA.DAT","w");         //ファイル書き込みモードでオープン 但しファイルがなければ新規ファイル作成
 
        if(pfile == NULL)                        //ファイルオープン失敗の場合(SDカードにライトプロテクトがされている場合など)
        {
                lcd_clear();
                sprintf(Buf,"W_ModeOpen Error");  //液晶に"W_ModeOpen Error" を表示
                lcd_str(Buf);
                return 0;
        }
        else                                            //ファイルオープン成功なら
        {
                lcd_clear();
                sprintf(Buf,"FileOpen OK !!");    //液晶に"W_ModeOpen OK" を表示
                lcd_str(Buf);
                lcd_cmd(0xC0);                          //2行目へ
                sprintf(Buf," (Write Mode)");
                lcd_str(Buf);
                delay_ms(1000);

        }


        Buf_Input[0] = 12345 ;                          //書き込みデータをセット
    //    Buf_Input[0] = 12345;                          //書き込みデータをセット
        N_Write = FSfwrite((const void*)Buf_Input,sizeof(Buf_Input),1,pfile);//ファイルにデータ書き込み
        if(N_Write == 1)                               //正常な場合:書き込み回数が返ってくる
        {
                lcd_clear();
                sprintf(Buf,"Write OK !!");       //液晶に"Write OK !" を表示
                lcd_str(Buf);
                delay_ms(1000);
        }
        else    //異常な場合
        {
                lcd_clear();
                sprintf(Buf,"Write NG !!");       //液晶に"Write NG !" を表示
                lcd_str(Buf);
                return 0;
        }


        FSfclose(pfile);                                // ファイルを閉じる
        SD_CS = 1;          //    LATCbits.LATC3 = 1;           //CS=1 SDカードのチップセレクトdisable




        //// SDカードを読込みモードでオープン
        SD_CS = 0;          //    LATCbits.LATC3 = 0;           //CS=0 SDカードのチップセレクトenable
        pfile = FSfopen("DATA.DAT","r");                //ファイル読込みモードでオープン 
        if(pfile == NULL)
        {
                lcd_clear();
                sprintf(Buf,"R_ModeOpen Error");  //液晶に"R_ModeOpen Error"を表示
                lcd_str(Buf);
                return 0;
        }
        else
        {
                lcd_clear();
                sprintf(Buf,"FileOpen OK !!");    //液晶に"W_ModeOpen OK" を表示
                lcd_str(Buf);
                lcd_cmd(0xC0);                          //2行目へ
                sprintf(Buf," (Read Mode)");
                lcd_str(Buf);
                delay_ms(1000);
        }
        FSfread(Buf_SD,sizeof(Buf_SD),1,pfile);         //ファイルからデータ読込み

        FSfclose(pfile);                                //ファイルを閉じる
        SD_CS = 1;          //    LATCbits.LATC3 = 1;           //CS=1 SDカードのチップセレクトdisable

   //// 読込みデータの表示
        lcd_clear();
        sprintf(Buf,"SD_DATA=%u",Buf_SD[0]);            //SDカードから読み込んだデータを液晶に表示
        lcd_str(Buf);
         lcd_cmd(0xC0);                          //2行目へ
         sprintf(Buf,"795 ch4 was used");
                lcd_str(Buf);
 




//------------------------------------------------------------------------------------------------------------------
//HardwareProfile.h
//Microchip Memory Disk Drive File System



#ifndef _HARDWAREPROFILE_H_
#define _HARDWAREPROFILE_H_


//クロック周波数設定    // Define your clock speed here
    #define RUN_AT_80MHZ

    #if defined(RUN_AT_48MHZ)
        #define GetSystemClock()            48000000UL              // System clock frequency (Hz)
        #define GetPeripheralClock()        48000000UL              // Peripheral clock frequency
        #define GetInstructionClock()       (GetSystemClock())      // Instruction clock frequency
    #elif defined(RUN_AT_24MHZ)
        #define GetSystemClock()            24000000UL
        #define GetPeripheralClock()        24000000UL
        #define GetInstructionClock()       (GetSystemClock())
    #elif defined(RUN_AT_80MHZ)    
        #define GetSystemClock()            (80000000ul)            //システムクロック
        #define GetPeripheralClock()        (GetSystemClock()/2)    //ペリフェラルクロック
        #define GetInstructionClock()       (GetSystemClock())      //インストラクションクロック
    #else
        #error Choose a speed
    #endif

    // Clock values

    #define MILLISECONDS_PER_TICK       10                  // Definition for use with a tick timer
    #define TIMER_PRESCALER             TIMER_PRESCALER_8   // Definition for use with a tick timer
    #define TIMER_PERIOD                37500               // Definition for use with a tick timer

 

// Description: Macro used to enable the SD-SPI physical layer (SD-SPI.c and .h)
#define USE_SD_INTERFACE_WITH_SPI


//SD カード選択・検出
   //CS:チップセレクト    // Description: SD-SPI Chip Select Output bit
    #define SD_CS       LATDbits.LATD14     //LATCbits.LATC3            
    #define SD_CS_TRIS  TRISDbits.TRISD14       //          TRISCbits.TRISC3    

    //CD:カードディテクト //      Description: SD-SPI Card Detect Input bit
    #define SD_CD       PORTFbits.RF12      //      PORTDbits.RD8               
    #define SD_CD_TRIS  TRISFbits.TRISF12   //      TRISDbits.TRISD8    

    //WE:ライトイネーブル Description: SD-SPI Write Protect Check Input bit
    #define SD_WE       PORTAbits.RA1           
    #define SD_WE_TRIS  TRISAbits.TRISA1        
     

//SPIコンフィギュレーション     //SPI Configuration

        #define SPI_START_CFG_1     (PRI_PRESCAL_64_1 | SEC_PRESCAL_8_1 | MASTER_ENABLE_ON | SPI_CKE_ON | SPI_SMP_ON)
        #define SPI_START_CFG_2     (SPI_ENABLE)

       #define SPI_FREQUENCY   (400000)      //SPI周波数     //Define the SPI frequency
    //    #define SPI_FREQUENCY   (20000000)      //SPI周波数     //Define the SPI frequency
  
    //チャンネル4:
        #define SPICON1         SPI4CON     //制御レジスタ
        #define SPISTAT         SPI4STAT    //SPIステータスレジスタ status register
        #define SPIBUF          SPI4BUF     //SPIバッファレジスタ
            
        #define SPISTAT_RBF     SPI4STATbits.SPIRBF //受信バッファ満杯ビット//  The receive buffer full bit in the SPI status register
        #define SPICON1bits     SPI4CONbits     //ビット単位の定義(制御レジスタ)The bitwise define for the SPI control register (i.e. _____bits)
        #define SPISTATbits     SPI4STATbits    //ビット単位の定義(ステータスレジスタ) //The bitwise define for the SPI status register (i.e. _____bits)
        #define SPIENABLE       SPI4CONbits.ON  //SPIモジュール イネーブルビット //The enable bit for the SPI module

        #define SPIBRG          SPI4BRG     //ボーレートジェネレータ//The definition for the SPI baud rate generator register (PIC32)

        //SCK,SDI,SDOピンアサイン   //Tris pins for SCK/SDI/SDO lines
        #define SPICLOCK        TRISFbits.TRISF12   //TRISGbits.TRISG6    //SCK
        #define SPIIN           TRISFbits.TRISF4    //PICのSDI4     //      TRISGbits.TRISG7    //PICのSDI2
        #define SPIOUT          TRISFbits.TRISF5    //PICのSDO4     //    TRISGbits.TRISG8    //SDO

        //SPIライブラリ関数 //library functions
 //       #define putcSPI     putcSPI4    //putcSPI2
 //       #define getcSPI     getcSPI4    //getcSPI2

 //        #define OpenSPI(config1, config2)   OpenSPI4(config1, config2)      //OpenSPI2(config1, config2)
   
        //システムクロックが遅すぎる場合のエラー表示    // Will generate an error if the clock speed is too low to interface to the card
        #if (GetSystemClock() < 100000)
            #error Clock speed must exceed 100 kHz
        #endif    
    
    #include <uart2.h>

#endif



//-------------------------------------------------------------------------------------------------------------------------------
//SD-SPI.c
//SD-SPI.cファイルは 以下を変更しています。



........
........

void InitSPISlowMode(void)
{
   
#if defined __C30__ || defined __C32__
       
#ifdef __PIC32MX__
           
SpiChnOpen(SPI_CHANNEL4,SPI_OPEN_MSTEN|SPI_OPEN_CKP_HIGH|SPI_OPEN_SMP_END|SPI_OPEN_MODE8,128);
           
//OpenSPI(SPI_START_CFG_1, SPI_START_CFG_2);


            SPIBRG
= SPICalutateBRG(GetPeripheralClock(), 400000);
       
#else //else C30 = PIC24/dsPIC devices
            WORD spiconvalue
= 0x0003;
            WORD timeout
;

.......
.......
}

.......
.......

BYTE MDD_SDSPI_ReadMedia
(void)
{

#ifdef __C32__
   
   
SpiChnPutC(SPI_CHANNEL4 , (BYTE)0xFF);  //putcSPI((BYTE)0xFF);
   
return SpiChnGetC(SPI_CHANNEL4);        //return (BYTE)getcSPI();

#elif defined __18CXX

    BYTE clear
;
    clear
= SPIBUF;
    SPI_INTERRUPT_FLAG
= 0;
    SPIBUF
= 0xFF;
.........
.........
}


unsigned char WriteSPIM( unsigned char data_out )
{
#ifdef __PIC32MX__
    BYTE   clear
;

   
SpiChnPutC(SPI_CHANNEL4 , (BYTE)data_out);  //putcSPI((BYTE)data_out);
    clear
= SpiChnGetC(SPI_CHANNEL4);   // clear = getcSPI();

   
return ( 0 );                // return non-negative#
#elif defined __18CXX
    BYTE clear
;
    clear
= SPIBUF;
    SPI_INTERRUPT_FLAG
= 0;
    SPIBUF
= data_out;
   
........
........
}
.......
....... //---------------------------------------------------------------------------------------- //************************************************************************* //インクルードファイル 1lcd_lib_C32.h //このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、 //C32コンパイラ対応等で変更したものです。 //************************************************************************* #include <p32xxxx.h> //#include <proc/p32mx795f512l.h> //MX795はイニシャライズループを抜けられない //#include <proc/p32mx360f512l.h> //PIC32MX460F512L #define Clock 80000000 // 単位はHzで指定 // LCDポート設定 #define lcd_port_DB7 LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定 #define lcd_port_DB6 LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定 #define lcd_port_DB5 LATBbits.LATB13 //のDB5(12番ピン)に接続されるPIC側ポート番号設定 #define lcd_port_DB4 LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定 #define lcd_rs LATAbits.LATA9 //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定 #define lcd_stb LATAbits.LATA10 //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定 void lcd_out(char code, char flag); void lcd_data(char asci); void lcd_cmd(char cmd); void lcd_clear(void); void lcd_init(void); void lcd_str(char *str); //---------------------------------------------------------------------------------------- //************************************************************************** //インクルードファイル 1lcd_lib_C32.c //このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、 //C32コンパイラ対応等で変更したものです。 //************************************************************************** /////////////////////////////////////////////// // 液晶表示器制御ライブラリ for C32コンパイラー // 内蔵関数は以下 //    lcd_init() ----- 初期化 // lcd_cmd(cmd) ----- コマンド出力 // lcd_data(chr) ----- 1文字表示出力 // lcd_clear() ----- 全消去 //    lcd_str(str*) ----- 文字列表示 ////////////////////////////////////////////// #include "1lcd_lib_C32.h" void lcd_delay_us(unsigned int usec) //1μsec遅延関数 { int count; count = (int)(Clock/20000000)*usec; do { asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); count--; }while(count != 0); } void lcd_delay_ms(unsigned int msec) //1msec遅延関数 { unsigned int i; for(i=0; i<msec; i++) lcd_delay_us(1000); } //////// データ出力サブ関数 void lcd_out(char code, char flag) { if(code & 0b10000000)lcd_port_DB7 = 1; //LCDのDB7への出力セット else lcd_port_DB7 = 0; if(code & 0b01000000)lcd_port_DB6 = 1; //LCDのDB6への出力セット else lcd_port_DB6 = 0; if(code & 0b00100000)lcd_port_DB5 = 1; //LCDのDB5への出力セット else lcd_port_DB5 = 0; if(code & 0b00010000)lcd_port_DB4 = 1; //LCDのDB4への出力セット else lcd_port_DB4 = 0; if (flag == 0) lcd_rs = 1; // 表示データの場合 else lcd_rs = 0; // コマンドデータの場合 lcd_delay_us(1); //1μsecウェイト lcd_stb = 1; // strobe(E) ON (Enable) lcd_delay_us(1); // 1μsec : strobe信号の幅 lcd_stb = 0; // reset strobe } //////// 1文字表示関数 void lcd_data(char asci) { lcd_out(asci, 0); // 上位4ビット出力 lcd_out(asci<<4, 0); // 下位4ビット出力 lcd_delay_us(50); //50μsecウェイト } /////// コマンド出力関数 void lcd_cmd(char cmd) { lcd_out(cmd, 1); // 上位4ビット出力 lcd_out(cmd<<4, 1); // 下位4ビット出力 if((cmd & 0x03) != 0) // clear Homeの場合 lcd_delay_ms(2); // 2msec待ち else lcd_delay_us(50); //50μsecウェイト } /////// 全消去関数 void lcd_clear(void) { lcd_cmd(0x01); // 初期化コマンド出力 } /////// 文字列出力関数 void lcd_str(char* str) { while(*str) //文字列終端の '\0'を検出するまで { lcd_data(*str); // 1文字表示 str++; //ポインタをインクリメント } } /////// 初期化関数 void lcd_init(void) { lcd_delay_ms(20); //20msecウェイト lcd_out(0x30, 1); // 8bit mode set lcd_delay_ms(5); //5msecウェイト lcd_out(0x30, 1); // 8bit mode set lcd_delay_ms(1); //1msecウェイト lcd_out(0x30, 1); // 8bit mode set lcd_delay_ms(1); //1msecウェイト lcd_out(0x20, 1); // 4bit mode set lcd_delay_ms(1); //1msecウェイト lcd_cmd(0x2E); // DL=0 4bit mode lcd_cmd(0x08); // display off C=D=B=0 lcd_cmd(0x0D); // display on C=D=1 B=0 lcd_cmd(0x06); // entry I/D=1 S=0 lcd_cmd(0x02); // cursor home }




 <動作結果>















SDカード読み書き    <PIC32MZ2048ECH100編>
 Harmonyを使って SDカードの読み書きを行う場合、 ファイル名として ロングファイル名が扱えます。

 
<試作品の仕様>
 1. PIC32MZとハーモニーをつかいSDカードの読み書きをおこなう
 2. ファイル名は myFileName01.txt とする
 3. SDカードがカードスロットに挿入されているかチェックし 液晶に表示を行う
 4. ファイルがオープンできたら液晶に表示する。
 5. ファイルを 上書き可のモードで開き ”Hellow Worold !!" のテキストをファイルに書き込む
 6. ファイルを閉じる
 7. ファイルを読み込みモードで開き、書き込まれている内容を液晶に表示する
 
 開発環境 Harmony ver 1.02    XC32 ver.1.34    MPLABX ver.2.35   PIC32MZ2048ECH100  revision 5


<試作品の回路図> (→ 回路図のPDFファイル




<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています




    

          

   <プログラム例>
//以下、main().c
//----------------------------------------------------------------------------------
/*******************************************************************************
  MPLAB Harmony Project Main Source File

  Company:
    Microchip Technology Inc.
  
  File Name:
    main.c

  Summary:
    This file contains the "main" function for an MPLAB Harmony project.

  Description:
    This file contains the "main" function for an MPLAB Harmony project.  The
    "main" function calls the "SYS_Initialize" function to initialize the state 
    machines of all MPLAB Harmony modules in the system and it calls the 
    "SYS_Tasks" function from within a system-wide "super" loop to maintain 
    their correct operation. These two functions are implemented in 
    configuration-specific files (usually "system_init.c" and "system_tasks.c")
    in a configuration-specific folder under the "src/system_config" folder 
    within this project's top-level folder.  An MPLAB Harmony project may have
    more than one configuration, each contained within it's own folder under
    the "system_config" folder.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

//Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include <stddef.h>                     // Defines NULL
#include <stdbool.h>                    // Defines true
#include <stdlib.h>                     // Defines EXIT_FAILURE
#include "system/common/sys_module.h"   // SYS function prototypes


// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************

int main ( void )
{
    /* Initialize all MPLAB Harmony modules, including application(s). */
    SYS_Initialize ( NULL );

    while ( true )
    {
        /* Maintain state machines of all polled MPLAB Harmony modules. */
        SYS_Tasks ( );

    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}


/*******************************************************************************
 End of File
*/





//以下、app.c
//---------------------------------------------------------------------------------------
/*******************************************************************************
  MPLAB Harmony Application Source File
  
  Company:
    Microchip Technology Inc.
  
  File Name:
    app.c

  Summary:
    This file contains the source code for the MPLAB Harmony application.

  Description:
    This file contains the source code for the MPLAB Harmony application.  It 
    implements the logic of the application's state machine and it may call 
    API routines of other MPLAB Harmony modules in the system, such as drivers,
    system services, and middleware.  However, it does not call any of the
    system interfaces (such as the "Initialize" and "Tasks" functions) of any of
    the modules in the system or make any assumptions about when those functions
    are called.  That is the responsibility of the configuration-specific system
    files.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files 
// *****************************************************************************
// *****************************************************************************

#include "app.h"

#include "1lcd_lib_C32.h"




int delay_Clock = 200000000;   //200MHz
char Buf[17];   //1液晶表示バッファー
int SdMode = 0;   //SDカードに対する操作モード
unsigned int Buf_Input[3];              //SDカード書き込み値
char Hellow[] = "Hellow World !!";
char myFileName01[] = "myFileName01.txt";
unsigned int Buf_SD[3];                 //SDカード読込み値
int N_Write;                            //書き込み回数戻り値

SYS_FS_HANDLE   fileHandle; //ファイルハンドル
SYS_FS_HANDLE   fileHandle2; //ファイルハンドル

    char tempBuf[20];
    char tempBuf2[20];
    char tempBuf3[20];
    int eof;
    int size;
    char* str1;


void delay_us(volatile unsigned int usec)        //1μsec遅延
{
        volatile  int count;

        count = (int)(delay_Clock/20000000)*usec;


        do      //実測 at 200MH (Clock=200000000)
        {       //delay_us(1000):1000.4μsec  delay_us(100):100.6μsec  delay_us(10):10.5μsec  delay_us(1):1.5μsec
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

                count--;
        }while(count != 0);


}

void delay_ms(volatile unsigned int msec)        //1msec遅延
{
        volatile unsigned int i;         //実測:at200MH (Clock=200000000)//delay_ms(1): 1.0006msec   delay_ms(100):100.04msec

        for(i=0; i<msec; i++)
        delay_us(1000);
}


// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* Application Data

  Summary:
    Holds application data

  Description:
    This structure holds the application's data.

  Remarks:
    This structure should be initialized by the APP_Initialize function.
    
    Application strings and buffers are be defined outside this structure.
*/

APP_DATA appData;

// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************

/* TODO:  Add any necessary callback funtions.
*/

// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************

/* TODO:  Add any necessary local functions.
*/


// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void APP_Initialize ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    appData.state = APP_STATE_INIT;
    
    /* TODO: Initialize your application's state machine and other
     * parameters.
     */



    lcd_init();                         // LCD初期化
    lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

    lcd_cmd(0x80);          //1目の先頭へ
    sprintf(Buf,"SD card Start !!       ");//
    lcd_str(Buf);                   //液晶表示

    lcd_cmd(0xC0);          //2行目の先頭へ
    sprintf(Buf,"                 ");   //
    lcd_str(Buf);           // 開始メッセージ1行目表示

    delay_ms(2000);

}


/******************************************************************************
  Function:
    void APP_Tasks ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Tasks ( void )
{
    /* Check the application's current state. */
     int ix = 0;

    switch(SdMode)
    {
//-------------------------------------------------------------------------------------------------
    case 0:    //カード挿入検出・ライトプロテクトチェック

            if(SYS_FS_Mount("/dev/mmcblka1", "/mnt/myDrive", FAT, 0, NULL) != 0)    //ファイルシステムが搭載されているか?
                //mmcblka1:SDカード //変更不可     //myDrive: 変更不可
            {   //失敗の場合   //カードがマウントされていても8回以上実行される

                lcd_cmd(0x80);          //1目の先頭へ
                sprintf(Buf,"SD notMounted     ");//
                lcd_str(Buf);                   //液晶表示

                SdMode = 0;
            }
            else
            {   //成功の場合
                lcd_cmd(0x80);          //1目の先頭へ
                sprintf(Buf,"SD mounted        ");//
                lcd_str(Buf);                   //液晶表示
                delay_ms(2000);



                //ライトプロテクトをチェック
                  if(PORTBbits.RB9 != 0)  //ライトプロテクトの場合  //  writeProtectStatus = DRV_SDCARD_WriteProtectionIsEnabled(fileHandle);
            //    if(PORTFbits.RF1 != 0)  //ライトプロテクトの場合  //  writeProtectStatus = DRV_SDCARD_WriteProtectionIsEnabled(fileHandle);
                {
                    lcd_cmd(0x80);          //1目の先頭へ
                    sprintf(Buf,"WriteProtected      ");       //液晶に"Write OK !" を表示
                    lcd_str(Buf);
                    while(1);
                }
                else
                {   //ライトプロテクトが解除されている場合

                 lcd_cmd(0x80);          //1目の先頭へ
                 sprintf(Buf,"WriteReleased        ");       //液晶に"Write OK !" を表示
                 lcd_str(Buf);

                 delay_ms(3000);
                }


                SdMode = 1;
            }
            break;


//--------------------------------------------------------------------------------------------
        case 1:     // ファイルを書き込みモードでオープン 但しファイルがなければ新規ファイル作成

            fileHandle = SYS_FS_FileOpen(myFileName01, (SYS_FS_FILE_OPEN_WRITE));
            if(fileHandle == SYS_FS_HANDLE_INVALID)
            { //ファイルオープンエラーの場合
                lcd_cmd(0x80);          //1目の先頭へ
                sprintf(Buf,"FileOpen_w failed     ");//
                lcd_str(Buf);                   //液晶表示
                while(1);
            }
            else
            {
                lcd_cmd(0x80);          //1目の先頭へ
                sprintf(Buf,"FileOpen_w  OK !!        ");    //液晶に"W_ModeOpen OK" を表示
                lcd_str(Buf);                   //液晶表示
                delay_ms(2000);

                SdMode = 2;
            }
            break;



//-------------------------------------------------------------------------------------------
        case 2: //データの書き込み

                 N_Write = SYS_FS_FileWrite(fileHandle, Hellow, sizeof(Hellow));//ファイルにデータ書き込み

                if(N_Write != -1) //正常な場合:書き込み回数が返ってくる
                {
                    lcd_cmd(0x80);          //1目の先頭へ
                    sprintf(Buf,"Write OK !!        ");       //液晶に"Write OK !" を表示
                    lcd_str(Buf);
                    delay_ms(2000);
                }
                else    //異常な場合
                {
                    lcd_cmd(0x80);          //1目の先頭へ
                    sprintf(Buf,"Write NG !!        ");       //液晶に"Write NG !" を表示
                    lcd_str(Buf);
                    while(1);

                }

                SYS_FS_FileClose(fileHandle);   //ファイルクローズ

                SdMode = 3;

            break;

//------------------------------------------------------------------------------------------
        case 3: //読出しファイルオープン

                fileHandle2 = SYS_FS_FileOpen(myFileName01, (SYS_FS_FILE_OPEN_READ));

                if(fileHandle2 == -1)  //ファイルオープン 失敗の場合
                //if(fileHandle2 == SYS_FS_HANDLE_INVALID)  //ファイルオープン 失敗の場合
                {
                    lcd_cmd(0x80);          //1目の先頭へ
                    sprintf(Buf,"FileOpen_r failed");//
                    lcd_str(Buf);                   //液晶表示
                    while(1);
                }
              else SdMode = 4;
         break;

//---------------------------------------------------------------
        case 4:     //ファイル読出し・表示

            do
            {
               SYS_FS_FileRead(fileHandle2, tempBuf, 1);  //1バイトづつ読出し
               eof = SYS_FS_FileEOF(fileHandle2);    //EOFチェック
               if(eof != true)
               {
                    tempBuf2[ix] = tempBuf[0];
                    ix++;
               }
            }while(eof != true);    //ファイルエンドでない場合は、繰り返し読む

            tempBuf2[ix] = '\0';    //文字列終端処理

            SYS_FS_FileClose(fileHandle2);  //ファイルを閉じる

            lcd_cmd(0x80);          //1目の先頭へ
            sprintf(Buf,"%s        ",myFileName01);       //液晶に"Write OK !" を表示
            lcd_str(Buf);

            lcd_cmd(0xC0);          //2目の先頭へ
             sprintf(tempBuf3,"%s                 ",tempBuf2);
            lcd_str(tempBuf3);
            SdMode = 5;

        break;
        case 5:
            delay_ms(10000);
            break;

//------------------------------------------------------------------------------
        default:
            break;
    }
}
 

/*******************************************************************************
 End of File
 */






//以下、system_init.c
//----------------------------------------------------------------------------------
/*******************************************************************************
  System Initialization File

  File Name:
    system_init.c

  Summary:
    This file contains source code necessary to initialize the system.

  Description:
    This file contains source code necessary to initialize the system.  It
    implements the "SYS_Initialize" function, configuration bits, and allocates
    any necessary global system resources, such as the systemObjects structure
    that contains the object handles to all the MPLAB Harmony module objects in
    the system.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "system_config.h"
#include "system_definitions.h"
#include "app.h"


// ****************************************************************************
// ****************************************************************************
// Section: Configuration Bits
// ****************************************************************************
// ****************************************************************************


//-----------------------------------------------------------------------
//DEVCFG0レジスタ
#pragma config EJTAGBEN = NORMAL
#pragma config DBGPER = ALLOW_PG2
#pragma config FSLEEP = OFF
#pragma config FECCCON = OFF_UNLOCKED
#pragma config BOOTISA = MIPS32
#pragma config TRCEN = OFF
#pragma config ICESEL = ICS_PGx2
#pragma config JTAGEN = OFF //JTAG ポート Disable
#pragma config DEBUG = OFF



//----------------------------------------------------------------------
//DEVCFG1レジスタ
#pragma config FNOSC = SPLL //PLL回路(システムPLL)選択   //システム発振回路 //内蔵FRC(8MHz)選択の場合:FNOSC = FRCDIV   //Oscillator Selection Bits (Fast RC Osc w/Div-by-N (FRCDIV))
#pragma config FDMTEN = OFF //デッドマンタイマ OFF (Deadman Timer is disabled)
//#pragma config DMTINTV = WIN_127_128 // DMT Count Window Interval (Window/Interval value is 127/128 counter value)

#pragma config FSOSCEN = OFF // 副発振器OFF   //Secondary Oscillator Enable (Disable SOSC)
#pragma config IESO = OFF //ウェイクアップ時の2段速度スタートアップ // Internal/External Switch Over (Disabled)

#pragma config POSCMOD = HS //HS: ハイスピードレゾネータモード // HS(High Speed Resonator Operation) Oscillator mode selected
                            //EC: 外部発振器    //EC(External Clock Input Operation) mode selected // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF //OSCCOピン出力無効
#pragma config FCKSM = CSECME   //クロック発振:切替及びモニタ有効  //主発振器失陥でFRC(内蔵高速発振器)に切替   //FSCM(Fail Safe Clock Monitor)制御

#pragma config FWDTEN = OFF // ウォッチドックタイマ OFF    //Watchdog Timer Disable
//#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576)
//#pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming)
//#pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode)
//#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%)



//--------------------------------------------------------------------------------------------------------------------
// DEVCFG2レジスタ
//システムクロック:200MHz
//ペリフェラル周波数://default: 100MHz    //PBxDIVで8系統毎に設定変更可
//PBxDIV: PERIPHERAL BUS CLOCK DIVISOR CONTROL レジスタのPBDIV<6:0>: Peripheral Bus Clock Divisor Control ビットで設定

#pragma config FPLLRNG = RANGE_5_10_MHZ        //PLL Input周波数入力範囲設定// System PLL Input Range (5-10 MHz Input)  //8(= 24/3)MHz故
#pragma config FPLLIDIV = DIV_3 //PLL入力側での分周: 1/3  // PLL Input周波数 = 24MHz ÷ 3 = 8MHz     // System PLL Input Divider (1x Divider)

//#pragma config FPLLICLK = PLL_POSC //主発振回路選択 //内蔵FRC(8MHz)の場合はFPLLICLK = PLL_FRC//  System PLL Input Clock Selection (POSC is input to the System PLL)
#pragma config FPLLICLK = PLL_FRC   //内蔵高速発振器選択    //★★★ バグ有 主発振回路選択の時、FPLLICLK = PLL_POSCではなくFPLLICLK = PLL_FRCを選択する。(at ver.1.33 XC32)

#pragma config FPLLMULT = MUL_50 //PLL倍率:50倍 //8MHz x 50 = 400MHz  //System PLL Multiplier (PLL Multiply by 50)
#pragma config FPLLODIV = DIV_2 //PLL出力側での分周: 1/2  //システムクロック = 400MHz ÷ 2 = 200MHz


#pragma config UPLLFSEL = FREQ_24MHZ //USBのPLL入力を 24MHz→12MHzに変換 // USB PLL Input Frequency Selection (USB PLL input is 12 MHz)
#pragma config UPLLEN = ON //USBのPLL変換:イネーブル // USB PLL Enable (USB PLL is enabled)




//--------------------------------------------------------------------------------------------------------------------------
//DEVCFG3レジスタ
#pragma config USERID =     0xffff
#pragma config FMIIEN =     ON
#pragma config FETHIO =     ON
#pragma config PGL1WAY =    ON
#pragma config PMDL1WAY =   ON
#pragma config IOL1WAY =    ON
#pragma config FUSBIDIO =   ON



/*** BF1SEQ0 ***/

#pragma config TSEQ =       0xffff
#pragma config CSEQ =       0xffff



// *****************************************************************************
// *****************************************************************************
// Section: Library/Stack Initialization Data
// *****************************************************************************
// *****************************************************************************/



// *****************************************************************************
// *****************************************************************************
// Section: Driver Initialization Data
// *****************************************************************************
// *****************************************************************************

//<editor-fold defaultstate="collapsed" desc="DRV_Timer Configuration">

/*** TMR Driver Initialization Data ***/

const DRV_TMR_INIT drvTmr0InitData =
{
    .moduleInit.sys.powerState = DRV_TMR_POWER_STATE_IDX0,
    .tmrId = DRV_TMR_PERIPHERAL_ID_IDX0,
    .clockSource = DRV_TMR_CLOCK_SOURCE_IDX0, 
    .prescale = DRV_TMR_PRESCALE_IDX0,
    .mode = DRV_TMR_OPERATION_MODE_IDX0,
    .interruptSource = DRV_TMR_INTERRUPT_SOURCE_IDX0,
    .asyncWriteEnable = false,
};
// </editor-fold>
//<editor-fold defaultstate="collapsed" desc="DRV_SPI Configuration">
 
 /*** SPI Driver Initialization Data ***/
 /*** Index 0  ***/
 DRV_SPI_INIT drvSpi0InitData =
 {
    .spiId = DRV_SPI_SPI_ID_IDX0,
    .taskMode = DRV_SPI_TASK_MODE_IDX0,
    .spiMode = DRV_SPI_SPI_MODE_IDX0,
    .allowIdleRun = DRV_SPI_ALLOW_IDLE_RUN_IDX0,
    .spiProtocolType = DRV_SPI_SPI_PROTOCOL_TYPE_IDX0,
    .commWidth = DRV_SPI_COMM_WIDTH_IDX0,
    .spiClk = DRV_SPI_SPI_CLOCK_IDX0,
    .baudRate = DRV_SPI_BAUD_RATE_IDX0,
    .bufferType = DRV_SPI_BUFFER_TYPE_IDX0,
    .clockMode = DRV_SPI_CLOCK_MODE_IDX0,
    .inputSamplePhase = DRV_SPI_INPUT_PHASE_IDX0,
    .txInterruptSource = DRV_SPI_TX_INT_SOURCE_IDX0,
    .rxInterruptSource = DRV_SPI_RX_INT_SOURCE_IDX0,
    .errInterruptSource = DRV_SPI_ERROR_INT_SOURCE_IDX0,
    .queueSize = DRV_SPI_QUEUE_SIZE_IDX0,
    .jobQueueReserveSize = DRV_SPI_RESERVED_JOB_IDX0,
 };
 
 
 
  
 
  
 
  
// </editor-fold>
//<editor-fold defaultstate="collapsed" desc="SYS_TMR Configuration">
/*** TMR Service Initialization Data ***/
const SYS_TMR_INIT sysTmrInitData =
{
    .moduleInit = {SYS_MODULE_POWER_RUN_FULL},
    .drvIndex = DRV_TMR_INDEX_0,
    .tmrFreq = 1000, 
};

// </editor-fold>
//<editor-fold defaultstate="collapsed" desc="DRV_SDCARD Configuration">
/*** SDCARD Driver Initialization Data ***/
const DRV_SDCARD_INIT drvSDCardInit =
{
    .spiId = SPI_ID_6,
    .spiIndex = 0,
    .sdcardSpeedHz = 20000000,
    .spiClk = CLK_BUS_PERIPHERAL_1,
    .sdCardPinActiveLogic = SDCARD_DETECTION_LOGIC_ACTIVE_LOW,
    .cardDetectPort = PORT_CHANNEL_F,
    .cardDetectBitPosition = PORTS_BIT_POS_12,
    .writeProtectPort = PORT_CHANNEL_B,
    .writeProtectBitPosition = PORTS_BIT_POS_9,
    .chipSelectPort = PORT_CHANNEL_B,
    .chipSelectBitPosition = PORTS_BIT_POS_13,
};
// </editor-fold>

// *****************************************************************************
// *****************************************************************************
// Section: System Data
// *****************************************************************************
// *****************************************************************************

/* Structure to hold the object handles for the modules in the system. */
SYSTEM_OBJECTS sysObj;

// *****************************************************************************
// *****************************************************************************
// Section: Module Initialization Data
// *****************************************************************************
// *****************************************************************************


//<editor-fold defaultstate="collapsed" desc="SYS_DEVCON Configuration">

/*** System Device Control Initialization Data ***/

const SYS_DEVCON_INIT sysDevconInit =
{
    .moduleInit = {0},
};
// </editor-fold>
//<editor-fold defaultstate="collapsed" desc="SYS_FS Configuration">

/*** File System Initialization Data ***/


const SYS_FS_REGISTRATION_TABLE sysFSInit [ SYS_FS_MAX_FILE_SYSTEM_TYPE ] =
{
    {
        .nativeFileSystemType = FAT,
        .nativeFileSystemFunctions = &FatFsFunctions
    }
};
// </editor-fold>

// *****************************************************************************
// *****************************************************************************
// Section: Static Initialization Functions
// *****************************************************************************
// *****************************************************************************



// *****************************************************************************
// *****************************************************************************
// Section: System Initialization
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void SYS_Initialize ( SYS_INIT_DATA *data )

  Summary:
    Initializes the board, services, drivers, application and other modules.

  Remarks:
    See prototype in system/common/sys_module.h.
 */

void SYS_Initialize ( void* data )
{
    /* Core Processor Initialization */
    SYS_CLK_Initialize( NULL );
    sysObj.sysDevcon = SYS_DEVCON_Initialize(SYS_DEVCON_INDEX_0, (SYS_MODULE_INIT*)&sysDevconInit);
    SYS_DEVCON_PerformanceConfig(SYS_CLK_SystemFrequencyGet());
    SYS_PORTS_Initialize();

    /* Initialize Drivers */

    sysObj.drvTmr0 = DRV_TMR_Initialize(DRV_TMR_INDEX_0, (SYS_MODULE_INIT *)&drvTmr0InitData);

    SYS_INT_VectorPrioritySet(INT_VECTOR_T9, INT_PRIORITY_LEVEL1);
    SYS_INT_VectorSubprioritySet(INT_VECTOR_T9, INT_SUBPRIORITY_LEVEL0);
 
 
 
    /*** SPI Driver Index 0 initialization***/

    SYS_INT_VectorPrioritySet(DRV_SPI_TX_INT_VECTOR_IDX0, DRV_SPI_TX_INT_PRIORITY_IDX0);
    SYS_INT_VectorSubprioritySet(DRV_SPI_TX_INT_VECTOR_IDX0, DRV_SPI_TX_INT_SUB_PRIORITY_IDX0);
    SYS_INT_VectorPrioritySet(DRV_SPI_RX_INT_VECTOR_IDX0, DRV_SPI_RX_INT_PRIORITY_IDX0);
    SYS_INT_VectorSubprioritySet(DRV_SPI_RX_INT_VECTOR_IDX0, DRV_SPI_RX_INT_SUB_PRIORITY_IDX0);
    SYS_INT_VectorPrioritySet(DRV_DRV_SPI_ERROR_INT_VECTOR_IDX0, DRV_SPI_ERROR_INT_PRIORITY_IDX0);
    SYS_INT_VectorSubprioritySet(DRV_DRV_SPI_ERROR_INT_VECTOR_IDX0, DRV_SPI_ERROR_INT_SUB_PRIORITY_IDX0);
 
    sysObj.spiObjectIdx0 = DRV_SPI_Initialize(0, (const SYS_MODULE_INIT  * const)&drvSpi0InitData);
    sysObj.drvSDCard = DRV_SDCARD_Initialize(DRV_SDCARD_INDEX_0,(SYS_MODULE_INIT *)&drvSDCardInit);

    /* Initialize System Services */
    SYS_INT_Initialize();  

    /*** TMR Service Initialization Code ***/
    sysObj.sysTmr  = SYS_TMR_Initialize(SYS_TMR_INDEX_0, (const SYS_MODULE_INIT  * const)&sysTmrInitData);
    SYS_FS_Initialize( (const void *) sysFSInit );

    /* Initialize Middleware */
    /* Enable Global Interrupts */
    SYS_INT_Enable();

    /* Initialize the Application */
    APP_Initialize();

}

/*******************************************************************************
 End of File
*/





//以下、sys_ports_static.c
//---------------------------------------------------------------------------------------
/*******************************************************************************
  SYS PORTS Static Functions for PORTS System Service

  Company:
    Microchip Technology Inc.

  File Name:
    sys_ports_static.c

  Summary:
    SYS PORTS static function implementations for the Ports System Service.

  Description:
    The Ports System Service provides a simple interface to manage the ports
    on Microchip microcontrollers. This file defines the static implementation for the 
    Ports System Service.
    
  Remarks:
    Static functions incorporate all system ports configuration settings as
    determined by the user via the Microchip Harmony Configurator GUI.  It provides 
    static version of the routines, eliminating the need for an object ID or 
    object handle.

*******************************************************************************/

//DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
*******************************************************************************/
//DOM-IGNORE-END

#include "system_config.h"
#include "peripheral/ports/plib_ports.h"
#include "peripheral/int/plib_int.h"


void SYS_PORTS_Initialize(void)
{


    //SDカード関係
//CS
    TRISBbits.TRISB13 = 0;   //RB13 CS: out
    ANSELBbits.ANSB13 = 0;   //RB13 デジタルモード
    
   // TRISAbits.TRISA1 = 0;   //RA1 CS: out
  //  ANSELAbits.ANSA1 = 0;   //RA1 デジタルモード

//CD
    TRISFbits.TRISF12 = 1;   //RF12 CD: in
    ANSELFbits.ANSF12 = 0;   //RF12 デジタルモード
    CNPUFbits.CNPUF12 = 1;   //RF12 プルアップ  //CD
    
    //TRISBbits.TRISB8 = 1;   //RB8 CD: in
    //ANSELBbits.ANSB8 = 0;   //RB8 デジタルモード
    //CNPUBbits.CNPUB8 = 1;   //RB8 プルアップ  //CD

//WP
    TRISBbits.TRISB9 = 1;   //RB9 WP: in
    ANSELBbits.ANSB9 = 0;   //RB9 デジタルモード
    CNPUCbits.CNPUC2 = 1;    //RB9 プルアップ  //

//SPI6リマッピング
//SDI      // PPS Input Remapping
    TRISFbits.TRISF13 = 1;    //in
    ANSELFbits.ANSF13 = 0;    //必須 //デジタルモード
    PLIB_PORTS_RemapInput(PORTS_ID_0, INPUT_FUNC_SDI6, INPUT_PIN_RPF13 );    //SDI6    //RF13
  //  SDI6Rbits.SDI6R = 0b1001;       //RPF13ピンに SDI6(入力)を割り付け

//SDO   // PPS Output Remapping
    TRISBbits.TRISB15 = 0;
    ANSELBbits.ANSB15 = 0;   //必須  //デジタルモード
    PLIB_PORTS_RemapOutput(PORTS_ID_0, OUTPUT_FUNC_SDO6, OUTPUT_PIN_RPB15 ); //SDO6   //RB15
    
//    TRISFbits.TRISF12 = 0;
//    ANSELFbits.ANSF12 = 0;   //必須  //デジタルモード
//    PLIB_PORTS_RemapOutput(PORTS_ID_0, OUTPUT_FUNC_SDO6, OUTPUT_PIN_RPF12 ); //SDO6   //RF12
//    RPF12Rbits.RPF12R = 0b1010;       //RPF12ピンに SDO6の出力を割り付け


    
}


/*******************************************************************************
 End of File
*/




//以下、1lcd_lib_C32.h
//-------------------------------------------------------------------------------------
//*************************************************************************
//インクルードファイル    1lcd_lib_C32.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//XC32コンパイラ対応等で変更したものです。
//*************************************************************************
#include <p32xxxx.h>
#define lcd_Clock   200000000        // 単位はHzで指定

//LCDポート出力モード設定
#define lcd_port_DB7_Config()   TRISAbits.TRISA1 = 0
#define lcd_port_DB6_Config()   TRISBbits.TRISB11 = 0
#define lcd_port_DB5_Config()   TRISAbits.TRISA10 = 0
#define lcd_port_DB4_Config()   TRISAbits.TRISA9 = 0
#define lcd_rs_Config()     TRISBbits.TRISB6 = 0
#define lcd_stb_Config()    TRISBbits.TRISB7 = 0


//LCDポートデジタルポート設定
#define lcd_port_DB7_Digital()   ANSELAbits.ANSA1 = 0
#define lcd_port_DB6_Digital()   ANSELBbits.ANSB11 = 0
#define lcd_port_DB5_Digital()   ANSELAbits.ANSA10 = 0
#define lcd_port_DB4_Digital()   ANSELAbits.ANSA9 = 0
#define lcd_rs_Digital()   ANSELBbits.ANSB6 = 0
#define lcd_stb_Digiata()   ANSELBbits.ANSB7 = 0



// LCDポート出力
#define lcd_port_DB7    LATAbits.LATA1  //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB11 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATAbits.LATA10 //のDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATAbits.LATA9  //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_rs          LATBbits.LATB6  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定
#define lcd_stb         LATBbits.LATB7  //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定



void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);







//以下、1lcd_lib_C32.c
//----------------------------------------------------------------------------------------------



//**************************************************************************
//インクルードファイル    1lcd_lib_C32.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//XC32コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C32コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C32.h"

void lcd_delay_us(unsigned int usec)    //1μsec遅延関数
{
        int count;

        count = (int)(lcd_Clock/20000000)*usec;

        do      //実測: at 200MH (Clock=200000000)
        {       //delay_us(1000)→1000.4μsec、 delay_us(100)→100.6μsec、delay_us(10)→10.5μsec、delay_us(1)→1.5μsec
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

                count--;
        }while(count != 0);
        

}

void lcd_delay_ms(unsigned int msec)    //1msec遅延関数
{
        unsigned int i;
        
        for(i=0; i<msec; i++)
        lcd_delay_us(1000);
}


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        lcd_delay_us(3);                //3μsecウェイト
//      lcd_delay_us(1);                //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
        lcd_delay_us(3);                //3μsecウェイト
//      lcd_delay_us(1);                // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        lcd_delay_us(50);               //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        lcd_delay_ms(2);        //      2msec待ち
        else
        lcd_delay_us(50);       //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
    //LCDポート出力モード設定
    lcd_port_DB7_Config();
    lcd_port_DB6_Config();  
    lcd_port_DB5_Config();
    lcd_port_DB4_Config();
    lcd_rs_Config();
    lcd_stb_Config();

    //LCDポートデジタルポート設定
    lcd_port_DB7_Digital();
    lcd_port_DB6_Digital();
    lcd_port_DB5_Digital();
    lcd_port_DB4_Digital();
    lcd_rs_Digital();
    lcd_stb_Digiata();
    
        lcd_delay_ms(20);               //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(5);                //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}



 <動作結果>
1. ピクチャー

   ステップ  液晶表示  
 @  SDカードスロットに SDカード挿入を確認    
 A ファイルオープン成功     
 B  書き込み成功    
 C  読み出し内容表示
 液晶1行目: ファイル名
 液晶2行目: 読み出し内容
   

2.  動画(YouTube)



★ ADコンバータ値読み書き          <dsPIC  C30編>
  ADコンバータ入力値を読み込んでのSDカードへ書込み、そしてこのSDカード内のADコンバータ値を読み出して
  DAコンバータに同じ時間軸で再現する例を紹介します。

<試作品仕様>
 @外部発振器からの三角波(周波数:1Hz Vp-p:0−4V)をAD変換してリアルタイムでSDカードに書き込む
 A1000個のデータをSDカードに書き込んだら書き込みを終了して、SDカードから書き込んだデータを読み出してリアル
  タイムでDAコンバータMCP4822に出力する。
 B書き込み及び読み出しのサンプリング周波数は100Hzとする。  

<試作品の回路図> (→ 回路図のPDFファイル


<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています



   <プログラム例>   


///************************************************************/
// ADコンバータ値をSDカードに書き込み
//   その後 SDカード読込            dsPIC30F4013
//************************************************************/
// MPLAB プロジェクトへの追加ファイル
// Source Filesフォルダ   FSIO.c
//                    SD-SPI.c
//                    1lcd_lib_C30.c
//                    SD R_W AD 4013.c
// Header Filesフォルダ   FScohfig.h
//                    FSDefs.h
//                    FSIO.h
//                    GenericTypeDefs.h
//                    SD-SPI.h
//                    1lcd_lib_C30.h
// Linker Scriptフォルダ  p30f4013.gld
// Library Filesフォルダ  lib30F4013-coff.a

#include        "p30f4013.h"
#include        "1lcd_lib_C30.h"
#include        "adc12.h"
#include        "stdio.h"
#include        <timer.h>

#include        "FSIO.h"

_FOSC(CSW_FSCM_OFF & XT_PLL8);                          // (10MHz)x8=80MHz
_FWDT(WDT_OFF);
_FBORPOR(PBOR_ON & BORV_42 & PWRT_64 & MCLR_EN);
_FGS(CODE_PROT_OFF); 

unsigned int Config1 =          //ADCON1レジスタの設定
        ADC_MODULE_ON &                 //ADON bit15=1 : ADコンバータモジュール → ON  //AD Module On/Off
        ADC_IDLE_CONTINUE &             //ADSIL bit13=0 : アイドル時の動作 → 動作継続 //Idle Mode Operation
        ADC_FORMAT_INTG &               //FORM bit9-8=00 :出力データのフォーマット → 整数 //Result Output Format
        ADC_CLK_AUTO &                  //SSRC bit5-7=111 :変換開始トリガ設定  //Conversion Trigger Source
                                                        //       →ADCON3のSAMCによるクロック(サンプルホールド)が終了後変換自動開始
        ADC_AUTO_SAMPLING_OFF & //ASAM bit2=1 : ADサンプリング自動開始→手動開始 //Auto Sampling Select
        ADC_SAMP_OFF;                   //SAMP bit1=0 : サンプリング手動制御→OFF //Sample Enable
                                                        //  (例)ASAM = 0(ADC_AUTO_SAMPLING_OFF) の時 SAMP=1(ADC_SAMP_ON)で変換開始
                                                        //DONE bit0     : AD変換終了フラグ(AD変換が終了すると1が立つ、 書き込み不可)

unsigned int Config2 =          //ADCON2レジスタの設定
        ADC_VREF_AVDD_AVSS &    //VCFG bit13-15=000: S/Hアンプのリファレンス設定: 基準電圧Vdd、シングルエンド //Voltage Reference
        ADC_SCAN_OFF &                  //CSCNA bit10=0 : MUX交互自動スキャン制御→オフ //Scan Section
        ADC_SAMPLES_PER_INT_1 & //SMPI bit2-5 : 割込み頻度→1回毎 //Number of Samples between Interrupts
        ADC_ALT_BUF_OFF &               //BUFM bit1=0: 交互バッファー制御→なし //Buffer mode Select
        ADC_ALT_INPUT_OFF;              //ALTS bit0=0: AD入力の複数バッファーへの格納//Alternate Input sample Mode Select(

unsigned int Config3 =          //ADCON3レジスタの設定
        ADC_SAMPLE_TIME_8 &             //SAMC bit8-12 :サンプルホールド時間 → 8サイクル(TAD)//Auto Sample Time bits
        ADC_CONV_CLK_SYSTEM &   //ADRC bit7=0 :AD変換クロック→システムクロック //Conversion Clock Source Select
        ADC_CONV_CLK_32Tcy;             //ADCS bit0-5 :変換クロック数→32Tcy(設定のMAXを選択) //Conversion Clock Select

unsigned int ConfigPort =       //ADPCFGレジスタの設定 ANLOG/DIGITAl Pin Select
                                                                //ex1.  ENABLE_ALL_ANA   ex2. ENABLE_ALL_DIG   ex3. ENABLE_AN0_ANA & ENABLE_AN1_ANA
        ENABLE_AN1_ANA;                 //AN1 → アナログポート

unsigned int ConfigScan =       //ADCSSLレジスタの設定         Scan Channel Select
        SCAN_NONE;                              //ADCSLL = 0x0000 : 自動スキャン→スキャンせず

unsigned int Channel1 =         //ADCHSレジスタの設定
        ADC_CH0_POS_SAMPLEA_AN1 &       //マルチプレクサA(S/Hアンプ)のVref+への接続チャンネル → チャンネル1
        ADC_CH0_NEG_SAMPLEA_NVREF;      //マルチプレクサA(S/Hアンプ)のVref-への接続チャンネル → Vss
        

unsigned int Count;
unsigned int AdcValue;
char Buf[17];   //文字列のバッファー用レジスタ
int Chanel = 0; //MCP4822 ChanelA 選択                                            

FSFILE* pfile; 
int N_Write;                    //書き込み回数戻り値
unsigned int N_Read;    //読み出し回数戻り値

int Mode_SD = 0;                //0:SDカード書き込みモード  0:SDカード読込モード
 

void delay_ms(unsigned int);
void AdcFunc(void);
//-------------------------------------------

void delay_ms(unsigned int N)                   //ウェイト関数
{
        __delay32(Clock/4000*N);
}

void DAout(unsigned int Out)            //DAコンバータ MCP4822への出力関数
{
        int     i =0;

        LATDbits.LATD9 = 0;     // clock low  // RD9 : Clock(SCK)
        LATDbits.LATD8 = 0;     // cs low (select) // RD8 : Chip Select(CS)
        LATDbits.LATD3 = Chanel; // VoutAに出力 0:Chanel A  1:Chanel B 
                                                         // RD3 : Data(SDI)
        LATDbits.LATD9 = 1;     // clock high
        LATDbits.LATD9 = 0;     // clock low

        LATDbits.LATD3 = 1;     //dumy
        LATDbits.LATD9 = 1;     // clock high
        LATDbits.LATD9 = 0;     // clock low

        LATDbits.LATD3 = 0;     //ゲイン設定ビット 1: G = 1      0: G = 2
                                        // G = 2; V = Data/4096 * 2.048*2 [V]
        LATDbits.LATD9 = 1;     // clock high
        LATDbits.LATD9 = 0;     // clock low

        LATDbits.LATD3 = 1;     //シャットダウン設定ビット 1: 出力イネイブル    0: シャットダウン
                        // output enable
        LATDbits.LATD9 = 1;     // clock high
        LATDbits.LATD9 = 0;     // clock low

        for(i=0; i<12; i++)             // 送信データをMSBから順次1ビットづつ出力する
        {
                if((Out & 0b0000100000000000) == 0)LATDbits.LATD3 = 0;
                else LATDbits.LATD3 = 1;
                Out = (Out << 1);
                LATDbits.LATD9 = 1;     // clock high
                LATDbits.LATD9 = 0;     // clock low
        }

        LATDbits.LATD8 = 1;     // cs high  (MCP4822 Disable)
} 


        
void SD_Func(void)                                              // AD変換読み取り & 液晶表示
{
        float Volt;
        unsigned int    I;      
        unsigned int    F;
        unsigned int Buf_Input[1];              //AD読込みのホールド値&SDカード書き込み値
        unsigned int Buf_Output[1];
        
        if(Mode_SD == 0)        //SDカードへ書き込み
        {
                SetChanADC12(Channel1);                 //Vref-(RB1、AN1) → GND
                ADCON1bits.SAMP =1;                             //サンプリング開始
                                                                                //サンプルホールド時間:8TAD (ADCON3のSAMC<3:0>)
                                                                                //変換の自動開始
                                                                                //変換時間:31TAD (ADCON3のADCS<5:0>)

                while(!ADCON1bits.DONE);                //AD変換終了フラグが1になるまでまつ

                Buf_Input[0] = ADCBUF0;                         //AD変換値読込み(読込みが早い) //バッファー0の読み出し
                N_Write = FSfwrite((const void*)Buf_Input,sizeof(unsigned int),1,pfile);//ファイルにデータ書き込み
 

       if(N_Write == 1)        //正常な場合:書き込み回数が返ってくる
        {
                        Count++;
                }
                else    //異常な場合
                {
                        lcd_clear();    
                        sprintf(Buf,"Write No%d NG !!",Count);     //液晶に"Write NG !" を表示
                        lcd_str(Buf);
                        return 0;
                }
        }
        else
        {

                PORTFbits.RF5 = 0;                      //CS=0 SDカードのチップセレクトenable 

                N_Read = FSfread(Buf_Output,sizeof(unsigned int),1,pfile);//ファイルからデータ読込み
                PORTFbits.RF5 = 1;  //CS=1 SDカードのチップセレクトdisable  
 
                if(N_Read != 0)
                {
                        DAout(Buf_Output[0]);   // SDからの出力をMCP4822に出力
                }
        }

}

void _ISR _T1Interrupt(void)          //100Hzの割込み発生
{
    IFS0bits.T1IF = 0;      //IFS0レジスタの T1IF(タイマ1の割込み検出)フラグリセット
        SD_Func();                              // AD変換読み取り & 液晶表示              
}


/// メイン関数
int     main(void) {

        TRISB = 0b0000000000000010;     // AD入力のbit1(AN1 RB1)のみ入力
        TRISF = 0;
        TRISD = 0;                                              //ポートDを出力モードに設定 
    TRISF = 0;
                        
        OpenADC12(
                                Config1,                //ADCON1レジスタの設定
                                Config2,                //ADCON2レジスタの設定
                                Config3,                //ADCON3レジスタの設定
                                ConfigPort,             //ADPCFGレジスタの設定
                                ConfigScan              //ADCSSLレジスタの設定
                                                );


///サンプリング周波数 100Hz(10Hz)
///     bit15:タイマOn制御ビット bit14:未実装 ビット13
        OpenTimer1(T1_ON  &                //タイマ1ON
                   T1_GATE_OFF     &       //ゲート制御off
                   T1_PS_1_256 &           //プリスケーラ 1/256
                   T1_SYNC_EXT_OFF &       //クロック同期制御OFF
                   T1_SOURCE_INT   ,       //クロック源:内部クロック
                   80000000/4/100/256 - 1    //サンプリング周波数100Hz  
//                                 80000000/4/10/256 - 1    //サンプリング周波数10Hz  
                   );

        lcd_init();                                                     // LCD初期化
        lcd_cmd(0b00001100);                            // カーソル:OFF  ブリンク:OFF

        lcd_clear();                                            // 全消去
        sprintf(Buf,"SD Ver6 !!%u",Count);//arguementがないと遅い  C30のバグ?
        lcd_str(Buf);                                           //液晶表示  

        delay_ms(2000);

    ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_ON);    //割込みレベル5 タイマ1割込みON
    EnableIntT1;                                    //割込み許可


        PORTFbits.RF5 = 0;                      //CS=0 SDカードのチップセレクトenable 
    LATDbits.LATD2 = 1;

        while(!FSInit());                       //SDカードイニシャライズ SDカードの実装とフォーマット済をチェック

        pfile = FSfopen("DATA.DAT","w");        //ファイル書き込みモードでオープン 但しファイルがなければ新規ファイル作成

        PORTFbits.RF5 = 1;  //CS=1 SDカードのチップセレクトdisable               
            Mode_SD = 0;        //SD書き込みモード
        Count = 0;
        ConfigIntTimer1(T1_INT_PRIOR_7 & T1_INT_ON);    //割込みレベル5 タイマ1割込みON
        EnableIntT1;                                                                    //割込み許可

        do
        {
        }while(Count < 1000);   // 50個の符号なし整数(2バイト)データをSDカードに書き込むまで繰り返す
                PORTFbits.RF5 = 1;  //CS=1 SDカードのチップセレクトdisable 
        DisableIntT1;
        FSfclose(pfile);        //      ファイルを閉じる

                PORTFbits.RF5 = 0;                      //CS=0 SDカードのチップセレクトenable 
                pfile = FSfopen("DATA.DAT","r");        //ファイル読込みモードでオープン 
        Mode_SD = 1;    //SDカード読込モード
        N_Read = 1;     //0だとwhile(N_Read !=0)が割込みが入る前に真となりループを抜けてしまう
        EnableIntT1;    //タイマ1割込み許可
        do
        {
        }while(N_Read !=0);                             //N_ReaDに0が戻ってくる(EOF)まで待つ

        FSfclose(pfile);        //      ファイルを閉じる
        DisableIntT1;

                while(1);


        CloseADC12();                           //AD変換終了処理
        CloseTimer1();
        return 0;
}







//**************************************************************************
//インクルードファイル    1lcd_lib_C30.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C30コンパイラー
//  内蔵関数は以下
//  lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//  lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C30.h"
unsigned int _1usec;    // 1μsec待つに必要なウェイト回数
unsigned int _50usec;   //50μsec待つに必要なウェイト回数
unsigned long N_msec;   // 1msec待つに必要なウェイト回数



//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;             // 表示データの場合
        else
                lcd_rs = 0;             // コマンドデータの場合

        __delay32(_1usec);              //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        __delay32(_1usec);              // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);            // 下位4ビット出力
        __delay32(_50usec);             //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)           // clear Homeの場合
        __delay32(2*N_msec);            //      2msec待ち
        else
        __delay32(_50usec);             //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
//      __delay32(15*N_msec);           //15msecウェイト
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                     //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                  //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        _1usec =(unsigned int)( Clock / 4000000);       // 1μsecに要するウェイト回数
                                                        //__delay32(N) : Nが11以下の場合でも11回ウェイト
        _50usec = (unsigned int)(Clock / 4000000 * 50); //50μescに要するウェイト回数

        N_msec = (unsigned long int)(Clock / 4000);     // 1msecに要するウェイト回数
                                                        // = Clock / 4000000*1000
        __delay32(20*N_msec);           //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(5*N_msec);            //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}



*************************************************************************************************   
*************************************************************************************************   
***                                              ***
***      その他のインクルードファイルは                                                       ***
***          「C言語ではじめるPIC24F活用ガイドブック」(後閑哲也 著 技術評論社)             ***
***                                        の付属CDに収納されています。     ***
*************************************************************************************************   
*************************************************************************************************   


//************************************************************************************************
//************************************************************************************************
//以下は インクルードファイル SD-SPI.hの中で変更部位のみを抜粋したものです。 ピンアサイン関係の
 変更です。
// 
    …
    …
/********************************************************************/
/*                Pin and register definitions                      */
/********************************************************************/

#define SD_CS                           PORTFbits.RF5
#define SD_CS_TRIS                      TRISFbits.TRISF5
#define SD_CD                           PORTDbits.RD0
#define SD_CD_TRIS                      TRISDbits.TRISD0
#define SD_WE                           PORTDbits.RD1
#define SD_WE_TRIS                      TRISDbits.TRISD1

// Registers for the SPI module you want to use
#define SPICON1                         SPI1CON
#define SPISTAT                         SPI1STAT
#define SPIBUF                          SPI1BUF
#define SPISTAT_RBF                     SPI1STATbits.SPIRBF
#define SPICON1bits                     SPI1CONbits
#define SPISTATbits                     SPI1STATbits
// Tris pins for SCK/SDI/SDO lines
#define SPICLOCK        TRISFbits.TRISF6        
#define SPIIN   TRISFbits.TRISF2        
#define SPIOUT  TRISFbits.TRISF3

 …
 …


//************************************************************************************************
//************************************************************************************************
// 以下は インクルードファイル SD-SPI.cの中で修正した部分のみを抜粋したものです。
// SDカードのソケットにより書き込みプロテクトの論理が異なるものがあるようです。
//                           (後閑さんにおしえていただきました)
// わたしが使用したSDカードソケットはサンハヤト鰍フCK29です。CK29のライトプロテクトWEの論理は // ”ライトプロテクトが書き込み可能な位置にあるSDカードを奥まで挿入すると ON ”です。すなわち // 以下の場合 SDカードのWEはOFFです。 //    ・SDカードが挿入されていない場合 //    ・ライトプロテクトが書き込み不可の位置にあるSDカードが奥まで挿入されている場合
//
// 以下は修正前のソースコードです。SDカードの検出チェックの部分です。修正したものは SD_WEの // 前の”!”が削除されています。 //  // BYTE // WriteProtectState(void)
// {
//   return(!SD_WE); // 修正後は”!”が削除されています。
// }
// // // // 以下は修正後のソースコードです。 BYTE WriteProtectState(void)
{
   return(SD_WE); // ”!”が削除されています。
}



//*********************************************************************************************************
//*************************************************************************************************:********

 // 以下はFSconfig.hファイルの中で変更した部分のみを記載しています。システムクロックを20MHzから80MHzに変更
 //したことに伴う変更です

// Define the system clock speed
//#define SYSTEM_CLOCK (DWORD)20000000
#define SYSTEM_CLOCK (DWORD)80000000




<動作結果>
外部発振器からの三角波(1Hz Vp-p:0-4V)をSDカードに読み込んだ後、再生してDAコンバータに出力した波形です。
サンプリング周波数が100Hzの場合と10Hzの場合を示します。
 尚、サンプルプログラムはサンプリング周波数が100Hzの場合のものです。

ADコンバータ入力電圧
(dsPIC30F4013のRB1ピン)
DAコンバータ出力電圧
(MCP4822の8ピン)
サンプリング周波数:100Hz サンプリング周波数:10Hz

 (外部発振器: ファンクションジェネレータ(INSTEC SFG-2104)     波形観測:デジタルオシロ 岩通 DS-5102


■ WAV録音付きMP3プレーヤー

(1) PIC24FJ64GA002 編

 PIC24FJ64GA002を使用した、WAVファイル形式録音機能付きMP3プレーヤーを紹介します。MP3のデコーダーICとしてはVS1011Eを
使用しています。 VS1011Eのライブラリ関数(VS1011.h、VS1011.c)は後閑哲也さんが設計されたものです。後閑さんには本プレーヤー製作に
あたり貴重なアドバイスを多々いただきました。
 
 ★ mp3デコーダーIC VS1011Eは QFPがキバンにハンダ付けされ、端子が2.54インチのピンヘッダーコネクタに変換されたもの(700円/個)が
   秋月電子で
販売されています。私はこれをつかって試作品を製作しました。

<試作品の仕様>
・再生モードと録音モードを有すること。再生、録音のモード切替はモメンタリースイッチでおこなうこと
・mp3ファイルについては再生のみとし、エンコード機能はつけない
・mp3、wav形式でSDカードに収録されている音楽・音声データを再生できること
・mp3ファイルのデコーダICとして、VS1011Eを使用すること
・再生はSDカード内にある音楽・音声データを順番におこなう。但し、スキップボタンをもうけ再生データをスキップできるようにすること
・録音は、マイクレベルの音声信号を増幅しPICでAD変換して、データはSDカードにWAV形式のファイルとしてファイルすること
・録音するWAVファイルの諸元は下記とする
 @圧縮のフォーマットID …… リニアPCM
 Aチャンネル数 …… モノラル
 Bサンプリングレート……22050 Hz
 Cデータ転送速度 ……44100 バイト/sec
 DBlock align …… 2 バイト/サンプル
 E量子化ビット数……16ビット
・録音するファイル名はVOICE.wavとする。SDカード内のルートにこのファイル名のファイルが存在しない場合はファイルをつくること。 また、 
 すでにVOICE.wavが存在する場合は上書きするものとする。
・キャラクタ液晶により、録音/再生時のファイル名を表示する。


<試作品の回路図>  (→ 回路図のPDFファイル








<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています







   <プログラム例>
/*
wavファイル録音付きMP3プレーヤ
   PIC24FJ64GA002+VS1011e,SDカード
                                     Ver.2 //バグ修正
                                           //・WAVファイル生成安定化
                                           //・スキップ操作における選択ファイル順序玉成   他
*/
#include <p24FJ64GA002.h>
#include "GenericTypeDefs.h"
#include "FSIO.h"
#include "VS1011.h"
#include <uart.h>
#include <timer.h>



#define STX     0x02    //STX
#define ETX     0x03    //ETX

/// コンフィギュレーション ビットの設定
_CONFIG1
(
        JTAGEN_OFF &  //JTAGポート: OFF
        GCP_OFF &      //コードプロテクト: OFF
        GWRP_OFF &      //書き込みプロテクト: OFF
        BKBUG_OFF &     //バックグランドデバック: OFF
        COE_OFF &       //クリップオン エミュレーション: OFF 
        ICS_PGx1&       //ICDピンの選択: EMUC/EMUDをPGC1/PGD1と共用
        FWDTEN_OFF              //ウォッチドックタイマ: OFF 
)

_CONFIG2
( 
        IESO_OFF &    // 2速度スタートアップ機能:OFF
        FNOSC_FRCPLL &  //内臓高速RC発振(8MHZ)回路 + 4倍PLL → 32MHz(= 8MHz × 4)
        FCKSM_CSDCMD &  //クロック切替え制御:OFF クロックモニタ:OFF
        OSCIOFNC_OFF &  //OSCO/RC15 function: OSCO or Fosc/2
        IOL1WAY_OFF &   //RP Register Protection: Unlimited Writes To RP Registers
        I2C1SEL_PRI &   //I2C1 pins Select: Use Primary I2C1 pins
        POSCMOD_NONE    //発振回路モード Oscillator Selection:  Primary disabled
) 


struct myWaveHeader             //全ヘッダサイズ: 44バイト
{
        char id_RIFF[4];        //Chunk ID RIFFヘッダ // 4バイト
        unsigned long int size_file;    //ファイルサイズ(総ファイルサイズ - 8)バイト //4バイト
        char id_WAVE[4];        //Chunk ID WAVE //4バイト
        char id_fmt[4];         //Chunk ID fmt  //4バイト
        unsigned long int size_fmt;     //フォーマット関連定義データのサイズ     //4バイト
        unsigned int code_wavefmt;      //WAVEファイルの圧縮フォーマットコード 但し、リニアPCMは圧縮なし//2バイト
        unsigned int channel;   //チャンネル数 //2バイト
        unsigned long int rate_sample;  //サンプリングレート     //4バイト
        unsigned long int rate_tranfer;         //転送速度[byte/sec] //4バイト
        unsigned int align_block;               //サンプルあたりのバイト数[byte/サンプル]       //2バイト
        unsigned int bit_sample;        //量子化ビット数[bit]  //2バイト

        char id_data[4];        //Chunk ID data //4バイト
        unsigned long int size_data;    //サンプリングデータのサイズ[byte] //4バイト

}
;

struct myWaveHeader mywaveheader =              // WAVEファイルヘッダ構造体の初期化   //44バイト
        {
                "RIFF",         //Chunk ID RIFF     // 4バイト
                0x0006C28C,     //(仮)ファイルサイズ: 443020バイト //特に値に意味なし
        "WAVE",         //Chunk ID WAVE     //4バイト
        "fmt ",         //char id_fmt[4];         //Chunk ID fmt  //4バイト
        16,                     //16バイト at リニアPCM   フォーマット関連定義データのサイズ   //4バイト
        0x0001,         //WAVEファイルの圧縮フォーマットコード: リニアPCM //2バイト
        1,                      //チャンネル数: モノラル  //2バイト
        22050,          //サンプリングレート: 22.05[Hz]     //4バイト
                44100,          //転送速度: 44100[byte/sec] //4バイト  //サンプリングレート: 22.05[Hz]  
                2,                      //サンプルあたりのバイト数: 2[byte]/サンプル      //2バイト
        16,                     //量子化ビット数: 16[bit]  //2バイト
        "data",         //Chunk ID data //4バイト
                0x0006C267      ////(仮)サンプリングデータのサイズ: 442983バイト //特に値に意味なし
        };
 
struct myWaveHeader* ptrWH;     //構造体のポインタ


Clock = 320000000;      //
FSFILE *fptr,*fptr2;    //FATファイル用構造体のポインタ変数 
size_t result;
BYTE Buffer[256];
SearchRec Record;
SearchRec *rptr = &Record;
BYTE Volume, ChgFlag, BASS;     // MP3用変数
 

int Mode = 0;   //録音/再生モード 0:再生 1:録音
unsigned long int adr_SD;
unsigned long int count_block = 0;      //SD送信ブロック(512バイト)数
unsigned int size_dataBlock = 512;

int count_buf1 = 0;     //バッファ1データ数
int count_buf2 = 0;     //バッファ2データ数

int flag_buf1 = 0;      //音声データバッファ1の状態 
int flag_buf2 = 0;      //音声データバッファ2の状態
                                        // 0:音声データ受信可能状態 1:SDへ音声データ送信可能状態
int mode_tranceive = 0; //送受信モード 
                                                //0: バッファ1=音声タ受信、バッファ2=SD送信
                                                //1: バッファ1=SD送信モード、バッファ2=音声受信

int data1_sound[512];   //音声データバッファ1
int data2_sound[512];   //音声データバッファ2


int ix = 0,iy = 0;

char* str_filename;
int Stop_SDwriting = 0;// 1: SDカードへの書込み停止 0: 書込み許可
int Next = 0;




void my_delay_ms(unsigned int N)   //1msec のディレー関数
{
        __delay32(Clock/2000*N);        //システムクロック周波数2000000HzのPICの1サイクルディレー時間=1μsec
}                                                                // → Clock(Hz)/2000 = 1000μsec = 1msec 

void wav_end(void)      //録音ファイル完成処理
{
        unsigned int result;
        int count_N;


        mywaveheader.size_data = count_block * 1024 ;   //[バイト]
        mywaveheader.size_file = count_block * 1024 + sizeof mywaveheader - 8;  //[バイト]


        count_N = 0;
    do{
        delay_ms(100);
        result = FSfseek(fptr,0,SEEK_SET);      //ファイルの先頭にファイルポインタの位置を移動
        putcUART1('\r');        // ¥r: 液晶画面をクリア& 文字表示位置を一行目の先頭へ移動
        printf("fseek N=%d   ",count_N);
        putcUART1('\n');        // ¥n: 文字表示位置を2行目の先頭へ
        printf("result=%d          ",result);   //文字データを送信
        putcUART1(STX);         // 液晶画面表示
        count_N++;
     }while(result != 0);

        delay_ms(1500);

        count_N = 0;
    do{
        delay_ms(100);
        result = FSfwrite((const void*)ptrWH,sizeof(struct myWaveHeader),1,fptr);       //ファイルにヘッダー情報書き込み

        putcUART1('\r');        // ¥r: 液晶画面をクリア& 文字表示位置を一行目の先頭へ移動
        printf("blk=%lu  N=%d     ",count_block,count_N);
        putcUART1('\n');        // ¥n: 文字表示位置を2行目の先頭へ
        printf("result=%d          ",result);   //文字データを送信
        putcUART1(STX);         // 液晶画面表示
        count_N++;
    }while(result != 1);


        delay_ms(1500);
        count_N = 0;
    do{
        delay_ms(100);
        result = FSfclose(fptr); //      ファイルを閉じる
        putcUART1('\r');        // ¥r: 液晶画面をクリア& 文字表示位置を一行目の先頭へ移動
        printf("fclose  N=%d         ",count_N);
        putcUART1('\n');        // ¥n: 文字表示位置を2行目の先頭へ
        printf("result=%d          ",result);   //文字データを送信
        putcUART1(STX);         // 液晶画面表示
        count_N++;
    }while(result != 0);


    delay_ms(1500);


}


void playmode_LCD()     //液晶表示
{
                putcUART1('\r');        // ¥r: 液晶画面をクリア& 文字表示位置を一行目の先頭へ移動
                printf("%s              ",str_filename);
                putcUART1('\n');        // ¥n: 文字表示位置を2行目の先頭へ
                printf("Play Mode       ");     //文字データを送信
                putcUART1(STX);         // 液晶画面表示
}


void play()             // 音楽データの出力 
{
        int i;

        ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_OFF);   //タイマ1割込み禁止
        DisableIntT1;

        if(fptr != 0)   // 正常にオープンできたか?
        {
                do{             // ファイルのEOFまで音声データ連続出力 
                        SRbits.IPL = 7;         // SPI処理中は割り込み禁止
                        MP3_XDCS_IO = 0;        //#define MP3_XDCS_IO    LATBbits.LATB15=0 → DREQ=0
                                                                
                        result = FSfread(Buffer, 1, 256, fptr); //SDカードのデータを256バイト単位で読み出し
                        for(i= 0; i<result; i++)        // 読み出したバイト数だけ繰り返し
                        {               
                                SendData(Buffer[i]);    // 音楽データ送信
                        }
                        SRbits.IPL = 2;                         // 割り込み再許可
                        if(Mode == 1)return;            //録音モードなら 再生は終了
                        if(Next == 1)result = 0;
                } while(result != 0);                   // ファイルのEOFまで継続

                Next = 0;

                MP3_XDCS_IO = 1;
                // 再生完了処理       
                FSfclose(fptr);         // ファイルのクローズ
                PlayEnd();                      // 再生終了処理

                result = FindNext(rptr);        // 連続再生のため次のファイルへ
                if((result != 0) || (Record.attributes != ATTR_ARCHIVE))
                FindFirst("*.*", ATTR_ARCHIVE, rptr);   // ファイルの終わりなら再度最初から繰り返し  

                fptr = FSfopen(Record.filename, "r");
                str_filename = Record.filename;

                SRbits.IPL = 2; // 割り込み再許可

                playmode_LCD();

        }
}

void SD_write()
{
        if(mode_tranceive == 0) //バッファ2=SD送信、バッファ1=音声受信モード
        {
                if(flag_buf2 == 1)      //バッファ2がSDへ送信可能状態の場合・バッファ1は音声受信可能状態
                {
                        FSfwrite((const void*)data1_sound,sizeof(int),size_dataBlock,fptr);//SDカードにデータ書き込み
                        count_block++;
                        flag_buf2 = 0;  //→ バッファ2送信完了、受信可能状態
                }
        }
        else    //バッファ1=SDへ送信可、バッファ2=音声受信モード
        {
                if(flag_buf1 == 1)      //バッファ1がSDへ送信可能状態の場合・バッファ2は音声受信可能状態
                {
                        FSfwrite((const void*)data2_sound,sizeof(int),size_dataBlock,fptr);//SDカードにデータ書き込み
                        count_block++;
                        flag_buf1 = 0;  //→ バッファ1送信完了、受信可能状態
                }
        }

        if(Stop_SDwriting == 1) //
        {
                delay_ms(200);
                wav_end();      //録音wavファイル終了処理
                Mode = 0;       //音楽再生モードへ
                delay_ms(1000);

                fptr = FSfopen("VOICE.WAV", "r");               // ファイルのオープン

                putcUART1('\r');        // ¥r: 液晶画面をクリア& 文字表示位置を一行目の先頭へ移動
                printf("VOICE.WAV              ");
                putcUART1('\n');        // ¥n: 文字表示位置を2行目の先頭へ
                printf("Play Mode       ");     //文字データを送信
                putcUART1(STX);         // 液晶画面表示
        }


}

void _ISR _T1Interrupt(void)    //タイマ1割込み、ADコンバータ読み込み、SDカード書き込み
{
        unsigned int temp1;
        long int temp2;

        IFS0bits.T1IF = 0;      //フラグクリア

        AD1CON1bits.SAMP =1;            //サンプリング開始
        while(!AD1CON1bits.DONE);       //AD変換終了フラグがたつ(1になるまで)待つ
        temp1 = ADC1BUF0;            //ADC1のAN1のバッファーからAD変換結果を読込む
        temp2 = temp1*64 - 32768;               //32768 = 64*1024 / 2;  //無音基準レベル:32768( = unsigned int / 2)
        if(temp2 >= 32767) temp2 = 32767;       //音声レベルクリップ
        if(temp2 <= -32768)temp2 = -32768;

        //送信優先: 未送信データがバッファに残っている場合は入力する音声データは無視する 
        if(mode_tranceive == 0) //バッファ1=音声受信、バッファ2=SD送信
        {
                if(flag_buf1 == 0)      //バッファ1が受信可能状態なら
                {
                        data1_sound[count_buf1] = temp2;        //受信データをバッファ構造体1のdata_sound[ ]に保存
                        count_buf1++;
                        if(count_buf1 >= size_dataBlock)
                        {
                                count_buf1 = 0;
                                flag_buf1 = 1;  //→ バッファ1: 音声データフル・SD転送待ち
                                mode_tranceive = 1;
                        
                        }
                }
                //バッファ1にまだ未送信音声データが残っていた場合は、音声データは受信しない

        }
        else    //バッファ2=音声受信、バッファ1=SD送信
        {
                if(flag_buf2 == 0)      //バッファ2が受信可能状態なら
                {
                        data2_sound[count_buf2] = temp2;        //受信データをバッファ構造体2のdata_sound[ ]に保存
                        count_buf2++;
                        if(count_buf2 >= size_dataBlock)
                        {
                                count_buf2 = 0;
                                flag_buf2 = 1;  //→ バッファ2:音声データフル・SD転送待ち
                                mode_tranceive  = 0;
                        
                        }
                }
        }
                //バッファ2にまだ未送信音声データが残っていた場合は、音声データは受信しない
        
}

 
void __attribute__((interrupt, no_auto_psv)) _CNInterrupt(void) // スイッチ 変化割りこみ
{


        if(!PORTAbits.RA4)      //再生/録音ボタンがクリックされた場合
        {
        
                if(Mode == 0)   //再生モードの場合
                {
                        Mode = 1;       //録音モードへ
                        Stop_SDwriting = 0;     //SDカードへの書き込み許可


                        MP3_XDCS_IO = 1;        //VS1011E 音データ信号ラインOFF
                        MP3_XCS_IO = 1; //VS1011E チップセレクト解除

                        FSfclose(fptr); // 現在のファイルを強制クローズ
                        PlayEnd();              // 再生終了処理

                        delay_ms(200);

                        fptr = FSfopen("VOICE.wav","w"); //ファイル上書き込みモードでオープン 但しファイルがなければ新規ファイル作成

                        ptrWH = &mywaveheader;  //構造体にmywaveheaderの先頭アドレス設定
                        FSfseek(fptr,0,SEEK_SET);       //ファイルの先頭にファイルポインタの位置を移動
                        delay_ms(50);
                        FSfwrite((const void*)ptrWH,sizeof(struct myWaveHeader),1,fptr);        //ファイルにヘッダー情報書き込み
                        delay_ms(50);
                

                        adr_SD = 0x2C;                  //ファイルの先頭から0x2C(44)バイト(音声データ書き込み開始オフセット)のところにに
                        FSfseek(fptr,adr_SD,SEEK_SET);//ファイルポインタの位置を移動  
                        count_block = 0;        //SDカードに512バイト単位で書き込んだ回数をリセット

                        putcUART1('\r');        // ¥r: 液晶画面をクリア& 文字表示位置を一行目の先頭へ移動
                        printf("VOICE.wav       ");
                        putcUART1('\n');        // ¥n: 文字表示位置を2行目の先頭へ
                        printf("Record Mode     ");     //文字データを送信
                        putcUART1(STX);                         // 液晶画面表示

                        delay_ms(300);

                        //LATBbits.LATB3 = 1;   //LED 消灯

                ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_ON);    //割込みレベル0 タイマ1割込みON
                EnableIntT1;                                    //割込み許可
                }

                if((Mode == 1) && (count_block >= 10))  //録音モード かつ 10ブロック以上書き込んでいるななら(チャタリング防止)
                {
                        ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_OFF);   //タイマ1: 割り込み優先レベル5      //      IPC0bits.T1IP = 5;      
                        DisableIntT1;   //タイマ1: 割り込み禁止 //IEC0bits.T1IE = 0;

                        Stop_SDwriting = 1;     //SDカード書込み終了
                                                                //1ブロック書込み後終了処理開始
                                                                //★ここですぐ終了処理を行わないこと!!

        }


        }


        if(!PORTAbits.RA2)      //スキップボタンがクリックされた場合
        {
                Next = 1;       //再生中のファイルのセクタ読み込み終了後、次の曲を再生
        }

        IFS1bits.CNIF = 0;      // 変化割り込みフラグクリア


}


int main(void)
{

        CLKDIV = 0;                                             // クロック1/1

        TRISA = 0b0000000000011110;             //RA1-4は入力、その他出力
        TRISB = 0b0100011100000100;             //入力:RA2-3,RB3:out 8-10,14  他:出力

        //AD1CON1レジスタの設定        
        AD1CON1bits.ADON = 1;   //A/Dコンバータモジュール有効
        AD1CON1bits.ADSIDL = 0; //アイドルモード中もモジュール動作継続
        AD1CON1bits.FORM1 = 0;  //AD1CON1bits.FORM0 と2ビットでセット
        AD1CON1bits.FORM0 = 0;  //00: 符号なし整数 (参考)11:符号なし固定少数、10:固定少数、01:整数
                                //★ Michrochip PIC24FJ64GA002のデータシートでは00がIntegerとなっているがUnsigned Integerの誤植である。 
        AD1CON1bits.SSRC2 = 1;  //AD1CON1bits.SSRC2-AD1CON1bits.SSRC0 でセット
        AD1CON1bits.SSRC1 = 1;  //111: 内蔵カウンタでサンプリングを終了させ変換を開始する
        AD1CON1bits.SSRC0 = 1;  //(参考)000: SAMPビットでサンプリングを終了し変換を開始する
        AD1CON1bits.ASAM = 0;   //SAMPビットのセットでサンプリングを開始する。 (参考)1: 自動開始(前の変換終了後すぐサンプリングを開始する)
        AD1CON1bits.SAMP = 0;   //サンプリング停止

        //AD1CON2レジスタの設定
        AD1CON2bits.VCFG2 = 0;  //AD1CON2bits.VCFG2 - AD1CON2bits.VCFG0(VCFG<2:0>)の3ビットでセット
        AD1CON2bits.VCFG1 = 0;  //000:リファレンス電圧 → Vdd -Vss
        AD1CON2bits.VCFG0 = 0;  //(参考)001:リファレンス電圧 → 外部入力 - Vss 他
        AD1CON2bits.CSCNA = 1;  //マルチプレクサMUXAでのスキャン: する
        AD1CON2bits.SMPI3 = 0;  //AD1CON2bits.SMPI3 - AD1CON2bits.SMPI0(SMPI<3:0>)の4ビットでセット
        AD1CON2bits.SMPI2 = 0;  //0000: AD変換完了毎の割り込み発生(割り込み有効の場合)
        AD1CON2bits.SMPI1 = 0;  //(参考)0011: 4サンプルのAD変換終了後       割り込み発生(割り込み有効の場合)
        AD1CON2bits.SMPI0 = 0;  //
        AD1CON2bits.BUFM = 0;   //バッファーを1個の16ワードバッファとする。 (参考)1: 2組の8ワードバッファーとする
        AD1CON2bits.ALTS = 0;   //常にMUXAを入力マルチプレクサにする (参考)1: MUXA,MUXBを交互につかう

        //AD1CON3レジスタの設定
        AD1CON3bits.ADRC = 0;   //AD変換クロック源:システムクロック (参考)1: A/D内臓RCクロック
        AD1CON3bits.SAMC4 = 1;  //AD1CON3bits.SAMC4 - AD1CON3bits.SAMC0(SAMC<4:0>)の5ビットでセット
        AD1CON3bits.SAMC3 = 1;  //アクイジションタイム(Tad(クロック周期)×N)設定
        AD1CON3bits.SAMC2 = 1;  //1111: 31Tad
        AD1CON3bits.SAMC1 = 1;  //(参考)0001: 1Tad    0010: 2Tad    0011: 3Tad  ・・・・
        AD1CON3bits.SAMC0 = 1;  //
        AD1CON3bits.ADCS7 = 0;  //AD1CON3bits.ADCS7 - AD1CON3bits.ADCS0(ADCS<7:0>)の8ビットでセット
        AD1CON3bits.ADCS6 = 0;  //AD変換のクロックとクロック源の関係
        AD1CON3bits.ADCS5 = 0;  //0000 0101: 1Tad = 5Tcy        
        AD1CON3bits.ADCS4 = 0;  //(参考) 0000 0000: 1Tad = 0.5Tcy
        AD1CON3bits.ADCS3 = 0;  //      0000 0001: 1Tad = 1.0Tcy
        AD1CON3bits.ADCS2 = 1;  //          0000 0010: 1Tad = 1.5Tcy
        AD1CON3bits.ADCS1 = 0;  //                                ・・・・    
        AD1CON3bits.ADCS0 = 1;  //     1111 1111: 1Tad = 128Tcy

        //AD1CHSレジスタの設定
        AD1CHSbits.CH0NB = 0;   //マルチプレクサMUXB用負側入力選択ビット: VR-  (参考)1: AN1
        AD1CHSbits.CH0SB3 = 0;  //AD1CHSbits.CH0SB3 - AD1CHSBbits.CH0SB0(<CH0SB<3:0>)の4ビットでセット
        AD1CHSbits.CH0SB2 = 0;  //マルチプレクサMUXBの正側入力選択
        AD1CHSbits.CH0SB1 = 0;  //0000: AN0
        AD1CHSbits.CH0SB0 = 0;  //(参考)0001: AN1  0011 AN2    ....  1111: AN15
        AD1CHSbits.CH0NA = 0;   //マルチプレクサMUXA用負側入力選択ビット: VR-  (参考)1: AN1
        AD1CHSbits.CH0SA3 = 0;  //AD1CHSbits.CH0SA3 - AD1CHSbits.CH0SA0(<CH0SA<3:0>)の4ビットでセット
        AD1CHSbits.CH0SA2 = 0;  //マルチプレクサMUXAの正側入力選択
        AD1CHSbits.CH0SA1 = 0;  //0000: AN0
        AD1CHSbits.CH0SA0 = 0;  //(参考)0001: AN1  0011 AN2    ....  1111: AN15

        //AD1PCFGレジスタの設定  
        // ★デバイスリセットでは全ビット0となるためデフォルトではアナログ入力となるのでデジタルで使う多重ピンは、コンフィグレーションでデジタル設定が必要!! 
        //PIC24FJ64GA002にはないピン・設定も特に必要ないが設定
        AD1PCFGbits.PCFG15 = 1;//RA15/AN15アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
//      AD1PCFGbits.PCFG14 = 1;//RA14/AN14アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
//      AD1PCFGbits.PCFG13 = 1;//RA13/AN13アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG12 = 1;//RA12/AN12アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG11 = 1;//RA11/AN11アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG10 = 1;//RA10/AN10アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ    
        AD1PCFGbits.PCFG9 = 1;//RA9/AN9アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
//      AD1PCFGbits.PCFG8 = 1;//RA8/AN8アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
//      AD1PCFGbits.PCFG7 = 1;//RA7/AN7アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
//      AD1PCFGbits.PCFG6 = 1;//RA6/AN6アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG5 = 1;//RA5/AN5アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG4 = 1;//RA4/AN4アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG3 = 1;//RA3/AN3アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG2 = 1;//RA2/AN2アナログ入力orデジタル入力選択: デジタル (参考)0: アナログ
        AD1PCFGbits.PCFG1 = 0;//RA1/AN1アナログ入力orデジタル入力選択: アナログ (参考)0: アナログ ★AN1のみアナログ入力
        AD1PCFGbits.PCFG0 = 1;//RA0/AN0アナログ入力orデジタル入力選択: デジタル (参考)0: デジタル


        //      AD1CSSLレジスタの設定
        //読み込むチャンネル(入力端子)をセットする
        AD1CSSLbits.CSSL15 = 0; //AN15をMUXAでスキャンしない (参考)1: スキャンする
//      AD1CSSLbits.CSSL14 = 0; //AN15をMUXAでスキャンしない (参考)1: スキャンする
//      AD1CSSLbits.CSSL13 = 0; //AN13をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL12 = 0; //AN12をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL11 = 0; //AN11をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL10 = 0; //AN10をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL9 = 0;  //AN9をMUXAでスキャンしない (参考)1: スキャンする
//      AD1CSSLbits.CSSL8 = 0;  //AN8をMUXAでスキャンしない (参考)1: スキャンする
//      AD1CSSLbits.CSSL7 = 0;  //AN7をMUXAでスキャンしない (参考)1: スキャンする
//      AD1CSSLbits.CSSL6 = 0;  //AN6をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL5 = 0;  //AN5をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL4 = 0;  //AN4をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL3 = 0;  //AN3をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL2 = 0;  //AN2をMUXAでスキャンしない (参考)1: スキャンする
        AD1CSSLbits.CSSL1 = 1;  //AN1をMUXAでスキャンしない (参考)1: スキャンする ★AN1のチャンネルだけ読み込む
        AD1CSSLbits.CSSL0 = 0;  //AN0をMUXAでスキャンする (参考)0: スキャンしない



   /// インターバルタイマ1 周期 45.3μsec (音データサンプリング周期)
                OpenTimer1
                (
                        T1_ON &         //タイマ1ON
                        T1_GATE_OFF &   //ゲート制御ON
                        T1_PS_1_1 &             //プリスケーラ 1/1  1/8 1/64 1/256
                        T1_SYNC_EXT_OFF &       //クロック同期制御OFF
                        T1_SOURCE_INT,  //クロック源:内部クロック

                        724             //サンプリング周波数 22.05KHz
//                      362             //サンプリング周波数 44.1KHz     //SPI転送速度(現:1Mbps)アップ、アルゴリズム見直し等が必要
                                        // →  22.68×(32MHz/2MHz)=362.88  → 363
                );                      //PR1 = 363 - 1 = 362



        CNPU1 = 0b0000000000000001;     //CN0(RA4),CN7(RB3)  プルアップするポート
        CNPU2 = 0b0100000011100001;     //CN16(RB10),CN21(RB9),CN22(RB8),CN23(RB7),CN29(RA3),CN30(RA2) プルアップするポート 

        CNEN1 = 0b0000000000000001;     //CN0(RA4)  変化割り込みを許可するポート 
        CNEN2 = 0b0100000000000000;     //CN30(RA2)の 変化割り込みを許可//何故かRA3(ピン10)を変化割込み許可すると音がでない

        IPC4bits.CNIP = 6;                      //変化割り込み優先レベル:6  //タイマ1割込み(優先レベル5)より高優先割り込みに設定
        IEC1bits.CNIE = 1;                      //変化割込み:割り込み許可

        // SPIのピン割り付け  
        RPINR20bits.SDI1R = 7;                          // SDI1をRP7に
        RPOR3bits.RP6R = 8;                                     // SCK1をRP6に
        RPOR2bits.RP5R = 7;                                     // SDO1をRP5に
        RPINR22bits.SDI2R = 10;                         // SDI2をRP15に
        RPOR6bits.RP12R = 11;                           // SCK2をRP13に
        RPOR5bits.RP11R = 10;                           // SDO2をRP14に

        /// 液晶表示用、 UART1初期設定 19200bps 8ビット パリティなし、フロー制御なし
        RPOR0bits.RP0R = 3;     // UART1ピン割付 リマッピング UART1 TX to RP0(RB0 ピン4番)
        U1BRG = 52;     // 19200bps  at システムクロック32MHz
                                //U1BRG = (Fosc(Hz)/2/16/baud(bps) - 1 
                                // = 32000000/2/16/19200 - 1 = 52.08 → 52
        U1MODE = 0b1000100000000000;            // UART1初期設定
        U1STA =  0b0000010000000000;            // UART1初期設定

        LATBbits.LATB4 = 0;     //CS = 0;



        VS1011_Init();  // VS1011eの初期化
        Volume = 0x08;  // 音量の初期設定
        SetVolume(Volume, Volume);
        BASS = 0;                                                                               // バスブーストの初期設定
        SetBassBoost(BASS,15);

        delay_ms(1000);

        while(!FSInit());                                                               // FATの初期化



        result = FindFirst("*.*", ATTR_ARCHIVE, rptr);  //最初のファイルのサーチ(ルートだけにMP3ファイルがあることが前提)
        if(result == 0)
        {
                fptr = FSfopen(Record.filename, "r");           // ファイルのオープン
                str_filename = Record.filename;
        }

        Mode = 0;

        playmode_LCD();


        LATBbits.LATB3 = 1;     //LED 消灯


        while(1)
        {
                if(Mode == 0)play();    //再生モード
                else    SD_write();             //録音モード

        }

}






//----------------------------------------------------------------------------------------------------------
//VS1011.h、VS1011.cは 後閑哲也さんが設計されたファイルです
/*********************************************************************
 *  VS1011E用ヘッダファイル : VS1011.h 
 
 *      
********************************************************************/
#include "GenericTypeDefs.h"
/** Delay関数用クロック周波数定義 **/
#define CLOCK 16                                // MHz 
/** ポートの定義 */
#define MP3_DREQ_TRIS                   (TRISBbits.TRISB14)     // Data Request
#define MP3_DREQ_IO                     (PORTBbits.RB14)                
#define MP3_XRESET_TRIS                 (TRISAbits.TRISA0)      // Reset, active low
#define MP3_XRESET_IO                   (LATAbits.LATA0)
#define MP3_XDCS_TRIS                   (TRISBbits.TRISB15)     // Data Chip Select
#define MP3_XDCS_IO                             (LATBbits.LATB15)
#define MP3_XCS_TRIS                    (TRISBbits.TRISB13)     // Control Chip Select
#define MP3_XCS_IO                              (LATBbits.LATB13)
/*  SPIはSPI2を使用 */
#define MP3_SCK_TRIS                    (TRISBbits.TRISB12)
#define MP3_SDI_TRIS                    (TRISBbits.TRISB10)
#define MP3_SDO_TRIS                    (TRISBbits.TRISB11)
#define MP3_SPI_IF                              (IFS2bits.SPI2IF)
#define MP3_SSPBUF                              (SPI2BUF)
#define MP3_SPICON1                             (SPI2CON1)
#define MP3_SPICON1bits                 (SPI2CON1bits)
#define MP3_SPICON2                             (SPI2CON2)
#define MP3_SPISTAT                             (SPI2STAT)
#define MP3_SPISTATbits                 (SPI2STATbits)
/* 関数プロトタイピング */
BYTE WriteSPI(BYTE output);
void Command(BYTE RegAdrs, BYTE UpData, BYTE LowData);
void SendData(BYTE Data);
void delay_ms(int msec);
void VS1011_Init(void);
void VS1011_SineTest(void);
void SetVolume(BYTE right, BYTE left);
void SetBassBoost(BYTE bass, BYTE gfreq);
void PlayEnd(void);

//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
//VS1011.h、VS1011.cは 後閑哲也さんが設計されたファイルです
/*****************************************************
*  VS1011E 制御ライブラリ : VS1011.c

*  
******************************************************/
#include "VS1011.h"
#include <p24FJ64GA002.h>
/************************************
* SPI Read after Write 基本関数
************************************/
BYTE WriteSPI(BYTE output){
        MP3_SPI_IF = 0;                         // 割り込みフラグクリア
        MP3_SSPBUF = output;            // SPI出力
        while(!MP3_SPI_IF);                     // 入力待ち
        return MP3_SSPBUF;                      // 入力データ戻り値
}
/************************************
*  VS1011用コマンド出力関数
************************************/
void Command(BYTE RegAdrs, BYTE UpData, BYTE LowData){
        MP3_XDCS_IO = 1;                        // データモード解除
        while(!MP3_DREQ_IO);            // レディー待ち
        MP3_XCS_IO = 0;                         // コマンドモード設定 
        WriteSPI(0x02);                         // 書き込み動作指定
        WriteSPI(RegAdrs);                      // レジスタアドレス出力
        WriteSPI(UpData);                       // 上位バイト出力
        WriteSPI(LowData);                      // 下位バイト出力
        MP3_XCS_IO = 1;                         // コマンドモード解除
}
/************************************
*  VS1011用コマンド出力関数(確認付き)
************************************/
void CmdCheck(BYTE RegAdrs, BYTE UpData, BYTE LowData){
        BYTE b1,b2;

        do{
                MP3_XDCS_IO = 1;                // データモード解除
                while(!MP3_DREQ_IO);    // レディー待ち
                MP3_XCS_IO = 0;                 // コマンドモード設定 
                WriteSPI(0x02);                 // 書き込み動作指定
                WriteSPI(RegAdrs);              // レジスタアドレス出力
                WriteSPI(UpData);               // 上位バイト出力
                WriteSPI(LowData);              // 下位バイト出力
                MP3_XCS_IO = 1;                 // コマンドモード解除
                while(!MP3_DREQ_IO);    // レディー待ち
                MP3_XCS_IO = 0;                 // 読み込み確認
                WriteSPI(0x03);                 // 読み込み動作
                WriteSPI(RegAdrs);              // レジスタアドレス指定
                b1 = WriteSPI(0xFF);    // return UpData
                b2 = WriteSPI(0xFF);    // return LowData
                MP3_XCS_IO = 1; 
        }while((b1 != UpData) || (b2 != LowData));
}
/************************************
*  VS1011用データ出力関数
************************************/
void SendData(BYTE Data){
        while(!MP3_DREQ_IO);            // レディー待ち
        WriteSPI(Data);
}

/***********************************************
*  音量レベル設定関数
*   vRight = 右チャネル用音量
*   vLeft  = 左チャネル用音量
*     いすれも 0x00=Max 0dB 0.5dBステップで下がる
************************************************/
void SetVolume(BYTE vRight, BYTE vLeft){
        Command(0x0B, vRight, vLeft);
}

/**********************************************
*  低音ブースト設定制御関数
*    bass: 低音ゲイン レンジは0dBから15dBの範囲
*    gfreq: 低音ブースト周波数設定 10Hzステップ 0〜15の範囲
***********************************************/
void SetBassBoost(BYTE bass, BYTE gfreq)
{
        BYTE temp1 = 0;
        /* 設定範囲の制限 */
        if(bass > 15)
                bass = 15;
        if(gfreq > 15)
                gfreq = 15;
        /* 8ビットに合成 */
        temp1 = gfreq;
        temp1 |= (bass << 4);
        Command(0x02, 0xFF, temp1);             // BASS 
        return;
}
/*********************************************
*       再生終了処理関数
*
*********************************************/
void PlayEnd(void){
        int i;

        /* 再生バッファクリアのため2048バイト送信 */
        MP3_XDCS_IO = 0;                                                // XDCSオン
        for(i=0; i<2048; i++)
                SendData(0);                                            // 0のデータ連続送信
        MP3_XDCS_IO = 1;                                                // XDCSオフ
        /*** ソフトウェアリセットで完了 **/
        Command(0x00, 0x08, 0x24);                              // SM_RESET送信
        while(!MP3_DREQ_IO);                                    // コマンド完了待ち
}
/********************************************
*  VS1011 初期化関数
*    VS1011転送モード、SDIテストモード に設定
*    VS1011と正常に通信できないと永久待ちとなる
*********************************************/
void VS1011_Init(void){
        unsigned int val;
        /***** VS1011用ポートの初期設定   ***/
        MP3_XDCS_IO = 1;                                // DCSをHigh
        MP3_XCS_IO = 1;                                 // XCSをHigh
        MP3_XRESET_IO = 0;                              // XRESETをLow
        MP3_XRESET_TRIS = 0;                    // 出力TRIS有効化
        MP3_DREQ_TRIS = 1;                              // DREQ入力モードに
        MP3_XDCS_TRIS = 0;                              // XDCS出力/////////
        MP3_XCS_TRIS = 0;                               // XCS出力
        MP3_SDI_TRIS = 1;                               // SDI2入力モード
        MP3_SDO_TRIS = 0;                               // SDO2出力モード
        MP3_SCK_TRIS = 0;                               // SCK2出力モード
        /***** SPI2の初期設定   ***/
        MP3_SPICON1 = 0x003E;                   // 8ビットモード,CKP = 0,CLK=Fosc/4 (4MHz)
                                                                        // 中央でサンプル(SMP=0) 立上りエッジで送信(CKE=1)
        MP3_SPICON2 = 0;                                // フレームモードなし
        MP3_SPI_IF = 0;                                 // 割り込みフラグクリア
        MP3_SPISTATbits.SPIEN = 1;              // SPI2イネーブル
        /* RESET解除、VS1011スタート  */
        delay_ms(50);                                   // 50msec delay
        MP3_XRESET_IO = 1;                              // RESET解除
        /** モード設定 */
        CmdCheck(0x00, 0x08, 0x20);             // モード初期設定 新モード、SDIテストモード
        /* クロックダブラ設定 */
        val = 12288 / 2 + 0x8000;               // 設定値を求める(データシートより)
        CmdCheck(0x03, (BYTE)(val /256), (BYTE)val);
        delay_ms(10);
}

/********************************************
*  VS1011 正弦波テストモード設定関数
*    MODEをSPIテストモードに設定しておく必要がある
*********************************************/
void VS1011_SineTest(void)
{
        /* テストモードシーケンス出力 */
        while(!MP3_DREQ_IO);
        MP3_XDCS_IO = 0;
        // Start Sine Test
        WriteSPI(0x53);
        WriteSPI(0xEF);
        WriteSPI(0x6E);
        WriteSPI(0x7D);                         // 22.050kHz Out is 5kHz
        WriteSPI(0x00);
        WriteSPI(0x00);
        WriteSPI(0x00);
        WriteSPI(0x00);
        MP3_XDCS_IO = 1;
}
/****************************
* usec単位ディレイ関数
****************************/
void delay_us(int usec){
        usec = (int)(CLOCK*usec)/ 10;
        while(usec)     {
                asm("NOP");
                asm("NOP");
                asm("NOP");
                asm("NOP");
                asm("NOP");                                     
                usec--;
        }
}
/***************************
* msec単位ディレイ関数
***************************/
void delay_ms(int msec){
        int i;
        for(i=0; i< msec; i++)
                delay_us(1000);
}


//------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
//******************************************************************
//  受信側 PIC
//******************************************************************

#include    <16F873.h>

#use delay(clock=10000000)
#FUSES  HS,NOWDT,,PUT,BROWNOUT,NOPROTECT,NOLVP
#use RS232(BAUD=19200,XMIT=PIN_C6,RCV=PIN_C7)   // TX=RC6,RX=RC7



#define STX             0x02            //      STX

#use fast_io(B)
//////// Port define and link LCD library 
#define mode     0

//   液晶
#define input_x         input_B
#define output_x        output_B
#define set_tris_x      set_tris_B
#define rs PIN_B1       //chip select
#define stb PIN_B0      //strobe

#include <1lcd_lib.c>
int n = 0,i=0;
char RX1[17],RX2[17];
char RX1_LCD[17],RX2_LCD[17];
int data1;
int LineMode = 1;


void LCD()
{
        data1 = getc();
        switch(data1)
        {
                case '\r':      
                        LineMode = 1;   // 1行目のモード
                        n = 0;  // 文字送信順番リセット
                        break;
                case '\n':      //      lcd_cmd(0xC0);  case 0x0a:  LF('\n')なら 2行目の先頭へ
                        LineMode = 2;
                        n = 0;  // 文字送信順番リセット
                        break;
                case STX:       // 表示開始命令

                
                        for(i = 0; i < 16; i++)
                        {
                                RX1_LCD[i] = RX1[i];    //1行目のデータ
                                RX1_LCD[16] = '\0'; 
                                RX2_LCD[i] = RX2[i];    //2行目のデータ
                                RX2_LCD[16] = '\0'; 
                        }

                        lcd_clear();    //液晶クリア
                        printf(lcd_data,RX1_LCD);       //1行目のデータを一括液晶表示
                        lcd_cmd(0xC0);                  //2行目の先頭へ
                        printf(lcd_data,RX2_LCD);       //2行目データを一括液晶表示

                        break;
                
                default:
                        switch(LineMode)
                        {
                                case 1:         //1行目のデータ
                                        RX1[n] = data1; break;//1行目データをメモリに記憶
                                case 2:         //2行目のデータ
                                        RX2[n] = data1; break;//2行目データをメモリに記憶
                                default:        break;
                        }
                        n++;    
                break;
        }

}


main(){
        lcd_init();
        lcd_cmd(0b00001100);                    // カーソル:OFF    ブリンク:OFF
        lcd_clear();
        printf(lcd_data,"First Line");
        lcd_cmd(0xC0);//2行目の先頭へ
        printf(lcd_data,"Second Line");
//      delay_ms(500);

  
        while(1)
        {
                if(kbhit())     LCD();  //RS232Cのデータ(1バイト)が受信完了しているなら LCD()実行

        }
        return 0;       

}




//------------------------------------
//その他 FAT関連のインクルーファイルは下記にあります。
// ・「C言語ではじめるPIC24F活用ガイドブック」後閑哲也著 (技術評論社)
// ・後閑哲也さんのホームページ: 電子工作実験室 PIC24F製作例


<動作結果>

1. 液晶画面

   液晶画面 備考
mp3ファイル再生中 エデンの東(ファイル名:EDENEAST.mp3)を演奏中の液晶画面         
wavファイル録音中 マイクからの音声をWAVファイル(ファイル名:VOICE.wav)に録音中の液晶画面
wavファイル再生中 録音したWAVファイル(ファイル名:VOICE.WAV)を再生中の画面  


2. 録音したwavファイル(例)
 試作品で録音した wavファイル(VOICE.wav)です。 PCで再生してみてください。


3.wavファイルのバイナリーデータ
 上記2.のVOICE.wavファイルの内部をバイナリーエディタで表示したものを以下に示します。

ファイルヘッダー情報
 ・ファイルサイズ ……596,024バイト ( = 0x00091838バイト) (注)
 ・圧縮のフォーマットID …… リニアPCM
 ・チャンネル数 …… モノラル
 ・サンプリングレート……22050 Hz
 ・データ転送速度 ……44100 バイト/sec
 ・Block align …… 2 バイト/サンプル
 ・量子化ビット数……16ビット
 ・データサイズ……595,968バイト ( = 0x00091800バイト)

(注)エクスプローラでみるとファイルサイズは582KBです。これはエクスプローラでの1KBは、1KB = 1000バイトではなく 1KB = 1024バイトに
   よる誤差(?)からくるものです。
     596024 ÷ 1024 = 582.05 [KB]


<バイナリーエディタによるVOICE.WAV内部>




(2) PIC32MX795F512L 編
  PIC32MX版も製作しましたので紹介します。 仕様は 上記のPIC24FJ64GA002と同じです。

PIC32MX795F512Lを使用した、WAVファイル形式録音機能付きMP3プレーヤーを紹介します。MP3のデコーダーICとしてはVS1011Eを
使用しています。 VS1011Eのライブラリ関数(VS1011.h、VS1011.c)は後閑哲也さんが設計されたものです。後閑さんには本プレーヤー製作に
あたり貴重なアドバイスを多々いただきました。
 
 ★ mp3デコーダーIC VS1011Eは QFPがキバンにハンダ付けされ、端子が2.54インチのピンヘッダーコネクタに変換されたもの(700円/個)が
   秋月電子で
販売されています。私はこれをつかって試作品を製作しました。

<試作品の仕様>
・再生モードと録音モードを有すること。再生、録音のモード切替はモメンタリースイッチでおこなうこと
・mp3ファイルについては再生のみとし、エンコード機能はつけない
・mp3、wav形式でSDカードに収録されている音楽・音声データを再生できること
・mp3ファイルのデコーダICとして、VS1011Eを使用すること
・再生はSDカード内にある音楽・音声データを順番におこなう。但し、スキップボタンをもうけ再生データをスキップできるようにすること
・録音は、マイクレベルの音声信号を増幅しPICでAD変換して、データはSDカードにWAV形式のファイルとしてファイルすること
・録音するWAVファイルの諸元は下記とする
 @圧縮のフォーマットID …… リニアPCM
 Aチャンネル数 …… モノラル
 Bサンプリングレート……22050 Hz
 Cデータ転送速度 ……44100 バイト/sec
 DBlock align …… 2 バイト/サンプル
 E量子化ビット数……16ビット
・録音するファイル名はVOICE.wavとする。SDカード内のルートにこのファイル名のファイルが存在しない場合はファイルをつくること。 また、 
 すでにVOICE.wavが存在する場合は上書きするものとする。
・キャラクタ液晶により、録音/再生時のファイル名を表示する。


<試作品の回路図>  (→ 回路図のPDFファイル



<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています




    

          

   <プログラム例>
//MPLAB X
//main.c
//------------------------------------------------------------------------------------------
//32MX795 MEB SD Play with wave Recorder

#include <p32xxxx.h>
#include <plib.h>               // PIC32 peripheral library

#include "1lcd_lib_C32.h"
#include "FSIO.h"
#include "VS1011.h"


#define STX     0x02    //STX
#define ETX     0x03    //ETX


// configuration CPU=80MHz Peri=80MHz,HS+PLL,Divider=1/2,PLL=x20,WDT=Off
#pragma config FNOSC=PRIPLL, POSCMOD=HS, FPLLIDIV=DIV_2
#pragma config FPLLMUL=MUL_20, FPBDIV=DIV_1, FPLLODIV=DIV_1
#pragma config FWDTEN=OFF, ICESEL=ICS_PGx2

//WAVEファイルヘッダ構造体定義
struct myWaveHeader             //全ヘッダサイズ: 44バイト
{
    char id_RIFF[4];        //Chunk ID RIFFヘッダ // 4バイト
    unsigned int size_file;    //ファイルサイズ(総ファイルサイズ - 8)バイト //4バイト
    char id_WAVE[4];        //Chunk ID WAVE //4バイト
    char id_fmt[4];         //Chunk ID fmt  //4バイト
    unsigned int size_fmt;     //フォーマット関連定義データのサイズ     //4バイト
    unsigned short int code_wavefmt;      //WAVEファイルの圧縮フォーマットコード 但し、リニアPCMは圧縮なし//2バイト
    unsigned short int channel;   //チャンネル数 //2バイト
    unsigned int rate_sample;  //サンプリングレート     //4バイト
    unsigned int rate_tranfer;         //転送速度[byte/sec] //4バイト
    unsigned short int align_block;               //サンプルあたりのバイト数[byte/サンプル]       //2バイト
    unsigned short int bit_sample;        //量子化ビット数[bit]  //2バイト
    char id_data[4];        //Chunk ID data //4バイト
    unsigned int size_data;    //サンプリングデータのサイズ[byte] //4バイト

}
;

struct myWaveHeader mywaveheader =              // WAVEファイルヘッダ構造体の初期化   //44バイト
{
    "RIFF",             //Chunk ID RIFF     // 4バイト
    0x0006C28C, //(仮)ファイルサイズ: 443020バイト //特に値に意味なし
    "WAVE",             //Chunk ID WAVE     //4バイト
    "fmt ",             //char id_fmt[4];         //Chunk ID fmt  //4バイト
    16,                 //16バイト at リニアPCM   フォーマット関連定義データのサイズ   //4バイト
    0x0001,             //WAVEファイルの圧縮フォーマットコード: リニアPCM //2バイト
    1,                  //チャンネル数: モノラル  //2バイト
    22050,              //サンプリングレート: 22.05[KHz]     //4バイト
    44100,              //転送速度: 44100[byte/sec] //4バイト  //サンプリングレート: 22.05[Hz]
    2,                  //サンプルあたりのバイト数: 2[byte]/サンプル      //2バイト
    16,                 //量子化ビット数: 16[bit]  //2バイト
    "data",             //Chunk ID data //4バイト
    0x0006C267  ////(仮)サンプリングデータのサイズ: 442983バイト //特に値に意味なし
};

struct myWaveHeader* ptrWH;     //構造体のポインタ


char Buf[17];   //文字列のバッファー用レジスタ
unsigned int Buf_Input[3];              //SDカード書き込み値
unsigned int Buf_SD[3];                 //SDカード読込み値

// FATファイル用構造体のポインタ変数
FSFILE* pfile;  //SDカードのファイルポインタ    //FSFILE *fptr;

size_t result;
BYTE Buffer[256];
SearchRec Record;
SearchRec *rptr = &Record;
int i;
// MP3用変数
BYTE Volume, ChgFlag, BASS;


int Mode = 0;   //録音/再生モード 0:再生 1:録音
unsigned int adr_SD;
unsigned int count_block = 0;   //SD送信ブロック(512バイト)数
unsigned int size_dataBlock = 512;

int count_buf1 = 0;     //バッファ1データ数
int count_buf2 = 0;     //バッファ2データ数

int flag_buf1 = 0;      //音声データバッファ1の状態 
int flag_buf2 = 0;      //音声データバッファ2の状態
                        // 0:音声データ受信可能状態 1:SDへ音声データ送信可能状態
int mode_tranceive = 0; //送受信モード  //0: バッファ1=音声タ受信、バッファ2=SD送信
                                        //1: バッファ1=SD送信モード、バッファ2=音声受信

short int data1_sound[512];     //音声データバッファ1
short int data2_sound[512];     //音声データバッファ2


char* str_filename;
int Stop_SDwriting = 0;// 1: SDカードへの書込み停止 0: 書込み許可
int Next = 0;

void delay_us(unsigned int usec)        //1μsec遅延関数
{
        int count;
        count = (int)(Clock/20000000)*usec;
        do      //実測: at Clock=80000000
        {       //delay_us(1000)→1003μsec、 delay_us(100)→102μsec、delay_us(10)→11μsec、delay_us(1)→1.6μsec
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                count--;
        }while(count != 0);
}

void delay_ms(unsigned int msec)        //1msec遅延関数
{
        unsigned int i;

        for(i=0; i<msec; i++)
        delay_us(1000);
}


void LcdCheck(void)
{

        INTDisableInterrupts(); //全割り込み禁止       // SPI処理中は割り込み禁止
        lcd_clear();            // 全消去
        lcd_cmd(0x80);          //1目の先頭へ


        sprintf(Buf,"M=%d block=%d",Mode,count_block);  //
        lcd_str(Buf);                   //液晶表示
        lcd_cmd(0xC0);          //2行目の先頭へ
        sprintf(Buf,"result=%d",result);
        lcd_str(Buf);           // 開始メッセージ1行目表示
        while(1);
}

void wav_end(void)      //録音ファイル完成処理
{
    unsigned int result;
    int count_N;

    mywaveheader.size_data = count_block * 1024 ;       //[バイト]
    mywaveheader.size_file = count_block * 1024 + sizeof mywaveheader - 8;      //[バイト]

    delay_ms(100);
        result = FSfseek(pfile,0,SEEK_SET);     //ファイルの先頭にファイルポインタの位置を移動
   
        delay_ms(100);
        result = FSfwrite((const void*)ptrWH,sizeof(struct myWaveHeader),1,pfile);      //ファイルにヘッダー情報書き込み
  
        delay_ms(100);
        result = FSfclose(pfile); //      ファイルを閉じる
 
}




void SD_write()
{
        if(mode_tranceive == 0) //バッファ2=SD送信、バッファ1=音声受信モード
        {
                if(flag_buf2 == 1)      //バッファ2がSDへ送信可能状態の場合・バッファ1は音声受信可能状態
                {
                 //     FSfwrite((const void*)data2_sound,sizeof(short int),size_dataBlock,pfile);//SDカードにデータ書き込み

                        FSfwrite((const void*)data1_sound,sizeof(short int),size_dataBlock,pfile);//SDカードにデータ書き込み
                        count_block++;
                        flag_buf2 = 0;  //→ バッファ2送信完了、受信可能状態
                }
                
        }
        else    //バッファ1=SDへ送信可、バッファ2=音声受信モード
        {
                if(flag_buf1 == 1)      //バッファ1がSDへ送信可能状態の場合・バッファ2は音声受信可能状態
                {

                 //     FSfwrite((const void*)data1_sound,sizeof(short int),size_dataBlock,pfile);//SDカードにデータ書き込み

                        FSfwrite((const void*)data2_sound,sizeof(short int),size_dataBlock,pfile);//SDカードにデータ書き込み
                        count_block++;
                        flag_buf1 = 0;  //→ バッファ1送信完了、受信可能状態
                }

        }

        if(Stop_SDwriting == 1) //
        {
                delay_ms(200);
                wav_end();      //録音wavファイル終了処理
                Mode = 0;       //音楽再生モードへ
                delay_ms(1000);

                pfile = FSfopen("VOICE.WAV", "r");              // ファイルのオープン

        }

}




void __ISR(4,ipl5)T1Hander(void)        //タイマ1割込 45.3μsec毎(22.05 KHz)
{
    unsigned int temp1;
    int temp2;

    mT1ClearIntFlag();  //フラグクリア

    AD1CON1bits.SAMP =1;            //サンプリング開始
    while(!AD1CON1bits.DONE);       //AD変換終了フラグがたつ(1になるまで)待つ
    temp1 = ADC1BUF0;               //ADC1のAN1のバッファーからAD変換結果を読込む
    temp2 = temp1*64 - 32768;           //32768 = 64*1024 / 2;  //無音基準レベル:32768( = unsigned int / 2)
    if(temp2 >= 32767) temp2 = 32767;   //音声レベルクリップ
    if(temp2 <= -32768)temp2 = -32768;

    //送信優先: 未送信データがバッファに残っている場合は入力する音声データは無視する 
    if(mode_tranceive == 0)     //バッファ1=音声受信、バッファ2=SD送信
    {
        if(flag_buf1 == 0)      //バッファ1が受信可能状態なら
        {
            LATDbits.LATD2 = 0;
            delay_us(2);
            data1_sound[count_buf1] = (short int)temp2; //受信データをバッファ構造体1のdata_sound[ ]に保存
            count_buf1++;
            if(count_buf1 >= size_dataBlock)
            {
                count_buf1 = 0;
                flag_buf1 = 1;  //→ バッファ1: 音声データフル・SD転送待ち
                mode_tranceive = 1; //バッファ1=SD送信モード、バッファ2=音声受信
            }
            LATDbits.LATD2 = 1;
           
        }
        //バッファ1にまだ未送信音声データが残っていた場合は、音声データは受信しない
    }
    else        //バッファ2=音声受信、バッファ1=SD送信
    {
        if(flag_buf2 == 0)      //バッファ2が受信可能状態なら
        {

            LATDbits.LATD3 = 0;
            delay_us(2);
            data2_sound[count_buf2] = (short int)temp2; //受信データをバッファ構造体2のdata_sound[ ]に保存
            count_buf2++;
            if(count_buf2 >= size_dataBlock)
            {
                count_buf2 = 0;
                flag_buf2 = 1;  //→ バッファ2:音声データフル・SD転送待ち
                mode_tranceive  = 0;    //バッファ1=音声タ受信、バッファ2=SD送信
            }
            LATDbits.LATD3 = 1;

        }
    }
                //バッファ2にまだ未送信音声データが残っていた場合は、音声データは受信しない

      
}

void __ISR(26,ipl2)ChangeInt(void)        //変化割り込み    //スイッチ検出
{
        if(!PORTBbits.RB0)      //再生/録音ボタンがクリックされた場合
        {

                if(Mode == 0)   //再生モードの場合
                {

                        Mode = 1;       //録音モードへ
                        Stop_SDwriting = 0;     //SDカードへの書き込み許可


                        MP3_XDCS_IO = 1;        //VS1011E 音データ信号ラインOFF
                        MP3_XCS_IO = 1; //VS1011E チップセレクト解除

                        FSfclose(pfile);        // 現在のファイルを強制クローズ
                        PlayEnd();              // 再生終了処理

                        delay_ms(200);

                        pfile = FSfopen("VOICE.wav","w"); //ファイル上書き込みモードでオープン 但しファイルがなければ新規ファイル作成

                         lcd_clear();            // 全消去

                        lcd_cmd(0x80);          //1行目の先頭へ
                        sprintf(Buf,"VOICE.WAV");   //ファイル名 //空白必須
                        lcd_str(Buf);           // 開始メッセージ1行目表示
                        lcd_cmd(0xC0);          //2行目の先頭へ
                        sprintf(Buf,"On recording");    //タッチY座標表示
                        lcd_str(Buf);           // 開始メッセージ2行目表示


                        ptrWH = &mywaveheader;  //構造体にmywaveheaderの先頭アドレス設定
                        FSfseek(pfile,0,SEEK_SET);      //ファイルの先頭にファイルポインタの位置を移動
                        delay_ms(50);
                        FSfwrite((const void*)ptrWH,sizeof(struct myWaveHeader),1,pfile);       //ファイルにヘッダー情報書き込み
                        delay_ms(50);

                        adr_SD = 0x2C;                  //ファイルの先頭から0x2C(44)バイト(音声データ書き込み開始オフセット)のところにに
                        FSfseek(pfile,adr_SD,SEEK_SET);//ファイルポインタの位置を移動
                        count_block = 0;        //SDカードに512バイト単位で書き込んだ回数をリセット


                        delay_ms(300);



               ConfigIntTimer1(T1_INT_ON | T1_INT_PRIOR_5);    //タイマ1割込ON、割り込みレベル5
        
                EnableIntT1;                                    //割込み許可
                }

                if((Mode == 1) && (count_block >= 10))  //録音モード かつ 10ブロック以上書き込んでいるななら(チャタリング防止)
                {
                        ConfigIntTimer1(T1_INT_OFF | T1_INT_PRIOR_5);    //タイマ1割込ON、割り込みレベル5
                    //    ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_OFF); //タイマ1: 割り込み優先レベル5      //      IPC0bits.T1IP = 5;
                        DisableIntT1;   //タイマ1: 割り込み禁止 //IEC0bits.T1IE = 0;

                        Stop_SDwriting = 1;     //SDカード書込み終了
                                                                //1ブロック書込み後終了処理開始
                                                                //★ここですぐ終了処理を行わないこと!!
                }


        }


        if(!PORTBbits.RB1)      //スキップボタンがクリックされた場合
        {
            Next = 1;   //再生中のファイルのセクタ読み込み終了後、次の曲を再生
        }

    mCNClearIntFlag();     // 変化割り込みフラグクリア  //IFS1bits.CNIF = 0;

}

void play()             // 音楽データの出力
{
        int i;
        ConfigIntTimer1(T1_INT_OFF | T1_INT_PRIOR_5);    //タイマ1割込ON、割り込みレベル5
        //ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_OFF);         //タイマ1割込み禁止
        DisableIntT1;

        if(pfile != 0)  // 正常にオープンできたか?
        {
                do{             // ファイルのEOFまで音声データ連続出力
                        INTDisableInterrupts(); //全割り込み禁止
                        MP3_XDCS_IO = 0;        //#define MP3_XDCS_IO    LATBbits.LATB15=0 → DREQ=0

                        result = FSfread(Buffer, 1, 256, pfile);        //SDカードのデータを256バイト単位で読み出し
                        for(i= 0; i<result; i++)        // 読み出したバイト数だけ繰り返し
                        {
                                SendData(Buffer[i]);    // 音楽データ送信
                        }
                        INTEnableInterrupts();  //全割り込み許可
                        if(Mode == 1)return;            //録音モードなら 再生は終了
                        if(Next == 1)result = 0;
                } while(result != 0);                   // ファイルのEOFまで継続

                Next = 0;

                MP3_XDCS_IO = 1;
                // 再生完了処理
                FSfclose(pfile);                // ファイルのクローズ
                PlayEnd();                      // 再生終了処理

                result = FindNext(rptr);        // 連続再生のため次のファイルへ
                if((result != 0) || (Record.attributes != ATTR_ARCHIVE))
                FindFirst("*.*", ATTR_ARCHIVE, rptr);   // ファイルの終わりなら再度最初から繰り返し

                pfile = FSfopen(Record.filename, "r");
                str_filename = Record.filename;

                  lcd_clear();            // 全消去

                lcd_cmd(0x80);          //1行目の先頭へ
                sprintf(Buf,"%s                 ",str_filename);   //ファイル名 //空白必須
                lcd_str(Buf);           // 開始メッセージ1行目表示
            // 開始メッセージ2行目表示

                INTEnableInterrupts();  //全割り込み許可

        }
}





int main(void)
{
    SYSTEMConfigPerformance(80000000);  // システム最適化
    INTEnableSystemMultiVectoredInt();  //マルチベクタ方式割り込み許可
    mJTAGPortEnable(DEBUG_JTAGPORT_OFF);    //JTAG無効化//DDPCONbits.JTAGEN = 0;  //I/OポートとしてRA0、RA1、RA4、RA5をつかう場合必須

//ADコンバータ初期設定  //音声入力
    AD1PCFG = 0xFEFF;  //b8=0以外は1  //Bポート:b8以外はデジタルピン
    TRISBbits.TRISB8 = 1;   //RB8/AN8を入力ピンに設定

    //AD1CON1レジスタの設定
    AD1CON1bits.ON = 1;      //A/Dコンバータモジュール有効
    AD1CON1bits.SIDL = 0;   //アイドルモード中もモジュール動作継続
    AD1CON1bits.FORM2 = 0;  //AD1CON1bits.FORM2-AD1CON1bits.FORM0のセットで出力データ形式指定 → 000:16ビット符号なし整数形式
    AD1CON1bits.FORM1 = 0;  //011:符号付固定16ビット小数 010:固定小数16ビット 001:符号付き整数16ビット 000:16ビット符号なし整数
    AD1CON1bits.FORM0 = 0;  //111:符号付32ビット固定小数 110:32ビット固定小数 101:符号付32ビット整数 100=32ビット符号なし整数
    AD1CON1bits.SSRC2 = 1;  //AD1CON1bits.SSRC2-AD1CON1bits.SSRC0 のセットでトリガーソースを指定
    AD1CON1bits.SSRC1 = 1;  //111: 内蔵カウンタでサンプリングを終了させ変換を開始する
    AD1CON1bits.SSRC0 = 1;  //(参考)000: SAMPビットでサンプリングを終了し変換を開始する
    AD1CON1bits.CLRASAM = 0;//AD変換割り込み時の変換停止 0:次の変換値でオーバーライト
    AD1CON1bits.ASAM = 0;   //SAMPビットのセットでサンプリングを開始する。(参考)1: 自動開始(前の変換終了後すぐサンプリングを開始する)
    AD1CON1bits.SAMP = 0;   //サンプリング停止

    //AD1CON2レジスタの設定
    AD1CON2bits.VCFG2 = 0;  //リファレンス選択//AD1CON2bits.VCFG2 - AD1CON2bits.VCFG0(VCFG<2:0>)の3ビットでセット
    AD1CON2bits.VCFG1 = 0;  //000:リファレンス電圧 → Vdd -Vss
    AD1CON2bits.VCFG0 = 0;  //(参考)001:リファレンス電圧 → 外部入力 - Vss 他
    AD1CON2bits.OFFCAL = 0; //較正モード設定 0:サンプルホールドアンプSHAの入力はAD1CHSレジスタとAD1CSSLレジスタで制御される
    AD1CON2bits.CSCNA = 1;  //マルチプレクサMUXAでのスキャン: する
    AD1CON2bits.SMPI3 = 0;  //割り込みタイミング AD1CON2bits.SMPI3 - AD1CON2bits.SMPI0(SMPI<3:0>)の4ビットでセット
    AD1CON2bits.SMPI2 = 0;  //0000: AD変換完了毎の割り込み発生(割り込み有効の場合)
    AD1CON2bits.SMPI1 = 0;  //(参考)0011: 4サンプルのAD変換終了後       割り込み発生(割り込み有効の場合)
    AD1CON2bits.SMPI0 = 0;  //
    AD1CON2bits.BUFM = 0;   //バッファーを1個の16ワードバッファとする。 (参考)1: 2組の8ワードバッファーとする
    AD1CON2bits.ALTS = 0;   //常にMUXAを入力マルチプレクサにする (参考)1: MUXA,MUXBを交互につかう

    //AD1CON3レジスタの設定
    AD1CON3bits.ADRC = 0;   //AD変換クロック源選択//0: PBCLK(Peripheral Bus Clock) (参考)1: A/D内臓RCクロック
    AD1CON3bits.SAMC4 = 1;  //AD1CON3bits.SAMC4 - AD1CON3bits.SAMC0(SAMC<4:0>)の5ビットでセット
    AD1CON3bits.SAMC3 = 1;  //アクイジションタイム(Tad(クロック周期)×N)設定(ホールドキャパシタ充電所要時間)
    AD1CON3bits.SAMC2 = 1;  //1111: 31Tad
    AD1CON3bits.SAMC1 = 1;  //(参考)0001: 1Tad    0010: 2Tad    0011: 3Tad  ・・・・
    AD1CON3bits.SAMC0 = 1;  //
    AD1CON3bits.ADCS7 = 0;  //AD変換時間の設定/AD1CON3bits.ADCS7 - AD1CON3bits.ADCS0(ADCS<7:0>)の8ビットでセット
                           //AD変換完了フラグAD1CON1bits.DONEにより、AD変換完了を検知する場合は設定不要
    AD1CON3bits.ADCS6 = 0;  //AD変換完了までののクロック数選択ビット
    AD1CON3bits.ADCS5 = 0;  //0000 0101: 1Tad = 6Tpb  (Tpb: PBCLKの周期)
    AD1CON3bits.ADCS4 = 0;  //(参考) 0000 0000: 1Tad = 2Tpb
    AD1CON3bits.ADCS3 = 0;  //      0000 0001: 1Tad = 3Tpb
    AD1CON3bits.ADCS2 = 1;  //      0000 0010: 1Tad = 4Tpb
    AD1CON3bits.ADCS1 = 0;  //                                ・・・・    
    AD1CON3bits.ADCS0 = 1;  //     1111 1111: 1Tad = 512Tpb

    //AD1CHSレジスタの設定 //SHAの+端子とー端子への接続(ポート)設定
    AD1CHSbits.CH0NB = 0;   //マルチプレクサMUXB用負側入力選択ビット: VR-  (参考)1: AN1
    AD1CHSbits.CH0SB3 = 0;  //AD1CHSbits.CH0SB3 - AD1CHSBbits.CH0SB0(<CH0SB<3:0>)の4ビットでセット
    AD1CHSbits.CH0SB2 = 0;  //マルチプレクサMUXBの正側入力選択
    AD1CHSbits.CH0SB1 = 0;  //0000: AN0
    AD1CHSbits.CH0SB0 = 0;  //(参考)0001: AN1  0011 AN2    ....  1111: AN15
    AD1CHSbits.CH0NA = 0;   //マルチプレクサMUXA用負側入力選択ビット: VR-  (参考)1: AN1
    AD1CHSbits.CH0SA3 = 0;  //AD1CHSbits.CH0SA3 - AD1CHSbits.CH0SA0(<CH0SA<3:0>)の4ビットでセット
    AD1CHSbits.CH0SA2 = 0;  //マルチプレクサMUXAの正側入力選択
    AD1CHSbits.CH0SA1 = 0;  //0000: AN0
    AD1CHSbits.CH0SA0 = 0;  //(参考)0001: AN1  0011 AN2    ....  1111: AN15

    //AD1PCFGレジスタの設定 // ポートのアナログorデジタル設定 
    //★デバイスリセットでは全ビット0となるためデフォルトではアナログ入力となるのでデジタルで使う多重ピンは、コンフィグレーションでデジタル設定が必要!! 
    AD1PCFGbits.PCFG15 = 1;//RB15/AN15アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG14 = 1;//RB14/AN14アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG13 = 1;//RB13/AN13アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG12 = 1;//RB12/AN12アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG11 = 1;//RB11/AN11アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG10 = 1;//RB10/AN10アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG9 = 1;//RB9/AN9アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG8 = 0;//RB8/AN8アナログ入力orデジタル入力選択: アナログ //★AN8から音声を入力する
    AD1PCFGbits.PCFG7 = 1;//RB7/AN7アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG6 = 1;//RB6/AN6アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG5 = 1;//RB5/AN5アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG4 = 1;//RB4/AN4アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG3 = 1;//RB3/AN3アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG2 = 1;//RB2/AN2アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG1 = 1;//RB1/AN1アナログ入力orデジタル入力選択: デジタル 
    AD1PCFGbits.PCFG0 = 1;//RB0/AN0アナログ入力orデジタル入力選択: デジタル 

    //AD1CSSLレジスタの設定  //読み込むチャンネル(入力端子)をセットする
    AD1CSSLbits.CSSL15 = 0; //AN15をMUXAでスキャンしない 
    AD1CSSLbits.CSSL14 = 0; //AN15をMUXAでスキャンしない 
    AD1CSSLbits.CSSL13 = 0; //AN13をMUXAでスキャンしない 
    AD1CSSLbits.CSSL12 = 0; //AN12をMUXAでスキャンしない 
    AD1CSSLbits.CSSL11 = 0; //AN11をMUXAでスキャンしない 
    AD1CSSLbits.CSSL10 = 0; //AN10をMUXAでスキャンしない 
    AD1CSSLbits.CSSL9 = 0;  //AN9をMUXAでスキャンしない 
    AD1CSSLbits.CSSL8 = 1;  //AN8をMUXAでスキャンする   //★使用するAN8のチャンネルだけ読み込む
    AD1CSSLbits.CSSL7 = 0;  //AN7をMUXAでスキャンしない 
    AD1CSSLbits.CSSL6 = 0;  //AN6をMUXAでスキャンしない 
    AD1CSSLbits.CSSL5 = 0;  //AN5をMUXAでスキャンしない 
    AD1CSSLbits.CSSL4 = 0;  //AN4をMUXAでスキャンしない 
    AD1CSSLbits.CSSL3 = 0;  //AN3をMUXAでスキャンしない 
    AD1CSSLbits.CSSL2 = 0;  //AN2をMUXAでスキャンしない 
    AD1CSSLbits.CSSL1 = 0;  //AN1をMUXAでスキャンしない  
    AD1CSSLbits.CSSL0 = 0;  //AN0をMUXAでスキャンしない     

 //キャラクタ液晶ポート入出力設定     //関数初期化
    TRISBbits.TRISB15 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB14 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB13 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB12 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA9 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA10 = 0;       //キャラクタ液晶ポート設定

    /// インターバルタイマ1 周期 45.3μsec (音データサンプリング周期)
    OpenTimer1(
                T1_ON | //      タイマ1 イネーブル  //T1_OFF → タイマ1 ディセーブル
                T1_SOURCE_INT | //クロックソース:インターナル //T1_SOURCE_EXT → 外部発振器
                T1_PS_1_1,    //プリスケール 1/256   //1/1、1/2、1/4、1/8、1/16、1/32、1/64、1/256
                3624   //PRx値:  T0[μsec] = 1000x1000/80000000x3624 = 1/80x3624 = 45.3μsec
    );


//状態変化モジュール(スイッチ検出)初期設定
    mCNOpen(
                CN_ON,  //状態変化モジュール ON
                CN2_ENABLE | //CN2 Enable   //RB0
                CN3_ENABLE , //CN3 Enable   //RB1
          //      CN5_ENABLE,  //CN5 Enable   //RB3

                CN2_PULLUP_ENABLE |  //CN2 プルアップ抵抗設定
                CN3_PULLUP_ENABLE   //CN3 プルアップ抵抗設定
           //     CN5_PULLUP_ENABLE    //CN5 プルアップ抵抗設定
    );
    ConfigIntCN(CHANGE_INT_ON | CHANGE_INT_PRI_2);  //状態変化割り込みON、優先度2
    
    //SDカード関係(SPI4等)ポート設定    --> HardwareProfile.h
    //VS1011e関係(含SPI3)ポート設定    -->  VS1011.h,VS1011.c
    //INT035TFT関係ポート設定           -->  HardwareProfile.h



        // VS1011eの初期化 
        VS1011_Init();
  
        Volume = 0x08;                                                                  // 音量の初期設定
        SetVolume(Volume, Volume);
        BASS = 0;                                                                               // バスブーストの初期設定
        SetBassBoost(BASS,15);
        // VS1011のデバッグ時テスト用のコマンド  
//      VS1011_SineTest();
 
                                                        // 正弦波出力テスト
        // カードの実装確認とディレクトリ読み込み (永久待ち)
        while(!FSInit());

        result = FindFirst("*.*", ATTR_ARCHIVE, rptr);  //最初のファイルのサーチ(ルートだけにMP3ファイルがあることが前提)
        if(result == 0)
        {
                pfile = FSfopen(Record.filename, "r");          // ファイルのオープン
                str_filename = Record.filename;
        }

        Mode = 0;


        lcd_init();                             // LCD初期化
        lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

        lcd_clear();            // 全消去
        sprintf(Buf,"Record 6 Player");
        lcd_str(Buf);                   //液晶表示

        delay_ms(1000);


        TRISDbits.TRISD2 = 0;
        TRISDbits.TRISD3 = 0;
        TRISGbits.TRISG15 = 0;

        LATGbits.LATG15 = 0;
        LATDbits.LATD3 = 0;
        LATDbits.LATD2 = 0;

        LATDbits.LATD2 = 1;
        LATDbits.LATD3 = 1;
        LATGbits.LATG15 = 1;

    while(1)
    {
        if(Mode == 0)play();    //再生モード
        else    SD_write();             //録音モード
    }
    return 0;
}


//----------------------------------------------------------------------------------------------------------
//HardwareProfile.h
//Microchip Memory Disk Drive File System


#ifndef _HARDWAREPROFILE_H_
#define _HARDWAREPROFILE_H_


//クロック周波数設定  システムクロック:80MHZ
  
        #define GetSystemClock()            (80000000ul)            //システムクロック
        #define GetPeripheralClock()        (GetSystemClock()/2)    //ペリフェラルクロック
        #define GetInstructionClock()       (GetSystemClock())      //インストラクションクロック
   

    // Clock values

  //  #define MILLISECONDS_PER_TICK       10                  // Definition for use with a tick timer
  //  #define TIMER_PRESCALER             TIMER_PRESCALER_8   // Definition for use with a tick timer
  //  #define TIMER_PERIOD                37500               // Definition for use with a tick timer

 

// Description: Macro used to enable the SD-SPI physical layer (SD-SPI.c and .h)
#define USE_SD_INTERFACE_WITH_SPI


//SD カード選択・検出
   //CS:チップセレクト    // Description: SD-SPI Chip Select Output bit
    #define SD_CS       LATDbits.LATD14         
    #define SD_CS_TRIS  TRISDbits.TRISD14       

    //CD:カードディテクト //      Description: SD-SPI Card Detect Input bit
    #define SD_CD       PORTFbits.RF12                  
    #define SD_CD_TRIS  TRISFbits.TRISF12       

    //WE:ライトイネーブル Description: SD-SPI Write Protect Check Input bit
    #define SD_WE       PORTAbits.RA1           
    #define SD_WE_TRIS  TRISAbits.TRISA1        
     

//SPIコンフィギュレーション     //SPI Configuration

        #define SPI_START_CFG_1     (PRI_PRESCAL_64_1 | SEC_PRESCAL_8_1 | MASTER_ENABLE_ON | SPI_CKE_ON | SPI_SMP_ON)
        #define SPI_START_CFG_2     (SPI_ENABLE)

          #define SPI_FREQUENCY   (4000000)      //SPI周波数     //Define the SPI frequency
     //   #define SPI_FREQUENCY   (20000000)      //SPI周波数     //Define the SPI frequency
  
    //チャンネル4:
        #define SPICON1         SPI4CON     //制御レジスタ
        #define SPISTAT         SPI4STAT    //SPIステータスレジスタ status register
        #define SPIBUF          SPI4BUF     //SPIバッファレジスタ
            
        #define SPISTAT_RBF     SPI4STATbits.SPIRBF //受信バッファ満杯ビット//  The receive buffer full bit in the SPI status register
        #define SPICON1bits     SPI4CONbits     //ビット単位の定義(制御レジスタ)The bitwise define for the SPI control register (i.e. _____bits)
        #define SPISTATbits     SPI4STATbits    //ビット単位の定義(ステータスレジスタ) //The bitwise define for the SPI status register (i.e. _____bits)
        #define SPIENABLE       SPI4CONbits.ON  //SPIモジュール イネーブルビット //The enable bit for the SPI module

        #define SPIBRG          SPI4BRG     //ボーレートジェネレータ//The definition for the SPI baud rate generator register (PIC32)

        //SCK,SDI,SDOピンアサイン   //Tris pins for SCK/SDI/SDO lines
        #define SPICLOCK        TRISFbits.TRISF12   //TRISGbits.TRISG6    //SCK
        #define SPIIN           TRISFbits.TRISF4    //PICのSDI4     //      TRISGbits.TRISG7    //PICのSDI2
        #define SPIOUT          TRISFbits.TRISF5    //PICのSDO4     //    TRISGbits.TRISG8    //SDO

        //SPIライブラリ関数 //library functions
 //       #define putcSPI     putcSPI4    //putcSPI2
 //       #define getcSPI     getcSPI4    //getcSPI2

 //        #define OpenSPI(config1, config2)   OpenSPI4(config1, config2)      //OpenSPI2(config1, config2)
  
    
 //   #include <uart2.h>

#endif


//-------------------------------------------------------------------------------------------------------------------------------------

/*********************************************************************
 *  VS1011E用ヘッダファイル
 *      
********************************************************************/
//このファイルは 後閑哲也さんがPIC24FJ64GA002用に設計されたファイルを
//PIC32MX795F512L用に変更したものです。

#include "GenericTypeDefs.h"
//Delay関数用クロック周波数定義 
//#define CLOCK 16                              // MHz
// ポートの定義
#define MP3_DREQ_TRIS       (TRISAbits.TRISA15)     //(TRISBbits.TRISB14)       // Data Request
#define MP3_DREQ_IO         (PORTAbits.RA15)        //(PORTBbits.RB14)
#define MP3_XRESET_TRIS     (TRISDbits.TRISD11)     //(TRISAbits.TRISA0)        // Reset, active low
#define MP3_XRESET_IO       (LATDbits.LATD11)       //(LATAbits.LATA0)
#define MP3_XDCS_TRIS       (TRISAbits.TRISA5)      //(TRISBbits.TRISB15)       // Data Chip Select
#define MP3_XDCS_IO         (LATAbits.LATA5)        //(LATBbits.LATB15)
#define MP3_XCS_TRIS        (TRISAbits.TRISA14)     //(TRISBbits.TRISB13)       // Control Chip Select
#define MP3_XCS_IO          (LATAbits.LATA14)       //(LATBbits.LATB13)


//SPI3を使用        //  SPIはSPI2を使用 
#define MP3_SCK_TRIS                    (TRISDbits.TRISD15)     //SDK3/RD15     (TRISBbits.TRISB12)     //VS1011e
#define MP3_SDI_TRIS                    (TRISFbits.TRISF2)      //SDI3/RF2      (TRISBbits.TRISB10)
#define MP3_SDO_TRIS                    (TRISFbits.TRISF8)      //SDO3/RF8      (TRISBbits.TRISB11)
#define MP3_SPI_IF                      (IFS0bits.SPI3RXIF)     //RX書込み完了フラグ    //(IFS2bits.SPI2IF)/Flag Status bit 1:interrupt occured  0:interrupt not occured
#define MP3_SSPBUF                      (SPI3BUF)               //      (SPI2BUF)
#define MP3_SPICON1                     (SPI3CON)              //                               (SPI2CON1)
//#define MP3_SPICON1bits                       (SPI3CONbits)           //(SPI2CON1bits)
//#define MP3_SPICON2                     (SPI3CON)               //SPI2CON2
//#define MP3_SPISTAT                   (SPI3STAT)               //(SPI2STAT)
//#define MP3_SPISTATbits                       (SPI3STATbits)          //(SPI2STATbits)
/* 関数プロトタイピング */
BYTE WriteSPI(BYTE output);
void Command(BYTE RegAdrs, BYTE UpData, BYTE LowData);
void SendData(BYTE Data);
//void delay_ms(int msec);
void VS1011_Init(void);
void VS1011_SineTest(void);
void SetVolume(BYTE right, BYTE left);
void SetBassBoost(BYTE bass, BYTE gfreq);
void PlayEnd(void);

//------------------------------------------------------------------------------------------------------------------------
//
/*****************************************************
*  VS1011E 制御ライブラリ 
*  
******************************************************/
//このファイルは 後閑哲也さんがPIC24FJ64GA002用に設計されたファイルを
//PIC32MX795F512L用に変更したものです。
#include "VS1011.h"

#include <p32xxxx.h>
//#include <p24FJ64GA002.h>
/************************************
* SPI Read after Write 基本関数
************************************/
BYTE WriteSPI(BYTE output){
        MP3_SPI_IF = 0;     //受信完了フラグクリア  // 割り込みフラグクリア
        MP3_SSPBUF = output;            // SPI出力
        while(!MP3_SPI_IF); //受信完了割込みフラグ待ち                      // 入力待ち
        return MP3_SSPBUF;  //                  // 入力データ戻り値
}
/************************************
*  VS1011用コマンド出力関数
************************************/
void Command(BYTE RegAdrs, BYTE UpData, BYTE LowData){
        MP3_XDCS_IO = 1;                        // データモード解除
        while(!MP3_DREQ_IO);            // レディー待ち
        MP3_XCS_IO = 0;                         // コマンドモード設定 
        WriteSPI(0x02);                         // 書き込み動作指定
        WriteSPI(RegAdrs);                      // レジスタアドレス出力
        WriteSPI(UpData);                       // 上位バイト出力
        WriteSPI(LowData);                      // 下位バイト出力
        MP3_XCS_IO = 1;                         // コマンドモード解除
}
/************************************
*  VS1011用コマンド出力関数(確認付き)
************************************/
void CmdCheck(BYTE RegAdrs, BYTE UpData, BYTE LowData){
        BYTE b1,b2;

        do{
                MP3_XDCS_IO = 1;                // データモード解除
                while(!MP3_DREQ_IO);    // レディー待ち
                MP3_XCS_IO = 0;                 // コマンドモード設定 
                WriteSPI(0x02);                 // 書き込み動作指定
                WriteSPI(RegAdrs);              // レジスタアドレス出力
                WriteSPI(UpData);               // 上位バイト出力
                WriteSPI(LowData);              // 下位バイト出力
                MP3_XCS_IO = 1;                 // コマンドモード解除
                while(!MP3_DREQ_IO);    // レディー待ち
                MP3_XCS_IO = 0;                 // 読み込み確認
                WriteSPI(0x03);                 // 読み込み動作
                WriteSPI(RegAdrs);              // レジスタアドレス指定
                b1 = WriteSPI(0xFF);    // return UpData
                b2 = WriteSPI(0xFF);    // return LowData

                MP3_XCS_IO = 1; 
        }while((b1 != UpData) || (b2 != LowData));
}
/************************************
*  VS1011用データ出力関数
************************************/
void SendData(BYTE Data){
        while(!MP3_DREQ_IO);            // レディー待ち
        WriteSPI(Data);
}

/***********************************************
*  音量レベル設定関数
*   vRight = 右チャネル用音量
*   vLeft  = 左チャネル用音量
*     いすれも 0x00=Max 0dB 0.5dBステップで下がる
************************************************/
void SetVolume(BYTE vRight, BYTE vLeft){
        Command(0x0B, vRight, vLeft);
}

/**********************************************
*  低音ブースト設定制御関数
*    bass: 低音ゲイン レンジは0dBから15dBの範囲
*    gfreq: 低音ブースト周波数設定 10Hzステップ 0?15の範囲
***********************************************/
void SetBassBoost(BYTE bass, BYTE gfreq)
{
        BYTE temp1 = 0;
        /* 設定範囲の制限 */
        if(bass > 15)
                bass = 15;
        if(gfreq > 15)
                gfreq = 15;
        /* 8ビットに合成 */
        temp1 = gfreq;
        temp1 |= (bass << 4);
        Command(0x02, 0xFF, temp1);             // BASS 
        return;
}
/*********************************************
*       再生終了処理関数
*
*********************************************/
void PlayEnd(void){
        int i;

        /* 再生バッファクリアのため2048バイト送信 */
        MP3_XDCS_IO = 0;                                                // XDCSオン
        for(i=0; i<2048; i++)
                SendData(0);                                            // 0のデータ連続送信
        MP3_XDCS_IO = 1;                                                // XDCSオフ
        /*** ソフトウェアリセットで完了 **/
        Command(0x00, 0x08, 0x24);                              // SM_RESET送信
        while(!MP3_DREQ_IO);                                    // コマンド完了待ち
}
/********************************************
*  VS1011 初期化関数
*    VS1011転送モード、SDIテストモード に設定
*    VS1011と正常に通信できないと永久待ちとなる
*********************************************/
void VS1011_Init(void){



   
        unsigned int val;
        // VS1011用ポートの初期設定 
        MP3_XDCS_IO = 1;                                // DCSをHigh
        MP3_XCS_IO = 1;                                 // XCSをHigh
        MP3_XRESET_IO = 0;                              // XRESETをLow
        MP3_XRESET_TRIS = 0;                    // 出力TRIS有効化
        MP3_DREQ_TRIS = 1;                              // DREQ入力モードに
        MP3_XDCS_TRIS = 0;                              // XDCS出力/////////
        MP3_XCS_TRIS = 0;                               // XCS出力
        MP3_SDI_TRIS = 1;                               // SDI2入力モード
        MP3_SDO_TRIS = 0;                               // SDO2出力モード
        MP3_SCK_TRIS = 0;                               // SCK2出力モード

        MP3_SPICON1 = 0x8120;                           // 8ビットモード,CKP = 0,CLK=Fosc/4 (4MHz)
                                                                        // 中央でサンプル(SMP=0) 立上りエッジで送信(CKE=1)
                                                                        // フレームモードなし
        SPI3BRG = 0x000F;                                       // 約2.5Mbps



        
        MP3_SPI_IF = 0;                                 // 割り込みフラグクリア
        // RESET解除、VS1011スタート
        delay_ms(50);                                   // 50msec delay
        MP3_XRESET_IO = 1;                              // RESET解除

        // モード設定 
        CmdCheck(0x00, 0x08, 0x20);             // モード初期設定 新モード、SDIテストモード

        // クロックダブラ設定 
        val = 12288 / 2 + 0x8000;               // 設定値を求める(データシートより)
        CmdCheck(0x03, (BYTE)(val /256), (BYTE)val);
        delay_ms(10);

}

/********************************************
*  VS1011 正弦波テストモード設定関数
*    MODEをSPIテストモードに設定しておく必要がある
*********************************************/
void VS1011_SineTest(void)
{
        /* テストモードシーケンス出力 */
        while(!MP3_DREQ_IO);
        MP3_XDCS_IO = 0;
        // Start Sine Test
        WriteSPI(0x53);
        WriteSPI(0xEF);
        WriteSPI(0x6E);
        WriteSPI(0x7D);                         // 22.050kHz Out is 5kHz
        WriteSPI(0x00);
        WriteSPI(0x00);
        WriteSPI(0x00);
        WriteSPI(0x00);
        MP3_XDCS_IO = 1;
}

/*
//usec単位ディレイ関数
void delay_us(int usec){
        usec = (int)(CLOCK*usec)/ 10;
        while(usec)     {
                asm("NOP");
                asm("NOP");
                asm("NOP");
                asm("NOP");
                asm("NOP");                                     
                usec--;
        }
}
//msec単位ディレイ関数
void delay_ms(int msec){
        int i;
        for(i=0; i< msec; i++)
                delay_us(1000);
}

*/


//*************************************************************************
//インクルードファイル    1lcd_lib_C32.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//*************************************************************************
#include <p32xxxx.h>
//#include <proc/p32mx795f512l.h>               //MX795はイニシャライズループを抜けられない
//#include <proc/p32mx360f512l.h>               //PIC32MX460F512L
#define Clock   80000000        // 単位はHzで指定


// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB13 //のDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_rs          LATAbits.LATA9  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定
#define lcd_stb         LATAbits.LATA10 //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定



void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);



//**************************************************************************
//インクルードファイル    1lcd_lib_C32.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C32コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C32.h"

void lcd_delay_us(unsigned int usec)    //1μsec遅延関数
{
        int count;

        count = (int)(Clock/20000000)*usec;
        do
        {
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                count--;        
        }while(count != 0);
}

void lcd_delay_ms(unsigned int msec)    //1msec遅延関数
{
        unsigned int i;
        
        for(i=0; i<msec; i++)
        lcd_delay_us(1000);
}


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        lcd_delay_us(1);                //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        lcd_delay_us(1);                // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        lcd_delay_us(50);               //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        lcd_delay_ms(2);        //      2msec待ち
        else
        lcd_delay_us(50);       //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_delay_ms(20);               //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(5);                //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}


//その他 FAT関連のインクルーファイルは下記にあります。
//マイクロチップのライブラリダウンロードページ: Microchip Libraries for Applications  私がつかったバージョンは \microchip_solutions_v2013-02-15 です。

<動作結果>

    ・ PIC32MX795F512Lで作成した音声です。 PCで聞いてみてください。   VOICE.WAV