« PICでSPI - 超高精度SPIバスRTC(リアルタイムクロック)DS3234Sの実装 | トップページ | バーナード星は動いているか? - 3 - その固有運動と年周視差を測定する »

2014年12月10日 (水)

PICでSPI SDカードを読み書きする

他のSPIデバイスといっしょに使うとSDカードが読み書きできないというトラブルに見舞われました。なんとか読み書きできるようにはなったのですが....

  SPI接続でSDカードとMCP3208がいっしょに使えない話

-------

今回の記事はきむしげさん(きむ茶工房ガレージハウス)の記事

  MMC/SDカードを接続し読書きを行って見ます

に書いてあることを自分でもやってみましたというだけの記事です。自分のメモみたいなものですので実際に自分でもやってみようという方はきむしげさんの記事を読まれた方がいいと思います。きむしげさんの記事は説明が詳しいです。

どうやって入出力をやるのかを基本的なところから自分で確かめて見たいという方にはこちらの方が参考になるかも

  ほよほよのブログ - 初めてのSPI通信、SDカードの読み書き
  ほよほよのブログ - PCから読める最小限のファイルシステム

---------

今回もPICはSPIと(LCD表示のための)I2Cが別々に使えるPIC18F26K22でやってみました。このシリーズはPIC18F23K22、PIC18F24K22、PIC18F25K22、PIC18F26K22、PIC18F43K22、PIC18F44K22、PIC18F45K22、PIC18F46K22といくつかありますが同じだと思います。

でやってみた結果なのですが読み書きとも問題なくできました。気になる速度なのですがSPIのクロックが4MHz(のはず)で16バイトのデータを1000回書き込んで十数秒くらいでした。気圧計とか温度計の記録をとるのが目的ですから特に問題なさそうです。多くても毎秒一回数百バイト程度の書き込みができれば十分ですから。

画像は基板にハンダ付けが終わったら追記しておきます。

-----

独自性(?)がちょっとはあるものがやっとできました。

  「PIC/I2C大気圧センサーLPS331APの測定値をSDカード(SPI)に記録する - はじめに

======

PIC PIC18F26K22
コンパイラー Microchip MPLAB XC8 C Compiler (Free Mode) V1.32
表示部分はI2C接続のACM1602を使っています。

じつは同じMSSPモジュールをI2CとSPIに切り替えて使ってみようと思ったのですがまだうまく行っていません。できるのかなあ....

SDカードのソケットは秋月で売っているSDカードスロットDIP化モジュールを使いました。3.3V電源のときはそのまま使え5V電源のときはジャンパー部にはんだをのせます。

なおこのDIP化モジュールは信号線がプルアップしてあるようです。
それと関係あるのかないのかわかりませんが、こんなこともありました。
    「SPI接続でトラブル! 複数のデバイスが使えない
    「SPI接続でSDカードとMCP3208がいっしょに使えない話」 (解決編)

SDカードはSanDiskの4GbyteのSDHCのものです。

-------

回路図を書くのが面倒なのでどういう具合に接続されているかだけ書いておきます。
カッコつきの数字はPICkit3のピン番号です。

// 01 /MCLR .....(1)
// 02 RA0/AN0  ====>  ソケットの CS
// 03 RA1/AN1  ====>  プログラムの制御用
// 14 RC3/SCL1 =====> I2Cバス
// 15 RC4/SDA1 =====> I2Cバス
// 19 VSS .....(3)
// 20 VDD .....(2)
// 22 RB1/INT1/P1C/SCK2/SCL2/C12IN3-/AN10 =====> ソケットの CLK
// 23 RB2/INT2/CTED1/P1B/SDI2/SDA2/AN8 =====>  ソケットの SDO
// 24 RB3/CTED2/P2A/CCP2/SDO2/C12IN2-/AN9 =====> ソケットの SDI
// 27 RB6/TX2/PGC .....(5)
// 28 RB7/RX2/PGD .....(4)

------

関連

  趣味の電子工作
    PIC

  「PIC18F26K22でSPI - 8ch/ADコンバータ MCP3208の使い方(ソース付き)
  「PICでSPI - 超高精度SPIバスRTC(リアルタイムクロック)DS3234Sの使い方」(ソース付き)
  「PICでSPI - 超高精度SPIバスRTC(リアルタイムクロック)DS3234Sの実装

--------

ソース

I2CライブラリとAMC1602のライブラリは

  「I2Cのソース - PIC12F1822/16F1705/16F1938/18F26K22 - LCD(ACM1602)を例にして

にあるものをそのまま使っています。SDカード関連のライブラリはきむしげさんのものを使いましたがほんのちょっとだけ修正して使いました。

main.c
きむしげさんのSD1.cとSD2.cをもとにしたテスト用のプログラムです。いつもどおり“最低限何が必要か”という視点でコーディングしてあります(/MCLRも無効にしていないです)
RA1がGNDに落ちていたら書き込み、RA1をVDDに接続したら読み込みをするように作ってあります。

#include <xc.h>
#include <stdio.h>
#include <string.h>
#include "..\..\include\common\MyDef.h"
#include "..\..\include\common\I2CLib.h"
#include "..\..\include\common\ACM1602lib.h"
#include "..\..\include\common\SPILib.h"
#include "..\..\include\common\SDlib.h"
// C:\Program Files (x86)\Microchip\xc8\v1.32\docs\chips\18f26k22.html
#ifdef _18F26K22
#pragma config FOSC = INTIO67
#pragma config WDTEN = OFF
#endif
void putLCDhex(unsigned char ch)
{
    char hex[]="0123456789SBCDEF";
    LCD_Putc(hex[ch>>4]) ;
    LCD_Putc(hex[ch & 0x0f]) ;
}
void interrupt InterFunction( void )
{
     // I2C関連の割り込み処理
     InterI2C() ;
}
void main()
{
    union {
        char c[2] ;
        int  i ;
    } ans ;
    char dt_r[32] ;
    char dt_w[3][22] = {
          "xxxxxxxxxxxxxx\r\n",
          "test2\r\n",
          "test3\r\n"
    } ;
    int j;
    int row=1;
    OSCCON = MyOSCCON ;
// for I2C
    ANSELCbits.ANSC3 = 0;
    ANSELCbits.ANSC4 = 0;
// for SPI
    ANSELBbits.ANSB2 = 0;
    ANSELBbits.ANSB1 = 0;
    TRISB1 = 0;
    TRISB3 = 0;
// OUTPUT /CS
    TRISA0 = 0;
    PORTAbits.RA0 = 1;
// INPUT
    ANSELAbits.ANSA1 = 0;
    SPI_Init(SPI_MODE2,SPI_CLOCK_DIV4) ;
    InitI2C_Master() ;
    LCD_Init() ;
    LCD_Clear();
    if( PORTAbits.RA1 == 1 ) {
        for(j=0; j<100; j++) __delay_ms(30) ;        // 3秒後に開始
        ans.i = SD_Init() ;                          // MMC/SDCの初期化を行う
        if (ans.i == 0) {
            ans.i = SD_Open("XYZ.TXT",O_READ) ;    // ファイルのオープン
            if (ans.i == 0) {
                while(1) {
                    memset(dt_r,0x00,sizeof(dt_r)) ;
                    ans.i = SD_fGets(dt_r,18) ;     // ファイルから1行読込む
                    dt_r[strlen(dt_r)-2]=0x00;
                    if (ans.i != 0) {
                        LCD_Puts(dt_r) ;
                        LCD_SetCursor(0,row);
                        row=1-row;
                    } else break ;
                    for(j=0; j<100; j++) __delay_ms(20) ;
                }
                SD_Close() ;                       // ファイルのクローズ
                if (ans.i == 0) LCD_Puts("Successful End!!") ;
                else            LCD_Puts("Abnormal Read!!") ;
            } else {
                LCD_Puts("Error Open!!") ;      // オープンエラー
            }
        } else {
            LCD_Puts("Error Init ") ;            // 初期化エラー
            putLCDhex(ans.c[1]) ;
            putLCDhex(ans.c[0]) ;
        }
    } else {
        for(j=0; j<100; j++) __delay_ms(30) ;        // 3秒後に開始
        // MMC/SDCの初期化を行う
        ans.i = SD_Init() ;
        if (ans.i == 0) {
            // ファイルを新規に作成してオープンする
            ans.i = SD_Open("XYZ.TXT",O_RDWR) ;
            if (ans.i == 0) {
                LCD_Puts("The write start") ;
                LCD_SetCursor(0,1);
                // ファイルへ1行ずつ書き込む
//                for(j=0; j<1000;j++){
//                    ans.i = SD_Write(dt_w[0],strlen(dt_w[0])) ;
//                }
                ans.i = SD_Write(dt_w[0],strlen(dt_w[0])) ;
                ans.i = SD_Write(dt_w[1],strlen(dt_w[1])) ;
                ans.i = SD_Write(dt_w[2],strlen(dt_w[2])) ;
                // ファイルのクローズ
                SD_Close() ;
                if (ans.i != -1) LCD_Puts("Successful End!!") ;
                else             LCD_Puts("Abnormal Write!!") ;
            } else {
                LCD_Puts("Error Open!!") ;      // オープンエラー
            }
        } else {
            LCD_Puts("Error Init ") ;            // 初期化エラー
            putLCDhex(ans.c[1]) ;
            putLCDhex(ans.c[0]) ;
        }
    }
    while(1) ;                                   // 処理中断

}

SPIlib.h
ここはきむしげさん(きむ茶工房ガレージハウス)のソースと同じですが_XTAL_FREQとCSはMyDef.hの方で設定しています。

#include "..\..\include\common\MyDef.h"
//#ifndef _XTAL_FREQ
// Unless already defined assume 8MHz system frequency
// This definition is required to calibrate __delay_us() and __delay_ms()
//#define _XTAL_FREQ 8000000    // 使用するPIC等により動作周波数値を設定する
//#endif
// #define CS   RC2                        // カード選択信号
 

SDlib.c
ここもきむしげさん(きむ茶工房ガレージハウス)のソースと同じです。CS(のポート)は事情があってCD_SDとしてMyDef.hで定義してあります。

void cs_select(int flag)
{
     CS_SD = flag ;
     SPI_transfer(0xff) ;     // 確実にCSを切替える為にクロックを送信しておく
}
.
.
.
int SD_Init()
{
     unsigned long arg ;
     unsigned char r7[4] ;
     unsigned int i , ans ;
     CS_SD    = 1 ;
     CardType = 0 ;


MyDef.h


/*
* File:   MyDef.h
* Author: Seppina
*
* Created on 2014/11/22, 14:38
*/

#ifndef MYDEF_H
#define MYDEF_H

// http://www.microchip.jp/docs/41406B_JP.pdf
#ifdef _12F1822
#define _XTAL_FREQ 16000000
#define MySSPADD    0x27
#define SSPIE   SSP1IE
#define SSPIF   SSP1IF
#define BCLIE   BCL1IE
#define BCLIF   BCL1IF
//#define CS   PORTAbits.RA0
#endif

// http://ww1.microchip.com/downloads/en/DeviceDoc/40001729A.pdf
// http://ww1.microchip.com/downloads/jp/DeviceDoc/40001722A_JP.pdf
// (下は16F1703のものですが参考になります。これもきむしげさん情報です)
#ifdef _16F1705
#define _XTAL_FREQ 8000000
#define MySSPADD    0x13
#define SSPIE   SSP1IE
#define SSPIF   SSP1IF
#define BCLIE   BCL1IE
#define BCLIF   BCL1IF
//#define CS   PORTAbits.RA0
#endif

// http://ww1.microchip.com/downloads/en/DeviceDoc/40001574C.pdf
#ifdef _16F1938
#define _XTAL_FREQ 8000000
#define MySSPADD    0x13
//#define CS   PORTAbits.RA0
#endif

// http://ww1.microchip.com/downloads/en/DeviceDoc/41412F.pdf
#ifdef _18F26K22
#define MyOSCCON    0b01110010
#define _XTAL_FREQ  16000000
#define MySSPADD   0x27
#define CS_SD   PORTAbits.RA0                     // カード選択信号
#endif

#endif /* MYDEF_H */

« PICでSPI - 超高精度SPIバスRTC(リアルタイムクロック)DS3234Sの実装 | トップページ | バーナード星は動いているか? - 3 - その固有運動と年周視差を測定する »

趣味の電子工作」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック


この記事へのトラックバック一覧です: PICでSPI SDカードを読み書きする:

« PICでSPI - 超高精度SPIバスRTC(リアルタイムクロック)DS3234Sの実装 | トップページ | バーナード星は動いているか? - 3 - その固有運動と年周視差を測定する »

フォト

サイト内検索

  • 記事を探されるんでしたらこれがいちばん早くて確実です。私も使ってます (^^;; 検索窓が表示されるのにちょっと時間がかかるのはどうにかしてほしいです。

新着記事

リンク元別アクセス数

  • (アクセス元≒リンク元、原則PCのみ・ドメイン別、サイト内等除く)

人気記事ランキング

  • (原則PCのみ、直近2週間)
無料ブログはココログ