;■■■■■■■■■■■■■ ; ; mmcをターミナル経由で読み ; 1MHz Tyny26L ; ; (PA0) ; (PA1) ; (PA2) ; (PA3) ; ; (PB0 DI) DO ; (PB1 DO) DI ; (PB2 SCK) SCK ; (PB3) CS1 ; (PB4) CS2 ; (PB5 TxD) RxD ; (PB6INT0 RxD) TxD ; ;■■■■■■■■■■■■■ .include "tn26def.inc" ;▼ピン .equ CS1=3 .equ TxD=5 .equ RxD=6 ;▼SPI関係レジスタの設定 .equ cUSIDR=0b01000000 ;||||++++-カウンタ ;|||+-----出力データ衝突(I2C) ;||+------停止条件検出 ;|+-------カウンタオーバーフロー割り込み要求クリア ;+--------開始条件割り込み要求 .equ cUSICR=0b00011011 ;|||||||+-クロック切り替え ;||||||+--クロックストローブ ;||||++---クロック選択 DI立上がり採取、DO立ち下がり変更 ;||++-----動作種別選択 ;|+-------カウンタオーバーフロー割り込み許可 ;+--------開始条件割り込み許可 .def ff=r2 .def tmp1=r3 .def tmp2=r4 .def A=r16 .def B=r17 .def C=r18 .def dark=r21 .def flags=r23 ;0b00000### rjmp RESET ; rjmp R_UART ;INT0 reti ;PIN_CHG reti ;TMCOMPA reti ;TMCOMPB reti ;TMOVF1 reti ;TMOVF0 reti ;USI_STRT reti ;USI_OVF reti ;EE_RDY reti ;ANA_COMP reti ;ADC ;▼▼▼▼▼初期化 RESET: ;▼スタックポインタ初期化 LDI A,LOW(RAMEND) out sp,A ldi A,0xff mov ff,A ;▼IO初期化 ldi A,0b00000000 out DDRA,A ldi A,0 out PORTA,A ldi A,0b00111110 out DDRB,A ldi A,0b00111100 out PORTB,A ;▼割り込み初期化(UART) ldi A,0b01000000 ; +-------外部割込み0許可 out GIMSK,A ldi A,0b00000010 ; ++-立下り割り込み out MCUCR,A ldi A,0x82 rcall T_UART ldi A,0xC8 rcall T_UART ldi A,0x82 rcall T_UART ldi A,0xE9 rcall T_UART ldi A,0x8C rcall T_UART ldi A,0xA4 rcall T_UART ldi A,0x0D rcall T_UART ldi A,0x0A rcall T_UART SEI rjmp MMC_INIT RE_MMC_INIT: MAIN: ldi A,0 mov tmp1,A mov tmp2,A MI_3: ldi A,0x0D;改行 rcall T_UART ldi A,0x0A rcall T_UART ldi A,0xff ;ダミークロック rcall SPI ldi A,0b01010001 ;01 000001 ;CMD17を送信 rcall SPI ldi A,0x00 rcall SPI mov A,tmp2 rcall SPI mov A,tmp1 rcall SPI ldi A,0x00 rcall SPI ldi A,0x01 ;0000000 1 rcall GetRes ;R1レスポンスを受ける(まで待つ) rcall tostr ;■レスポンスを報告{ rcall T_UART ; mov A,B ; rcall T_UART ;} mov A,tmp2 ;■アドレス報告 rcall tostr ; rcall T_UART ; mov A,B ; rcall T_UART ;} mov A,tmp1 ;■アドレス報告 rcall tostr ; rcall T_UART ; mov A,B ; rcall T_UART ;} ldi A,0x20 rcall T_UART ;データトークンの御尻0を待つ ldi A,cUSICR ; out USIDR,ff ;Hで待つ MI_4: out USICR,A ;SCK変化 sbic USIDR,0 ;0が出るまで繰り返し rjmp MI_4 ldi C,0xff MI_2: ldi A,0xff ;受信 rcall SPI ; rcall tostr ;■報告 ; rcall T_UART ; mov A,B rcall fix_unstr rcall T_UART subi C,1 brcc MI_2 ldi A,0xff rcall SPI ;CRCを無視 ldi A,0xff rcall SPI ;CRCを無視 ldi A,1 add tmp1,A brcc MI_3 add tmp2,A brcc MI_3 END: rjmp END ;▼▼▼UART送信 T_UART: push A push B cbi PORTB,TxD ;スタートビット rcall wUART ldi B,8 T2: lsr A ;1 右シフト brcs T0 ;2 C=1で分岐 cbi PORTB,TxD ;3 rjmp T1 ; T0: ;3 sbi PORTB,TxD ;4 nop ;5 T1: ;5 rcall wUART ; subi B,1 ;6 brne T2 ;8 sbi PORTB,TxD ;ストップビット rcall wUART pop B pop A ret wUART: ;UART専用待ち 19200bps ;3+2+1+((9+1)*3)+1+1+2+4= push B ;2 ldi B,9 ;1 w2_0: subi B,1 ;1 brcc w2_0 ;2 nop ;1 nop ;1 nop ;1 pop B ;2 ret ;4 ;▼▼▼UART受信 R_UART: push A push B push C in A,SREG push A ;((13+1)*3)=42 ldi B,13 ;1 R_0: subi B,1 ;1 brcc R_0 ;2 rcall wUART ;スタートビット ldi C,8 R_1: in B,PINB ;1 lsl B ;2 lsl B ;3 C=PINB6 ror A ;4 rcall wUART ; nop ;5 subi C,1 ;6 brne R_1 ;8 rcall T_UART rcall tostr rcall T_UART mov A,B rcall T_UART pop A out SREG,A pop C pop B in A,GIFR ; out GIFR,A ;割り込み要求クリア pop A reti ;▼▼▼サブルーチンコールを含めて1msピッタリ ; 3+1+(4*248-1)+1+4=1000 wait1ms: ;3 ldi A,248 ;1 w1A: nop ;1 subi A,1 ;1 brcc w1A ;2 nop ;1 ret ;4 ;▼▼▼バイナリA→16進文字列 0xAB tostr: mov B,A andi B,0x0f cpi B,10 brcc S1 ori B,0x30 rjmp S2 S1: subi B,9 ori B,0x40 S2: swap A andi A,0x0f cpi A,10 brcc S3 ori A,0x30 rjmp S4 S3: subi A,9 ori A,0x40 S4: ret ;▼▼▼制御コード未定義コードを!にする fix_unstr: push B cpi A,0x60 breq fu_2 cpi A,0x7f breq fu_2 andi A,0b01111111; mov B,A andi B,0b11100000; breq fu_2 rjmp fu_1 fu_2: ldi A,0x21 fu_1: pop B ret ;▼▼▼MMC初期化 MMC_INIT: ;▼SPIモードに切り替え sbi PORTB,CS1 ;カードをNonActiveにする ldi B,15 ;ダミークロック74以上(120) MI_0: ldi A,0xff ;Hで待つ rcall SPI subi B,1 brcc MI_0 cbi PORTB,CS1 ;カードをActiveにする ldi A,0x40 ;01 000000 ;CMD0を送信 ⊂長!!? rcall SPI ldi A,0x00 rcall SPI ldi A,0x00 rcall SPI ldi A,0x00 rcall SPI ldi A,0x00 rcall SPI ldi A,0x95 ;1001010 1 rcall SPI ;○SPIモードになりました、たぶん; rcall GetRes ;R1レスポンスを受ける(まで待つ) rcall tostr ;■報告 rcall T_UART mov A,B rcall T_UART MI_1: ldi A,0xff ;ダミークロック rcall SPI ldi A,0b01000001 ;01 000001 ;CMD1を送信 rcall SPI ldi A,0x00 rcall SPI ldi A,0x00 rcall SPI ldi A,0x00 rcall SPI ldi A,0x00 rcall SPI ldi A,0x01 ;0000000 1 rcall SPI ;○準備できました、たぶん汗; rcall GetRes ;R1レスポンスを受ける(まで待つ) push A rcall tostr ;■報告 rcall T_UART mov A,B rcall T_UART pop A cpi A,0x00 brne MI_1 ldi A,0xff ;ダミークロック rcall SPI ldi A,0b01010000 ;01 000001 ;CMD16を送信 rcall SPI ldi A,0x00 rcall SPI ldi A,0x00 rcall SPI ldi A,0x01 ;ブロック長 rcall SPI ldi A,0x00 ;ブロック長 rcall SPI ldi A,0x01 ;0000000 1 rcall SPI rcall GetRes ;R1レスポンスを受ける(まで待つ) rcall tostr ;■報告 rcall T_UART mov A,B rcall T_UART rjmp RE_MMC_INIT ;▼▼▼MMC レスポンスを受け取りAに格納 ;レスポンスは頭が0 GetRes: ldi A,cUSIDR ; out USISR,A ;フラグ解除、カウンタ初期化 ldi A,cUSICR ; out USIDR,ff ;Hで待つ GR_1: out USICR,A ;SCK変化 sbic USIDR,0 ;レスポンスの頭0を待つ rjmp GR_1 ldi A,0xff rcall SPI lsr A ret ;▼▼▼SPI送受信 ;A:送信データ SPI: out USIDR,A ;送信データを設定 ldi A,cUSIDR ; out USISR,A ;フラグ解除、カウンタ初期化 ldi A,cUSICR ; SPI0: out USICR,A ;SCK変化 sbis USISR,6 ;if(オーバーフロー) rjmp SPI0 ;else 繰り返し then... in A,USIDR ;受信データを取得 ret