叶鋼は午前1時に計算をする

電子工作と計算の記録

【BLEを使う】nRF51822 のUART機能を使う

このUARTというのは Universal Asynchronous Receiver Transmitter の略でシリアル通信装置の一種です。

1バイト8ビットのデータを1本の電線で送るために、時系列にデータを分解して、1ビットづつ出力(送信)または入力(受信)します。

最近のほとんどのマイコンには、UART機能が搭載されていますのでマイコン間のデータ交換や、変換ICを使用しRS232C規格の通信としてパソコンとデータのやり取りをすることも可能です。

マイコンメーカーによってはUART以外に独自の呼び方をするメーカーもあります。

例えば、PICはUSARTと呼び、ルネサス製H8マイコンはUART機能を持った内蔵デバイスのことをSCIといいます。

http://www.ele-lab.com/tips_uart.htmlより引用

いままでの記事はこちらをご覧ください。

  

今回はnRF51822のUART機能の使い方を説明します。

 

今まではBLEで無線送信する方法ばかり説明してきましたが、そのBLEが送信する当のデータは、外部から取り込まないといけません。

UART通信やSPI通信はセンサや外部のマイコンからデータを取り込むための手段であり、それらの使用は必須と言えます。

今回は、nRF51822のUART機能を使用してみます。

  

・端子配置

nRF51822で面白いと思ったのは、周辺機能に対応する特定の端子がないということです。

例えば、ルネサスマイコンでは、TX機能を持つのはPORT1.6で、RX機能を持つのはPORT1.7と割り当てられていた場合、それらの機能を使いたい場合はPORT1.6とPORT1.7を使うしかありません。

(多くの場合、別端子に同じ機能が割り当てられていますが、使う端子が決められているという点では同じです。)

一方で、nRF51822の場合、機能に割り当てる端子は自分で設定して決めてやります。

端子番号0から31の中から、使いたい端子を選んで、機能を割り当てます。

例えば後述するレジスタPSELRXDについて

PSELRXD = 16;

と設定すれば、端子P0.16がRX端子となります。

開発キットの場合、この設定によりコネクタP2の29番がRX端子になります。

f:id:yegang:20140914151237j:plain

(nRF51822_Development_Kit_User_Guide_v1.4の 5.1.4より引用)

レジスタの値を変えれば、RX端子も変わります。実際に私はPSELRXD = 20に変更して、実際にRX機能がP0.20になったことを確認しました。

 

レジスタ

UARTに関連するレジスタは以下になります。

名称初期値
RXD 0x00000000受信したRXデータ
TXD 0x00000000転送するTXデータ
ENABLE0x00000000 0x00000000:UART禁止
0x00000004:UART許可
PSELRTS 0xFFFFFFFF 0~31:RTSに使用する端子番号
0xFFFFFFFF:UART使用禁止
PSELTXD 0xFFFFFFFF 0~31:TXDに使用する端子番号
0xFFFFFFFF:UART使用禁止
PSELCTS 0xFFFFFFFF 0~31:CTSに使用する端子番号
0xFFFFFFFF:UART使用禁止
PSELRXD 0xFFFFFFFF 0~31:RXDに使用する端子番号
0xFFFFFFFF:UART使用禁止
ERRORSRC 0x00000000 bit0
0:Overrunエラー未発生
1:Overrunエラー発生
bit1
0:Parityエラー未発生
1:Parityエラー発生
bit2
0:Framingエラー未発生
1:Framingエラー発生
bit3
0:ブレーク条件未発生
1:ブレーク条件発生
CONFIG 0x00000004 bit0
0:フロー制御禁止
1:フロー制御許可
bit2:bit1
0x00:Parityなし
0x07?:Parityあり
BAUDRATE 0x01980000ボーレート

 

・初期設定

PSELTXDレジスタとPSELRXDレジスタにより、TX機能とRX機能端子を割り当てるか設定します。

また、TX機能を割り当てた端子を出力端子に設定して、初期値をHigh出力にします。RX機能を割り当てた端子を入力端子に設定します。

 

CONFIGレジスタでフロー制御やパリティビットを使うかどうかを決めます。

フロー制御を有効にした場合は、PSELRTSレジスタとPSELCTSレジスタにより、RTS機能とCTS機能端子を割り当てるか設定します。

また、RTS機能を割り当てた端子を出力端子に設定して、初期値をHigh出力にします。CTS機能を割り当てた端子を入力端子に設定します。

 

BAUDRATEレジスタで通信速度を何bpsにするか決めます。

 

最後にENABLEレジスタをUART許可にすれば、UART初期設定完了です。

 

・送信

タスク信号STARTTX taskを1にすると送信シーケンスが始まります。

TXDレジスタに書き込むことで送信されます。イベント信号EVENTS_TXDRDYが1になると送信完了です。

EVENTS_TXDRDYを監視して、1になるまで待機してから、EVENTS_TXDRDYを0にクリアします。

STOPTX taskにより送信シーケンスは停止します。

 

・受信

タスク信号STARTRX taskを1にすると受信シーケンスが始まります。

イベント信号EVENTS_RXDRDYが1になると受信データが在ることを意味します。

EVENTS_RXDRDYを監視して、1になるまで待機してから、RXレジスタのデータを読み込み、EVENTS_RXDRDYを0にクリアします。

STOPRX taskにより受信シーケンスは停止します。

 

・関数

Noridicが提供するサンプルプログラムは以下になります。

nRF51 SDK - S110 SoftDevice: Simple UART driver

 

・simple_uart_get

1byte受信関数

 

・simple_uart_get_with_timeout

タイムアウト機能付き1byte受信関数。タイムアウト時間はmsec単位で指定可能。

 

・simple_uart_put

1byte送信関数

 

・simple_uart_putstring

文字列送信関数

 

・simple_uart_config

UART初期設定関数。ボーレート初期設定値38400bps。

 

・補足

UARTのサンプルプログラムをKeilで開くとnrf_dleay.hにErrorが表示されることがありますが、コンパイルは正常に行えます。特定のバージョンのKeil環境に由来する無視しても問題ない擬似エラーです。

The Keil shows an error when #include "nrf_delay.h" - Nordic Developer Zone

 

・実験

Norodicが提供しているuart_exampleを使用してみました。

まずはビルドして書き込みます。このサンプルプログラムはS110ドライバが書き込まれていると書き込みできないので、一度Erase allでS110を消してから、Programで書き込みます。

f:id:yegang:20140914151300j:plain

最初はnRFGoマザーボードでプログラムを走らせ、送信は正常に行えたのですが、受信はうまくいきませんでした。

プログラムの問題ではなく、UARTケーブルとnRFGoマザーボードとパソコンの相性が悪いからだと考え、自作の評価ボードで試したところ正常に送受信できるようになりました。

f:id:yegang:20140914151316j:plain

 

追記

 

・受信割り込み

受信による割り込みを発生させたい場合は、UARTの初期設定に以下を追加します。

    NRF_UART0->INTENSET      |= (UART_INTENSET_RXDRDY_Enabled << UART_INTENSET_RXDRDY_Pos );
    
    NVIC_EnableIRQ(UART0_IRQn);

以上を追加すると、受信時に関数UART0_IRQHandlerが呼び出されます。

例えば、UART0_IRQHandlerにおいて、受信データを変数に格納し、そのデータをそのまま送信する処理をさせてみます。

void UART0_IRQHandler(void)
{
        uint8_t cr = simple_uart_get();
        simple_uart_putstring((const uint8_t *)"\n\rYour input is ");
        simple_uart_put(cr);
}

キーボードから文字を入力すると、受信割り込みによりUART0_IRQHandlerの処理が実行されているのが確認できます。

f:id:yegang:20140920134017j:plain