PIC で MIDI の送受信 - 2. MIDI の送信

[前回](https://qiita.com/qtsoundlab/items/6fabef1d4317ec6a9597) は MIDI 送受信に必要な回路について書きました。
いよいよ PIC にプログラムを書き込み、実際に送信をしてみたいと思います。

今回は PIC16F1827 を使用し、内蔵クロックで動作させることにします。


# サンプルプログラム

このサンプルプログラムで MIDI の受信はしていませんが、EUSART の受信のための設定も一緒にしてしまいます。

動作環境 : MPLAB X IDE v4.10 / Microchip MPLAB XC8 C Compiler (v1.45)

```c
#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;
}
```




## 各レジスタの設定

### クロックの設定

```c
OSCCON = 0b01101010;
```
- 内蔵クロック ４ MHz
- PLL は使用しない

### 入出力ピンの設定

```c
ANSELA = 0b00000000;
ANSELB = 0b00000000;
```
- すべての入出力ピンをデジタル入出力に設定する

```c
TRISA = 0b00100000;
TRISB = 0b00000010;
```
- RA5 (Pin 4) は入力専用
- EUSART の RX として使用する RB1 (Pin 7) を入力にする

### EUSART の設定

```c
APFCON1bits.TXCKSEL = 0;
APFCON0bits.RXDTSEL = 0;
```
- RB2 (Pin 8) を送信 (TX) に使用
- RB1 (Pin 7) を受信 (RX) に使用

```c
TXSTA = 0b00100100;
```
- 送信有効
- 非同期
- 高ボーレート選択 : ハイスピード

```c
RCSTA = 0b10010000;
```
- シリアルポート有効
- 連続受信有効

```c
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

のとき、

```math
baudrate = \frac{F_{OSC}}{16\ (n + 1)}
```

で計算できるようです（n は SPBRG レジスタに設定する値）。

今回、PIC のクロックは 4 MHz の設定で、また、MIDI の転送速度は 31.25 kbps なので、 $n = 7$ と求められます。
この結果から、

```c
SPBRGL = 0x07;
```

となります。

## MIDI 信号の送信

```c
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 のノートオンメッセージ）を送信します。
続いて、

```c
__delay_ms(1000);

while (!TXSTAbits.TRMT);
TXREG = 0x80;
while (!TXSTAbits.TRMT);
TXREG = 0x3C;
while (!TXSTAbits.TRMT);
TXREG = 0x00;
```

1 秒待機してから同じノートナンバーのノートオフメッセージを送信します。

回路を組み、ボーレートの設定さえ正しくすれば、送信自体は簡単にできました。
1 バイト送信するたびに必要な



```c
while (!TXSTAbits.TRMT);
TXREG = byte_data;
```
この部分は、関数にしてしまったほうが実用的だと思います。

さて、次回は MIDI 信号の受信に挑戦してみます。

# 参考資料

PIC16(L)F1826/27 Data Sheets
http://ww1.microchip.com/downloads/en/DeviceDoc/41391D.pdf