//======================================================================== // This library derived from skSPIlib.c below and was modified for // use of two SPI(SPI1 and SPI2) interfaces. // 2022.04.03 Tosh_Kojima //======================================================================== /******************************************************************************* * skSPIlib.c - SPI通信を行う関数ライブラリ(16ビットMCU専用) * * * * SPI_Init - SPIモード(マスター)の設定と初期化を行う処理 * * SPI_setDataMode - SPIの転送モード設定を行う処理 * * SPI_setClockDivider - SPIの通信速度設定を行う処理 * * SPI_transfer - SPI通信でのデータ送信とデータ受信を行う処理 * * * * メモ:SDIピンは必ず「デジタル入力ピン」に設定を行って下さい。 * * 使用するSS(CS)ピンは初期化時にHIGHにします。 * * SPI2を利用する場合は、skSPIlib.hに"#define SPI_MSSP2_USE"を宣言する * * ============================================================================ * * VERSION DATE BY CHANGE/COMMENT * * ---------------------------------------------------------------------------- * * 1.00 2015-07-30 きむ茶工房 Create * * 1.10 2016-06-14 きむ茶工房(きむしげ) SPI_MODEのCKE(クロック位相)を変更 * * 1.20 2019-01-08 きむ茶工房(きむしげ) PIC24F動作確認 * * ============================================================================ * * PIC24E(24EP256MC202) PIC24F(24FJ64GB002) * * MPLAB X(v4.10) * * MPLAB(R) XC16 C Compiler Version 1.30 * *******************************************************************************/ //#include #include "p24FJ64GA002.h" // MPLAB IDE V8.60でデバッグ 231004 #include "skSPIlib.h" //########################################################################### // Begin of SPI1 ############################################################ #ifdef SPI1_USE /******************************************************************************* * SPI_Init(mode,divider,sdo) * * SPIモードの設定(マスター)と初期化を行う処理 * * SPI_CLOCK_DIV1にする場合は、セカンダリプリスケールは 1:1以外に設定します。* * * * mode : SPIの転送モードを設定します(クロック極性とクロック位相の組合せ) * * SPI_MODE1 = 極性(0:LOW) 位相(0:アイドル0Vで、0V->5Vに変化で転送)* * SPI_MODE0 = 極性(0:LOW) 位相(1:アイドル0Vで、5V->0Vに変化で転送)* * SPI_MODE3 = 極性(1:HIGH) 位相(0:アイドル5Vで、5V->0Vに変化で転送)* * SPI_MODE2 = 極性(1:HIGH) 位相(1:アイドル5Vで、0V->5Vに変化で転送)* * divider :SPIの通信速度を設定します(プライマリプリスケール) * * SPI_PPRE_DIV4 = 4:1 (FCY/4)/セカンダリプリスケール * * SPI_PPRE_DIV16 = 16:1 (FCY/16)/セカンダリプリスケール * * SPI_PPRE_DIV64 = 64:1 (FCY/64)/セカンダリプリスケール * * sdo : 使用するSDO送信のピン番号を指定する(未使用) * *******************************************************************************/ void SPI1_Init(char mode,char divider,int sdo) { int con ; // マスターモード、8ビット通信、SPI_MODE1、セカンダリプリスケールは 1:1、SPI_PPRE_DIV64 con = 0b0010000000111100 ; con = con | divider ; // 指定のクロック速度(プライマリプリスケール)を設定する if (mode == SPI1_MODE0 || mode == SPI1_MODE2) { con = con | 0x0100 ; // 指定のクロック位相を設定する(クロック位相は1とする) } if (mode == SPI1_MODE2 || mode == SPI1_MODE3) { con = con | 0x0040 ; // 指定のクロック極性を設定する(極性をHIGHとする) } SPI1_CON1 = con ; SPI1_STAT_SPIEN = 1 ; // SPI有効 SPI1_IF = 0 ; // SPIの割込みフラグを初期化する } /******************************************************************************* * SPI_setDataMode(mode) * * SPIの転送モード設定を行う処理 * * mode : SPIの転送モードを設定します(クロック極性とクロック位相の組合せ) * *******************************************************************************/ void SPI1_setDataMode(char mode) { if (mode == SPI1_MODE0 || mode == SPI1_MODE2) { SPI1_CON1 = SPI1_CON1 | 0x0100 ; // 指定のクロック位相を1設定する } else { SPI1_CON1 = SPI1_CON1 & 0xFEFF ; // 指定のクロック位相を0設定する } if (mode == SPI1_MODE2 || mode == SPI1_MODE3) { SPI1_CON1 = SPI1_CON1 | 0x0040 ; // 指定のクロック極性をHIGH設定する } else { SPI1_CON1 = SPI1_CON1 & 0xFFBF ; // 指定のクロック極性をLOW設定する } } /******************************************************************************* * SPI_setClockDivider(divider1,divider2) * * SPIの通信速度設定を行う処理 * * プライマリプリスケール 1:1とセカンダリプリスケール 1:1の組み合わせは避ける* * divider1 :プライマリプリスケールを設定する * * divider2 :セカンダリプリスケールを設定する * *******************************************************************************/ void SPI1_setClockDivider(char divider1,char divider2) { SPI1_CON1 = (SPI1_CON1 & 0xFFE3) | divider1 ; // プライマリプリスケールを設定する SPI1_CON1 = (SPI1_CON1 & 0xFFFC) | divider2 ; // セカンダリプリスケールを設定する } /******************************************************************************* * ans = SPI_transfer(dt) * * SPI通信でのデータ送信とデータ受信を行う処理 * * 16ビット通信の場合は改造しましょう(char -> int) * * * * dt : 8ビットの送信するデータを指定します * * ans : 8ビットの受信したデータを返します * *******************************************************************************/ unsigned char SPI1_transfer(char dt) { SPI1_BUF = dt ; // データの送信 while(SPI1_IF == 0) ; // 受信待ち SPI1_IF = 0 ; // フラグクリア return SPI1_BUF ; // データの受信 } #endif // End of SPI1 ############################################################# //########################################################################### // Begin of SPI2 ############################################################ #ifdef SPI2_USE /******************************************************************************* * SPI2_Init(mode,divider,sdo) * * SPI2モードの設定(マスター)と初期化を行う処理 * * SPI2_CLOCK_DIV1にする場合は、セカンダリプリスケールは 1:1以外に設定します。* * * * mode : SPI2の転送モードを設定します(クロック極性とクロック位相の組合せ) * * SPI2_MODE1 = 極性(0:LOW) 位相(0:アイドル0Vで、0V->5Vに変化で転送)* * SPI2_MODE0 = 極性(0:LOW) 位相(1:アイドル0Vで、5V->0Vに変化で転送)* * SPI2_MODE3 = 極性(1:HIGH) 位相(0:アイドル5Vで、5V->0Vに変化で転送)* * SPI2_MODE2 = 極性(1:HIGH) 位相(1:アイドル5Vで、0V->5Vに変化で転送)* * divider :SPI2の通信速度を設定します(プライマリプリスケール) * * SPI2_PPRE_DIV4 = 4:1 (FCY/4)/セカンダリプリスケール * * SPI2_PPRE_DIV16 = 16:1 (FCY/16)/セカンダリプリスケール * * SPI2_PPRE_DIV64 = 64:1 (FCY/64)/セカンダリプリスケール * * sdo : 使用するSDO送信のピン番号を指定する(未使用) * *******************************************************************************/ void SPI2_Init(char mode,char divider,int sdo) { int con ; // マスターモード、8ビット通信、SPI_MODE1、セカンダリプリスケールは 1:1、SPI_PPRE_DIV64 con = 0b0010000000111100 ; con = con | divider ; // 指定のクロック速度(プライマリプリスケール)を設定する if (mode == SPI2_MODE0 || mode == SPI2_MODE2) { con = con | 0x0100 ; // 指定のクロック位相を設定する(クロック位相は1とする) } if (mode == SPI2_MODE2 || mode == SPI2_MODE3) { con = con | 0x0040 ; // 指定のクロック極性を設定する(極性をHIGHとする) } SPI2_CON1 = con ; SPI2_STAT_SPIEN = 1 ; // SPI有効 SPI2_IF = 0 ; // SPIの割込みフラグを初期化する } /******************************************************************************* * SPI2_setDataMode(mode) * * SPIの転送モード設定を行う処理 * * mode : SPIの転送モードを設定します(クロック極性とクロック位相の組合せ) * *******************************************************************************/ void SPI2_setDataMode(char mode) { if (mode == SPI2_MODE0 || mode == SPI2_MODE2) { SPI2_CON1 = SPI2_CON1 | 0x0100 ; // 指定のクロック位相を1設定する } else { SPI2_CON1 = SPI2_CON1 & 0xFEFF ; // 指定のクロック位相を0設定する } if (mode == SPI2_MODE2 || mode == SPI2_MODE3) { SPI2_CON1 = SPI2_CON1 | 0x0040 ; // 指定のクロック極性をHIGH設定する } else { SPI2_CON1 = SPI2_CON1 & 0xFFBF ; // 指定のクロック極性をLOW設定する } } /******************************************************************************* * SPI2_setClockDivider(divider1,divider2) * * SPIの通信速度設定を行う処理 * * プライマリプリスケール 1:1とセカンダリプリスケール 1:1の組み合わせは避ける* * divider1 :プライマリプリスケールを設定する * * divider2 :セカンダリプリスケールを設定する * *******************************************************************************/ void SPI2_setClockDivider(char divider1,char divider2) { SPI2_CON1 = (SPI2_CON1 & 0xFFE3) | divider1 ; // プライマリプリスケールを設定する SPI2_CON1 = (SPI2_CON1 & 0xFFFC) | divider2 ; // セカンダリプリスケールを設定する } /******************************************************************************* * ans = SPI2_transfer(dt) * * SPI通信でのデータ送信とデータ受信を行う処理 * * 16ビット通信の場合は改造しましょう(char -> int) * * * * dt : 8ビットの送信するデータを指定します * * ans : 8ビットの受信したデータを返します * *******************************************************************************/ unsigned char SPI2_transfer(char dt) { SPI2_BUF = dt ; // データの送信 while(SPI2_IF == 0) ; // 受信待ち SPI2_IF = 0 ; // フラグクリア return SPI2_BUF ; // データの受信 } #endif // End of SPI2 #############################################################