稼働中

マイクロビット(c_08)SDカード初期化 用モジュール

SDカードモジュール(SPI) SDC_INIT_c.py

2GB以下(MMC)とSDHC(2GB超~32GB)SDカードの初期化で使う自作の’SDC_INIT_c.py’を作成しました。使い方だけを記載します。(※記事e_022を元にクラスにしました。)
‘SDC_INIT_c.py’は末尾にあります。

使い方

ファイル転送
micro:bitへ’SDC_INIT_c.py’を送った後でimportして使います。micro:bitに直接ファイルをアップロード出来ない場合(Thonny 3.1.12など)は、microfsなどを使ってアップロードします。
※microfsについては、当サイト内のこちらを参照ください。
※ファイルシステムへ送って使わないとメモリーエラーになると思います。(micro:bit V1)

メソッド
‘SDC_INIT_c’をimportすると「SDC_init, SDC_cmd00, SDC_cmd01, SDC_cmd08, SDC_acmd41, SDC_end」のメソッドが使えるようになります。
SDC_INIT()で初期化します。CS(chip select)と接続するmicro:bitのpinを指定して初期化します。defaltはpin8です。
(01)SDC_init()
ダミークロックを’0xff’を80個送りspi通信にします。CSをLowにしてデバイスを選択します。
(02)SDC_cmd00()
cmd0(GO_IDLE_STATE)コマンドを送ります。
(03)SDC_cmd08()
cmd8(SEND_IF_COND)コマンドを送ります。
(04)SDC_acmd41()
cmd55(APP_CMD)に続けてacmd41(SD_APP_OP_COND)コマンドを送ります。
SDHCの初期化に使うコマンドのようです。
(05)SDC_cmd01()
cmd1(SEND_OP_CND)コマンドを送ります。2GB以下のSDカードの初期化に使うようです。
(06)SDC_end()
CSをHighにしてデバイスを非選択にします。

使用例

2GB以下(MMC)とSDHC(2GB超~32GB)の初期化をしてみました。 


SDC_INIT_ex.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from microbit import *
#SDC_INIT_c.py
from SDC_INIT_c import *
import sys

## example ------------------
# SPI init bps=100kHz
spi.init(baudrate=100000, bits=8, mode=0, sclk=pin13, mosi=pin15, miso=pin14)
sleep(10)
a=SDC_INIT()
## SDHC or MMC INIT START
a.SDC_init()   
##CS(0)
a.SDC_cmd00()
a.SDC_cmd08()
a.SDC_end()

実行結果
standard SD 1GBの初期化


>>> %Run SDC_INIT_ex.py
START CLK>80
cmd0 OK resp=0x01
CMD8 R7-5bytes >> b'\xff\xff\xff\xff\xfe'
CARD ERROR >> MMC(Standard) 
cmd0 OK resp=0x01
cmd1 OK resp=0x00
MMC_INIT
>>>

SDHC16GBの初期化


>>> %Run SDC_INIT_ex.py
START CLK>80
cmd0 OK resp=0x01
CMD8 R7-5bytes >> b'\x01\x00\x00\x01\xaa'
CMD8 0x01 or 0x00 >>> 1
CMD55 Pass 0x01 >>>
ACMD41 0x01 RETRY b'\x01'
CMD55 Pass 0x01 >>>
ACMD41 Pass 0x00 b'\x00'
SDHC_INIT
>>>

モジュール

SDカードの初期化用モジュール


SDC_INIT_c.py
from microbit import *
import sys
# ------------------------INIT (SDC 2GB<)---- CMD0>>CMD8>>CMD55>>ACMD41
# ------------------------INIT (SD MMC <=2GB) CMD0>>CMD1 
# command
# cmd0=0x40    GO_IDLE_STATE
# cmd1=0x41    SEND_OP_CND 
# cmd8=0x48    SEND_IF_COND
# cmd55=0x77   APP_CMD 
# acmd41=0x69  SD_APP_OP_COND 
class SDC_INIT:
    def __init__(self,pins=pin8):    
        # micro:bit pin8 for CS active(0)
        self.CS_pin=pins

    # card send data
    def spi_cmd(self,cmd,da1,da2,da3,da4,crc):
        buf=bytearray(6)
        buf[0]=0x40+cmd
        buf[1]=da1
        buf[2]=da2
        buf[3]=da3
        buf[4]=da4
        buf[5]=crc
        spi.write(buf)
        return buf
    # dummy 8clk
    def spi_ff(self):
        spi.write(b'\xff') 
    # chip select active(0)
    def CS(self,dat):
        self.CS_pin.write_digital(dat)
   
    # SDCの初期化 Initialization sequence
    def SDC_init(self): 
        print('START CLK>80')
        self.CS(1)               #CS=Hでダミークロックを80個送信(74個<)
        for i in range(10):
            self.spi_ff()
        self.CS(0)
    # ---------------------------------------------------------- CMD00
    def SDC_cmd00(self):     
        #print('CMD0')
        #cmd0=0x40  #GO_IDLE_STATE
        self.spi_ff()
        self.spi_cmd(0,0x00,0x00,0x00,0x00,0x95) 

        while True:
            self.spi_ff() 
            res=spi.read(1) # response
            #print('response=',res)
            if res== b'\x01':
                print('cmd0 OK resp=0x01')
                break
    # ---------------------------------------------------------- CMD08
    def SDC_cmd08(self):
        #print('CMD8')
        # cmd8=0x48(SEND_IF_COND)
        self.spi_ff()
        self.spi_cmd(8,0x00,0x00,0x01,0xAA,0x87)
        self.spi_ff() 
        # R7(5bytes)=R1+4bytes
        res=spi.read(5) #response
        print('CMD8 R7-5bytes >>',res)

        if (res[0]== 0x01) or (res[0]== 0x00):
            print('CMD8 0x01 or 0x00 >>>',res[0])
            self.SDC_acmd41()       
        else:
            print('CARD ERROR >> MMC(Standard) ')
            #sys.exit()
            self.SDC_cmd00()
            self.SDC_cmd01()
            print('MMC_INIT')

    def SDC_acmd41(self):
        while True:
        # ---------------------------------------------------------- CMD55 APP_CMD
            #print('CMD55')
            # cmd55=0x77(APP_CMD)
            self.spi_ff()
            self.spi_cmd(55,0x00,0x00,0x00,0x00,0x01)
            self.spi_ff()
            res=spi.read(1) #response

            if res == b'\x01':
                print('CMD55 Pass 0x01 >>>')
            else:
                print('CMD55 ERROR EXIT')
                sys.exit()
            # ---------------------------------------------------------- acmd41
            #print('ACMD41')
            # acmd41=0x69(SD_APP_OP_COND) 
            self.spi_ff()
            self.spi_cmd(41,0x40,0x00,0x00,0x00,0x01)
            self.spi_ff()
            res=spi.read(1) #response
            if res == b'\x01':
                print('ACMD41 0x01 RETRY', res)
            if res == b'\x00':
                print('ACMD41 Pass 0x00', res)
                print('SDHC_INIT')
                break
                #CS(1)
                #spi_ff()       
    # ---------------------------------------------------- CMD01 SEND_OP_CND
    def SDC_cmd01(self):
        #print('CMD01')
        while True:
            #cmd1=0x41(SEND_OP_CND)
            self.spi_ff()
            self.spi_cmd(1,0x00,0x00,0x00,0x00,0x01) # CMD>>0xFF out>>read response
            self.spi_ff()
            res=spi.read(1) # response
            #print('response=',res)
            if res== b'\x00':
                print('cmd1 OK resp=0x00')
                break
    #END
    def SDC_end(self):       
        self.spi_ff()
        self.CS(1)
        self.spi_ff()