ホームに戻る
PIC16F88 で MIDIデータを出力する
0、はじめに
MIDI は音そのものを含まない音楽の演奏情報の統一規格です。
例えば、ドの音を出すとかドの音を止めるとか。
MIDI の規格についての説明はここではしません。
今回は PIC16F88 を使って MIDI 信号を MIDI 対応の楽器に転送します。
MIDI の情報交換のやり方は非常にシンプルで逆に不安になるほどですが、
思ったよりも正確に情報のやり取りができます。
2、必要なもの
PIC16F88 と MIDI楽器 と MIDIケーブルが必要です。
他に、5V電源、220Ωの抵抗が2本、配線が必要です。
抵抗は220Ωに近いもので代用できると思います。
3、PIC と MIDIケーブルの配線について
MIDIケーブルの左から4番目が4番ピン。
MIDIケーブルの左から2番目が5番ピン。
逆にしても大きな問題は起きないので、
動作しなかったら入れ替えれば良いと思います。
MIDIケーブルの4番ピンを抵抗をはさんで5Vへ。
MIDIケーブルの5番ピンを抵抗をはさんで、
PIC の任意の出力ポートにつなぎます。
5V -----抵抗(220Ω)-----MIDIケーブル(4番ピン)
PIC -----抵抗(220Ω)-----MIDIケーブル(5番ピン)
4、MIDI信号の詳細
MIDIデータの出力が無いときは常に HIGH になっています。
最初に LOW になったときがスタートビットです。
続いて8ビットが転送ビットになります。
このとき下位ビットから上位ビットに向かって転送します。
最後に HIGH にするのがエンドビットになります。
例えば、0x90 を転送したい場合には、
H の状態から LLLLLHLLHH の10ビットを転送します。
続けて、0x90 0x3C を転送したい場合には、
H の状態から LLLLLHLLHHLLLHHHHLLH の20ビットを転送します。
1ビットを維持する時間はおよそ 32 マイクロ秒です。
1つの MIDIデータを送るのにおよそ 320 マイクロ秒かかります。
5、サンプルコード
; PIC16F88 で内部クロック 4MHz を使用します。
; MIDI出力は PORTB の0番ピンを使用しています。
LIST P=16F88
INCLUDE P16F88.INC
__CONFIG _CONFIG1, _WDT_OFF & _PWRTE_ON & _INTRC_IO & _LVP_OFF & _MCLR_OFF
__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF
T0 EQU 20H
T1 EQU 21H
MIDI_DATA EQU 22H
COUNT1 EQU 23H
BITCOUNT EQU 24H
PORT_OUT EQU 0 ; 使用するポートBの番号
BSF STATUS,RP0 ; Bank 1
MOVLW 064h
MOVWF OSCCON ; 内部クロック 4MHz
MOVLW 000h
MOVWF TRISB ; すべて出力に
CLRF ANSEL ; アナログ入出力を使用しない
BCF STATUS,RP0 ; Bank 0
BSF PORTB,PORT_OUT
MAIN
CALL WAIT_250MS
CALL WAIT_250MS
MOVLW 0x90
MOVWF MIDI_DATA
CALL MIDI_OUT
MOVLW 0x3C
MOVWF MIDI_DATA
CALL MIDI_OUT
MOVLW 0x7F
MOVWF MIDI_DATA
CALL MIDI_OUT
CALL WAIT_250MS
CALL WAIT_250MS
MOVLW 0x80
MOVWF MIDI_DATA
CALL MIDI_OUT
MOVLW 0x3C
MOVWF MIDI_DATA
CALL MIDI_OUT
MOVLW 0x00
MOVWF MIDI_DATA
CALL MIDI_OUT
GOTO MAIN
MIDI_OUT
BCF PORTB,PORT_OUT
NOP
MOVLW D'8'
MOVWF COUNT1
START_BIT_WAIT
DECFSZ COUNT1,F
GOTO START_BIT_WAIT
MOVLW D'8'
MOVWF BITCOUNT
SET_BIT
BTFSC MIDI_DATA,0
GOTO BIT_1
BIT_0
NOP
BCF PORTB,PORT_OUT
GOTO SET_BIT2
BIT_1
BSF PORTB,PORT_OUT
GOTO SET_BIT2
SET_BIT2
RRF MIDI_DATA,F
MOVLW D'7'
MOVWF COUNT1
SET_BIT_WAIT
DECFSZ COUNT1,F
GOTO SET_BIT_WAIT
DECFSZ BITCOUNT
GOTO SET_BIT
STOP_BIT
NOP
NOP
NOP
NOP
BSF PORTB,PORT_OUT
MOVLW D'8'
MOVWF COUNT1
STOP_BIT_WAIT
DECFSZ COUNT1,F
GOTO STOP_BIT_WAIT
NOP
RETURN
; 1ms
WAIT_01MS
MOVLW D'250'
MOVWF T0
TIMELOOP
NOP
DECFSZ T0, F
GOTO TIMELOOP
RETURN
; 250ms
WAIT_250MS
MOVLW D'250'
MOVWF T1
TIMELOOP2
CALL WAIT_01MS
DECFSZ T1, F
GOTO TIMELOOP2
RETURN
END