micro:bitではハードウェアシリアル通信ポートが1つ利用出来ます。
Arduino環境で利用する場合、USB経由のシリアル通信専用に割り付けれています。
具体的にはポート21、22に割り付けられていているのですが、このポートは
外部端子には接続されていせん。
しかし、ハードウェア的にmicro:bitではシリアル通信ポートを任意の外部端子に
割り付けることが出来ます。
Arduino環境でも任意のポートに割り付けられないかとやってみました。
まずは、Serialインスタンスを実装しているUartクラスを使って試してみます。
スケッチ(注意:このスケッチはダメだったケースです)
//
// micro:bit シリアルポートの利用
// 任意のポートを使ってシリアル通信を行う
//
#define Rxpin 12 // シリアル RxDピン(任意指定可能)
#define Txpin 13 // シリアル TxDピン(任意指定可能)
#define baudRate 9216000 // 通信速度(1200 ~ 921600bps)
// Uartインスタンスの生成
Uart Serial2(NRF_UART0, UART0_IRQn, Rxpin, Txpin);
//extern "C" void UART0_IRQHandler() { Serial2.IrqHandler(); };
void setup() {
Serial2.begin(baudRate); // 通信開始
}
void loop() {
Serial2.println("Hello,world");
delay(1000);
}
上記の例では、Uartクラスを使ってデフォルトのSerialオブジェクトとは
別のインスタンスを生成しています。
インスタンス生成時に利用するポートを指定することが出来ます。
外部端子を使う利点として、通信速度に115200以上の指定が可能です。
(USB経由だと115200までしか利用出来ない)
試しに、上限の921600bpsを指定してみると、TeraTermにで問題なく出力できました。
(パソコンに接続にはUSB-Serialモジュールを利用しています)
送信については、任意のポートに割り付けて利用することが出来ました。
ところが、受信処理を実装するとデータ受信を行うことが出来ません。
問題点を調べると、
シリアル受信を行うコールバック関数(割り込み処理)が
デフォルトのSerialインスタンスに固定されています。
Uart.cpp
extern "C"
{
void UART0_IRQHandler()
{
Serial.IrqHandler();
}
}
Arduinoのコア部分で上記のように固定されており、
これを修正することが出来ません。
本来ならば
Serial.IrqHandler();
を
Serial2.IrqHandler();
に変更しないといけません。
IrqHandler()の実体は下記のようになっており、
Serialインスタンスのリングバッファにデータを格納しています。
これでは、後から生成したSerail2インスタンスでのデータ受信を行うことが出来ません。
void Uart::IrqHandler()
{
if (nrfUart->EVENTS_RXDRDY)
{
rxBuffer.store_char(nrfUart->RXD);
nrfUart->EVENTS_RXDRDY = 0x0UL;
}
}
この方法は諦めて、Arduino環境のUart.h、Uart.cppに修正を入れることにしました。
ポート設定を行うメンバー関数setPort()を追加しました。
Uart.hの修正:下記の2つのメンバー関数の宣言の追加
// <-- add by Tamakichi 2018/02/07
void setPort(uint8_t _pinRX, uint8_t _pinTX);
void setPort(uint8_t _pinRX, uint8_t _pinTX, uint8_t _pinCTS, uint8_t _pinRTS );
// -->>
Uart.cppの修正:下記の2つのメンバー関数の本体の追加
// <-- add by Tamakichi 2018/02/07
void Uart::setPort(uint8_t _pinRX, uint8_t _pinTX)
{
uc_pinRX = g_ADigitalPinMap[_pinRX];
uc_pinTX = g_ADigitalPinMap[_pinTX];
uc_hwFlow = 0;
}
void Uart::setPort(uint8_t _pinRX, uint8_t _pinTX, uint8_t _pinCTS, uint8_t _pinRTS)
{
uc_pinRX = g_ADigitalPinMap[_pinRX];
uc_pinTX = g_ADigitalPinMap[_pinTX];
uc_pinCTS = g_ADigitalPinMap[_pinCTS];
uc_pinRTS = g_ADigitalPinMap[_pinRTS];
uc_hwFlow = 1;
}
// -->>
この追加したメンバー関数を利用したスケッチ
//
// micro:bit シリアルポートの利用
// 任意のポートを使ってシリアル通信を行う
// 本スケッチはArduinoのUart.h、Uart.cppの修正が必要
//
#define Rxpin 12 // シリアル RxDピン(任意指定可能)
#define Txpin 13 // シリアル TxDピン(任意指定可能)
#define baudRate 9216000 // 通信速度(1200 ~ 921600bps)
void setup() {
Serial.setPort(Rxpin, Txpin);
Serial.begin(baudRate); // 通信開始
Serial.println("Hello,world");
}
void loop() {
if (Serial.available()) {
Serial.write(Serial.read());
}
}
実行結果

これで、とりあえずは任意のポートを利用した送受信を行うことが出来ました。
ただし、Arduino環境に修正を加える必要があります。
2018/5/11 追記
シリアル通信のためのUart.h、Uart.cppの修正、もっと簡単な方法で修正出来ました。
Uart.hの中で
#define ARDUINO_GENERIC
を追記することで、追加した関数と同等のsetPins()が有効になります。
#include <nrf.h>
#include "HardwareSerial.h"
#include "RingBuffer.h"
#include <cstddef>
// <-- add by Tamakichi 2018/05/06
#define ARDUINO_GENERIC
// -->
class Uart : public HardwareSerial
{
public:
Uart(NRF_UART_Type *_nrfUart, IRQn_Type _IRQn, uint8_t _pinRX, uint8_t _pinTX);
Uart(NRF_UART_Type *_nrfUart, IRQn_Type _IRQn, uint8_t _pinRX, uint8_t _pinTX, uint8_t _pinCTS, uint8_t _pinRTS );
#ifdef ARDUINO_GENERIC
void setPins(uint8_t _pinRX, uint8_t _pinTX);
void setPins(uint8_t _pinRX, uint8_t _pinTX, uint8_t _pinCTS, uint8_t _pinRTS);
#endif // ARDUINO_GENERIC
最近のコメント