3.3 Vで直接動かせるSC1602BBWB-XA-LB-Gを使う。PIC16F1789/1939 & MPUトレーナー カテゴリーの記事一覧 -の評価基板に載っていたのを外した。8ビットモードで動かす。
下のように接続する。
CPUのOUT[7:0] → LCDのDB[7:0]
CPUのOUT[8] → LCDのRS
CPUのOUT[9] → LCDのE
書き込みしかしないのでLCDのR/!WはGNDに固定する。
############################ # アセンブラ(のようなもの) # ############################ import math def constrain(val, _max, _min): return int(min(max(val, _min), _max)) def generate_mif(file_name, width, depth, rom): f = open(file_name, "w") f.write("WIDTH=%d;\n" % width) f.write("DEPTH=%d;\n" % depth) f.write("ADDRESS_RADIX=UNS;\n") f.write("DATA_RADIX=BIN;\n") f.write("CONTENT BEGIN\n") format_of_code = "0" + str(width) + "b" for i in range(depth): machine_code = format(rom[i], format_of_code) f.write("%10d : %s;\n" % (i, machine_code)) f.write("END;\n") f.close() def mov(ra, rb): return 0 << 11 | ra << 8 | rb << 5 def add(ra, rb): return 1 << 11 | ra << 8 | rb << 5 def sub(ra, rb): return 2 << 11 | ra << 8 | rb << 5 def _and(ra, rb): return 3 << 11 | ra << 8 | rb << 5 def _or(ra, rb): return 4 << 11 | ra << 8 | rb << 5 def sl(ra): return 5 << 11 | ra << 8 # 左シフト def sr(ra): return 6 << 11 | ra << 8 # 右シフト #def sra(ra): return 7 << 11 | ra << 8 # 算術右シフト def jmp_reg(ra): return 7 << 11 | ra << 8 # レジスタに記憶してあるアドレスへジャンプ def ldl(ra, ival): return 8 << 11 | ra << 8 | (ival & 0xFF) # 下位バイトに即値をロード def ldh(ra, ival): return 9 << 11 | ra << 8 | (ival & 0xFF) # 上位バイトに即値をロード def cmp(ra, rb): return 10 << 11 | ra << 8 | rb << 5 # 一致したらフラグが立つ。 def je(addr): return 11 << 11 | (addr & 0xFF) # 一致フラグが立っていたらジャンプ def jmp(addr): return 12 << 11 | (addr & 0xFF) # 無条件ジャンプ def ld(ra, addr): return 13 << 11 | ra << 8 | (addr & 0xFF) # RAMからレジスタへ値を持ってくる。 def st(ra, addr): return 14 << 11 | ra << 8 | (addr & 0xFF) # レジスタの値をRAMへ格納する。 #def hlt(): return 15 << 11 def jnc(addr): return 15 << 11 | (addr & 0xFF) # jump if no carry def nop() : return 0 def _in(ra): return ld(ra, 65) # INポートからレジスタへ読み込む。 def out(ra): return st(ra, 64) # レジスタからOUTポートへ書き出す。 # レジスタへ2バイト即値をロード(★2命令★) def ld_hl(ra, two_bytes): return ldh(ra, two_bytes >> 8), \ ldl(ra, two_bytes & 0xFF) FILE_NAME = "rom_init.mif" WIDTH = 15 DEPTH = 256 _ = [0] * DEPTH ################################################ ########### アセンブリ(のようなもの) ########### ################################################ ################################## # directive、macro(のようなもの) # ################################## F_CPU = 10E3 DELAY_40ms = 40E-3 DELAY_2ms = 2E-3 DELAY_50us = 50E-6 # (3命令×4クロック + 2命令×4クロック×(LOOPS定数 + 1) + 1命令×4クロック) / F_CPU = delay # LOOPS定数 = (delay * F_CPU - 16) / 8 - 1 LOOPS_for_40ms = constrain(math.ceil((DELAY_40ms * F_CPU - 16) / 8 - 1), 2**16-1, 0) # F_CPU = 10E6のとき49997 LOOPS_for_2ms = constrain(math.ceil((DELAY_2ms * F_CPU - 16) / 8 - 1), 2**16-1, 0) LOOPS_for_50us = constrain(math.ceil((DELAY_50us * F_CPU - 16) / 8 - 1), 2**16-1, 0) FUNC_SET = 0b111000 # 1, 8/4 bits, 2/1 lines, 10/8 dots, don't care, don't care DISP_CNT = 0b1111 # 1, 文字表示, カーソル表示, カーソル点滅 CLS = 0b1 # 表示を消去 ENT_MOD = 0b110 # 1, 右/左シフト, 表示範囲全体シフト有効化 r0, r1, r2, r3, r4, r5, r6, r7 = range(8) # 汎用レジスタ COUNTER = r0 OUT = r1 RET_TO = r2 DEC = r3 # call命令 ★2命令★ # サブルーチンから戻ってくるアドレスを保存しておいてからサブルーチンへ飛ぶ、 def call(go_to, return_to): return ldl(RET_TO, return_to), \ jmp(go_to) # ret命令 def ret(): return jmp_reg(RET_TO) ############### # subroutines # ############### # DELAY_LONG: DELAY_LONG = 230 _[(pc := DELAY_LONG)] = ldl(DEC, 1) _[(pc := pc+1)], \ _[(pc := pc+1)] = ld_hl(COUNTER, LOOPS_for_40ms) _[(pc := pc+1)] = sub(COUNTER, DEC) _[(pc := pc+1)] = jnc(pc) _[(pc := pc+1)] = ret() # COMMAND_W: COMMAND_W = 215 _[(pc := COMMAND_W)] = out(OUT) _[(pc := pc+1)] = ldh(OUT, 0b00) _[(pc := pc+1)] = out(OUT) _[(pc := pc+1)] = ldh(OUT, 0b10) _[(pc := pc+1)] = out(OUT) _[(pc := pc+1)] = nop() _[(pc := pc+1)] = ldh(OUT, 0b00) _[(pc := pc+1)] = out(OUT) _[(pc := pc+1)] = ldl(DEC, 1) # ビジーループ _[(pc := pc+1)], \ _[(pc := pc+1)] = ld_hl(COUNTER, LOOPS_for_50us) _[(pc := pc+1)] = sub(COUNTER, DEC) _[(pc := pc+1)] = jnc(pc) _[(pc := pc+1)] = ret() # DELAY_SHORT: DELAY_SHORT = 205 _[(pc := DELAY_SHORT)] = ldl(DEC, 1) _[(pc := pc+1)], \ _[(pc := pc+1)] = ld_hl(COUNTER, LOOPS_for_2ms) _[(pc := pc+1)] = sub(COUNTER, DEC) _[(pc := pc+1)] = jnc(pc) _[(pc := pc+1)] = ret() # DATA_W: DATA_W = 190 _[(pc := DATA_W)] = out(OUT) _[(pc := pc+1)] = ldh(OUT, 0b11) _[(pc := pc+1)] = out(OUT) _[(pc := pc+1)] = nop() _[(pc := pc+1)] = ldh(OUT, 0b01) _[(pc := pc+1)] = out(OUT) _[(pc := pc+1)] = ldl(DEC, 1) # ビジーループ _[(pc := pc+1)], \ _[(pc := pc+1)] = ld_hl(COUNTER, LOOPS_for_50us) _[(pc := pc+1)] = sub(COUNTER, DEC) _[(pc := pc+1)] = jnc(pc) _[(pc := pc+1)] = ret() ################ # main routine # ################ ad = -1 # 最初にLCDをdisableにする。 _[(ad := ad+1)] = ldh(OUT, 0b00) _[(ad := ad+1)] = out(OUT) # CALL DELAY_40ms _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DELAY_LONG, ad+3) # Function Set _[(ad := ad+1)] = ldl(OUT, FUNC_SET) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(COMMAND_W, ad+3) # Display ON/OFF Control _[(ad := ad+1)] = ldl(OUT, DISP_CNT) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(COMMAND_W, ad+3) # Clear Display _[(ad := ad+1)] = ldl(OUT, CLS) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(COMMAND_W, ad+3) # CALL DELAY_2ms _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DELAY_SHORT, ad+3) # Entry Mode Set _[(ad := ad+1)] = ldl(OUT, ENT_MOD) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(COMMAND_W, ad+3) # 1文字ずつ表示する。 _[(ad := ad+1)] = ldl(OUT, ord('h')) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DATA_W, ad+3) _[(ad := ad+1)] = ldl(OUT, ord('e')) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DATA_W, ad+3) _[(ad := ad+1)] = ldl(OUT, ord('l')) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DATA_W, ad+3) _[(ad := ad+1)] = ldl(OUT, ord('l')) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DATA_W, ad+3) _[(ad := ad+1)] = ldl(OUT, ord('o')) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DATA_W, ad+3) _[(ad := ad+1)] = ldl(OUT, ord(',')) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DATA_W, ad+3) _[(ad := ad+1)] = ldl(OUT, ord(' ')) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DATA_W, ad+3) _[(ad := ad+1)] = ldl(OUT, ord('w')) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DATA_W, ad+3) _[(ad := ad+1)] = ldl(OUT, ord('o')) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DATA_W, ad+3) _[(ad := ad+1)] = ldl(OUT, ord('r')) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DATA_W, ad+3) _[(ad := ad+1)] = ldl(OUT, ord('l')) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DATA_W, ad+3) _[(ad := ad+1)] = ldl(OUT, ord('d')) _[(ad := ad+1)], \ _[(ad := ad+1)] = call(DATA_W, 255) _[255] = jmp(255) generate_mif(FILE_NAME, WIDTH, DEPTH, _)