PICでUART通信をゼロから理解する(USART入門~PICからの信号送信)

前回の記事では、PIC16F1938を使ってPWMを5ch制御し、
Timer・CCP・ADCを組み合わせた制御を実装しました。

今回はその次のステップとして、
「UART通信(USART)」に進みます。

・外部機器と通信したい
・ログをPCに出したい
・最終的にはDMXにつなげたい

こういった用途では、UARTは避けて通れません。

この記事では、

・UARTとは何か
・USARTの初期化方法
・実際に文字を送信するところまで

を、実機ベースで解説します。

※今回は送信のみを扱っています。受信については次回解説します。

UARTとは何か?

UART(Universal Asynchronous Receiver Transmitter)は、
マイコン同士やPCと通信するためのシリアル通信方式です。

特徴は以下の通りです。

・非同期通信(クロック線なし)
・TX/RXの2本で通信
・決めたボーレートで通信する

例えば9600bpsの場合、

1秒間に9600ビット送れる
=1ビット 約104μs

という時間でデータが流れます。

USARTとは?

PICではUART機能は「USART」と呼ばれています。

USART = Universal Synchronous Asynchronous Receiver Transmitter

つまり、

・非同期通信(UART)
・同期通信

両方に対応していますが、

今回は「非同期(UART)」のみ使います。

UARTのデータ構造

UARTでは1文字を以下の形で送ります。

スタートビット:1bit(必ず0)
データ:8bit
ストップビット:1bit(必ず1)

つまり合計10ビット(設定によっては11ビット)

例えば’A’(0x41)を送ると、

0(スタート) + 01000001 + 1(ストップ)

という形になります。

UARTのデータ構造

UARTでは1文字を以下の形で送ります。

スタートビット:1bit(必ず0)
データ:8bit
ストップビット:1bit(必ず1)

つまり合計10ビット(設定によっては11ビット)

例えば’A’(0x41)を送ると、

0(スタート) + 01000001 + 1(ストップ)

という形になります。

USART初期化

今回の設定は以下です。

・内部クロック:8MHz
・ボーレート:9600bps
・非同期モード
・送信有効
・受信有効

c

void USART_Init(void) {
    OSCCON = 0b01110010; // 8MHz

    TRISCbits.TRISC6 = 1; // TX
    TRISCbits.TRISC7 = 1; // RX

    // ボーレート設定
    SPBRG = 51; // 9600bps(8MHz時)

    TXSTAbits.BRGH = 1;   // 高速モード
    BAUDCONbits.BRG16 = 0;

    RCSTAbits.SPEN = 1;   // シリアル有効

    TXSTAbits.TXEN = 1;   // 送信有効
    RCSTAbits.CREN = 1;   // 受信有効
}

文字を送信する

UARTは1バイトずつ送信します。
あくまでも一文字ずつで、単語や文章を一気におくることはしてません。

c

void USART_Write(char data) {
    while(!PIR1bits.TXIF);
    TXREG = data;
}

動作確認

回路図は以下の通りです。

PICとUSBシリアル変換(CH340など)は以下のように接続します。

PIC TX → USBシリアル RX
PIC RX → USBシリアル TX
GND → GND

例えば以下のコードで、

c

USART_Write('A');

‘A’が送信されます。

USB-シリアル変換(CH340など)を使い、
PCのターミナルソフトで確認できます。
今回はtera termを使いました。

今回は、次のコードを使いました。

c

while (1) {
        LATAbits.LATA1 = 1;
        
        unsigned char Strings[] = "Hello!!\r\n";
        unsigned int len = strlen(Strings);

        for (unsigned char i = 0; i < len; i++) {
            while (!PIR1bits.TXIF);
            TXREG = Strings[i];

        }
        __delay_ms(500);
    }

メインの中で、上のコードを入力し、
0.5秒間隔で、
”Hello”が表示されます。

無事に通信できていることが確認できました。 
画面録画で録画のクオリティのせいなのか、
全く0.5秒間隔には見えませんが、
生で見るとちゃんと0.5秒間隔になってました。

このように一定周期でデータを送信することで、
デバッグ出力や状態監視にも応用できます。

 

なぜSPBRGが51なのか?

ボーレートは以下の式で決まります。

ボーレート = Fosc / (16 × (SPBRG + 1))

今回、

Fosc = 8MHz
ボーレート = 9600

なので、

SPBRG ≒ 51

になります。

PWMとの違い

PWMは「波形を作る制御」でしたが、

UARTは「情報を送る手段」です。

PWM:
→ LEDの明るさ制御

UART:
→ データ通信

つまり、

PWM → 出力制御
UART → 情報伝達

という役割になります。

よくあるミス

UARTが動かない原因として多いのは以下です。

・ボーレート設定ミス(SPBRG)
・TX/RXの配線ミス
・GND未接続
・ターミナルの設定違い

特にGNDが共通になっていないと通信できません。

今回はこのあたりでのミスは無かったのですが、
なかなか初歩的なところでつまづいてしまっていました。

書き込みは成功しているにも関わらず、
全く動かない時間が長くてかなり大変でした。

ハマったポイントはコンフィギュレーションの設定です。

c

#pragma config LVP = OFF

ただ1行、
これが無かっただけで、
ちゃんと動いてくれなくて
1~2時間ぐらい
いろいろ思考錯誤しました。

Lチカすら動かなかった…

まとめ

・UARTはシリアル通信の基本
・PICではUSARTとして実装されている
・初期化すれば簡単に送信できる

PWMで「制御」を学んだ後は、
UARTで「通信」を学ぶことで、

マイコンの世界が一気に広がります。

 

次回予告

今回は「送信」までを実装しました。

次回は、

・受信処理
・文字列送信
・実用的なデバッグ出力

をやっていきます。

最終的には、

DMX通信にもつながる内容になります。

コメント

タイトルとURLをコピーしました