マイクロビット(c_09)SDカード 読書き、消去 用モジュール
SDカードモジュール(SPI) SDC_RWE_c.py
2GB以下(MMC)とSDHC(2GB超~32GB)SDカードの読書き、消去で使う自作の’SDC_RWE_c.py’を作成しました。使い方だけを記載します。(※記事e_023を元にクラスにしました。)
‘SDC_RWE_c.py’は末尾にあります。
ファイル転送
micro:bitへ’SDC_RWE_c.py’を送った後でimportして使います。micro:bitに直接ファイルをアップロード出来ない場合(Thonny 3.1.12など)は、microfsなどを使ってアップロードします。
※microfsについては、当サイト内のこちらを参照ください。
※ファイルシステムへ送って使わないとメモリーエラーになると思います。(micro:bit V1)
メソッド
‘SDC_RWE_c’をimportすると「SDC_init, SDC_cmd17, SDC_cmd24, SDC_cmd32, SDC_cmd33, SDC_cmd38 SDC_end」のメソッドが使えるようになります。
SDC_RWE(pins=pin8)で初期化します。CS(chip select)と接続するmicro:bitのpinを指定して初期化します。defaltはpin8です。
(01)SDC_init()
ダミークロックを’0xff’を80個送りspi通信にします。CSをLowにしてデバイスを選択します。
(02)SDC_cmd17(adm)
cmd17(READ_SINGLE_BLOCK)コマンドを送ります。
admは読み出すアドレスです。アドレスは512バイト単位です。[0x00,0x00,0x00,0x00]で指定します。
(03)SDC_cmd24(block_buf,adm)
cmd24(WRITE_BLOCK)コマンドを送ります。
block_bufは書込むbytearrayデータです。512バイト単位で送ります。(256バイトx2にしています)
admは書込むアドレスです。アドレスは512バイト単位です。[0x00,0x00,0x00,0x00]で指定します。
(04)SDC_cmd32(s_adr)
cmd32(ERASE_WR_BLK_START_ADDR)コマンドを送ります。
s_adrは消去開始するアドレスです。512バイト単位です。[0x00,0x00,0x00,0x00]で指定します。
(05)SDC_cmd33(e_adr)
cmd33(ERASE_WR_BLK_END_ADDR)コマンドを送ります。
e_adrは消去終了するアドレスです。512バイト単位です。[0x00,0x00,0x00,0x00]で指定します。
(06)SDC_cmd38()
cmd38(ERASE)コマンドを送ります。SDC_cmd32、SDC_cmd33で指定したアドレスのデータを消去を実行します。
(07)SDC_end()
CSをHighにしてデバイスを非選択にします。
使用例
SDカードの読込み、書込み、消去の使用例です。
SDC_RWE_ex.py
from microbit import *
from SDC_RWE_c import SDC_RWE
## example ------------------
# SPI init bps=100kHz
spi.init(baudrate=100000, bits=8, mode=0, sclk=pin13, mosi=pin15, miso=pin14)
sleep(10)
# Write Data 256byte 512byteだとMemoryエラーになるので256x2回で書き込み
block_buf=bytearray(256)
for i in range(256):
block_buf[i]=0xff
a=SDC_RWE()
## SDHC WRITE_BLOCK
a.SDC_init()
w_adr=[0x00,0x00,0x00,0x00]
a.SDC_cmd24(block_buf,w_adr)
a.SDC_end()
# read address 512xnum num wo set
#SDC_cmd17(adm) [xx,xx,xx,xx] hex(512)'0x200'hex(1024)'0x400'
a.SDC_init() ## 必要
m_adr=[0x00,0x00,0x00,0x00]
a.SDC_cmd17(m_adr)
a.SDC_end()
# SDHC ERASE_BLOCK
#a.SDC_init()
#s_adr=[0x00,0x00,0x00,0x00] # erase start address
#a.SDC_cmd32(s_adr) # erase start address set
#
#e_adr=[0x00,0x00,0x04,0x00] # erase end address
#a.SDC_cmd33(e_adr) # erase end address set
#
#a.SDC_cmd38() # erase
#a.SDC_end()
実行結果
メモリーエラーが生じるので各個別にコメントアウトを外して確認しています。
書込み0xffを512bytes実行後(0x00番地から512バイト)
読出し(0x00番地から512バイト)0xffが書き込まれている
>>> %Run SDC_RWE_ex.py
START CLK>80
cmd24 WRITE_BLOCK START
cmd24 OK
write-ok res=5 b'\xe5' 0b11100101
START CLK>80
cmd17 READ_SINGLE_BLOCK START
cmd17 pass >>
token 0xfe find
read_block_address= bytearray(b'\x00\x00\x00\x00')
512bytes= b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
省略
xff\xff\xff\xff\xff\xff\xff\xff\xff'
CRC2= b'\x7f\xa1'
>>>
消去(0x00~0x400(1024)番地)
>>> %Run SDC_RWE_ex.py
START CLK>80
ERASE OK DONE
>>>
読出し(0x00番地から512バイト)消去されている
>>> %Run SDC_RWE_ex.py
START CLK>80
cmd17 READ_SINGLE_BLOCK START
cmd17 pass >>
token 0xfe find
read_block_address= bytearray(b'\x00\x00\x00\x00')
512bytes= b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
省略
x00\x00\x00\x00\x00\x00\x00\x00'
CRC2= b'\x00\x00'
モジュール
SDカードの読込み、書込み、消去
SDC_RWE_c.py
from microbit import *
import sys
# 2022.06.30 ------------------- CMD17-24-38 READ WRITE ERASE SDC_RWE_c.py
# >>> %Run SDC_RWE_c.py MemoryError: なので ufs put SDC_RWE_c.py
class SDC_RWE:
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)
def SDC_init(self):
# SDCの初期化
# Initialization sequence
print('START CLK>80')
self.CS(1) #CS=Hでダミークロックを80個送信(74個<)
for i in range(10):
self.spi_ff()
self.CS(0)
def SDC_end(self):
#END
self.spi_ff()
self.CS(1)
self.spi_ff()
##-------------------------------------------CMD17 (READ)
#cmd17=0x51 READ_SINGLE_BLOCK
def SDC_cmd17(self,adm):
print('cmd17 READ_SINGLE_BLOCK START')
self.spi_ff()
radr=self.spi_cmd(17,adm[0],adm[1],adm[2],adm[3],0x01)
b_add=radr[1:5] # address
# 0x00>>0xfeが返るまで受信
while True:
self.spi_ff() # CMD>>0xFF out>>read response
res=spi.read(1) # response
if res== b'\x00':
print('cmd17 pass >>')
break
while True:
self.spi_ff() # CMD>>0xFF out>>read response
res=spi.read(1) # response
#print(res)
if res== b'\xfe':
print('token 0xfe find')
break
block_buf=spi.read(512)
#crc 2byte read
crc_buf=spi.read(2)
print('read_block_address=',b_add)
print('512bytes=',block_buf)
print('CRC2=',crc_buf) #特に使わない
##-------------------------------------------CMD24 (WRITE)
# cmd24=0x58 WRITE_BLOCK
def SDC_cmd24(self,block_buf,adm):
print('cmd24 WRITE_BLOCK START')
self.spi_ff()
#spi_cmd(24,0x00,0x00,0x04,0x00,0x01)
self.spi_cmd(24,adm[0],adm[1],adm[2],adm[3],0x01)
self.spi_ff()
while True:
#spi_ff() # CMD>>0xFF out>>read response
res=spi.read(1)
if res== b'\x00':
print('cmd24 OK')
break
self.spi_ff()
spi.write(b'\xfe') #Start Block Token
spi.write(block_buf) #512バイトデータを送ります
spi.write(block_buf) # MEMORY ERR で256*2 にしている
spi.write(b'\x00') #//Send CRC1
spi.write(b'\x01') #//Send CRC2
#
cnt=0
while True:
cnt=cnt+1
res=spi.read(1)
re=res[0] & 0x1f
if re==0x05:
print('write-ok res=5',res,bin(res[0]))
break
if cnt>10:
print('WRITE-NG',cnt)
##-------------------------------------------CMD32-33-38 (ERASE)
#cmd32=0x60 ERASE_WR_BLK_START_ADDR R1
def SDC_cmd32(self,s_adr):
self.spi_ff()
self.spi_cmd(32,s_adr[0],s_adr[1],s_adr[2],s_adr[3],0x01)
self.spi_ff()
res=spi.read(1) #response
if res != b'\x00':
print('CMD32 START ADD SET ERROR',res)
sys.exit()
# --------------------------------------------- CMD33 BLK_END_ADD
#cmd33=0x61 ERASE_WR_BLK_END_ADDR R1
def SDC_cmd33(self,e_adr):
self.spi_ff()
self.spi_cmd(33,e_adr[0],e_adr[1],e_adr[2],e_adr[3],0x01)
self.spi_ff()
res=spi.read(1) #response
if res != b'\x00':
print('CMD33 END ADD SET ERROR',res)
sys.exit()
# --------------------------------------------- CMD38 ERASE
#cmd38=0x66 ERASE Erases R1b
def SDC_cmd38(self):
self.spi_ff()
self.spi_cmd(38,0x00,0x00,0x00,0x00,0x01)
self.spi_ff()
res=spi.read(1) #response
if res != b'\x00':
print('CMD38 ERASE ERROR',res)
sys.exit()
print('ERASE OK DONE')