PIC16F18325の基本動作から応用プログラムまでを学びます。

ホーム
12F1822
16F1455
16F1459
18F14K50
18F26J50
dsPIC
その他
    
16F18313
16F18325
16F18346
16F1619
Curiosity
---
---
UARTシリアル送信・受信。送受信プログラム
2020-07-08

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」デジタルにする必要があります。

<回路図>

シリアルUART送信のプログラム例

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・・・と送信
    }
}

シリアルUART受信のプログラム例

非同期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;
		}
	}
}

シリアルUART送受信のプログラム例

非同期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");    // 開始のメッセージ
            }
        }
    }
}

シリアルUART送信、割込み受信のプログラム例

非同期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;  // ! なら デバイスのリセット
            }
        }
    }
}

同じ動作のアセンブラプログラムは、[こちら