SDカードを使ってみよう
by K.I
2005/10/01〜
Index
ふーむ、SPIモードっていうのは、結構単純なのかも。。
- PSoCにもSPIインターフェースのモジュールがあるので、それを使ってみよう。
[top]
- SDカードは追加された2ピンのデータ線を加えて、4ピンでデータ転送を行うため、理論上MMCカードの4倍の転送速度があるらしい。
- とりあえず、SDカードはMMCの上位互換らしいので、何とかなるだろう。
- SPIモードは将来的に無くなる方向らしいので、ちょっと心配だが。
→MMCカードは1〜7だけ使う
- 8、9ピンは、いかにも取って付けたような感じ。後から追加した規格であることが良く解かる。
- 3、4ピンが、わずかに飛び出してるのは、電源を先に入れるためかな?
とにかく、仕様書を読んでみよう。
- 仕様自体も複雑だが、仕様書の情報が分散していて、なかなか難解だ。
- 自分なりの解釈なので、間違いもあるかもしれないが、ざっと概略をまとめてみた。
- MMCモードでは、それぞれのカードに固有の相対アドレス(RCA)を割り当て、そのRCAを指定してカードを選択する。。
- クロック、コマンド、データの3線で通信、データとコマンドは双方向。
- シングルブロック転送、マルチブロック転送、ストリーム転送がある。
PIN No. | Name | Type | PIN Description |
1 | RSV | NC | Reserved/Allways'L' |
2 | CMD | I/O,PP,OD | Command/Response |
3 | VSS1 | S | Ground |
4 | VDD1 | S | Power Supply |
5 | CLK | I | Clock |
6 | VSS2 | S | GND |
7 | DAT | I/O,PP | Data |
- PP:PushPull, OD:OpenDrain
- SPIモードでは、CSでカードを選択する。
- チップセレクト、データイン、データアウト、クロックの4線で通信。全て単方向。
- シングルブロック転送、マルチブロック転送がある。
PIN No. | Name | Type | PIN Description |
1 | CS | I | Chip Select(Low active) |
2 | DI | I | Data in |
3 | VSS | S | Ground |
4 | VDD | S | Power Supply |
5 | SCLK | I | Clock |
6 | VSS2 | S | Ground |
7 | DO | OUT,PP | Data out |
CRCは、MMCモードでは必須。
//------- CRC7 by K.I 051020 --------
int CRC7(c,n)
char c[];
int n;
{
int i,j;
char d,r=0;
for (i=0; i<n ;i++) {
d = c[i];
for (j=0; j<8 ; j++) {
if ((d & 0x80) ^ (r & 0x80))
r = (r<<1) ^ 0x12; // reverse of 0x48
else
r <<= 1;
d <<= 1;
}
}
return(r & 0xFE);
- 最初は、式からプログラムを組もうと思ったんだけど、結局、計算が合わず諦めた。
- 結局は、以下のCRC7ジェネレータの回路を基にプログラムした。
- ちょっと冗長かな。変数が多い。もう少しすっきり書きたいけど。
- やっぱり自分としては、回路図からの方がプログラムのイメージがし易い。
- でも、この回路が式と同じ意味になるというのが、いまいち納得出来ていないんだけど。。
- MMCカードは以下のレジスタを持つ
- OCR →MMCの動作電圧を100mV単位で表す →32bit
- CID →カードID、製造者・個別番号等を含む →128bit
- RCA →相対カードアドレス、ホストで設定可能なアドレス?(MMCモード)→16bit
- CSD →カード特性データ、カード固有情報(PCMCIAのCISに対応)→128bit
- DSR →ドライバステージレジスタ →16bit
- ステータスレジスタ →32bit
- なんか面倒だな〜。固定長レジスタにして、項目毎に細かくレジスタ分けた方が、扱い易いんじゃないかしらん。
- コマンドは48bit固定長
- 01XXXXXX AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA CCCCCCC0
- X:コマンドインデックス、A:アーギュメント、C:CRC
- 使うのはSPIモードだけなので、SPIモードのコマンドだけ抜き出してみた。
index | Argument | Resp | Abbreviation | Command description |
CMD0 | None | R1 | GO_IDLE_STATE | MMCリセット |
CMD1 | None | R1 | SEND_OP_COND | カード初期化 |
CMD9 | None | R1 | SEND_CSD | CSD送信要求 |
CMD10 | None | R1 | SEND_CID | CID送信要求 |
CMD13 | None | R2 | SEND_STATUS | STATUS送信要求 |
CMD16 | 32bit | R1 | SEND_BKICKLEN | ブロック長(byte数) |
CMD17 | 32bit | R1 | READ_SINGLE_BLK | ブロック読出し |
CMD24 | 32bit | R1b | WRITE_BLOCK | ブロック書込み |
CMD27 | None | R1b | PROGRAM_CSD | CSD programable bit設定 |
CMD28 | 32bit | R1b | SET_WRITE_PROT | 書込みプロテクト |
CMD29 | 32bit | R1b | CLR_WRITE_PROT | クリア書込みプロテクト |
CMD30 | 32bit | R1 | SEND_WRITE_PROT | プロテクトSTATUS要求 |
CMD32 | 32bit | R1 | TAG_SECT_START | 消去選択最初のブロック |
CMD33 | 32bit | R1 | TAG_SECT_END | 消去選択最後のブロック |
CMD34 | 32bit | R1 | UNTAG_SECTOR | 消去選択前の1セクタ消去 |
CMD35 | 32bit | R1 | TAG_ERASE_G_SEL | 消去選択最初のグループ |
CMD36 | 32bit | R1 | TAG_ERASE_G_END | 消去選択最後のブロック |
CMD37 | 32bit | R1 | UNTAG_ERASE_GRP | 消去選択前の1グループ消 |
CMD38 | 32bit | R1b | ERASE | 選択されたセクタ消去 |
CMD42 | 32bit | R1b | LOCK/UNLOCK | パスワード設定・解除 |
CMD39 | 32bit | R1 | CRC_ON_OFF | CRCオプションON/OFF |
- R1b→R1の後にbusyを持つレスポンス
- 多分、レスポンス直後の状態が'L'ならばbusyだということだと思う。
- R1,R1b →通常のレスポンス
- 01XXXXXX SSSSSSSS SSSSSSSS SSSSSSSS SSSSSSSS CCCCCCC1
- R2 →CID,CSDレジスタのレスポンス
- 00111111 RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRR1
- R3 →OCRレジスタのレスポンス
- 00111111 RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR 11111111
- OCRレジスタの最初のビットがBusy/Readyを示す
SPIモードでは、R1,R2の2種類のレスポンスがある。
No | 各ビットの意味 |
0 | 常に0 |
1 | Card is locked |
2 | wp erase skip lock/unlock cmd failed |
3 | error |
4 | CC error |
5 | card ecc failed |
6 | wp violation |
7 | erase param |
| |
8 | out of range |
9 | in idle state |
10 | erase reset |
11 | illegal command |
12 | com crc error |
13 | erase sequence error |
14 | address error |
15 | parameter error |
MMCはデータの送受信にデータトークンを使う。
- データトークンは、4byte〜2051byteの長さで、最初の1バイト目は
- Single Block Read →11111110
- Multiple Block Read →11111110
- Single Block Write →11111110
- Multiple Block Write →11111100
- 2〜2049バイト目が、データ部分
- 最後の2050〜2051バイト目がCRC16になっている。
- Multiple Block Writeは、MMCモードではCMD12、SPIモードでは以下の'Stop Tran'トークンにより、いつでも書込みを中断することが出来る。
- 'Stop Tran'トークン →11111101
- ビジートークンの正確な定義を見付けられなかったが、ビジートークンの連続により'L'状態になるという記述があるので、上のように解釈した。
- もしかすると単にトークン以外の部分が'H'ならばReady、'L'ならばBusyということかもしれない。
- エラートークン は、もしかするとデータ送信時のR1として返るのかな?
- 000EEEEE
- bit3 →Card is Locked
- bit4 →Out of Range
- bit5 →Card ECC Failed
- bit6 →CC Error
- bit7 →Error
- データレスポンス は、最初のbitの定義が0じゃないので、どうやってスタートビットを判断するんだろう?
- XXX0SSS1
- '000'→Data accepted.
- '101'→Data rejected due to a CRC error.
- '110'→Data rejected due to a Write error.
- しかし、調べれば調べるほど、分かり難い仕様だ。。
- SPIモードって簡単かも、って思ったのが運の尽きだったな。。
[top]
- 概略は分かってきたような気がするけど、結局どういう手順で読み書きすれば良いのか、なかなか分かり難い。
- ここらへんは、 なる研さんの解説が、非常に噛み砕いた要点だけをまとめており、分かり易い。
- ここで十分に解説されているので、それ以上は必要ないんだけど、一応は自分でも考えてみる。
- MMCはパワーオンリセット後、初期化シーケンスには、ホストからクロックを64クロック+10クロック(マージン?)の74クロックが必要になるようだ。
- 初期化シーケンスは電源が2Vまで上昇した時点で開始することが可能。
- 論理'1'の連続シーケンスを送信することになる。(1ms以内)
- 初期化シーケンス後にidle状態になる。
- idle状態のMMCは、CMD0,CMD1しか受け付けない。
- CMD0(ソフトウェアリセット)でも同様に、idle状態になる。
- CMD0 = '01000000 00000000 00000000 00000000 00000000 10010101'
- CSを'0'にしてから、CMD0(リセット)すると、SPIモードに移行してR1が返る。
- R1が'01h'以外、或は応答がなければ、エラー。
- CMD1の応答がReadyになるまで待つ。
- CMD1 = '01000001 00000000 00000000 00000000 00000000 11111001'1
- MMCモードでは、R3レスポンスのOCRレジスタの最初のビットがBusy/Readyを示す。
- SPIモードでは、R1レスポンスが01h(Busy),00h(Ready)を示す。
- CMD0を送信する時点では、MMCモードなので、CRCは必須。
- でも、SPIモードにした後は、CMD1のCRCは付けなくてもOK。
- CMD17のアーギュメントにアドレスを指定すると、MMCは、1ブロック分(デフォルトで512byte)のデータを出力する。
- CMD17 = '01010001 AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA CCCCCCC1'
- アドレスは32bitなので、最大4GBってことかな。
- データバイト長はデフォルトで512byte、CMD16で指定可能だが、MMCによっては固定になっているようだ。
- MMCは、CMD17を受けると、まずR1を送信、次にデータトークンを送信する。
- 01010001 AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA CCCCCCC1
← 0XXXXXXX
← 11111110 DDDDDDDD DDDDDDDD ..512byte.. DDDDDDDD DDDDDDDD CCCCCCCC CCCCCCCC
- CMD24のアーギュメントにアドレスを指定してから、1ブロック分(デフォルトで512byte)のデータを送信して、MMCにデータを書き込むことが出来る。
- CMD24 = '01011000 AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA CCCCCCC1'
- MMCは、CMD24を受けると、まずR1を送信、次にデータトークンを受信し、書込み中はビジートークンを返す。書込み完了でR1を送信する。
- 01011000 AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA CCCCCCC1
← 0XXXXXXX
- 11111110 DDDDDDDD DDDDDDDD ..512byte.. DDDDDDDD DDDDDDDD CCCCCCCC CCCCCCCC
← 00000000 ...書込み完了までビジートークンを返す。'1'になるまで待つ必要がある
← 0XXXXXXX
1このCRCの値は、自分のCRC7プログラムで求めたんだけど、合ってるのかなぁ?
[top]
- ここまで来て初めて気が付いたけど、MMCのSPIモードって、PSoCのSPIM,SPISモジュールで使ってる規格と同じだ。
- PICにも、MSSPモジュールって奴があるみたいだ。
- SPIって規格があること自体、恥ずかしながら、全然知らなかった。。
- フィリップスのI2Cに対して、モトローラが作った規格がSPI。
- あとNS(ナショナルセミコンダクタ)のMicroWireというのもSPIに近い規格のようだ。
- PSoCのSPIモジュールは、4つのモードがあるようだ。
Mode | SCLK Edge | クロック極性 | 説明 |
0 | Leading | Non-Inverting | Leadingエッジでラッチ、 |
1 | Leading | Inverted | 変化させる |
2 | Trailing | Non-Inverting | Trailingエッジでラッチ |
3 | Trailing | Inverted | 変化させる |
- あと、LSB firstと、MSB firstが選べる。
- うーん、Non-InvertingのLeading Edgeと、InvertedのTrailing Edgeって同じじゃないの?
- PCWEBの解説の波形から類推すると、Normally Low と、Normally Highの違いってことなのかな?
SPIM API | 意味 |
SPIM_Start | 起動、(モード設定、LSB/MSB first指定) |
SPIM_Stop | 停止 |
SPIM_EnableInt | 割込み許可 |
SPIM_DisableInt | 割込み禁止 |
SPIM_SendTxData | 1byte送信 |
SPIM_bReadRxData | 1byte受信(受信データはDxBxxDR2?) |
SPIM_bReadStatus | SPIMステータスを返す |
- これで分かるように、使い方は単純なようだ。
- CRCとか計算してくれて、っていうんじゃないのね。→そりゃ、そうか。
- データのスタートビット判断とか、どうしようかと思っていたんだけど、任せられるんだったら便利だな。
- MMCのパワーオン後の初期化シーケンス(74個のクロック)は、どうするんだろう。
- Startで勝手にやってくれるのかな?それとも基本的には全部自分でやるのかな?
- まぁ、FFhを10byte送信すれば良いんだろうけど。。
- ちょっと疑問なのは、SPIM_bReadRxDataの解説では、
Returns a received data byte from a slave device. The Rx Buffer Full flag should be checked prior to calling this routine, to verify that a data byte has been received.
なので、如何にもデータを戻しそうなんだけど、この関数はBOOLになってる。
BOOL SPIM_bReadRxData(void)
- それで受信データは、DxBxxDR2だと思うんだけど、何か引っ掛かるなぁ。。
- SPIMモジュールのサンプルプログラムを基に、初期化のプログラムを書いてみる。
- とりあえずザっと適当に書いたけど、ちゃんと動くかな?
- SPIM_bReadRxDateが、受信データを戻すとして書いた。
#include "PSoCAPI.h"
const char CMD0[] = {6,0x40,0x00,0x00,0x00,0x00,0x95};
const char CMD1[] = {6,0x41,0x00,0x00,0x00,0x00,0xf9};
#define SPIM_SEND(data) do { \
while(!(SPIM_bReadStatus() & SPIM_SPIM_TX_BUFFER_EMPTY)); \
SPIM_SendTxData( data ); \
} while(0)
void cmmc_cmd(const char *ccmd))
{
char cmd[7],*p;
cstrcpy(cmd,ccmd);
for (p=cmd+1; p<=cmd+(*cmd) ;p++) SPIM_SEND(*p);
}
void main()
{
int i;
SPIM_Start(SPIM_SPIM_MODE_0 | SPIM_SPIM_MSB_FIRST);
//---- initial sequence
for (i=0; i<10 ;i++) SPIM_SEND( 0xFF );
//---- send CMD0 change SPI mode
PRT0DR &= ~0x80; //SS='L'
cmmc_cmd(CMD0);
while (!SPIM_bReadRxData()); //It should be 01h
//---- send CMD1 & wait response is ready
do {
cmmc_cmd(CMD1);
} while(SPIM_bReadRxData()): //wait for ready(00h)
}
[top]
- いろいろ調べたけど、イマイチ分からん。やっぱり、やってみないと分かんないか。。
- とりあえず配線が面倒なので、基本的な回路は今まで2の使いまわし。→MMC接続部分のみ配線
- 電源は、LCDを使う関係で5Vとしたので、3.3Vのレギュレータを通して電源を供給するようにした。
- コントロールは、COMポート経由でターミナルソフトで動かすようにしよう。
- LCDモジュール
- UARTモジュール
- SPIMモジュール
- PSoCのモジュールは、これだけ配置すれば大丈夫かな。
- 試しに、LCDだけ表示しようとしたが、、LCDが表示されない。1行目が真っ黒、2行目は真っ白。
- 配線をチェックしても全然分からなかったが、結局UARTのクロックを分周してやったら直った。→何で?と結構悩む。
- あぁ、そうか。UARTの割込みで喰われてたのか。。
- UARTに、ちゃんとしたクロックを入れることにしよう。9600bpsとして、24M/9600/8=312.5か。さらに/8で約39。
- SPIM →VC1=24M/8=3M
- UART →VC3=VC1/39
って、ところか。
- UARTは変換アダプタを通して、P12,P13にTX,RXを接続。
- うーん今度は、PSoCの書き込みがFailになる。→UARTを外すと書き込める。
- 何故? 今までも、UARTを接続しての書き込みは良くやってたのに?
- 結局、変換アダプタにUSBから電源供給出来るように改造したため、Rx,Txを通じてPSoCに電源供給されちゃったみたいだ。
- 変換アダプタの電源は、Writerから供給するように戻して、、書けた!
- これで、LCDの表示とUART出力はOK。
- って、ここまでは出来て当然なんだけどね。。何やってんだか。。
- あれ、波形出てないような?
- ループにしてみる→ちゃんと出てる。SCLKの周波数がMOSIの倍だからOKか。
- あっ、ダメだ。レベルが5Vのままだった。。。
- PSoCの動作電圧を3.3Vにする方が良いかもしれないが、やはりLCDが5Vだからなぁ。
- ちょっと無駄っぽいけど、CS,SCLK,DIは抵抗分割で電圧を調整するか。
- しかし、この程度の信号捕まえられる測定器欲しいなぁ。
- シリアルインターフェース程度の速度なら、簡単に見れるんだけど。
- 仕方ない。。速度を落として、信号が見れるようにしよう。
- VC1=24M/8=3M
- VC2=VC1/16
- PWM8モジュールを追加して、SPIM→VC2/10=約9600×2
- 波形は出るんだけど、出る時間が一定じゃないような。。→コンマ何秒〜数秒ぐらい?
- ちゃんと出来てるのかなぁ。良く分かんないけど、まぁいいや。
- まず、読めるかってことだけど。。
- 受信したデータを、とにかくUARTから送信してみるか。
- SPIMのデータの読み方に疑問があったので、調べてたら、 こんなプログラムがあった。
char SPIM_IO(char in) {
while (!(SPIM_bReadStatus() & SPIM_SPIM_TX_BUFFER_EMPTY));
SPIM_SendTxData(in);
while (!(SPIM_bReadStatus() & SPIM_SPIM_RX_BUFFER_FULL));
return (SPIM_bReadRxData());
}
これは、如何にも送受信を同時にやってる感じのプログラムだ。
- これが正しいとすると、SPIM_bReadRxDataがBOOLというのは間違いなのかなぁ?
- BOOLは、unsigned charだから、必ずしも間違いと言う訳じゃないが。。
SPIは送受信同時に出来る方式だから、それらしい感じだし。
- 送受信の切替えがイマイチはっきりしないので、こんな風にやった方が良いのかもしれないなぁ。
W%lcome to PSoC MMC program
SPIM initial sdquence
send CMD0 change SPI mode
send CMD1 & wait response is ready
CMD17 00000000
FFF8000000FFFFFFFFFFFF0000001FFF
FFFFFFFF000000FFFFFFFFFFFFFF0000
00FFFFFFFFFF8000001FFFFFFFFFFF0000FFFFFFFFFFFFFF000000FFFFFFFF
FFFC00001FFFFFFFFFFFFF0000007FFF
FFFFFFFF000000FFFFFFFFFFFF800000
07FFFFFFFFFF0000007FFFFFFFFFFFFF
0000FFFFFFFFFFFF80000003FFFFFFFF
FF0000007FFFFFFFFFFFFF000000FFFF
FFFFFF80000000FFFFFFFFFF
F000000
3FFFFFFFFFFF000000FFFFDFFFFFFF80
0000FFFFFFFF0000000FFFFFFFFF
FF000000FFFFFFFFFFFF00000000FFFF
FFFFFF00000007FFFFFFFFFFFE000000
7FFFFFFFFF00000000FFFFFFFFFFFF00
0000FFFFFFFFFFFC0000007FFFFFFFFF
FF000000FFFFFFFFFFFF00000000FFFF
FFFFFC0000003FFFFFFFFFFF00000000
FFFFFFFFFF00000000FFFFFFFFFFF800
0000FFFFFFFFFF000000007FFFFFFFFF
FF0000000007FFFFFBFFFFF00000000
FFFFFFFFF000000003FFFFFFFFFF0000
0003FFFFFFFFFF00000000FFFFFFFFFF
F0000000FFFFFFFFFF000000003FFFFF
FFFF00000000FFFFFFFDFFE000000000
FFFFFFFF000000001FFFFFFFFFFF0000
001FFFFFFFFFF000000000FFFFFFFFFF
00000007FFFFFFFFFF000000007FFFFF
FFFF00000000FFFFFFFFFF0000000003
FFFFFFFF000000007FFFFFFFFFE00000
007FDFFFFFFF0000000000FFFFFFFFFF
CMD17 00000000
00000000FFFFFFFFFF000000000FFFFF
FFFF000000007FFFFFFFFF0000000000
FFFFFFFF0000000003FFFFFFFFF00000
0003FFFFFFFF0000000000FFFFFFFFFF
00000003FFFFFFFFF0000000007FFFFF
FFE000000000FFFFFFFFFF0000000000
FFFFFFC0000000003FFFFFFFFF000000
003FFFFFFFFF0000000000FFFFFFFFF0
0000001FFFFFFFFF00000000007FFFFF
FF0000000000FFFFFFFFC0000000000F
FFFFFF00000000007FFFFFFFFF000000
007FFFFFFFE00000000007FFFFFFFF00
0000007FFFFFFFFF0000000000FFFFFF
FF0000000001FFFFFFFF00000000003F
FFFFFF0000000000FFFFFFFFE0000000
00FFFFFFFF00000000001FFFFFFFFF00
000000FFFFFFFFC00000000000FFFFFF
FF000000000FFFFFFFFF0000000000FF
FFFFE00000000000FFFFFFFF00000000
00FFFFFFFF00000000007FFFFFFFC000
000000FFFFFFFF000000000003FFFFFF
FF000000007FFFFFFFE00000000000FF
FFFF000000000003FFFFFFFF000FFFE00000000000FFFFFFFF0000
000000FFFFFFFF00000000003FFFFFFF
E000000000FFFFFFFF000000000000FF
FFFF00000000003FFFFFFFE000000000
00FFFFFF000000000000FFFFFFFF0000
00000FFFFFFFE0000 000000FFFFFFFF
0000000000FFFFFFFF000000000007FF
FFFF00000000007FFFFFFF0000000000
00FFFFFF000000000003FFFFFFE00000
CMD17 00000020
000000FFFFFFF000000000001FFFFFFF
00000000007FFFFFFF000000000000FF
FFFF00000000000FFFFFFF0000000000
00FFFFFF000000000000FFFFFFF00000
00000FFFFFFF0000000000007FFFFFFF
0000000000FFFFFFF8000000000003FF
FFF000000000007FFFFFFF0000000000
00FFFFF8000000000003FFFFFF000000
00007FFFFFFF000000000000FFFFFFFC
0000000000FFFFFF0000000000003FFF
FF000000000000FFFFFFF80000000000
00FFFF0000000000003FFFFFFF000000
0000FFFFFFFC000000000000FFFFFF00
000000000FFFFFFF0000000000007FFF
FF000000000000FFFFFF000000000000
07FFFF0000000000007FFFFFF8000000
0000FFFFFF00000000000003FFFFFF00
000000007FFFFFF8000000000000FFFF
FF000000000001FFFFFF000000000000
7FFFFC000000000000FFFFFF00000000
0000FFFFFF0000000000003FFFFFFC00
00000000FFFFFF00000000000000FFFF
FF00000000001FFFFFFE000000000000
7FFF00000000000000FFFFFF00000000
0000FFFFFC000000000000FFFFFF0000
00000000FFFFFF0000000000000FFFFF
FE0000000000FFFFFF00000000000000
FFFF00000000000007FFFFFC00000000
0007FFFF00000000000000FFFFFF0000
00000003FFFFFE0000000000007FFFFF
000000000000FFFFFF00000000000001
FFFF0000000000003FFFFF0000000000````````````
0000FFFFFFFFFFF800000007FFFFFFFF
const char CMD0[] = {6,0x40,0x00,0x00,0x00,0x00,0x95};
const char CMD1[] = {6,0x41,0x00,0x00,0x00,0x00,0xf9};
char SPIM_IO(data) {
while(!(SPIM_1_bReadStatus() & SPIM_1_SPIM_TX_BUFFER_EMPTY));
SPIM_1_SendTxData( data );
while (!(SPIM_1_bReadStatus() & SPIM_1_SPIM_RX_BUFFER_FULL));
return (SPIM_1_bReadRxData());
}
void cmmc_cmd(const char *ccmd)
{
char *p,*cmd;
cmd = (char*)ccmd;
for (p=cmd+1; p<=cmd+*cmd ;p++)
SPIM_IO(*p);
}
void mmc_init(void)
{
int i;
SPIM_1_EnableInt();
// ---- SPIM initial sequence
PRT0DR |= 0x02; // CS='H'
SPIM_1_Start(SPIM_1_SPIM_MODE_0 | SPIM_1_SPIM_MSB_FIRST);
for (i=0; i<10 ;i++)
SPIM_IO( 0xFF ); // send 80clock
PRT0DR &= ~0x02; // CS='L'
UART_1_CPutString("send SPIM initial clock\r\n");
// ---- send CMD0 change SPI mode
cmmc_cmd(CMD0);
i = 0;
while (SPIM_1_bReadRxData() != 0x01) // wait response 0x01
if (i++>100) break;
if (i<1000) UART_1_CPutString("send CMD0 & response 0x01\r\n");
//---- send CMD1 & wait response is ready
cmmc_cmd(CMD1);
i = 0;
while (SPIM_1_bReadRxData()) // wait response 0x00
if (i++>100) break;
if (i<1000) UART_1_CPutString("send CMD1 & response 0x00\r\n");
}
- まず、SDカードなしで、波形を確認してみるが、実行する度に波形が違う。。
- このSCLKの波形は何だ?どうしたら、こんな変な波形になるんだろう。
- それに、CSがLに落ちないのは何故だ?
- SCLKがフローティングになってれば、こうなるかもしれないけど。。。どういうこと?
2「はじめてのPSoC」の回路を基にしてる。
[top]
いろいろ参考にさせてもらいました。感謝。
3SDカードは契約しないと資料は見れないらしい。
[top]
[電子工作関連に戻る]