OrangePi-PCを使ってみる

シリアル通信

OrangePi-PC でのシリアル通信を紹介します。
Orange Pi PCのマニュアルによると、ボード上に1組、ピンヘッダー上に3組の合計4組のTx/Rxポートがありますが、
Armbianの初期状態ではデバイススペシャルファイルは「/dev/ttyS0」しか有りません。
このデバイスは、シリアルコンソール用のポートとしてアサインされていて、そのままでは、シリアル通信では使えません。
Orange Pi PCのマニュアルに、コンソールポートの場所とピンヘッダーの説明があります。



そこで、script.binを変更して、デバイスを追加します。
script.binの変更手順はこちらで紹介しています。
それぞれのパラメータの意味はこちらに解説が ありますが、2線式しか使わないのでuart_typeはすべて2に変更しています。
{中略}

[uart0]
uart_used = 1
uart_port = 0
uart_type = 2
uart_tx = port:PA04<2><1><default><default>
uart_rx = port:PA05<2><1><default><default>

[uart1]
uart_used = 0 → 1
uart_port = 1
uart_type = 4 → 2
uart_tx = port:PG06<2><1><default><default>
uart_rx = port:PG07<2><1><default><default>
uart_rts = port:PG08<2><1><default><default>
uart_cts = port:PG09<2><1><default><default>

[uart2]
uart_used = 0 → 1
uart_port = 2
uart_type = 4 → 2
uart_tx = port:PA00<2><1><default><default>
uart_rx = port:PA01<2><1><default><default>
uart_rts = port:PA02<2><1><default><default>
uart_cts = port:PA03<2><1><default><default>

[uart3]
uart_used = 0 → 1
uart_port = 3
uart_type = 4 → 2
uart_tx = port:PA13<3><1><default><default>
uart_rx = port:PA14<3><1><default><default>
uart_rts = port:PA15<3><1><default><default>
uart_cts = port:PA16<3><1><default><default>

{後略}

修正が終わったら、「script.fex」を「script.bin」に変換してリブートします。
リブートすると今まで1つしかなかったデバイススペシャルファイルが4つに増えます。



デバイススペシャルファイルとピンの関係は以下の様になります。
ピンの名前 デバイススペシャルファイル Txピンの場所 Rxピンの場所
TxD0/RxD0 /dev/ttyS0 オンボード上のTx オンボード上のRx
TxD1/RxD1 /dev/ttyS1 ピンヘッダーのPin#38 ピンヘッダーのPin#40
TxD2/RxD2 /dev/ttyS2 ピンヘッダーのPin#13 ピンヘッダーのPin#11
TxD3/RxD3 /dev/ttyS3 ピンヘッダーのPin#8 ピンヘッダーのPin#10

そこで、これらのデバイス を使ったシリアル通信を試してみます。
通信相手はRaspberryPiを使います。
RaspberryPi側が送信、OrangePi側が受信で、OrangePi側のコードは以下です。
起動時の引数でデバイスファイルを指定します。

//
// Serial Receive Program
//
// cc -o serialR serialR.c -lwiringPi
//
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <wiringPi.h>
#include <wiringSerial.h>

#define    DEBUG    1

int readSerial(int fd, char * buff, int blen, int timeout) {
  unsigned long endTime;
  int ch;
  int pos = 0;

if(DEBUG)printf("millis=%d\n",millis());
  endTime = millis () + timeout;
if(DEBUG)printf("endTime=%d\n",endTime);
  buff[pos] = 0;

  while (1) {
    if (millis () > endTime) return -1;
    if (serialDataAvail (fd)) {
      ch = serialGetchar (fd);
if(DEBUG)printf (" -> %02x\n", ch);
      if (ch == 0x0d) {

      } else if (ch == 0x0a) {
        return pos;
      } else {
        if (pos < blen) buff[pos++] = ch;
        if (pos < blen) buff[pos] = 0;
      }
    } // end if
  } // end while
}


int main (int argc, char **argv) {
  int fd;
  int len;
  char buff[64];
  char device[32];

  strcpy(device,"/dev/ttyAMA0");
  if (argc == 2) strcpy(device,argv[1]);

//  if ((fd = serialOpen ("/dev/ttyAMA0", 115200)) < 0) {
  if ((fd = serialOpen (device, 115200)) < 0) {
    printf ("Unable to open serial device: %s\n", strerror (errno)) ;
    return 1 ;
  }

  if (wiringPiSetup () == -1) {
    printf ("Unable to start wiringPi: %s\n", strerror (errno)) ;
    return 1 ;
  }
  printf("wiringPiSetup\n");

  while(1) {
//  Receive data
    len=readSerial(fd, buff, sizeof(buff),10000);
    if (len != -1) {
      printf("readSerial data=[%s]\n",buff);
//    Send data
      serialPrintf (fd,"You are Welcome!! This is %s\n",device);
  }
}

RaspberryPi側の送信プログラムは以下のコードです。
実行前に必ず「raspi-config」でシリアルポートからのログインを無効にしてください。

//
// Serial Send Program
//
// cc -o serialS serialS.c -lwiringPi
//
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <wiringPi.h>
#include <wiringSerial.h>

#define    DEBUG    0

int readSerial(int fd, char * buff, int blen, int timeout) {
  unsigned long endTime;
  int ch;
  int pos = 0;

if(DEBUG)printf("millis=%d\n",millis());
  endTime = millis () + timeout;
if(DEBUG)printf("endTime=%d\n",endTime);
  buff[pos] = 0;

  while (1) {
    if (millis () > endTime) return -1;
    if (serialDataAvail (fd)) {
      ch = serialGetchar (fd);
if(DEBUG)printf (" -> %02x\n", ch);
      if (ch == 0x0d) {

      } else if (ch == 0x0a) {
        return pos;
      } else {
        if (pos < blen) buff[pos++] = ch;
        if (pos < blen) buff[pos] = 0;
      }
    } // end if
  } // end while
}


int main (int argc, char **argv) {
  int fd;
  int len;
  char buff[64];
  char device[32];

  strcpy(device,"/dev/ttyAMA0");
  if (argc == 2) strcpy(device,argv[1]);
  printf("device=%s\n",device);

//  if ((fd = serialOpen ("/dev/ttyAMA0", 115200)) < 0) {
  if ((fd = serialOpen (device, 115200)) < 0) {
    printf ("Unable to open serial device: %s\n", strerror (errno)) ;
    return 1 ;
  }

  if (wiringPiSetup () == -1) {
    printf ("Unable to start wiringPi: %s\n", strerror (errno)) ;
    return 1 ;
  }

//Send data
  serialPrintf (fd,"Hello!!\n");
//Receive data
  len=readSerial(fd, buff, sizeof(buff),10000);
  printf("readSerial len=%d data=[%s]\n",len,buff);
}


RaspberryPi と OrangePi のTX/RXを交互につなぎます。
RaspberryPi OrangePi
TX RX1(PG7)
RX TX1(PG6)

OrangePi側のプログラムを引数=/dev/ttyS1で起動します。
RaspberryPi側のプログラムを起動すると、以下のように表示されます。


次に 結線を一部変更して、OrangePi側のプログラムを引数=/dev/ttyS2で再起動します。
RaspberryPi OrangePi
TX RX2(PA1)
RX TX2(PA1)

RaspberryPi側のプログラムを再起動すると、以下のように表示されます。


再び 結線を一部変更してOrangePi側のプログラムを引数=/dev/ttyS3で再起動します。
RaspberryPi OrangePi
TX RX3(PA14)
RX TX3(PA13)

RaspberryPi側のプログラムを再起動すると、以下のように表示されます。



/dev/ttyS1 /dev/ttyS2 /dev/ttyS3 全て問題なく動作しました。

次回は 同時に複数のポートを使って、複数の相手とシリアル通信してみます。