UART (Universal Asynchronous Receiver Transmitter)

MPLAB C30コンパイラの、UARTモジュールのライブラリについて解説します。

ライブラリ

ライブラリファイルはuart.hですので、先にこれをインクルードします。

#include <uart.h>

なお、このファイルは既定では/Microchip/MPLAB C30/support/peripheral_30F_24H_33F/にあります。

関数、マクロ

関数名やマクロ名はOpenUARTx()のような形式で、使用するUARTモジュールに応じてxの部分でUARTの番号を指定します。 UARTモジュールが1つしか搭載されていない場合には、つねに1となります。

関数

用途 関数
オープン/クローズ OpenUARTx
CloseUARTx
送受信 ReadUARTx (getcUARTx)
WriteUARTx (putcUARTx)
putsUARTx
getsUARTx
通信状態 DataRdyUARTx
BusyUARTx
割り込み ConfigIntUARTx
dsPIC30F/dsPIC33F/PIC24H/dsPIC33E/PIC24E UART Peripheral Module Library Help

マクロ

用途 マクロ
割り込み EnableIntUxRX
EnableIntUxTX
DisableIntUxRX
DisableIntUxTX
SetPriorityIntUxRX
SetPriorityIntUxTX

レジスタ (Register)

  • UxMODE (MODe) … モード
  • UxSTA (STAtus) … ステータス
  • UxTXREG (Transmit REGister) … 送信データ
  • UxRXREG (Receive REGister) … 受信データ
  • UxBRG (Baud Rate Generator prescaler) … ボーレート
  • UxTSR (Trasmit Shift Register) ※1 … 送信シフトレジスタ
  • UxRSR (Receive Shift Register) ※1 … 受信シフトレジスタ
※1 UxTSRとUxRSRへは、ユーザーは直接アクセスできません。
区分 SFR名 Bit 15 Bit 14 Bit 13 Bit 12 Bit 11 Bit 10 Bit 9 Bit 8 Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 リセット後の値
(モード) U1MODE UARTEN - USIDL - reserved ALTIO reserved reserved WAKE LPBACK ABAUD - - PDSEL<1:0> STSEL 0000 0000 0000 0000
(ステータス) U1STA UTXISEL - - - UTXBRK UTXEN UTXBF TRMT URXISEL<1:0> ADDEN RIDLE PERR FERR OERR URXDA 0000 0001 0001 0000
(送信データ) U1TXREG - - - - - - - UTX8 Transmit Register 0000 0000 0000 0000
(受信データ) U1RXREG - - - - - - - URX8 Receive Register 0000 0000 0000 0000
(ボーレート) U1BRG Baud Rate Generator Prescaler 0000 0000 0000 0000
Table 19-3: Registers Associated with UART1 (DS70066C)

ブロック図


送信


受信

ピン
ピン 説明
UxTX  
UxRX  

I/Oの設定

UARTモジュールを有効にすると、送受信のピンは出力と入力にそれぞれ自動で設定されます。よってI/Oの設定をする必要はありません。≫I/Oと周辺モジュール

ポートのオープン、クローズ

ポートのオープン (OpenUART)

使用する関数はOpenUARTx()となっていますが、PICにはポートを開くという概念はないため、実際にはUARTの動作設定をすることになります。

void OpenUARTx(
  unsigned int config1,  // UxMODEレジスタ (Mode register) の値
  unsigned int config2,  // UxSTAレジスタ (Status register) の値
  unsigned int ubrg      // UxBRGレジスタ (Baud rate generator register) の値
  )
config1の定数 (UxMODE)
区分 定数 説明
UARTモジュール 有効/無効 UART_EN モジュールを有効にする
UART_DIS モジュールを無効にする
パリティ・データビット長 UART_NO_PAR_9BIT No parity 9 bit
UART_ODD_PAR_8BIT odd parity 8 bit
UART_EVEN_PAR_8BIT even parity 8 bit
UART_NO_PAR_8BIT no parity 8 bi
ストップビット UART_2STOPBITS 2 stop bits
UART_1STOPBIT 1 stop bits
アイドルモード時の動作 UART_IDLE_CON Work in IDLE mode
UART_IDLE_STOP Stop all functions in IDLE mode
スリープ時のスタートビット検出によるウェイクアップ 有効/無効 UART_EN_WAKE Enable Wake-up on START bit Detect during SLEEP Mode bit
UART_DIS_WAKE Disable Wake-up on START bit Detect during SLEEP Mode bit
ループバック 有効/無効 UART_EN_LOOPBACK Loop back enabled
UART_DIS_LOOPBACK Loop back disabled
自動ボーレート UART_EN_ABAUD Enable baud rate measurement on the next character
UART_DIS_ABAUD Baud rate measurement disabled or completed
IrDAエンコーダ 有効/無効 UART_IrDA_ENABLE IrDA encoder and decoder enabled
UART_IrDA_DISABLE IrDA encoder and decoder disabled
Alternate I/O※1 UART_ALTRX_ALTTX Communication through ALT pins
UART_RX_TX Communication through the normal pins
UxRTSピンモード UART_MODE_SIMPLEX UxRTS pin in Simplex mode
UART_MODE_FLOW UxRTS pin in Flow Control mode
Port latch control UART_UEN_11 UxTX,UxRX and BCLK pins are enabled and used; UxCTS pin controlled by port latches
UART_UEN_10 UxTX,UxRX, UxCTS and UxRTS pins are enabled and used
UART_UEN_01 UxTX,UxRX and UxRTS pins are enabled and used; UxCTS pin controlled by port latches
UART_UEN_00 UxTX and UxRX pins are enabled and used; UxCTS and UxRTS/BCLK pins controlled by port latches
Idle state UART_UXRX_IDLE_ZERO UxRX Idle state is zero
UART_UXRX_IDLE_ONE UxRX Idle state is one
BRG UART_BRGH_FOUR BRG generates 4 clocks per bit period
UART_BRGH_SIXTEEN BRG generates 16 clocks per bit period
※1 代替I/Oが有効なデバイスは、dsPIC30F1010、dsPIC30F2020、dsPIC30F2023、dsPIC30F4011のみ
config2の定数 (UxSTA)
区分 定数 説明
送信 有効/無効 UART_TX_ENABLE 送信を有効にする
UART_TX_DISABLE 送信を無効にする
送信の割り込み条件 UART_INT_TX_BUF_EMPTY 送信バッファが空になったとき
UART_INT_TX_LAST_CH 最後のデータがシフトレジスタに転送されたとき
UART_INT_TX データがシフトレジスタに転送されるごと
受信の割り込み条件 UART_INT_RX_BUF_FUL 受信バッファの4/4がフルになったとき
UART_INT_RX_3_4_FUL 受信バッファの3/4がフルになったとき
UART_INT_RX_CHAR データを受信するごと
送信ブレーク UART_TX_PIN_NORMAL UART TX pin operates normally
UART_TX_PIN_LOW UART TX pin driven low
IrDAエンコード UART_IrDA_POL_INV_ONE IrDA encoded, UxTX Idle state is '1'
UART_IrDA_POL_INV_ZERO IrDA encoded, UxTX Idle state is '0'
Sync break UART_SYNC_BREAK_ENABLED Send sync break on next transmission
UART_SYNC_BREAK_DISABLED Sync break transmission disabled or completed
アドレス検出 有効/無効 UART_ADR_DETECT_EN address detect enable
UART_ADR_DETECT_DIS address detect disable
バッファオーバーラン UART_RX_OVERRUN_CLEAR Rx buffer Over run status bit clear
ループバック (Loopback)
通信テストを行うための機能。有効にすると、送信データが受信ポートに返されるようになる。
送信ブレーク (Transmit Break)
送信ラインをLowにして、強制的に送信を停止させる。
アドレス検出 (Address Detect)
送受信バッファの9ビット目をアドレス指定のフラグとして、それがセットされているときにはデータをアドレスとみなす。そしてそのアドレスに合致したデバイスだけが続くデータを処理することで、複数のデバイスとの通信を可能とする。

ボーレート (Baud rate) (UxBRG)

システムクロック (System clock) は、

FOSC = オシレータ周波数 * PLLの乗数

であり、命令サイクルクロック (Instruction cycle clock) 周波数は

FCY = FOSC / 4

です。またボーレートを算出する式は、

Baud rate = FCY / ( 16 * ( BRG + 1 ) )

であることから、UxBRGレジスタ値 (Baud Rate Generator) は

BRG = ( FOSC / 4 ) / ( 16 * Baud rate ) - 1

となり、OpenUARTx()の第3引数ubrgに与える値が求められます。

※dsPICには高ボーレートの設定は存在しません。
ボーレートエラー (Baud rate Error)

ボーレートの設定値は整数で与える必要があるため、小数点以下を丸めることで理論値との誤差が生じます。

たとえばボーレートなどの条件を次のように仮定すると、

オシレータ周波数 10MHz
PLL 8
ボーレート 115.2kbps

BRGに設定する値は、

( 10 * 10⁶ * 8 / 4 ) / ( 16 * 115.2 * 10³ ) - 1 ≒ 10

と求まり、これから逆にボーレートを求めると、

( 10 * 10⁶ * 8 / 4 ) / ( 16 * ( 10 + 1 ) ) ≒ 113636 [bps]

となります。よって、

( 113636 - 115200 ) / 115200 ≒ -1.36%

のボーレートの誤差が生じることになります。

サンプルコード

ポートをオープンするコードを示します。

#define CPU_CLOCK 10000000L                        // クロック [Hz]
#define CPU_PLL   8                                // PLL
#define FCY       ( ( CPU_CLOCK * CPU_PLL ) / 4 )  // 命令サイクルクロック [Hz]

#define BAUDRATE  115200L                          // ボーレート [bps]

const unsigned int Mode
     = UART_EN              // UARTモジュール - 有効
     & UART_IDLE_STOP       // アイドルモード - 動作停止
     & UART_DIS_WAKE        // ウェイクアップ - 無効
     & UART_DIS_LOOPBACK    // ループバック - 無効
     & UART_DIS_ABAUD       // 自動ボーレート - 無効
     & UART_NO_PAR_8BIT     // パリティなし/データ 8ビット
     & UART_1STOPBIT;       // ストップビット - 1ビット

const unsigned int Status
     = UART_TX_ENABLE           // 送信 - 有効
     & UART_INT_TX_BUF_EMPTY    // 送信の割り込み条件 - 送信バッファが空
     & UART_INT_RX_CHAR         // 受信の割り込み条件 - 受信するたび
     & UART_TX_PIN_NORMAL       // 送信ブレーク - 通常
     & UART_ADR_DETECT_DIS      // アドレス検出 - 無効
     & UART_RX_OVERRUN_CLEAR;   // 受信バッファオーバーランエラー - クリア

const double Baudrate = ( double )FCY / ( 16 * BAUDRATE ) - 1;

// ボーレートの小数点以下を四捨五入する
unsigned int baudrate = ( unsigned int )( Baudrate + 0.5 );

OpenUART1( Mode, Status, baudrate );

ポートのクローズ (CloseUART)

CloseUARTx()を使用します。この関数は、内部的には割り込みを無効とする処理をします。

void CloseUARTx( void )

送受信 (Read、Write)

区分 データサイズ 関数 関与する変数
送信 1byte WriteUARTx() UxTXREG
putcUARTx()
複数byte putsUARTx()  
受信 1byte ReadUARTx() UxRXREG
getcUARTx()
複数byte getsUARTx()  

送信

送信バッファがフルの状態で送信を試みても、バッファには書き込まれず送信が無視されます。

送信バッファへデータを書き込みます。

void WriteUARTx( unsigned int data )

送信にはputcUARTx()という関数もありますが、これは

#define putcUART1 WriteUART1

のように定義されていて、実体はWriteUARTx()の別名です。または、

UxTXREG = data;

のようにレジスタに直接書き込んでも同じです。

送信の完了は、送信ステータスまたは割り込みで確認します。

連続した送信

連続してデータを送信するには、putsUARTx()という関数があります。

void putsUARTx( unsigned int *buffer )

たとえば文字列を送信するならば、

char* str = "abc";
putsUART1( (unsigned int*)str );

のようにします。

受信

受信バッファオーバーランエラーが発生した場合、その状態がクリアされるまでは受信が行われません。このときバッファから読み込むと、つねに最後に受信したデータが返されます。

受信バッファからデータを読み込みます。

unsigned int ReadUARTx( void )

getcUARTx()という関数もありますが、これはReadUARTx()のエイリアス別名です。

#define getcUART1 ReadUART1

または送信と同様に、

unsigned int data = UxRXREG;

のようにレジスタから直接読み込む方法もあります。

連続した受信

連続してデータを受信するには、getsUARTx()という関数があります。

unsigned int getsUARTx(
    unsigned int length,
    unsigned int *buffer,
    unsigned int uart_data_wait
    )

データのサイズ

WriteUARTx()とReadUARTx()のそれぞれの引数と戻り値はunsigned intであり、MPLAB C30のデータ型ではそれは16ビットです。またそれぞれのバッファUxTXREGとUxRXREGレジスタも16ビットです。しかし上位8ビットはアドレス検出に使用されるため、実際のデータサイズは8ビットになります。

通信状態の取得

対象 関数 関与する変数
送信バッファ --- UxSTAbits.UTXBF
受信バッファ DataRdyUARTx() UxSTAbits.URXDA
送信ステータス BusyUARTx() UxSTAbits.TRMT

受信バッファと送信ステータスの確認には関数が用意されていますが、レジスタの値を調べることと同義です。

送信バッファ

UxSTAレジスタのUTXBFビットで、送信バッファがフル (Full) かどうかを確認できます。

if( U1STAbits.UTXBF )
{
    // 送信バッファはフル
}
else
{
    // 送信バッファはフルではない
}

ところで、

#define _UTXBF U1STAbits.UTXBF

のようにマクロが定義されているため、_UTXBFのようにも記述できます。

なお送信バッファは4word (8byte) ありますが、アドレス検出のビットを含むため、保持できるデータは4byteです。

受信バッファ

DataRdyUARTx()で、受信バッファにデータがあるかどうかを確認できます。

char DataRdyUARTx( void )

受信バッファにデータがあれば1が、さもなくば0が返されます。受信バッファも4word (8byte) ありますが、送信バッファと同様の理由により4byteのデータしか保持できません。

受信バッファの確認には関数が用意されていますが、内部的にはUxSTAレジスタのURXDAビットを調べているだけです。よって送信バッファの場合と同様に、

if( _URXDA )

のようにも記述できます。

受信バッファオーバーランエラーが発生した場合、その状態がクリアされるまでは、つねに受信バッファにデータがある状態 (_URXDA == 1) となります。

送信ステータス

BusyUARTx()で、送信の実行中かどうかを確認できます。送信中ならば1を、さもなくば0を返します。これは内部的にはUxSTA<TRMT>の値の否定であり、_TRMTとは逆の値を返します。

char BusyUARTx( void )

通信エラー

エラー 関与する変数
受信バッファオーバーランエラー
(receive buffer Overrun ERRor)
UxSTAbits.OERR
フレーミングエラー
(Framing ERRor)
UxSTAbits.FERR
パリティエラー
(Parity ERRor)
UxSTAbits.PERR

フレーミングエラー (framing error)

データの転送において、データを構成するフレームに異常があること。 非同期通信では、データのストップビットが"0"となっている場合に、フレーミングエラーとなる。

http://japan.renesas.com/fmwk.jsp?cnt=w-mcu_k.framing_error.htm&fp=/support/glossary_child/w-mcu_k.ha/&title=フレーミングエラーとは

パリティチェック (parity check)

通信処理で用いられる単純な誤り検出方法。データ中の"1"の個数を常に奇数 (奇数パリティ) または偶数 (偶数パリティ) になるように、検査用のビット (パリティビット) を付加して送信する。受信側において"1"の個数を数えることにより、受信したデータが正しいか検証できる。

http://japan.renesas.com/fmwk.jsp?cnt=w-mcu_k.parity_check.htm&fp=/support/glossary_child/w-mcu_k.ha/&title=パリティチェックとは

受信バッファオーバーランエラー

受信バッファオーバーランエラーが発生したときには、そのOERRビットをクリアするまでは、受信シフトレジスタ UxRSR (Receive Shift Register) が固定されます。これにより受信バッファも書き換えられなくなるため、受信できるようにするためにはOERRビットをクリアする必要があります。

割り込み (Interrupt)

送信ではデータがシフトレジスタに転送されることによって、受信ではデータがバッファに格納されることによって割り込みが発生します。具体的な割り込みの発生条件は、ステータスレジスタ (UxSTA) で設定します。

割り込みフラグ
変数名 説明
IFS0bits.UxTXIF 送信 割り込みフラグ
  • 0:割り込みなし
  • 1:割り込み発生
IFS0bits.UxRXIF 受信

許可、禁止

機能 区分 マクロ
割り込みを許可 送信 EnableIntUxTX
受信 EnableIntUxRX
割り込みを禁止 送信 DisableIntUxTX
受信 DisableIntUxRX

これらのマクロは、

/* Macros to Enable/Disable interrupts of UART1 */
#define EnableIntU1RX      _U1RXIE = 1
#define EnableIntU1TX      _U1TXIE = 1

#define DisableIntU1RX     _U1RXIE = 0
#define DisableIntU1TX     _U1TXIE = 0

のように定義されており、割り込み有効制御レジスタ (IECx) に設定することと同義です。

割り込み優先順位

機能 区分 マクロ
割り込み優先順位を設定 送信 SetPriorityIntUxTX( priority )
受信 SetPriorityIntUxRX( priority )

これもまたマクロであり、

/* Macros to set Interrupt priority of UART1 */
#define SetPriorityIntU1RX(priority)     _U1RXIP = priority
#define SetPriorityIntU1TX(priority)     _U1TXIP = priority

のように定義されています。優先順位を指定する引数には、

送信 UART_TX_INT_PRn (nは0~7の数値)
受信 UART_RX_INT_PRn (nは0~7の数値)

の定数を使用します。レベルは0~7まであり、既定では4となっています。

設定

ConfigIntUARTx()関数で、割り込みの許可、禁止および割り込み優先順位の設定を一括して行えます。

void ConfigIntUARTx( unsigned int config )

たとえば受信割り込みを有効にし、その優先順位を7とするには、

ConfigIntUART1( UART_RX_INT_EN & UART_RX_INT_PR7 );

とします。設定可能な定数は以下の通りです。

/* defines for UART Interrupt configuartion */
#define UART_RX_INT_EN          0xFFFF  /*Receive interrupt enabled*/
#define UART_RX_INT_DIS         0xFFF7  /*Receive interrupt disabled*/

#define UART_RX_INT_PR0         0xFFF8  /*Priority RX interrupt 0*/
#define UART_RX_INT_PR1         0xFFF9  /*Priority RX interrupt 1*/
#define UART_RX_INT_PR2         0xFFFA  /*Priority RX interrupt 2*/
#define UART_RX_INT_PR3         0xFFFB  /*Priority RX interrupt 3*/
#define UART_RX_INT_PR4         0xFFFC  /*Priority RX interrupt 4*/
#define UART_RX_INT_PR5         0xFFFD  /*Priority RX interrupt 5*/
#define UART_RX_INT_PR6         0xFFFE  /*Priority RX interrupt 6*/
#define UART_RX_INT_PR7         0xFFFF  /*Priority RX interrupt 7*/

#define UART_TX_INT_EN          0xFFFF  /*transmit interrupt enabled*/
#define UART_TX_INT_DIS         0xFF7F  /*transmit interrupt disabled*/

#define UART_TX_INT_PR0         0xFF8F  /*Priority TX interrupt 0*/
#define UART_TX_INT_PR1         0xFF9F  /*Priority TX interrupt 1*/
#define UART_TX_INT_PR2         0xFFAF  /*Priority TX interrupt 2*/
#define UART_TX_INT_PR3         0xFFBF  /*Priority TX interrupt 3*/
#define UART_TX_INT_PR4         0xFFCF  /*Priority TX interrupt 4*/
#define UART_TX_INT_PR5         0xFFDF  /*Priority TX interrupt 5*/
#define UART_TX_INT_PR6         0xFFEF  /*Priority TX interrupt 6*/
#define UART_TX_INT_PR7         0xFFFF  /*Priority TX interrupt 7*/

割り込みサービスルーチン (ISR)

割り込みにより呼び出される関数は、

記述方法 区分
__attribute__(( interrupt, auto_psv )) _UxRXInterrupt() 受信
__attribute__(( interrupt, auto_psv )) _UxTXInterrupt() 送信

のように定義します。

参考

  • Section 19. UART (DS70066C)
  • dsPIC30Fファミリー リファレンスマニュアル (DS70046B_JP)
    19章「UART」
  • dsPIC30F/dsPIC33F/PIC24H/dsPIC33E/PIC24E UART Peripheral Module Library Help (/Microchip/MPLAB C30/docs/periph_lib/dsPIC30F_dsPIC33F_PIC24H_dsPIC33E_PIC24E_UART_Help.htm)

参考書

  • 電子制御のためのPIC応用ガイドブック [技術評論社] 後閑哲也
    対象とするのはPIC16Fであり、基本的にアセンブラでの解説であるため、MPLAB C30についての解説は一切ありません。しかしUARTモジュールを使用しないで通信を実現する方法など、通信に関して深く解説されています。