前回 は MIDI 送受信に必要な回路について書きました。
いよいよ PIC にプログラムを書き込み、実際に送信をしてみたいと思います。
今回は PIC16F1827 を使用し、内蔵クロックで動作させることにします。
サンプルプログラム
このサンプルプログラムで MIDI の受信はしていませんが、EUSART の受信のための設定も一緒にしてしまいます。
動作環境 : MPLAB X IDE v4.10 / Microchip MPLAB XC8 C Compiler (v1.45)
#include <xc.h>
#pragma config FOSC = INTOSC // Oscillator Selection : Internal
#pragma config WDTE = OFF // Watchdog Timer Enable : Off
#pragma config PWRTE = ON // Power-up Timer Enable : On
#pragma config MCLRE = OFF // MCLR Pin Function Select : Off
#pragma config CP = OFF // Flash Program Memory Code Protection : Off
#pragma config CPD = OFF // Data Memory Code Protection : Off
#pragma config BOREN = ON // Brownout Reset Enable : On
#pragma config CLKOUTEN = OFF // Clock Out Enable : Off
#pragma config IESO = OFF // Internal/External Switchover : Off
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable : Off
#pragma config WRT = OFF // Flash Memory Self-Write Protection : Off
#pragma config PLLEN = OFF // PLL Enable : Off
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable : On
#pragma config BORV = LO // Brown-out Reset Voltage Selection : Low
#pragma config LVP = OFF // Low-Voltage Programming Enable : Off
#define _XTAL_FREQ 4000000
void main(void) {
// Internal Clock (4 MHz)
OSCCON = 0b01101010;
// I/O : Digital Mode
ANSELA = 0b00000000;
ANSELB = 0b00000000;
// Configure Input / Output
TRISA = 0b00100000; // RA5: Input
TRISB = 0b00000010; // RX: Input
// Configure TX / RX Pins
APFCON1bits.TXCKSEL = 0; // TX : RB2 (Pin 8)
APFCON0bits.RXDTSEL = 0; // RX : RB1 (Pin 7)
// Setup EUSART
TXSTA = 0b00100100;
RCSTA = 0b10010000;
BAUDCON = 0b00000000;
SPBRGL = 0x07;
// Send Note On Message
while (!TXSTAbits.TRMT);
TXREG = 0x90;
while (!TXSTAbits.TRMT);
TXREG = 0x3C;
while (!TXSTAbits.TRMT);
TXREG = 0x7F;
__delay_ms(1000);
// Send Note Off Message
while (!TXSTAbits.TRMT);
TXREG = 0x80;
while (!TXSTAbits.TRMT);
TXREG = 0x3C;
while (!TXSTAbits.TRMT);
TXREG = 0x00;
while(1);
return;
}
各レジスタの設定
クロックの設定
OSCCON = 0b01101010;
- 内蔵クロック 4 MHz
- PLL は使用しない
入出力ピンの設定
ANSELA = 0b00000000;
ANSELB = 0b00000000;
- すべての入出力ピンをデジタル入出力に設定する
TRISA = 0b00100000;
TRISB = 0b00000010;
- RA5 (Pin 4) は入力専用
- EUSART の RX として使用する RB1 (Pin 7) を入力にする
EUSART の設定
APFCON1bits.TXCKSEL = 0;
APFCON0bits.RXDTSEL = 0;
- RB2 (Pin 8) を送信 (TX) に使用
- RB1 (Pin 7) を受信 (RX) に使用
TXSTA = 0b00100100;
- 送信有効
- 非同期
- 高ボーレート選択 : ハイスピード
RCSTA = 0b10010000;
- シリアルポート有効
- 連続受信有効
BAUDCON = 0b00000000;
- 16 ビットボーレートジェネレータを使わない
ボーレートと SPBRG レジスタの設定
- EUSART のモード(SYNC : TXSTA レジスタの bit 4)
- 高ボーレート選択(BRGH : TXSTA レジスタの bit 2)
- 16 ビットボーレートジェネレータ設定(BRG16 : BAUDCON レジスタの bit 3)
これらのビットの設定値と SPBRG レジスタ の値、ボーレートの関係がデータシートに記載されています。
- SYNC = 0
- BRGH = 1
- BRG16 = 0
のとき、
baudrate = \frac{F_{OSC}}{16\ (n + 1)}
で計算できるようです(n は SPBRG レジスタに設定する値)。
今回、PIC のクロックは 4 MHz の設定で、また、MIDI の転送速度は 31.25 kbps なので、 $n = 7$ と求められます。
この結果から、
SPBRGL = 0x07;
となります。
MIDI 信号の送信
while (!TXSTAbits.TRMT);
TXREG = 0x90;
while (!TXSTAbits.TRMT);
TXREG = 0x3C;
while (!TXSTAbits.TRMT);
TXREG = 0x7F;
TXREG レジスタに送信データを格納する前に、TXSTA レジスタの TRMT ビット(送信シフトレジスタステータスビット)の値が 1 になる、すなわち、送信シフトレジスタが空になるまで while 文で待機しています。
この例では、0x90, 0x3C, 0x7F の 3 バイト(チャンネル 1、ノートナンバー 60、ベロシティ 127 のノートオンメッセージ)を送信します。
続いて、
__delay_ms(1000);
while (!TXSTAbits.TRMT);
TXREG = 0x80;
while (!TXSTAbits.TRMT);
TXREG = 0x3C;
while (!TXSTAbits.TRMT);
TXREG = 0x00;
1 秒待機してから同じノートナンバーのノートオフメッセージを送信します。
回路を組み、ボーレートの設定さえ正しくすれば、送信自体は簡単にできました。
1 バイト送信するたびに必要な
while (!TXSTAbits.TRMT);
TXREG = byte_data;
この部分は、関数にしてしまったほうが実用的だと思います。
さて、次回は MIDI 信号の受信に挑戦してみます。
参考資料
PIC16(L)F1826/27 Data Sheets
http://ww1.microchip.com/downloads/en/DeviceDoc/41391D.pdf