LCDキャラクターディスプレイ / LPM命令を使って文字列を書き込む
p.402
これまでは1文字ずつ指定していたが、ここでは文字列で指定できるようにする。
.EQU RS = PD0 .EQU EN = PD2 ; スタックポインタの初期化マクロ .MACRO INITSTACK LDI R16, HIGH(RAMEND) OUT SPH, R16 LDI R16, LOW(RAMEND) OUT SPL, R16 .ENDMACRO INITSTACK ; PD7:4をLCDのD7:4に接続して命令とデータとを書き込むことにする。 ; PD0からRS信号を、PD2からEN信号を出すことにする。 LDI R16, 0xF0 | (1 << RS) | (1 << EN) OUT DDRD, R16 LDI R16, 0b00110011 CALL COMMAND_W CALL DELAY_2ms LDI R16, 0b00110010 CALL COMMAND_W CALL DELAY_2ms LDI R16, 0b00101000 CALL COMMAND_W CALL DELAY_2ms LDI R16, 0b1111 CALL COMMAND_W LDI R16, 0b0001 CALL COMMAND_W CALL DELAY_2ms LDI R16, 0b0110 CALL COMMAND_W MESSAGE: .DB "June 12th, 2020 " ; 文字数は偶数にする。 LDI ZH, HIGH(MESSAGE << 1) ; ZHはR31。 LDI ZL, LOW(MESSAGE << 1) ; ZLはR30。 CALL COMMAND_W LOOP: LPM R16, Z+ ; LPMはLoad Program Memory。Z+の+はpost incremented。 CPI R16, 0 ; null文字であったら、(CPIはCompare with Immediate) BREQ MAIN ; ループを抜ける。(BREQはBranch if Equal) CALL DATA_W RJMP LOOP MAIN: RJMP MAIN ; 上位ニブルを書き込むためのサブルーチン HI_NIBBLE_W: ANDI R27, 0xF0 IN R26, PORTD ; ポートDの下位ニブル(制御線)に触りたくないので一旦全部取り込んで、 ANDI R26, 0x0F OR R26, R27 ; 下位ニブルは変えないまま、 OUT PORTD, R26 ; またポートDに書き込んで、 SBI PORTD, EN CALL SHORT_DELAY CBI PORTD, EN ; そのままLCDへ書き込む。 CALL DELAY_100us RET ; 1バイトを書き込むためのサブルーチン BYTE_W: MOV R27, R16 CALL HI_NIBBLE_W MOV R27, R16 SWAP R27 CALL HI_NIBBLE_W RET ; 命令を書き込むためのサブルーチン COMMAND_W: CBI PORTD, RS CALL BYTE_W RET ; データを書き込むためのサブルーチン DATA_W: SBI PORTD, RS CALL BYTE_W RET SHORT_DELAY: RET ; 4 DELAY_100us: PUSH R17 ; 2 LDI R17 , 200 ; 1 DR0: RCALL SHORT_DELAY ; 3 DEC R17 ; 1W BRNE DR0 ; falseで1, trueで2 POP R17 ; 2 RET ; 4 DELAY_2ms: PUSH R17 ; 2 LDI R17, 20 ; 1 LDR0: RCALL DELAY_100us ; 3 DEC R17 ; 1 BRNE LDR0 ; falseで1, trueで2 POP R17 ; 2 RET ; 4