16F18325には、シリアル通信を行うためのEUSART(Enhanced Universal Synchronous Asynchronous Receiver Transmitter )が組み込まれています。EUSARTには、同期および非同期のシリアル送受信を行う機能がありますが、
このページでは、
を示します。
*注意*
TX/CKをどのピンにするかは、PPS機能の希望するピンのRxyPPSレジスターに、”TX/CK"を表す"20"を書き込み指示します。また、指示したピンの TRISは「1」入力、ANSELは「0」デジタルにする必要があります。
*注意*
RX/DTピンは、RC5に設定されていますが、PPS機能を利用し他に変更することが可能です。また、RXピンの TRISは「1」入力、ANSELは「0」デジタルにする必要があります。
<回路図>
RA5に接続されたPushSWを押すと「Hello OK>」を送信、 その後、押すたびに 10 11 12・・・と9600ボーのシリアル送信をするプログラムです。
<プログラム>
/*************************************
* File: UART TX sample
* System ClockはConfigで内部1MHzに設定
* UARTでデータを送信する。
* SWを押すと開始メッセージ。その後 SWを押すたびに、カウントUP
* PIC16F18325
* Created on Aug 22, 2017, 2:37 PM
**************************************/
#include <xc.h>
#include <stdio.h>
#define _XTAL_FREQ 1000000 // delay_ms(x) のための定義
#pragma config FEXTOSC = OFF,RSTOSC = HFINT1 // HFINTOSC (1MHz)
#pragma config CLKOUTEN = OFF,CSWEN = OFF,FCMEN = OFF
#pragma config MCLRE = OFF,PWRTE = OFF,WDTE = OFF,LPBOREN = OFF
#pragma config BOREN = OFF,BORV = LOW,PPS1WAY = OFF,STVREN = ON
#pragma config DEBUG = OFF
#pragma config WRT = OFF,LVP = OFF,CP = OFF,CPD = OFF
#define pushSW PORTAbits.RA5
// ================= printf関数を使用するための定義 =================
void putch(unsigned char ch) {
while (!TXIF); //送信終了待ち
TX1REG = ch;
}
// ******************* main *************************************
void main() {
char num = 10;
TRISA = 0b111111; // Port すべて入力
TRISC = 0b111111; // Port すべて入力
ANSELA = 0; // すべてデジタル
ANSELC = 0; // すべてデジタル
WPUA = 0b100000; // RA5 弱プルアップ ON
RC4PPS = 20; // RC4をTX出力とする
//------------ Initialize UART ----------------------------------
RC1STA = 0b10000000; // 非同期送信 9600baud
TX1STA = 0b00100100;
BAUD1CON = 0b00001000;
SP1BRGH = 0;
SP1BRG = 25;
while(pushSW); // SWが押されるのを待つ
printf("Hello OK\r\n"); // 開始のメッセージ
// ----------- 繰返し --------------------------------------------
while(1){
while(!pushSW); // SWが離れるのを待つ
__delay_ms(10); // 10mS遅延
while(pushSW); // SWが押されるのを待つ
__delay_ms(10); // 10mS遅延
printf("%d\r\n",num++); // 0123・・・と送信
}
}
非同期8ビットシリアル、パリティーなし、9600bpsで受信するプログラムを作成しました。 受信したASCII文字データにより、指定されたLEDを点滅します。
シリアル信号をPICに加える信号源に、PICkit2 のUART機能を使用しています。
<プログラム>
/*************************************
* File: UART RX sample
* System ClockはConfigで内部1MHzに設定
* UARTで受信したシリアルデータで以下pinをONにする
* 1:RC0 2:RC1 3:RC2 4:RC3
* 0:全てOFF
*
* PIC16F18325
* Created on Sep 2, 2017, 2:37 PM
**************************************/
#include <xc.h>
#pragma config FEXTOSC = OFF,RSTOSC = HFINT1 // HFINTOSC (1MHz)
#pragma config CLKOUTEN = OFF,CSWEN = OFF,FCMEN = OFF
#pragma config MCLRE = OFF,PWRTE = OFF,WDTE = OFF,LPBOREN = OFF
#pragma config BOREN = OFF,BORV = LOW,PPS1WAY = OFF,STVREN = ON
#pragma config DEBUG = OFF
#pragma config WRT = OFF,LVP = OFF,CP = OFF,CPD = OFF
// ******************* main *************************************
void main() {
char RxData;
TRISA = 0b111111; // Port すべて入力
TRISC = 0b110000; // RC0-RC3 出力
ANSELA = 0; // すべてデジタル
ANSELC = 0; // すべてデジタル
// RXPPS = 0x15; // RC5をRX入力とする
//------------ Initialize UART ----------------------------------
RC1STA = 0b10010000; // 8 bit 連続受信
TX1STA = 0b00000100; // 非同期受信 High Baud Rate選択
BAUD1CON = 0b00001000; // 16 bit SPBRG
SP1BRGH = 0; // 9600bps
SP1BRGL = 25;
// ----------- 繰返し --------------------------------------------
while(1){
while (!RCIF); // 受信するまで待つ
RxData = RC1REG; // 受信データを取り込む
switch(RxData){ // データ内容で、On/Off
case '0': LATC = 0; break;
case '1': LATC = 1; break;
case '2': LATC = 2; break;
case '3': LATC = 4; break;
case '4': LATC = 8; break;
default: break;
}
}
}
非同期8ビットシリアル、パリティーなし、9600bpsで受信するプログラムを作成しました。 リセット直後にSWを押すと開始メッセージ。その後 SWを押すたびに、「SW OK」と送信します。また、データを受信すると、値を +1 して送り返します。
<プログラム>
/*************************************
* File: UART TXRX sample
* System ClockはConfigで内部1MHzに設定
* UARTでデータを送受信する。
* SWを押すと開始メッセージ。その後 SWを押すたびに、「SW OK」
* データを受信すると、値を +1 して送り返す
* PIC16F18325
* Created on Aug 22, 2017, 2:37 PM
**************************************/
#include <xc.h>
#include <stdio.h>
#define _XTAL_FREQ 1000000 // delay_ms(x) のための定義
#pragma config FEXTOSC = OFF,RSTOSC = HFINT1 // HFINTOSC (1MHz)
#pragma config CLKOUTEN = OFF,CSWEN = OFF,FCMEN = OFF
#pragma config MCLRE = ON,PWRTE = OFF,WDTE = OFF,LPBOREN = OFF
#pragma config BOREN = OFF,BORV = LOW,PPS1WAY = OFF,STVREN = ON
#pragma config DEBUG = OFF
#pragma config WRT = OFF,LVP = OFF,CP = OFF,CPD = OFF
#define pushSW PORTAbits.RA5
// ================= printf関数を使用するための定義 =================
void putch(unsigned char ch) {
while (!TXIF); //送信終了待ち
TX1REG = ch;
}
// ******************* main *************************************
void main() {
char RxData;
char SWstate = 0; // SWの状態
TRISA = 0b111111; // Port すべて入力
TRISC = 0b111111; // Port すべて入力
ANSELA = 0; // すべてデジタル
ANSELC = 0; // すべてデジタル
WPUA = 0b101000; // RA5 弱プルアップ ON
RC4PPS = 20; // RC4をTX出力とする
RXPPS = 0x15; // RC5をRX入力とする
//------------ Initialize UART ----------------------------------
RC1STA = 0b10010000; // 8 bit 連続受信
TX1STA = 0b00100100; // 非同期送受信 High Baud Rate選択
BAUD1CON = 0b00001000;
SP1BRGH = 0;
SP1BRG = 25;
while(pushSW); // SWが押されるのを待つ
printf("Hello OK\r\n"); // 開始のメッセージ
// ----------- 繰返し --------------------------------------------
while(1){
// ------ 受信 ------------------------------------------------
if(RCIF){
RxData = RC1REG; // 受信データを取り込む
switch(RxData){ // データ内容で、On/Off
case 0x0A:
case 0x0D:
while (!TXIF); //送信終了待ち
TX1REG = RxData;
break;
default:
while (!TXIF); //送信終了待ち
TX1REG = RxData + 1;
break;
}
}
// ------ 送信 ------------------------------------------------
if(pushSW != SWstate){ // SWの状態が変化したら
__delay_ms(10); // 10mS遅延
SWstate = pushSW; // 新しい状態を記録
if(pushSW == 0){ // SWが押されたのなら
printf("SW ON\r\n"); // 開始のメッセージ
}
}
}
}
非同期8ビットシリアル、パリティーなし、115200bpsを割り込みで受信処理するプログラムを作成しました。 リセット直後にLEDが点滅し、「Start」とシリアル送信します。その後は、PCからの受信データで以下の処理を実行します。
<プログラム>
/*************************************
* File:uart interrupt
* System ClockはConfigで内部32MHzに設定
* 115200 baud で通信
* '1'を受信でLED ON、 '2'を受信でLED OFF
* '!'を受信でデバイスリセットしLED点滅
* PIC16F18325
* Serial port RA4:Rx RA5:Tx
* LED RA2
*
* Created on 2021-10-22
**************************************/
#include <xc.h>
#include <stdio.h>
#define _XTAL_FREQ 32000000 // delay_ms(x) のための定義
#pragma config FEXTOSC = OFF,RSTOSC = HFINT32 // 32MHz clock
#pragma config CLKOUTEN = OFF,CSWEN = OFF,FCMEN = OFF
#pragma config MCLRE = ON,PWRTE = OFF,WDTE = OFF,LPBOREN = OFF
#pragma config BOREN = OFF,BORV = LOW,PPS1WAY = OFF,STVREN = ON
#pragma config DEBUG = OFF
#pragma config WRT = OFF,LVP = ON,CP = OFF,CPD = OFF
#define LED LATAbits.LATA2
// ================= printf関数を使用するための定義 ==========
void putch(unsigned char ch) {
while (!TXIF); //送信終了待ち
TX1REG = ch;
}
// ******************* main *******************************
void main() {
TRISA = 0b111011; // RA2 出力 他は すべて入力
TRISC = 0b111111; // Port すべて入力
ANSELA = 0; // すべてデジタル
ANSELC = 0; // すべてデジタル
WPUA = 0b001011; // RA0-RA3 弱プルアップ ON
WPUC = 0b100000; // RC5 弱プルアップ ON
RXPPS = 0x04; // RA4->EUSART:RX
RA5PPS = 0x14; // RA5->EUSART:TX
//------------ Initialize UART ----------------------------
RC1STA = 0b10010000; // 8 bit 連続受信
TX1STA = 0b00100100; // 非同期送受信 High Baud Rate選択
BAUD1CON = 0b00001000; // 115200 baud
SP1BRGH = 0;
SP1BRG = 68;
LED = 1;__delay_ms(200); // LED 点滅
LED = 0;__delay_ms(200);
LED = 1;__delay_ms(200);
LED = 0;__delay_ms(200);
RCIE = 1; // UART Rx 割込みを使用許可
PEIE = 1; // 周辺機能割込みの使用許可
GIE = 1; // 全割込みの使用許可
printf("Start\r\n"); // 準備完了を送信
// ----------- 繰返し --------------------------------------------
while(1) ;
}
/* ********************************************************
* Uart1 Rx割込み処理
* ********************************************************/
void __interrupt() Rx_isr(void) {
char RxData;
if(RCIF){
if(RC1STAbits.OERR){ // 受信エラーなら
RC1STAbits.CREN = 0; // ON/OFFで
RC1STAbits.CREN = 1; // エラークリア
}else{ // 正常受信なら
RxData = RC1REG; // 受信データ取得
switch(RxData){ // 受信したら、
case '1': LED = 1; break; // 1 なら LED 点灯
case '2': LED = 0; break; // 2 なら LED 消灯
case '!': RESET(); break; // ! なら デバイスのリセット
}
}
}
}
同じ動作のアセンブラプログラムは、[こちら]