16F1619には、シリアル通信を行うためのEUSART(Enhanced Universal Synchronous Asynchronous Receiver Transmitter )が組み込まれています。EUSARTには、同期および非同期のシリアル送受信を行う機能がありますが、このページでは、非同期の送信にかかわる機能だけの説明です。
非同期モードでは、標準の非ゼロ復帰(NRZ)形式を使用してデータを送受信します。データは2つのレベルで表し、「1」を VOHマーク状態といい、「0」は、VOLスペース状態です。NRZは、同じ値の連続して送信されたデータビットが、各ビット送信間でニュートラルレベルに戻ることなく、そのビットの出力レベルに留まることを指します。NRZ送信のアイドルはマーク状態で、各文字送信は、1つのスタートビットとそれに続く8または9つのデータビットで構成され、EUSARTはLSbから送受信します。1つ以上のストップビットで終了します。スタートビットはスペースで、ストップビットはマークで、最も一般的なデータ形式はパリティなしの8ビット長です。オンチップの専用8ビット/ 16ビットボーレートジェネレータを使用して、システムオシレータから標準ボーレートクロックを作りさします。EUSARTのトランスミッターとレシーバーは機能的に独立していますが、同じデータ形式とボーレートを共有しています。
重要;
RXおよびCK入力ピンは、それぞれRXPPSおよびCKPPSレジスタで選択します。TX/CK、および DT出力ピンは、各ピンのRxyPPSレジスタで選択します。同期モードではRX入力がDT出力と結合されるため、同期モードで動作させる場合、ユーザーの責任で、これら両方に同じピンを選択する必要があります。なおEUSART制御ロジックは、データ方向ドライバーを自動的に制御します。
非同期の送信は、TXIFの内容を読み込みTX1REG(送信バッファ)の準備ができたこと(TXIF = 1)を確認し、送信データをTX1REGに書き込みます。Tx Shift Registor(TSR)の内容が送り出されるとTX1REGの内容が、TSRに移され、TXIFが1になります。このとき送信インタラプト(TXIE =1)が許可されているとインタラプトが発生します。非同期の送信に必要なシフトクロックは、システムクロックをBaud Rate Genaratorで分周して発生させます。非同期の送信に関連するレジスター一覧を下表に示します。
EUSART送信機のブロック図を示します。トランスミッタの中心は、ソフトウェアから直接アクセスできないシリアル送信シフトレジスタ(TSR)です。TSRは、TXxREGレジスタである送信バッファからデータを取得します。
注(1);同期モードでは、DT出力とRX入力のPPS選択で同じピンを指定します。
EUSARTトランスミッターは、次の3つの制御ビットを構成することにより、非同期動作が可能になります。他のすべてのEUSART制御ビットは、デフォルト状態にあると仮定します。
注:TXENイネーブルビットが設定されると、TXIF送信機割り込みフラグが設定されます。
TXxREGレジスタに文字を書き込むと送信が開始されます。これが最初の文字である場合や、前の文字がTSRから完全に送信されていた場合、TXxREGのデータはすぐにTSRレジスタに転送されます。TSRに前の文字のすべてまたは一部がまだ残ってるいる場合、新しい文字データは、前の文字のストップビットが送信されるまでTXxREGに保持されます。TXxREGの保留中の文字は、ストップビット送信の直後の 1 Tcy後にTSRに転送され、その直後にスタートビット、データビット、ストップビットシーケンスが開始されます。
送信データの極性は、BAUDxCONレジスタのSCKPビットで制御できます。このビットのデフォルト状態は「0」で、正論理の送信アイドルおよびデータビットを出力します。SCKPビットを「1」に設定すると、送信データが反転し、負論理のアイドルとデータビットに設定されます。
PUS1レジスタのTXIF割り込みフラグビットは、EUSARTトランスミッタが有効で、TXxREGに送信する文字がロードされていない場合は常にセットされます。つまり、TXIFビットは、TSRが文字でビジー状態で、TXxREGに送信待ちの新しい文字がある場合にのみクリアされます。TXxREGに書き込んでも、TXIFフラグビットはすぐにはクリアされません。TXIFは、書き込み実行から2命令サイクル後でないと有効になりません。TXxREG書き込みの直後にTXIFをポーリングすると、無効な値が返されます。TXIFビットは読み取り専用で、ソフトウェアでセットやクリアすることはできません。
TXIE割り込みを有効にするには、PIE1レジスタのTXIE割り込み有効化ビットをセットします。ただし、TXIEイネーブルビットの状態に関係なく、TXxREGが空の場合は常にTXIFフラグビットがセットされます。
データ送信時に割り込みを使用するには、送信するデータがまだある場合にのみTXIEビットをセットします。送信の最後の文字をTXxREGに書き込んだら、TXIE割り込み有効ビットをクリアします。
TXxSTAレジスタのTRMTビットは、TSRレジスタのステータスを示します。これは読み取り専用ビットです。TRMTビットは、TSRレジスタが空のときにセットされ、TXxREGからTSRレジスタに文字が転送されるとクリアされます。すべてのビットがTSRレジスタからシフトアウトされるまで、TRMTビットはクリアされたままです。このビットには割り込みロジックが関連付けられていないため、ユーザーはこのビットをポーリングしてTSRステータスを判別する必要があります。
注意;
TSRレジスタはデータメモリにマップされていないため、ユーザーは使用できません。
非同期モードは通常、RS-232システムで使用されます。レシーバのブロック図を図25-2に示します。データは RX/DTピンで受信され、データ回復ブロックを駆動します。データ回復ブロックは、実際にはボーレートの16倍で動作する高速シフターですが、シリアル受信シフトレジスタ(RSR)はビットレートで動作します。文字の8ビットまたは9ビットすべてがシフトインされると、それらはすぐに2文字の先入れ先出し(FIFO)メモリに転送されます。FIFOバッファリングにより、ソフトウェアがEUSART受信機のサービスを開始する前に、2つの完全な文字の受信と3番目の文字の開始が可能になります。FIFOおよびRSRレジスタは、ソフトウェアから直接アクセスできません。受信データへのアクセスは、RCxREGレジスタを介して行われます。
注(1);同期モードでは、RX入力とDT出力のPPS選択で同じピンを指定します。
EUSARTレシーバーは、以下の3つの制御ビットを構成することにより、非同期動作が可能になります。
他のすべてのEUSART制御ビットは、デフォルト状態にあると仮定しています。
注意;
RX/DT I/Oピンの対応するTRISビットをセットし、入力に設定する必要があります。
アナログ併用ピンの場合、対応するANSELビットをクリアし、デジタル入力にする必要があります。
レシーバのデータ回復回路は、最初のビットの立ち下がりエッジで文字の受信を開始します。開始ビットとも呼ばれる最初のビットは常にゼロです。データ回復回路は、スタートビットの中央までの半分のビット時間をカウントし、ビットがまだゼロであることを確認します。ゼロでない場合、データ回復回路はエラーを生成せずに文字の受信を中止し、スタートビットの立ち下がりエッジの検索を再開します。スタートビットゼロ検証が成功した場合、データ回復回路は次のビットの中央までのフルビット時間をカウントします。次に、ビットは多数決検出回路によってサンプリングされ、結果の「0」または「1」がRSRにシフトされます。これは、すべてのデータビットがサンプリングされ、RSRにシフトされるまで繰り返されます。最後の1ビット時間を測定し、レベルをサンプリングします。これはストップビットです。これは常に「1」です。データ回復回路がストップビット位置で「0」をサンプリングした場合、この文字にフレーミングエラーが設定されます。それ以外の場合、この文字のフレーミングエラーはクリアされます。フレーミングエラーの詳細は、セクション25.1.2.4「受信フレーミングエラー」を参照してください。
すべてのデータビットとストップビットを受信した直後に、RSR内の文字がEUSART受信FIFOに転送され、PIR1レジスタのRCIF割り込みフラグビットが設定されます。FIFOの先頭文字は、RCxREGレジスタを読み取ることによってFIFOから転送されます。
注意;
受信FIFOがオーバーランしている場合、オーバーラン状態が解消されるまで、追加の文字は受信されません。オーバーランエラーの詳細はセクション25.1.2.5「オーバーランエラーの受信」を参照してください。
PUS1レジスタのRCIF割り込みフラグビットは、EUSART受信機が有効になっていて、受信FIFOに未読文字がある場合は常に設定されます。RCIF割り込みフラグビットは読み取り専用で、ソフトウェアでセットまたはクリアできません。RCIF割り込みは、次のビットをすべて設定することで有効になります。
受信FIFOバッファの各文字には、対応するフレーミングエラーステータスビットがあります。フレーミングエラーは、ストップビットが予期された時間に表示されなかったことを示します。フレーミングエラーステータスは、RCxSTAレジスタのFERRビットを介してアクセスされます。FERRビットは、受信FIFOの先頭の未読文字のステータスを表します。したがって、RCxREGを読み取る前にFERRビットを読み取る必要があります。
FERRビットは読み取り専用であり、受信FIFOの先頭の未読文字にのみ適用されます。フレーミングエラー(FERR = 1)は、追加の文字の受信を妨げません。FERRビットをクリアする必要はありません。FIFOバッファから次の文字を読み取ると、FIFOが次の文字と対応する次のフレーミングエラーに進みます。
EUSARTをリセットするRCxSTAレジスタのSPENビットをクリアすると、FERRビットを強制的にクリアできます。RCxSTAレジスタのCRENビットをクリアしても、FERRビットには影響しません。フレーミングエラー自体は割り込みを生成しません。
受信FIFOバッファは2つの文字を保持できます。FIFOにアクセスする前に3番目の文字全体を受信すると、オーバーランエラーが生成されます。これが発生すると、RCxSTAレジスタのOERRビットがセットされます。FIFOバッファに既にある文字を読み取ることはできますが、エラーが解消されるまで追加の文字は受信されません。エラーは、RCxSTAレジスタのCRENビットをクリアするか、RCxSTAレジスタのSPENビットをクリアしてEUSARTをリセットすることによってクリアする必要があります。
ボーレートジェネレーター(BRG)は、非同期と同期の両方のEUSART動作サポート専用の8ビットまたは16ビットのタイマーです。デフォルトでは、BRGは8ビットモードで動作します。BAUDxCONレジスタのBRG16ビットを設定すると、16ビットモードが選択されます。
| Configuration Bits | Baud Rate Formula | ||
|---|---|---|---|
| SYNC | BRG16 | BRGH | |
| 0 | 0 | 0 | FOSC/[64 (n+1)] |
| 0 | 0 | 1 | FOSC/[16 (n+1)] |
| 0 | 1 | 0 | |
| 0 | 1 | 1 | FOSC/[4 (n+1)] |
SPxBRGH、SPxBRGLレジスタペアは、ボーレートタイマーの周期を決定します。非同期モードでは、ボーレート周期の乗数は、TXxSTAレジスタのBRGHビットとBAUDxCONレジスタのBRG16ビットの両方によって決定されます。
右表に、ボーレートを決定する式を示します。
( n = SPxBRGH, SPxBRGLペアの値)
また、代表的なボーレートとボーレートエラーも示します。
| ボーレート | SYNC = 0, BRGH = 1, BRG16 = 1 | |||||||
|---|---|---|---|---|---|---|---|---|
| 1M | 4M | 8M | 32M | |||||
| SP1BRG | % Error | SP1BRG | % Error | SP1BRG | % Error | SP1BRG | % Error | |
| 2400 | 103 | 0.16 | 416 | 0.08 | 832 | 0.04 | 3332 | 0.01 |
| 9600 | 25 | 0.16 | 103 | 0.16 | 207 | 0.16 | 832 | 0.04 |
| 19.2K | 12 | 0.16 | 51 | 0.16 | 103 | 0.16 | 416 | -0.08 |
| 115.2K | - | - | 8 | -3.55 | 16 | 2.12 | 68 | -0.64 |
| レジスタ | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
|---|---|---|---|---|---|---|---|---|
| INTCON | GIE | PEIE | - | - | - | - | - | INTEDG |
| PIE1 | TMR1GIE | ADIE | RCIE | TXIE | SSP1IE | BCL1IE | TMR2IE | TMR1IE |
| PIR1 | TMR1GIF | ADIF | RCIF | TXIF | SSP1IF | BCL1IF | TMR2IF | TMR1IF |
| RC1STA | SPEN | RX9 | SREN | CREN | ADDEN | FERR | OERR | RX9D |
| TX1STA | CSRC | TX9 | TXEN | SYNC | SENDB | BRGH | TRMT | TX9D |
| RC1REG | EUSART Receive Data Register | |||||||
| TX1REG | EUSART Transmit Data Register | |||||||
| BAUD1CON | ABDOVF | RCIDL | SCKP | BRG16 | WUE | ABDEN | ||
| SP1BRGH | Baud Rate Generator<15:8> | |||||||
| SP1BRGL | Baud Rate Generator< 7:0> | |||||||
| レジスタ | BIT | 名 | 内容 | 1 | 0 |
|---|---|---|---|---|---|
| INTCON | 7 | GIE | 全インタラプトの使用許可 | 許可 | 否 |
| 6 | PEIE | 周辺機能インタラプトの使用許可 | 許可 | 否 | |
| PIE1 | 5 | RCIE | シリアル送信のインタラプト許可 | 許可 | 否 |
| PIE1 | 4 | TXIE | シリアル送信のインタラプト許可 | 許可 | 否 |
| PIR1 | 5 | RCIF | シリアル送信バッファフラグ | 空 | 使用中 |
| PIR1 | 4 | TXIF | シリアル送信バッファフラグ | 空 | 使用中 |
| RC1STA | 7 | SPEN | 入出力ピンのシリアル設定 | ON | OFF |
| 6 | RX9 | 9 ビット受信 | 9 bit | 8 bit | |
| 5 | SREN | シングル受信 (同期モードのみ) | ON | OFF | |
| 4 | CREN | 連続受信 | ON | OFF | |
| 3 | ADDEN | アドレス検出 (RX9 = 0では使用しない | ON | OFF | |
| 2 | FERR | フレーミング エラー (Read Only) | あり | なし | |
| 1 | OERR | オーバーランエラー (Read Only) | あり | なし | |
| 0 | RX9D | 受信データの9 ビット目 (Read Only) | 1 | 0 | |
| TX1STA | 7 | CSRC | Clock Source Select (同期モードのみ) | - | - |
| 6 | TX9 | 9 ビット送信 | 9 bit | 8 bit | |
| 5 | TXEN | 送信許可 | 許可 | 否 | |
| 4 | SYNC | 同期モード | 同期 | 非同期 | |
| 3 | SENDB | Break文字を送信 | 送信 | 完了 | |
| 2 | BRGH | High Baud Rate選択 | High | Low | |
| 1 | TRMT | TSRステイタス(Read Only) | 空 | 使用中 | |
| 0 | TX9D | 9 ビット目送信データ | 1 | 0 | |
| BAUD1CON | 4 | SCKP | 送信極性 | 反転出力 | 正論理 |
| 3 | BRG16 | Baud Rate Generatorのビット長 | 16bit | 8bit |
非同期8ビットシリアル、パリティーなし、9600bpsで送受信するプログラムを作成しました。
<回路図>
送信部 --------------------------------------
RC4に接続されたPushSWを押すと「SW ON」を送信します。
受信部 --------------------------------------
受信したASCII文字データにより、指定されたLEDを点滅します。
Curiosityデモボードでプログラムの確認をしています。
<プログラム>
/*********************************************************************
* File name: EUSATR TxRx 9800
* Notes: 4MHz内部クロック PLLはOFF
* LED4 RA5 LED6 RA2
* LED5 RA1 LED7 RC5
* pushSW RC4
* Rx RB5 Tx RB7
* PIC16F1619 MPLAB X IDE with XC8
* Copyright (c) 2020 iwamoto All Rights Reserved
* *******************************************************************/
#include <xc.h>
#define _XTAL_FREQ 4000000
#define LED4 LATA5
#define LED5 LATA1
#define LED6 LATA2
#define LED7 LATC5
#define pushSW RC4
// CONFIG
#pragma config FOSC = INTOSC, PWRTE = OFF, MCLRE = ON, CP = OFF
#pragma config BOREN = ON, CLKOUTEN = OFF, IESO = ON, FCMEN = ON
#pragma config WRT = OFF, PPS1WAY = ON, ZCD = OFF, PLLEN = OFF
#pragma config STVREN = ON, BORV = LO, LPBOR = OFF, LVP = ON
#pragma config WDTCPS = WDTCPS1F, WDTE = OFF, WDTCWS = WDTCWSSW, WDTCCS = SWC
void strOutUSART(char *);
void outCRLFT();
/********************** Main ***************/
void main(void)
{
char SWstate = 0; // SWの状態
char RxData;
OSCCON = 0b01101000; // PLL disabled; 4MHz_HF; FOSC;
TRISC5 = 0; // Outputs RC5
TRISA = 0b011001; // Outputs RA5.2,1
RB7PPS = 0b10010; // TX/CK Outputs RB7
LATA = 0; LATC = 0; // LEDを消灯
ANSB5 = 0; // RB5をデジタル入力とする
RB7PPS = 0b10010; // TX/CK Outputs RB7
// RXPPS = 0b01101; // RB5をRX入力とする デフォルトで設定
// ----------- UART 初期化 -----------
RC1STA = 0b10010000; // 8 bit 連続受信
TX1STA = 0b00100100; // 非同期送受信 High Baud Rate選択
BAUD1CON = 0b00001000; // 16 bit SPBRG
SP1BRG = 103;
while(pushSW); // RC0が押されるのを待つ
strOutUSART("Hello OK>"); // 開始のメッセージ
outCRLFT();
// ----------- 繰返し --------------------------------------------
while(1){
// ------ 受信 ------------------------------------------------
if(RCIF){
RxData = RC1REG; // 受信データを取り込む
switch(RxData){ // データ内容で、On/Off
case '0': LATA = 0; LATC = 0; break;
case '4': LED4 = 1; break;
case '5': LED5 = 1; break;
case '6': LED6 = 1; break;
case '7': LED7 = 1; break;
default: break;
}
}
// ------ 送信 ------------------------------------------------
if(pushSW != SWstate){ // SWの状態が変化したら
__delay_ms(10); // 10mS遅延
SWstate = pushSW; // 新しい状態を記録
if(pushSW == 0){ // SWが押されたのなら
strOutUSART("SW ON"); // メッセージを送る
outCRLFT(); // 改行
}
}
}
}
//-------- 文字列出力
void strOutUSART(char *str){
while(*str){ //文字列の終わり(00)まで継続
while (!PIR1bits.TXIF); //送信終了待ち
TXREG = *str++; //文字出力しポインタ+1
}
}
void outCRLFT(){
while (!PIR1bits.TXIF); //送信終了待ち
TXREG = 0x0D; //文字出力
while (!PIR1bits.TXIF); //送信終了待ち
TXREG = 0x0A; //文字出力
}