UARTモジュールの使い方

UARTモジュールの使い方

概要

UARTとは

dsPIC33CHシリーズにはUARTモジュールがマスターコアに2ch、スレーブコアに1ch搭載されています。これらのモジュールを使えばパソコンや外部機器、LIN通信や赤外線通信等の通信が行えます。

名前はメーカや種類によって異なりますが、恐らく現状発売されているマイコンの全てに搭載されているのでは無いかと推測されるくらい一般的な機能です。

UARTとは

UARTとは「Universal Asynchronous Receiver/Transmitter」の頭文字をとった用語で、汎用非同期式送受信機の事です。

以下にUartの基本フレームを示します。Idle状態(通常High)から「StartBit(Low)」「DataBit(8 or 9Bit)」「パリティビット(無し or 1ビット)」「ストップビット(High , 1 or 2bit)」といった順番に創出します。またこの1ビットの時間がボーレートです。

(fig.1)Uartフレーム

開発ボード

dsPIC33CH Curiosity Development Boardには(fig.2)の青丸で囲んだ場所にUart-USBインターフェースが搭載されています。ここにUSBケーブルを接続しPCと通信を行います。

(fig.2)UART-USB変換インターフェースの実装位置

ペリフェラル構造

UARTモジュールの簡易ブロック図は以下のとおりです。

また以下のプロトコルに 対応してます。

  • 非同期送受信 7bit/8bit/9bit , アドレス検知 無し/有り
  • DMX
  • Lin (Master/Slave)
  • SmartCard
(fig.3)Uartモジュールブロック図 DS70005371D-page 576より抜粋

ハードウェア構成と制御ブロック

UARTモジュールから66、67番ピンを介し絶縁IC(SI8422AB-D-IS)、UART-USB I/F(MCP2221A)、USBコネクタ(J16)を経由しPCと接続します。

(fig.4)全体ブロック図

レジスタ

UART関連のレジスタは以下の15種類です。

レジスタ名機能説明
UxMODEUARTx CONFIGURATION
Register
UARTの共通設定レジスタ
UxMODEHUARTx CONFIGURATION
Register High
UARTの共通設定レジスタ High
UxSTAUARTx STATUS
Register
UARTのステータスレジスタ
UxSTAHUARTx STATUS
Register High
UARTのステータスレジスタ High
UxBRGUARTx BAUD RATE
Register
UARTの通信速度設定レジスタ
UxBRGHUARTx BAUD RATE
High Register
UARTの通信速度設定レジスタ High
UxRXREGUARTx Receive Buffer
Register
UART受信バッファレジスタ
UxTXREGUARTx Transmit Buffer
Register
UART送信バッファレジスタ
UxP1UARTx Timming
Parameter1 Register
UARTタイミングパラメータ1
UxP2UARTx Timming
Parameter2 Register
UARTタイミングパラメータ2
UxP3UARTx Timming
Parameter3 Register
UARTタイミングパラメータ3
UxTXCHKUARTx Transmit
Checksum Register
UART送信チェックサムレジスタ
UxRXCHK UARTx Receive
Checksum Register
UART受信チェックサムレジスタ
UxSCCONUARTx Smart Card
Configuration Register
UARTスマートカード設定レジスタ
UxSCINTUARTx Smart Card
Interrupt Register
UARTスマートカード割り込みレジスタ
(fig.5)UART関連レジスタ

ソースコード

パソコンからシリアル経由で’G’の文字を受信した場合に、ポテンションの値を返信するソフトウェア例です。

コンフィグレーション設定について

コンフィグレーション設定についてはコンフィグレーション設定に記載しております。

コピーして下記のソースコードの「 //ここにコンフィグレーション設定を挿入する// 」の位置に挿入してください。

クロック設定について

クロック設定用関数 vds_Main_Init_Clock_Register(); のソースコードはクロック設定のページに記載しております。

コピーして下記のソースコードの「 //ここにクロック設定ソースをコピペする// 」の位置に挿入してください。

/*------------------------------------------------------------------------------*/
/* @file      PC_UART1.c */
/* @brief     PCとのデータ通信 */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* コンフィグレーション設定*/
/*------------------------------------------------------------------------------*/
//ここにコンフィグレーション設定を挿入する//
/*------------------------------------------------------------------------------*/
/* インクルードファイル*/
/*------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
/*------------------------------------------------------------------------------*/
/* 定数定義*/
/*------------------------------------------------------------------------------*/
#define UART1_BAUDRATE       115200     /* 115kbps */
#define UART1_TX_BUF_SIZE    16
/*------------------------------------------------------------------------------*/
/*変数定義*/
/*------------------------------------------------------------------------------*/
struct
    {
        unsigned int u2_Sum;
        unsigned int u2_Head;
        unsigned int u2_Ave;
        unsigned int u2_Buffer[8];
    }Pot;
/*------------------------------------------------------------------------------*/
/* クロック設定 */
/*------------------------------------------------------------------------------*/
//ここにクロック設定ソースを挿入する//
/*------------------------------------------------------------------------------*/
/* Main関数 */
/*------------------------------------------------------------------------------*/
int main(int argc, char** argv) 
{
   unsigned int u2_SamplingTime;
    unsigned long u4l_Temp;
    char c1l_Buff[UART1_TX_BUF_SIZE];
    char c1l_Loop;
    /*-------------------------------------------------------------------------*/
    /* クロック初期化*/
    /*-------------------------------------------------------------------------*/
        vds_Main_Init_Clock_Register();     /* クロック初期化 */
    /*-------------------------------------------------------------------------*/
    /* GPIO初期化*/
    /*-------------------------------------------------------------------------*/
        TRISEbits.TRISE0 = 0u;         /* LED1 */
        ANSELAbits.ANSELA0 = 1u;       /* RA0ピンはアナログピン(ポテンション入力)*/
        RPINR18bits.U1RXR = 58u;       /* U1RX入力ピン選択ビット */
        RPOR13bits.RP59R = 1u;	   /* RP59ピン出力機能選択ビット */
    /*-------------------------------------------------------------------------*/
    /* UART初期化*/
    /*-------------------------------------------------------------------------*/
    /*-------------------------------------------------------------------------*/
    /* UART1レジスタ */	
    /*-------------------------------------------------------------------------*/
        U1MODE	= 0x0000u;
            U1MODEbits.BRGH = 1u;   /* 高 baudレート選択ビット */
            U1MODEbits.UTXEN = 1u;  /* 送信イネーブルビット */
            U1MODEbits.URXEN = 1u;  /* 受信イネーブルビット */
            U1MODEbits.MOD = 0u;    /* UARTモードビット */
        
        U1MODEH	= 0x0000u;
        U1STA = 0x0000u;        
        U1STAH = 0x0000u;
    /*-------------------------------------------------------------------------*/ 
    /* UARTxボーレートレジスタ  */	
    /*-------------------------------------------------------------------------*/  
        u4l_Temp = (_u4)(FP / (UART1_BAUDRATE * 4u)) - 1;
        U1BRGH = (u4l_Temp >> 16u) & 0xFFFFu;
        U1BRG = u4l_Temp - (_u4)U1BRGH * 65536L;
 
        U1RXREG	= 0x0000u;	
        U1TXREG	= 0x0000u;

    /*-------------------------------------------------------------------------*/
    /* AD初期化*/
    /*-------------------------------------------------------------------------*/
        ADCON1L = 0x0000u;
        ADCON1H = 0x0000u;
        ADCON2L = 0x0000u;
        ADCON2H = 0x0000u;
        ADCON3L = 0x0000u;
        ADCON3H = 0x0000u;
        ADCON5H = 0x0000u;
        
        /***** AD制御レジスタの設定 ******/
        ADCON1Hbits.SHRRES = 3u;        /* シェアADC分解能 (3 = 12bit) */
        ADCON2Lbits.SHRADCS = 2u;       /* シェアADCクロックディバイダ  */
        ADCON2Hbits.SHRSAMC = 4u;       /* シェアADCサンプル時間 (3 = 4TAD) */
        ADCON3Lbits.CNVCHSEL = 0u;      /* ソフトウェアAD入力(0 =AN0入力)*/
        ADCON3Hbits.CLKSEL = 2u;        /* ADCクロックソース (2 = AFVCODIV) */
        ADCON3Hbits.CLKDIV = 2u;        /* ADCクロックディバイダ(2 = 3Clock)*/
        ADCON5Hbits.WARMTIME = 15u;     /* ウォームアップ時間(15 = 32768Clock) */
        
        /***** ADの有効化 ******/
        ADCON1Lbits.ADON = 1u;              /* ADC全体のパワーON */
        ADCON5Lbits.SHRPWR = 1u;            /* シェアADCのパワーON */
        while(ADCON5Lbits.SHRRDY == 0u){;}
        ADCON3Hbits.SHREN = 1u;             /* シェアADCの有効化 */
        ADCON3Lbits.CNVCHSEL = 0u;
        
        U1MODEbits.UARTEN = 1u;             /*Uart1を有効にする */
    /*-------------------------------------------------------------------------*/
    /* メインルーチン*/
    /*-------------------------------------------------------------------------*/
        while(1)
        {
            /*-----------------------------------------------------------------*/
            /* サンプリング*/
            /*-----------------------------------------------------------------*/
                u2_SamplingTime = 30u;
                while (ADCON3Lbits.CNVRTCH == 1u){;}
                ADCON3Lbits.SHRSAMP = 1u;
                while(u2_SamplingTime > 0){u2_SamplingTime --;}
                ADCON3Lbits.SHRSAMP = 0u;
            /*-----------------------------------------------------------------*/
            /* AD変換*/
            /*-----------------------------------------------------------------*/
                ADCON3Lbits.CNVRTCH = 1u;
                u2_SamplingTime = 10;
                while(u2_SamplingTime > 0){u2_SamplingTime --;}
            /*-----------------------------------------------------------------*/
            /* 移動平均*/
            /*-----------------------------------------------------------------*/
                if ((ADSTATL & 0x0001u) == 0x0001u)
                {
                    Pot.u2_Sum -= Pot.u2_Buffer[Pot.u2_Head];
                    Pot.u2_Buffer[Pot.u2_Head] = ADCBUF0;
                    Pot.u2_Sum += Pot.u2_Buffer[Pot.u2_Head];
                    Pot.u2_Head ++;
                    Pot.u2_Head &= 0x07;
                    Pot.u2_Ave = Pot.u2_Sum >> 3u;
                }
            /*-----------------------------------------------------------------*/
            /* PCから"G"の文字を受信したらポテンションの値を返す*/
            /*-----------------------------------------------------------------*/
            if (U1STAHbits.URXBE == 0u)
            {
                
                if (U1RXREG =='G')
                {
                    /****** バッファに文字列を格納 *****/
                    	sprintf(c1l_Buff,"AD =%5d\r\n",Pot.u2_Ave);
                    /****** カウンタクリア *****/
                    	c1l_Loop = 0u;
                    /****** バッファがNullになるまで送信 *****/
                    while (1)
                    {
                        /*** NULLかバッファサイズオーバー時にはwhileを抜ける **/
                        if ((c1l_Buff[c1l_Loop] == 0u)||
                                (c1l_Loop >= UART1_TX_BUF_SIZE)) {break;}		   			     
                        /****** 送信バッファがフルの時には待機 *****/
                        	while(U1STAHbits.UTXBF == 1u){;}        
                        /****** 1Byteずつ送信する *****/
                        	U1TXREG = c1l_Buff[c1l_Loop++];
                    }
                }
            }
        }
}

結果

今回はPCにSerial Debbugerという通信ソフトをダウンロードし動作確認を行いました。

PCからdsPICに’G’という文字を送るとADの値が返って来る事が確認できます。

参考文献

コメント

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