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; // ! なら デバイスのリセット } } } }
同じ動作のアセンブラプログラムは、[こちら]