[PIC24]UART機能を使用してRS-232C通信を行う

PIC24でUART機能を使用するサンプルです。
とりあえず動いたので、メモ代わりにアップしておきます。

設定は以下の通り。

PIC24FJ32GA002で確認
UART1を使用
送受信処理はポーリングベース(割り込みは使わない)
 
9600bps
8bit
ノンパリティ
ストップ 1bit
 
TxDのピン: RP5
RxDのピン: RP6



PICからの出力はFT2232経由でPCに取り込みます。

#include <p24FJ32GA002.h>
#include "uart.h"
#include "PPS.h"
 
#define UART_CLK8MHZ_9600BPS 25
 
//--------------------------------------
// コンフィグレーションビットの設定
//--------------------------------------
_CONFIG2(   POSCMOD_NONE  &       // Primary oscillator disabled
            IOL1WAY_OFF   &       // IOLOCK may be changed via unlocking seq
            OSCIOFNC_ON   &       // OSC2/CLKO/RC15 functions as port I/O (RC15)
            FCKSM_CSDCMD  &       // Clock switching and Fail-Safe Clock Monitor are disabled
            FNOSC_FRC     &       // Fast RC Oscillator (FRC)
            WUTSEL_LEG            // Legacy Wake-up Timer
        );
 
_CONFIG1 (  FWDTEN_OFF &          // Watchdog Timer is disabled
            ICS_PGx1   &          // Emulator EMUC1/EMUD1 pins are shared with PGC1/PGD1
            COE_ON     &          // Reset Into Clip On Emulation Mode
            BKBUG_ON   &          // Device resets into Debug mode
            GWRP_OFF   &          // Writes to program memory are allowed
            GCP_OFF    &          // Code protection is disabled
            JTAGEN_OFF            // JTAG port is disabled
         );
 
 
int main( void )
{   
    volatile int recvCount = 0; // 受信文字数
    volatile int errCount  = 0; // 受信エラー回数
    volatile int waitCount = 0; // 送信待ち回数
 
 
    //------------------------------------
    // クロックの定義
    //------------------------------------
    OSCCONbits.COSC  = 0; // CPUクロックにFast RC Oscillator (FRC)を使用
    CLKDIVbits.DOZE  = 0; // クロックのレート1:1(postscaler)
    CLKDIVbits.RCDIV = 0; // 8Mhz(prescaler)
 
 
    //------------------------------------
    // RPピンの役割マッピング設定
    //------------------------------------                              
    iPPSOutput( OUT_PIN_PPS_RP5, OUT_FN_PPS_U1TX ); // RP5を UART1のTXDとして使用
    iPPSInput(  IN_FN_PPS_U1RX,  IN_PIN_PPS_RP6  ); // RP6を UART1のRXDとして使用
 
 
    //----------------------
    // UART1のオープン
    //----------------------
    CloseUART1();
 
    unsigned int config1 =  UART_EN &               // UART有効
                            UART_IDLE_CON &         // アイドル時も動作させる
                            UART_DIS_WAKE &         // スリープ時はWakeupさせない
                            UART_IrDA_DISABLE &
                            UART_DIS_LOOPBACK &     // ループバックさせない
                            UART_NO_PAR_8BIT &      // パリティなし8bit
                            UART_1STOPBIT &         // ストップビット1
                            UART_MODE_SIMPLEX  &    // フローコントロール無し
                            UART_UEN_00 &
                            UART_UXRX_IDLE_ONE &    // U1RXのアイドルを1にする
                            UART_BRGH_SIXTEEN &     // 高速転送を無効
                            UART_DIS_ABAUD;         // ボーレートの自動検出を無効
 
    unsigned int config2 =  UART_INT_TX_BUF_EMPTY &  // TXDバッファが空のとき割り込みを発生
                            UART_IrDA_POL_INV_ZERO & // U1TXアイドルを0とする
                            UART_TX_ENABLE &         // TXDを有効(同時にRXDも有効になる
                            UART_INT_RX_CHAR &       // RXD受信時に割り込みを発生
                            UART_ADR_DETECT_DIS & 
                            UART_RX_OVERRUN_CLEAR;  
 
    OpenUART1(config1, config2, UART_CLK8MHZ_9600BPS );
 
    ConfigIntUART1( UART_RX_INT_DIS & UART_TX_INT_DIS ); 
 
 
 
    //-----------------------------
    // シリアル送受信の無限ループ
    // 一定周期で文字を送信します
    //-----------------------------
    while(1) {
        volatile unsigned int recvText;
        volatile long int loop;
 
        //-------------------------
        // 定期的に文字を送信する
        //-------------------------
 
        // 1byte書き込み
        U1TXREG = 'a';
 
        //バッファが空になるまで待つ(TRMT:bit8)
        while ( U1STAbits.TRMT == 0 ) {
            waitCount++;
        }
 
        // ちょっと待つ     
        for ( loop = 0; loop < 10000; loop++) { 
            /* nop */;
        }
    } 
 
    return 0;
}



今回、Microchip PIC24FのPeripheral Libraryを使用してみました。


RPピンの役割マッピング設定の…

    iPPSOutput( OUT_PIN_PPS_RP5, OUT_FN_PPS_U1TX ); // RP5を UART1のTXDとして使用



は、以下のコードと等価です。

    RPOR2bits.RP5R = 3;






また、OpenUART1()は、以下のコードと同じです。

    // I/Oレジスタを直接指定する場合
    U1MODEbits.UARTEN = 1;
    U1MODEbits.USIDL  = 0;
    U1MODEbits.IREN   = 0;
    U1MODEbits.RTSMD  = 1;
    U1MODEbits.UEN    = 0;
    U1MODEbits.WAKE   = 0;
    U1MODEbits.LPBACK = 0;
    U1MODEbits.ABAUD  = 0;
    U1MODEbits.RXINV  = 0;
    U1MODEbits.BRGH   = 0;  
    U1MODEbits.PDSEL  = 0;
    U1MODEbits.STSEL  = 0;
 
    U1STAbits.UTXISEL1 = 0;
    U1STAbits.UTXINV  = 0;
    U1STAbits.UTXBRK  = 0;
    U1STAbits.UTXEN   = 1;
    U1STAbits.URXISEL = 0;
    U1STAbits.ADDEN   = 0;
 
    U1BRG = UART_CLK8MHZ_9600BPS;





実際の文字送信ループは、以下のコードに変更すると渡された文字のエコーバックが行えます

    while(1) {
        //---------------------------------------
        // 受信エラーが発生していないかチェック     
        //---------------------------------------
        if ( U1STAbits.PERR == 1 || U1STAbits.FERR == 1 || U1STAbits.OERR == 1 ) {
            errCount++;
        }
 
        //-----------------------------         
        // バッファから文字を受信する
        //-----------------------------         
        if ( U1STAbits.URXDA == 1 ) {
            recvText = U1RXREG;
            recvCount++;
 
            //-----------------------------         
            // エコーバックする         
            //-----------------------------         
            U1TXREG = recvText;
 
            //バッファが空になるまで待つ
            while ( U1STAbits.TRMT == 0 ) {
                waitCount++;
            }   
        }
    }



送受信処理は、byte単位での送信に加えて、文字列単位のgetsUART1()/putsUART1() も使用できるようです。

getsUART1(
    unsigned int length, 
    unsigned int * buffer, 
    unsigned int uart_data_wait
);
 
putsUART1(
    unsigned int * buffer
);



関連記事

One Response to “[PIC24]UART機能を使用してRS-232C通信を行う”

  1. トンちゃん より:

    getsUART1()/putsUART1() は、PIC24Fも使っているので、とても参考になりました。ありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。