概要
UARTとは
dsPIC33CHシリーズにはUARTモジュールがマスターコアに2ch、スレーブコアに1ch搭載されています。これらのモジュールを使えばパソコンや外部機器、LIN通信や赤外線通信等の通信が行えます。
名前はメーカや種類によって異なりますが、恐らく現状発売されているマイコンの全てに搭載されているのでは無いかと推測されるくらい一般的な機能です。
UARTとは「Universal Asynchronous Receiver/Transmitter」の頭文字をとった用語で、汎用非同期式送受信機の事です。
以下にUartの基本フレームを示します。Idle状態(通常High)から「StartBit(Low)」「DataBit(8 or 9Bit)」「パリティビット(無し or 1ビット)」「ストップビット(High , 1 or 2bit)」といった順番に創出します。またこの1ビットの時間がボーレートです。

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

ペリフェラル構造
UARTモジュールの簡易ブロック図は以下のとおりです。
また以下のプロトコルに 対応してます。
- 非同期送受信 7bit/8bit/9bit , アドレス検知 無し/有り
- DMX
- Lin (Master/Slave)
- SmartCard

ハードウェア構成と制御ブロック
UARTモジュールから66、67番ピンを介し絶縁IC(SI8422AB-D-IS)、UART-USB I/F(MCP2221A)、USBコネクタ(J16)を経由しPCと接続します。

レジスタ
UART関連のレジスタは以下の15種類です。
| レジスタ名 | 機能 | 説明 |
| UxMODE | UARTx CONFIGURATION Register | UARTの共通設定レジスタ |
| UxMODEH | UARTx CONFIGURATION Register High | UARTの共通設定レジスタ High |
| UxSTA | UARTx STATUS Register | UARTのステータスレジスタ |
| UxSTAH | UARTx STATUS Register High | UARTのステータスレジスタ High |
| UxBRG | UARTx BAUD RATE Register | UARTの通信速度設定レジスタ |
| UxBRGH | UARTx BAUD RATE High Register | UARTの通信速度設定レジスタ High |
| UxRXREG | UARTx Receive Buffer Register | UART受信バッファレジスタ |
| UxTXREG | UARTx Transmit Buffer Register | UART送信バッファレジスタ |
| UxP1 | UARTx Timming Parameter1 Register | UARTタイミングパラメータ1 |
| UxP2 | UARTx Timming Parameter2 Register | UARTタイミングパラメータ2 |
| UxP3 | UARTx Timming Parameter3 Register | UARTタイミングパラメータ3 |
| UxTXCHK | UARTx Transmit Checksum Register | UART送信チェックサムレジスタ |
| UxRXCHK | UARTx Receive Checksum Register | UART受信チェックサムレジスタ |
| UxSCCON | UARTx Smart Card Configuration Register | UARTスマートカード設定レジスタ |
| UxSCINT | UARTx Smart Card Interrupt Register | 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の値が返って来る事が確認できます。



コメント