0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PIC 8bitマイコンでシリアル通信

0
Posted at

全体の構成

EUSARTの受信/送信は、マイコンのペリフェラルに任せます。これにより、データの受信、送信をハードウェアで処理させ、ソフトウェア処理の負荷を抑えることができます。

フローチャートを示します。

main()では、EUSARTの初期化をし、メインループ(無限ループ)の中で受信と送信操作を行います。

fig1.jpg

受信操作は、receive_data()によって、グローバル変数配列のバッファから受信データを読み出しています。

fig3.jpg

送信操作は、transmit_data()で送信データをグローバル変数配列のバッファにセットし、EUSART TX 割り込みを許可します。

fig4.jpg

受信バッファ、送信バッファはそれぞれ割り込み処理の中で処理されます。

  • 受信では、シリアル通信ポートに入ってきたデータが受信バッファに取り込まれると、割り込み要求が出されます。割り込み要求によって割り込み処理に入り、受信バッファのデータをグローバル変数配列のバッファにコピーします。
  • 送信では、送信バッファが空になっていると、割り込み要求が出され、割り込み処理の中でグローバル変数配列のバッファのデータを送信バッファに格納します。送信データがなければ、EUSART TX割り込みを禁止して終了します。

fig2.jpg

以下、それぞれの処理の実装例を示します。なお、実装例(レジスタ)はPIC16f15245の例です。

EUSARTの初期化

PICマイコンはPPS(Peripheral Pin Select)で、EUSARTのTX, RXピンの割当を設定することができます。以下の例では、RB6(PORTBの6pin)ピンをEUSARTのTXに、RB5(PORTBの5pin)をRXに割り当てています。

#define RX1PORT 0x0d    // RB5(01:101) for RX
#define TX1PORT RB6PPS  // RB6 for TX

void EUSART_init() {
  BADUD1CON = 0x08;     // bit4:SCKP(Clock/Transmit Polarity) = 0,
                        // bit3:BRG16(16-bit Baud Rate Generator) = 1,
                        // bit0:ABDEN(Auto-Baud Detect) = 0
  RC1STA = 0x90;        // bit7:SPEN(Serial Port Enable) = 1
                        // bit6:RX9(9-Bit Receive Enable) = 0
                        // bit5:SREN(Single Receive Enable) = 0
                        // bit4:CREN(Continuous Receive Enable) = 1
  SP1BRG = 25;          // Baud Rate Register
  TX1STA = 0x00;        // bit7:CSRC(Clock Source Select) = 0
                        // bit6:TX9(9-Bit Transmit Enable) = 0
                        // bit5:TXEN(Transmit Enable) = 0
                        // bit4:SYNC(EUSART Mode Select) = 0
                        // bit2:BRGH(High Baud Rate Select) = 0
  RX1PPS = RX1PORT;     //
  TX1PORT = 0x05;       // 
  PIE1 |= 0x10;         // bit4:RC1IE(EUSART1 Receive Interrupt) = 1
}

受信

受信は、グローバル変数のrxBuf[]のデータを読み出します。rxBuf[]には、EUSARTの受信割り込みで、受信バッファからデータをコピーしており、そのデータを読み出すことができます。

rxBufはリングバッファとなっており、バッファ内の最古のデータ位置がrxBufHead、最新のデータ位置の次がrxBufTailとしています。したがって、バッファ内のまだ読みだしていないデータは、rxBufHead~rxBufTail-1のデータとなります。

#define RX_BUF_SIZE 8

unsigned char rxBuf[RX_BUF_SIZE]; // receive data buffer
unsigned char rxBufHead = 0;    // receive data head index
unsigned char rxBufTail = 0;    // receive data tail index

void receive_data(unsinged char data[]) {
  int i = 0;
  while (rxBufHead != rxBufTail) {
    data[i] = rxBuf[rxBufHead];
    rxBufHead++;
    if (rxBufHead >= RX_BUF_SIZE) {
      rxBufHead = 0;
    }
  }
}

送信

送信は、グローバル変数のtxBuf[]に送信データをセットし、EUSARTの送信を許可、EUSARTの送信割り込みを許可すれば、後は割り込み処理でrxBuf[]のデータを送信します。

unsigned char txBuf[8];         // transmit data buffer
unsigned char txBufIdx = 0;     // transmit data index

void transmit_data(unsigned char txData[], int nTxData) {
  /* txDAta : transmit data array     */
  /* nTxData: number of transmit data */
  for (int i = 0; i < nTxData; i++) {
  	txBuf[nTxData - 1 - i] = txData[i];
  }
  RC1STA &= ~0x10;      // bit4:CREN(Continuous Receive) = 0 to transmit
  TX1STA |= 0x20;       // bit5:TXEN(Transmit Enable) = 1
  PIE1 |= 0x04;         // bit3:TX1IE(Transmit Interrupt) = 1
}

割り込み処理

EUSARTの受信バッファ(RC1REG)、送信バッファ(TX1REG)の操作は、割り込みで行います。

受信は、EUSARTの受信バッファ(RC1REG)のデータを読み出して、グローバル変数rxBuf[]に格納します。ただし、EUSARTの受信バッファのオーバーフロー、フレーミングエラーの処理を行っています。オーバーフローについては、受信できなかったデータはしかたないので、オーバーフローフラグ(RC1STA, bit1)をクリアする(CRENまたはSRENを一旦クリアする)のみ行います。

フレーミングエラーについては、エラー情報(RC1STA, bit2)をグローバル変数(ferr)にセットしておきます。

unsigned char ferr = 0;

void __interrupt() isr(void) {
  if (PIR1 & 0x10 != 0) {       // EUSART1 Receive Interrupt
  	if (RC1STA & 0x02 != 0) {
  	  RC1STA &= ~0x10;
  	  RC1STA |= 0x10;
  	}
  	ferr = RC1STA & 0x04;       // set framing error flag
  	rxBuf[rxBufTail] = RC1REG;  // read receive buffer
  }
  if (PIR1 & 0x08 != 0) {       // EUSART1 Transmit Interrupt
  	if (txBufIdx == 0) {
  	  TX1STA &= ~0x20;          // bit5:TXEN(Transmit Enable) = 0
  	  RC1STA |= 0x10;           // bit4:CREN(Continuous Receive) = 1 to receive
  	  PIE1 &= ~0x04;            // bit3:TX1IE(Transmit Interrupt) = 0
  	  return;
  	}
  	txBufIdx--;
  	TX1REG = txBuf[txBufIdx];   // set transmit buffer
  }
}

メイン関数

ここまでの処理が実装できていれば、メイン関数で、EUSARTの初期化と受信操作、送信操作を行うのみとなります。

#include "pic16f15245.h"        // head file for mpu

void EUSART_init(void);
void receive_data(unsigned char[]);
void transmit_data(void);

int main() {
  int n = 10;                   // number of data
  unsigned char data[n];

  EUSART_init();
  INTCOPN |= 0xc0;              // bit7:GIE(Global Interrupt Enable) = 1
                                // bit6:PIE(Peripheral Interrupt Enable) = 1
  while (1) {
  	receive_data(data);         // read -> data[]

  	/* make sample data to transmit */
    for (int i = 0; i < n; i++) {
      data[i] = 'a' + i;
    }
    /*                              */

  	transmit_data(data, n);     // transmit data[]
  }
  return 0;
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?