dsPIC33AKシリーズ⑳ SPIモジュールの使い方

dsPIC33Aシリーズ

概要

今回は、dsPIC33AKシリーズのSPIモジュールの動作を確認します。Curiosityボード上には2MByteのQSPIフラッシュメモリが搭載されていますので、読み書きを実装します。

SPIとは

SPIとは「Serial Peripheral Interface」の頭文字をとった用語で、主に基板内でデバイス同士の通信を行う規格です。

関連記事

記事リンク
第1回dsPIC33AKシリーズについてdsPIC33Aシリーズに関して – ぴくおの電子工作的な何かWP (electricpico.com)
第2回開発ボード、コンフィグレーション設定、クロック設定についてdsPIC33AKシリーズ②開発ボード,コンフィグレーション設定,クロック設定について – ぴくおの電子工作的な何かWP (electricpico.com)
第3回CPU性能についてdsPIC33AKシリーズ③CPU性能について – ぴくおの電子工作的な何かWP (electricpico.com)
第4回FPU性能についてdsPIC33AKシリーズ④FPU性能について – ぴくおの電子工作的な何かWP (electricpico.com)
第5回DSPについてdsPIC33AKシリーズ⑤DSPについて – ぴくおの電子工作的な何かWP (electricpico.com)
第6回タイマー1割り込みの使い方dsPIC33AKシリーズ⑥Timer1割り込みの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第7回PMUの使い方dsPIC33AKシリーズ⑦PMUの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第8回高速ADCの使い方dsPIC33AKシリーズ⑧高速ADCの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第9回高速OPAMPの使い方dsPIC33AKシリーズ⑨高速OPAMPの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第10回DMAモジュールの使い方dsPIC33AKシリーズ⑩DMAモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第11回WDTモジュールの使い方dsPIC33AKシリーズ⑪WDTモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第12回DMTモジュールの使い方dsPIC33AKシリーズ⑫DMTモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第13回I/Oインテグリティモニタモジュールの使い方dsPIC33AKシリーズ⑬I/Oインテグリティモニターモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第14回QEIモジュールの使い方dsPIC33AKシリーズ⑭QEIモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第15回UARTモジュールの使い方dsPIC33AKシリーズ⑮UARTモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第16回DSPの使い方1 (デジタルフィルタ)dsPIC33AKシリーズ⑯ DSPの使い方1(デジタルフィルタ) – ぴくおの電子工作的な何かWP (electricpico.com)
第17回DSPの使い方2 (FFT)dsPIC33AKシリーズ⑰ DSPの使い方2(FFT) – ぴくおの電子工作的な何かWP (electricpico.com)
第18回DSPの使い方3 (自己相関アルゴリズム)dsPIC33AKシリーズ⑱ DSPの使い方3(自己相関アルゴリズム) – ぴくおの電子工作的な何かWP (electricpico.com)
第19回DSPの使い方4(LMSアルゴリズム)dsPIC33AKシリーズ⑲ DSPの使い方4(LMSアルゴリズム) – ぴくおの電子工作的な何かWP (electricpico.com)
第20回(本記事)SPIモジュールの使い方dsPIC33AKシリーズ⑳ SPIモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
(fig.1-1)dsPIC33Aシリーズ各関連記事リンク
関連記事リンク
SPIモジュールの使い方SPIモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
(fig.1-2)各関連記事リンク

開発環境

開発環境を以下に示します。
今回はCPUボード(EV02G02A)で動作確認を行います。

項目リンク
ベースボードdsPIC33A CURIOSITY PLATFORM
DEVELOPMENT BOARD
dsPIC33A Curiosity Platform Development Board User’s Guide (microchip.com)
CPUボード(EV68M17A)EV68M17A – dsPIC33AK128MC106 Motor Control DIMdsPIC33AK128MC106 Motor Control Dual In-Line Module (DIM) Information Sheet (microchip.com)
CPUボード(EV02G02A)dsPIC33AK128MC106 General Purpose Dual In-Line Module (DIM)dsPIC33AK128MC106 General Purpose Dual In-Line Module (DIM) | Microchip Technology
統合開発環境MPLAB X IDE v6.20MPLAB® X IDE | Microchip Technology
コンパイラMPLAB XC DSC v3.10MPLAB® XC DSC Compiler | Microchip Technology
(fig.2-1)本記事の動作確認環境
(fig.2-2)動作環境

SPIモジュールについて

ブロック図

下記にSPIモジュールのブロック図を示します。

(fig.3-1)SPIモジュールブロック図 (データシート 70005539B – p.996 より抜粋)

レジスタ

以下にSPIレジスタとその説明を示します。

レジスタ名(xは1~3)機能説明
SPIxCON1SPI制御レジスタ1SPIモジュールの設定を行う
SPIxCON2SPI制御レジスタ2送信ビット長設定
SPIxSTATSPIステータスレジスタSPIモジュールのステータスレジスタ
SPIxBUFSPIバッファレジスタSPI送受信のためのバッファ設定を行う
SPIxBRGSPIボーレートレジスタボーレートの設定を行う
SPIxIMSKSPI割り込みマスクレジスタSPI割り込みの要因について設定する
SPIxURDTSPIアンダーランレジスタSPIアンダーランデータの設定を行う
(fig.3-1)SPIレジスタ

動作説明

ブロック図

今回のブロック図を以下に示します。

SCKピンについて

本来、RP33ピンにはフラッシュメモリのSCK入力が接続されているため、SCK機能を割り当てる必要があります。しかし、SCKをRP33ピンに割り当てた場合に動作が不安定になる現象が発生しました。RP33ピンにはもともとクロックアウトが割り当てられており、クロックアウトを無効にすれば正常に動作するはずですが、問題は解消されませんでした。

この現象がチップ自体のエラッタによるものなのか、私のCPUボードの故障によるものなのかは不明です。そこで今回は、下図のようにCPUボードのエッジコネクタの76番ピンと83番ピンにテープを貼り、フラッシュメモリとの接続を切断した上で、SCKをRP51ピンに割り当ててベースボード上で接続しました。

(fig.4-1)ブロック図

ソースコード

コンフィグレーションファイル

コンフィグレーションファイル、クロック設定ファイルは以下のファイルをインクルードしてください。

なおSST26VF020Aのドライバファイルついて、全ての機能の動作確認を行っていません。

■コンフィグレーションファイル 

■クロック設定ソースファイル

■クロックヘッダーファイル

■SST26VF020Aソースファイル

■SST26VF020Aヘッダーファイル

ソースコード全体

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "config.h"
#include "clock_driver.h"
#include "FlashMemory_SST26VF_driver.h"

/*----------------------------------------------------------------------------*/
/* 定数定義*/
/*----------------------------------------------------------------------------*/
#define RX_BUFF_SIZE	128
/*----------------------------------------------------------------------------*/
/*変数定義*/
/*----------------------------------------------------------------------------*/
uint32_t ID;
uint8_t FlashBuff[RX_BUFF_SIZE];

static void Uart_Send_Blocking_TX_Data(uint8_t *u1pa_Data);

/*----------------------------------------------------------------------------*/
/**
* @fn          main(int argc, char** argv) 
* @brief       PROJECT_3_1_6_SPI_FLASH
* @param[in]   argc argument count
* @param[in]   argv argument vector
* @retval      EXIT_SUCCESS 成功
* @retval      EXIT_FAILURE 失敗
* @detail      SPIによるフラッシュメモリアクセス
* @note        
 */
/*----------------------------------------------------------------------------*/
int main(int argc, char** argv) 
{
    /*-----------------------------------------------------------------------*/
    /* クロック初期化*/
    /*-----------------------------------------------------------------------*/
        vdg_Clock_Set_Register();
    /*-----------------------------------------------------------------------*/
    /* 変数初期化*/
    /*-----------------------------------------------------------------------*/
	for (int i = 0 ;i<16;i++){FlashBuff[i] = i+2;}
		
    /*-----------------------------------------------------------------------*/
    /* ピン設定*/
    /*-----------------------------------------------------------------------*/
	RPOR12bits.RP50R = 9u;	//UART1出力 RP50
	RPINR9bits.U1RXR = 52u;	//UART1入力 RP52
	RPOR10bits.RP44R = 13u; //SDO1
	RPOR12bits.RP51R = 14u;	//SCK1
	RPINR10bits.SDI1R = 60u; //SDI1
	TRISDbits.TRISD4 = 0;    //SS
	//RPOR13bits.RP53R = 15u;	//SS1
	TRISCbits.TRISC3 = 0;    //LED1
	TRISCbits.TRISC4 = 0;    //LED1
	LATDbits.LATD4 = 0u;
    /*-----------------------------------------------------------------------*/
    /* SPI初期化*/
    /*-----------------------------------------------------------------------*/
	SPI1CON1 = 0x00000000u;
	SPI1CON1bits.ENHBUF = 0u;
	SPI1CON1bits.SPIFE = 0u;	
	SPI1CON1bits.MCLKEN = 0u;	//Standard Speed Peripheral Clock
	SPI1CON1bits.DISSCK = 0u;
	SPI1CON1bits.DISSDI = 0u;
	SPI1CON1bits.MSTEN = 1u;	//Host mode
	SPI1CON1bits.CKP = 0u;
	SPI1CON1bits.SSEN = 0u;
	SPI1CON1bits.CKE = 1u;
	SPI1CON1bits.SMP = 0u;
	SPI1CON1bits.MODE16 = 0u;
	SPI1CON1bits.MODE32 = 0u;
	SPI1CON1bits.DISSDO = 0u;
	SPI1CON1bits.SIDL = 0u;
	SPI1CON1bits.FRMCNT = 0u;
	SPI1CON1bits.FRMSYPW = 0u;
	SPI1CON1bits.MSSEN = 0u;
	SPI1CON1bits.FRMPOL = 0u;
	SPI1CON1bits.FRMSYNC = 0u;
	SPI1CON1bits.FRMEN = 0u;
	SPI1CON1bits.AUDMOD = 0u;
	SPI1CON1bits.URDTEN = 0u;
	SPI1CON1bits.AUDMONO = 0u;
	SPI1CON1bits.IGNTUR = 0u;
	SPI1CON1bits.IGNROV = 0u;
	SPI1CON1bits.SPISGNEXT = 0u;
	SPI1CON1bits.AUDEN = 0u;
		
	SPI1BRG = 0x00000003u;
		
	SPI1CON1bits.ON = 1u;

		
	// IDの読込
	ID = SST26VF_Read_ID();
		
	//ステータス・コンフィグレジスタへの書込み
	SST26VF_Write_StatusAndConfig(0,0);
		
	//チップの消去
	SST26VF_Erase_Chip();
		
	//ページライト
	SST26VF_Write_Page(FlashBuff,0,16);
	
	//バッファクリア
	for (int i = 0 ;i<16;i++){FlashBuff[i] = 0;}
		
	//データリード
	SST26VF_Read_Data(FlashBuff,0,16);
		
    /*-----------------------------------------------------------------------*/
    /*メインルーチン*/
    /*-----------------------------------------------------------------------*/
        while(1)
        {

	}
		
    return EXIT_SUCCESS;
}

結果

データリード後のFlashBuffメモリの値を示します。

記事についての注意点

本記事は慎重に内容を検討し正確さに努めておりますが、内容に誤りがあったとしても、この記事を参考にして生じた損害等については一切の責任を負いません。

コメント

タイトルとURLをコピーしました